Python 适当的自定义可写(和可读)ModelSerializer字段
我在做一个管理学校员工的项目。在我看来,两者之间的关系实现得很差,所以我正在尝试重构它。然而,为了最大限度地减少影响,因为这不是一个优先事项,所以我正在尝试在不破坏前端的情况下做到这一点,前端应该在以后进行重构。当前的Python 适当的自定义可写(和可读)ModelSerializer字段,python,django-rest-framework,django-serializer,Python,Django Rest Framework,Django Serializer,我在做一个管理学校员工的项目。在我看来,两者之间的关系实现得很差,所以我正在尝试重构它。然而,为了最大限度地减少影响,因为这不是一个优先事项,所以我正在尝试在不破坏前端的情况下做到这一点,前端应该在以后进行重构。当前的Staff模型如下所示: class Staff(models.Model): principal_at = models.ForeignKey(School, null=True) teacher_at = models.ForeignKey(School, nu
Staff
模型如下所示:
class Staff(models.Model):
principal_at = models.ForeignKey(School, null=True)
teacher_at = models.ForeignKey(School, null=True)
# I'm only showing these two roles for the sake of simplicity but there are more.
class StaffSerializer(serializers.ModelSerializer):
class Meta:
model = Staff
fields = (
"principal_at",
"teacher_at",
# ...
)
# There is also some custom validation to ensure the Staff can only have
# one role.
我正在将其重构为:
class Staff(models.Model):
ROLE_CHOICES = (
"principal",
"teacher",
# ...
)
school = models.ForeignKey(School)
role = models.CharField(choices=ROLE_CHOICES)
# ...
@property
def principal_at(self):
return self.school if self.role == "principal" else None
# ...
我的StaffSerializer
如下所示:
class Staff(models.Model):
principal_at = models.ForeignKey(School, null=True)
teacher_at = models.ForeignKey(School, null=True)
# I'm only showing these two roles for the sake of simplicity but there are more.
class StaffSerializer(serializers.ModelSerializer):
class Meta:
model = Staff
fields = (
"principal_at",
"teacher_at",
# ...
)
# There is also some custom validation to ensure the Staff can only have
# one role.
如果我只是保持it不变,则位于的主体字段将成为一个只读字段
,并且不会保存,这是有意义的,因为我的模型属性现在是一个属性,而不是实际的可写字段。因此,我将序列化程序更改为:
class StaffSerializer(serializers.ModelSerializer):
kwargs = {"required": False, "queryset": School.objects.all()}
principal_at = serializers.PrimaryKeyRelatedField(**kwargs)
teacher_at = serializers.PrimaryKeyRelatedField(**kwargs)
class Meta:
model = Staff
fields = (
"principal_at",
"teacher_at",
# ...
)
def validate(self, data):
principal_at = data.pop("principal_at", None)
teacher_at = data.pop("teacher_at", None)
# ...
if principal_at:
data.update(school_id=principal_at, role="principal")
elif teacher_at:
data.update(school_id=teacher_at, role="teacher")
# ...
return data
现在模型已正确保存(我使用ipdb进行了检查),但在构建响应的过程中,我得到以下结果:
TypeError: Object of type School is not JSON serializable
在这一点之后,我真的不记得我试过什么,但我试过很多东西,但都不管用。我记得有一件事我试过了,当时让我大吃一惊,那就是创建了一个自定义字段并将重写为_表示法
:
class RelatedSchoolSerializer(serializers.PrimaryKeyRelatedField):
def to_representation(self, value):
import ipdb; ipdb.set_trace()
return value.pk
class StaffSerializer(serializers.ModelSerializer):
kwargs = {"required": False, "queryset": School.objects.all()}
principal_at = serializers.PrimaryKeyRelatedField(**kwargs)
teacher_at = serializers.PrimaryKeyRelatedField(**kwargs)
# ...
但是,由于同样的错误,这一直失败,提示我添加一个断点并检查f**k正在发生什么。在调试器内部,我得到了以下结果,这让我非常沮丧:
ipdb> value
<rest_framework.relations.PKOnlyObject object at 0x7f9563c87f90>
ipdb> value.pk
<School: School 0>
ipdb> value.pk.pk
1
ipdb>
ipdb>值
ipdb>value.pk
ipdb>value.pk.pk
1.
ipdb>
如果我返回value.pk.pk
而不是value.pk
,则一切正常。但是,即使我的测试套件通过了,我担心这样一个奇怪的黑客可能会在未来产生意想不到的神秘后果。到底发生了什么事?这样做的正确方式是什么