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!
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
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