2014-04-09 6 views
5

Próbuję znaleźć eleganckie rozwiązanie tego problemu napotykanego przy użyciu frameworku RMS Django. Mamy model nadrzędny z obiektem podrzędnym i relacją jeden do jednego. Nasze wymagania są takie, że obiekt podrzędny jest opcjonalny, może mieć wartość NULL i może być również poprawiony na wartość null z wcześniej istniejącej wartości. Dodatkowo, jeśli obiekt nadrzędny zostanie usunięty, obiekt potomny również powinien być.obiekty reszta zagnieżdżonych obiektów django

Ten prosty set-up, które odtwarza problem:

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 

to działa:

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

To dostaje błąd:

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

Należy pamiętać, że obiekt podrzędny jest opcjonalne i domyślnie struktura REST wypełnia pole wartością null.

Używam Django v.1.5.4 i odpoczynek ramy v.2.3.13

Błąd:

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 

Obejście my obecnie używasz ma mieć pole OneToOne dla rodzic, a następnie użyj funkcji obsługi sygnału post_delete, aby usunąć obiekt potomny. To wydaje się bardzo hacky. W zasadzie napotkaliśmy kilka problemów z próbą manipulowania zagnieżdżonymi obiektami i zastanawiamy się, czy nie podejmiemy się tego źle, czy może w tym przypadku napotkaliśmy błąd w django lub reszcie frameworka.

Dzięki!

+0

Czy próbowałeś użyciu [PK związanego pole] (http://www.django-rest-framework.org/api-guide/relations#primarykeyrelatedfield) zamiast serializatora dziecko? Wierzę, że biorąc pod uwagę twój model, to by działało. – AdelaN

+0

W końcu musieliśmy stworzyć funkcje sprawdzania poprawności, aby chronić przed warunkiem zerowym. Nasz wniosek był taki, że funkcje obiektu zagnieżdżonego w strukturze django rest są po prostu nie dojrzałe i istnieją przypadki użycia, które po prostu nie są obsługiwane w kodzie. – JamesHutchison

Odpowiedz

2

Podczas gdy to pytanie było zadawane rok temu, Django Rest Framework opublikował od tego czasu ważną aktualizację (3.1.1), która upraszcza i ulepsza sposób, w jaki framework radzi sobie z zagnieżdżonymi obiektami.

Twoje wymagania:

  1. jeden na jeden związek - w macierzystym Serializatora definicji, można określić paramter many=False.

  2. Usuwanie obiektu podrzędnego, gdy rodzic jest usuwany - w macierzystym Serializatora, realizacji funkcji perform_destroy. W tej funkcji usuń instancję nadrzędną i instancję potomną.

Here is the DRF Serializer documentation

0

Czy próbowałeś ustawić allow_null = True w ChildSerializer?