python - DRF : Simple foreign key assignment with nested serializers?

标签 python django django-rest-framework

使用 Django REST 框架,标准 ModelSerializer 将允许通过将 ID 作为整数发布来分配或更改 ForeignKey 模型关系。

从嵌套序列化程序中获得这种行为的最简单方法是什么?

注意,我只是在谈论分配现有的数据库对象,不是嵌套创建。

我过去在序列化程序中使用额外的“id”字段以及自定义 createupdate 方法解决了这个问题,但这看起来很简单我很想知道最好的方法。

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

最佳答案

2020 年 7 月 5 日更新

这篇文章越来越受到关注,这表明更多人有类似的情况。所以我决定添加一个通用方式来处理这个问题。如果您有更多需要更改为这种格式的序列化程序,这种通用方式最适合您

由于 DRF 没有提供开箱即用的功能,我们需要先创建一个序列化器字段

from rest_framework import serializers


class RelatedFieldAlternative(serializers.PrimaryKeyRelatedField):
    def __init__(self, **kwargs):
        self.serializer = kwargs.pop('serializer', None)
        if self.serializer is not None and not issubclass(self.serializer, serializers.Serializer):
            raise TypeError('"serializer" is not a valid serializer class')

        super().__init__(**kwargs)

    def use_pk_only_optimization(self):
        return False if self.serializer else True

    def to_representation(self, instance):
        if self.serializer:
            return self.serializer(instance, context=self.context).data
        return super().to_representation(instance)

这个类名RelatedFieldAlternative给我留下了深刻的印象,你可以使用任何你想要的东西。 然后在您的父序列化程序中使用这个新的序列化程序字段,

class ParentSerializer(ModelSerializer):
   <b>child = RelatedFieldAlternative(queryset=Child.objects.all(), serializer=ChildSerializer)</b>

    class Meta:
        model = Parent
        fields = '__all__'

原帖

使用两个不同的字段会ok(如 @Kevin Brown@joslarson 所述),但我认为它不是 完美强>(对我来说)。因为从一个键 (child) 获取数据并将数据发送到另一个键 (child_id) 对于 front-end 开发人员。 (完全没有冒犯)


所以,我在这里建议的是,重写 ParentSerializerto_representation() 方法就可以了。

def to_representation(self, instance):
    response = super().to_representation(instance)
    response['child'] = ChildSerializer(instance.child).data
    return response


序列化器的完整表示

class ChildSerializer(ModelSerializer):
    class Meta:
        model = Child
        fields = '__all__'


class ParentSerializer(ModelSerializer):
    class Meta:
        model = Parent
        fields = '__all__'

    <b>def to_representation(self, instance):
        response = super().to_representation(instance)
        response['child'] = ChildSerializer(instance.child).data
        return response</b>



Advantage of this method?

通过使用这种方法,我们不需要创建和读取两个单独的字段。这里创建和读取都可以使用child键完成。


用于创建 parent 实例的示例负载

{
        "name": "TestPOSTMAN_name",
        "phone_number": 1,
        "child": 1
    }



截图
POSTMAN screenshot

关于python - DRF : Simple foreign key assignment with nested serializers?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29950956/

相关文章:

django - 无法使用 Python 3.8 在 Windows 10 上安装 "psycopg2"

python - Django Rest Framework + Django-Allauth 密码重置/恢复

python - 使用 Django 查询集访问不同的外键关系

python - 如何从 django 中包含逗号分隔数据的列中获取唯一值?

Python 列表 - L1+=[5] 和 L1 = L1+[5] 的不同结果

python - 如何比较 itertools.combinations 中的元素?

python - 如何获取一列特定值的第一次出现,但前提是它至少有 5 个连续的行在彼此下方

python - 将表单数据保存到数据库并将其发送到API; Django

python - django.db.utils.IntegrityError : duplicate key value violates unique constraint "core_user_pkey" DETAIL: Key (id)=(23) already exists

python - 'collections.OrderedDict' 对象没有属性 'pk' - django rest 框架