【问题标题】:django rest framework nested objectsdjango rest框架嵌套对象
【发布时间】:2014-05-21 23:42:22
【问题描述】:

我正在尝试找到一个优雅的解决方案来解决使用 Django REST 框架遇到的这个问题。我们有一个带有子对象和一对一关系的父模型。我们的要求是子对象是可选的,可以为 null,也可以从先前存在的值修补为 null。此外,如果父对象被删除,子对象也应该被删除。

这个重现问题的简单设置:

class ChildSerializer(serializers.ModelSerializer):
    class Meta:
        model = Child


class ParentSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Parent

    parent_value = serializers.CharField(required=False, max_length=1024)
    child = ChildSerializer(read_only=False, required=False, many=False)


class Parent(models.Model):
    class Meta:
        app_label = "testparent"

    parent_value = models.CharField(max_length=1024, null=True, blank=True)


class Child(models.Model):
    class Meta:
        app_label = "testparent"

    child_value = models.CharField(max_length=1024, null=True, blank=True)
    parent = models.ForeignKey(Parent, null=True, blank=True, related_name="child")


class ParentViewSet(viewsets.ModelViewSet):
    permission_classes = (AllowAny,)

    queryset = Parent.objects.all()
    serializer_class = ParentSerializer

这行得通:

{
    "parent_value": "abc", 
    "child": { "child_value": "something" }
}

这会出错:

{
    "parent_value": "abc", 
    "child": null
}

请注意,子对象是可选的,默认情况下,REST 框架会使用 null 填充该字段。

我正在使用 Django v.1.5.4 和 REST framework v.2.3.13

错误:

Traceback:
File "{site-packages}/django/core/handlers/base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File "{site-packages}/rest_framework/viewsets.py" in view
  78.             return self.dispatch(request, *args, **kwargs)
File "{site-packages}/django/views/decorators/csrf.py" in wrapped_view
  77.         return view_func(*args, **kwargs)
File "{site-packages}/rest_framework/views.py" in dispatch
  400.             response = self.handle_exception(exc)
File "{site-packages}/rest_framework/views.py" in dispatch
  397.             response = handler(request, *args, **kwargs)
File "{site-packages}/rest_framework/mixins.py" in create
  54.             self.object = serializer.save(force_insert=True)
File "{site-packages}/rest_framework/serializers.py" in save
  596.             self.save_object(self.object, **kwargs)
File "{site-packages}/rest_framework/serializers.py" in save_object
  1023.                     setattr(obj, accessor_name, related)
File "{site-packages}/django/db/models/fields/related.py" in __set__
  474.         manager.add(*value)


Exception Value: add() argument after * must be a sequence, not NoneType

我们目前使用的解决方法是为父对象设置一个 OneToOne 字段,然后使用 post_delete 信号处理程序删除子对象。这感觉非常hacky。通常,我们在尝试操作嵌套对象时遇到了一些问题,并且想知道我们是否做错了,或者在这种情况下,我们是否在 django 或其他框架中遇到了错误。

谢谢!

【问题讨论】:

  • 您是否尝试过使用PK related field 而不是子序列化程序?我相信,根据您的模型,这会起作用。
  • 我们最终不得不创建验证函数来防止出现 null 条件。我们的结论是,django rest 框架的嵌套对象功能还不够成熟,而且有些用例根本没有在代码中处理。

标签: python django rest django-rest-framework


【解决方案1】:

虽然这个问题是在一年前提出的,但 Django Rest Framework 已经发布了一个重大更新 (3.1.1),它简化并增强了框架处理嵌套对象的方式。

您的要求:

  1. 一对一关系 - 在父序列化器定义中,可以指定参数many=False

  2. 删除父对象时删除子对象 - 在父序列化程序中,实现perform_destroy 函数。在这个函数中,删除 Parent 实例和 Child 实例。

Here is the DRF Serializer documentation

【讨论】:

    【解决方案2】:

    您是否尝试在 ChildSerializer 中设置 allow_null = True?

    【讨论】:

    • 是的,你是对的,这是使用 allow_null = True。我已经按照相同的方式进行了验证。
    猜你喜欢
    • 2020-11-07
    • 2012-11-02
    • 2019-06-14
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多