2014-04-09 483 views
5

我試圖找到一個優雅的解決方案,以解決使用Django REST框架遇到的這個問題。我們有一個帶有子對象和一對一關係的父模型。我們的要求是子對象是可選的,可以爲null,也可以從先前存在的值修補爲null。另外,如果父對象被刪除,那麼子對象也應該是這樣。django rest框架嵌套對象

這種簡單的設置,再現問題:

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框架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信號處理程序刪除子對象。這感覺很不方便。一般來說,我們遇到了一些試圖操縱嵌套對象的問題,並想知道我們是否錯了,或者在這種情況下,我們是否遇到過django或其他框架中的錯誤。

謝謝!

+0

您是否嘗試過使用[PK相關領域(http://www.django-rest-framework.org/api-guide/relations#primarykeyrelatedfield),而不是一個子串?我相信,根據你的模型,這將工作。 – AdelaN

+0

我們最終不得不創建驗證函數來防止null條件。我們的結論是,django rest框架的嵌套對象功能尚不成熟,並且存在一些用例,這些用例在代碼中不能被處理。 – JamesHutchison

回答

2

雖然在一年前提出這個問題,但Django Rest Framework自那時以來發布了一個主要更新(3.1.1),它簡化並增強了框架處理嵌套對象的方式。

您的要求:

  1. 一對一的關係 - 在父串行定義,你可以指定放慢參數many=False

  2. 刪除父對象時刪除子對象 - 在母串行器中,實現perform_destroy函數。在這個函數中,刪除父實例和子實例。

Here is the DRF Serializer documentation

0

您是否嘗試在ChildSerializer中設置allow_null = True?