Joh*_*ork 52 python django django-rest-framework
使用Django REST Framework,标准的ModelSerializer将允许通过将ID作为整数进行POST来分配或更改ForeignKey模型关系.
从嵌套的序列化器中获取此行为的最简单方法是什么?
注意,我只讨论分配现有数据库对象,而不是嵌套创建.
我过去已经在序列化程序中添加了"id"字段以及自定义create和update方法,但这对我来说是一个看似简单且常见的问题,我很想知道最好的方法.
class Child(models.Model):
name = CharField(max_length=20)
class Parent(models.Model):
name = CharField(max_length=20)
phone_number = models.ForeignKey(PhoneNumber)
child = models.ForeignKey(Child)
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
class ParentSerializer(ModelSerializer):
# phone_number relation is automatic and will accept ID integers
children = ChildSerializer() # this one will not
class Meta:
model = Parent
Run Code Online (Sandbox Code Playgroud)
jos*_*son 40
以下是Kevin的答案所讨论的一个例子,如果你想采用这种方法并使用2个单独的字段.
在你的models.py中......
class Child(models.Model):
name = CharField(max_length=20)
class Parent(models.Model):
name = CharField(max_length=20)
phone_number = models.ForeignKey(PhoneNumber)
child = models.ForeignKey(Child)
Run Code Online (Sandbox Code Playgroud)
然后serializers.py ...
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
class ParentSerializer(ModelSerializer):
# if child is required
child = ChildSerializer(read_only=True)
# if child is a required field and you want write to child properties through parent
# child = ChildSerializer(required=False)
# otherwise the following should work (untested)
# child = ChildSerializer()
child_id = serializers.PrimaryKeyRelatedField(
queryset=Child.objects.all(), source='child', write_only=True)
class Meta:
model = Parent
Run Code Online (Sandbox Code Playgroud)
设置source=child允许child_id作为子进程默认情况下不会被覆盖(我们想要的行为).child_id使child_id可以写入,但防止它显示在响应中,因为id已经显示在ChildSerializer中
Kev*_*own 38
这里最好的解决方案是使用两个不同的字段:一个用于阅读,另一个用于写入.如果不做一些繁重的工作,很难在一个领域找到你想要的东西.
只读字段将是您的嵌套序列化程序(ChildSerializer在本例中),它将允许您获得您期望的相同嵌套表示.大多数人将此定义为公正child,因为他们已经通过这一点编写了前端并且更改它会导致问题.
只写字段将是a PrimaryKeyRelatedField,这是您通常用于根据主键分配对象的字段.这不一定是只写的,特别是如果你试图在接收的内容和发送的内容之间保持对称,但听起来这可能最适合你.该字段应该有一个source设置为(外键字段child在这个例子中),因此适当分配给它的创建和更新.
这已经在讨论组中提出过几次,我认为这仍然是最好的解决方案.感谢Sven Maurer指出它.
JPG*_*JPG 32
使用两个不同的领域将是确定(如@Kevin布朗和@joslarson提到的),但我认为这不是完美的(对我来说).因为从一个密钥(child)获取数据并将数据发送到另一个密钥(child_id)可能对前端开发人员来说有点模棱两可.(完全没有冒犯)
那么,我在这里建议的是,覆盖将要完成工作的to_representation()方法ParentSerializer.
def to_representation(self, instance):
response = super().to_representation(instance)
response['child'] = ChildSerializer(instance.child).data
return response
Run Code Online (Sandbox Code Playgroud)
完整的Serializer表示
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
fields = '__all__'
class ParentSerializer(ModelSerializer):
class Meta:
model = Parent
fields = '__all__'
def to_representation(self, instance):
response = super().to_representation(instance)
response['child'] = ChildSerializer(instance.child).data
return responseRun Code Online (Sandbox Code Playgroud)
这种方法的优点?
通过使用此方法,我们不需要两个单独的字段来创建和读取.在这里,创建和阅读都可以通过使用child 密钥来完成.
示例有效负载以创建parent实例
{
"name": "TestPOSTMAN_name",
"phone_number": 1,
"child": 1
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21372 次 |
| 最近记录: |