当父记录存在时,如何在 django rest 框架的子序列化程序中设置外键值

Posted

技术标签:

【中文标题】当父记录存在时,如何在 django rest 框架的子序列化程序中设置外键值【英文标题】:how to set foreignkey value in child serializer in django rest framework when the parent record exists 【发布时间】:2019-02-28 09:53:13 【问题描述】:

我有两个模型首先作为父模型“Country”,在第二个模型之前填充为子模型“City”。如下

class Country(models.Model):
    name = models.CharField(max_length=35)
    icon = models.ImageField()

    def __str__(self):
        return self.name


class City(models.Model):
    name = models.CharField(max_length=35)
    country = models.ForeignKey(to=Country, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

我的 serializers.py 满足我的需要如下:

class CountrySerializer(ModelSerializer):
    class Meta:

        model = Country
        fields = '__all__'

class CitySerializer(ModelSerializer):
    country = serializers.PrimaryKeyRelatedField(queryset=Country.objects.all())

    class Meta:

        model = City
        fields = ('name', 'country')

view.py

class CountryAPIView(ListAPIView):
    queryset = Country.objects.all()
    serializer_class = CountrySerializer
    permission_classes = [AllowAny, AllowAnonymous]


class CityAPIView(ListAPIView):
    queryset = City.objects.all()
    serializer_class = CitySerializer
    permission_classes = [AllowAny, AllowAnonymous]

    def post(self, request):

        serializer = CitySerializer(data=request.data)
        if serializer.is_valid(raise_exception=ValueError):
            serializer.create(validated_data=request.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.error_messages,
                        status=status.HTTP_400_BAD_REQUEST)

现在,当我运行 get api 时,它会运行并给我一个很好的结果。但是当我试图创建一个新城市并在 json 中设置“国家”:“id”时,我得到了这个错误

无法分配“2”:“City.country”必须是“Country”实例。

所以如果我不清楚,我需要的是在创建城市时为城市设置外键,而不是创建城市和国家,

请任何人提供解决方案帮助,因为我尝试了很多方法并阅读了关于这一点的 django rest 框架文档,但我没有得到它。

【问题讨论】:

【参考方案1】:

首先,raise_exception 应该是一个布尔值(TrueFalse) 您可以通过使用从ListCreateAPIView 继承视图类来避免此错误


from rest_framework.generics import ListCreateAPIView

class CityAPIView(ListCreateAPIView): queryset = City.objects.all() serializer_class = CitySerializer permission_classes = [AllowAny, AllowAnonymous]

如果您正在使用ListCreateAPIView,您不想使用 post() 方法,因为 DRF 会很好地处理该部分。

建议 由于您正在处理模型的 CRUD 功能,因此您可以使用 DRF 的 ModelViewset 类

【讨论】:

你能看到这个问题吗,***.com/questions/52850354/…非常感谢@JPG【参考方案2】:

您没有使用经过验证的数据来创建新城市,只需更改此行:

        serializer.create(validated_data=request.data)

到这里:

        serializer.save()

当您执行serializer.save() 时,序列化程序将使用其经过验证的数据。

此外,DRF 有一个通用视图 (ListCreateAPIView),涵盖了您的用例。

【讨论】:

以上是关于当父记录存在时,如何在 django rest 框架的子序列化程序中设置外键值的主要内容,如果未能解决你的问题,请参考以下文章

当父元素可拖动时如何允许文本框插入符号位置(在鼠标单击时)

Django REST框架:POST请求:仅在数据不存在时如何保存数据

如何使用 Django Rest Framework 在 Django 中进行操作日志记录

django-rest-framework 和 swagger api 文档

Django REST Framework:当 POST 上存在额外字段时引发错误

如何在 Django Rest Framework 中编写涉及两个模型的业务逻辑