I am trying to save a nested relationship in Django REST Framework following the Django REST Framework guide but I couldn't do that.
I have a class "Asiento" which is a foregin key for another class "Apunte". When I get every "Asiento" Django REST Framework returns them and all of their "Apunte" objects. This works, but when I try to create/update an "Asiento" with writable nested serializers I get that AsientoSerializer(data=data).is_valid() == False
.
class Apunte(TxerpadBase):
debe = models.DecimalField(null=True, blank=True, max_digits=18, decimal_places=6)
haber = models.DecimalField(null=True, blank=True, max_digits=18, decimal_places=6)
cuenta = models.ForeignKey(Cuenta, related_name='mayor', on_delete=models.PROTECT)
partner = models.ForeignKey(Partner, null=True, blank=True, on_delete=models.PROTECT)
asiento = models.ForeignKey(Asiento, related_name='apuntes')
fecha = models.DateField()
recc = models.BooleanField(blank=True, default=False)
conciliacion = models.ForeignKey('Conciliacion', null=True, blank=True, on_delete=models.SET_NULL)
estado = FSMField(default='borrador')
class Asiento(TxerpadBase):
numero = models.PositiveIntegerField(null=True, blank=True)
fecha = models.DateField(blank=True, default=datetime.datetime.now)
libro = models.ForeignKey('Libro', on_delete=models.PROTECT)
periodo = models.ForeignKey(Periodo, on_delete=models.PROTECT)
estado = FSMField(default='borrador')
class ApunteSerializer(serializers.ModelSerializer):
fecha = serializers.DateField(
format='%d-%m-%Y', input_formats=('%d-%m-%Y',),
error_messages={'invalid': 'La fecha del apunte no esta en el formato correcto.'}
)
class Meta:
model = Apunte
class AsientoSerializer(serializers.ModelSerializer):
fecha = serializers.DateField(
format='%d-%m-%Y', input_formats=('%d-%m-%Y',),
error_messages={'invalid': 'La fecha del asiento no esta en el formato correcto.'}
)
apuntes = ApunteSerializer(many=True)
class Meta:
model = Asiento
def create(self, data):
apuntes_data = data['apuntes']
asiento_data = data
asiento_data['fecha'] = datetime.datetime.strptime(asiento_data['fecha'], '%d-%m-%Y').date()
del asiento_data['apuntes']
asiento = Asiento.objects.create(**asiento_data)
for apunte in apuntes_data:
apunte['fecha'] = datetime.datetime.strptime(apunte['fecha'], '%d-%m-%Y').date()
Apunte.objects.create(asiento=asiento, **apunte)
class AsientoViewSet(viewsets.ModelViewSet):
queryset = Asiento.objects.all()
serializer_class = AsientoSerializer
def create(self, validated_data):
# JSON dictionary is inside validated_data.data
serializer = AsientoSerializer(data=validated_data.data)
if serializer.is_valid():
return Response(serializer.data)
else:
raise AttributeError('Error al validar')
This is JSON that I send with my request:
{
u'name': u'prueba 3000',
u'periodo': 13,
u'fecha': u'18-02-2016',
u'numero': None,
u'estado': u'borrador',
u'libro': 1,
u'apuntes': [
{
u'name': u'a',
u'recc': False,
u'debe': u'1',
u'haber': u'0.00',
u'cuenta': u'5',
u'partner': 8, u'fecha':
u'18-02-2016',
u'conciliacion': u''
}
]
}
If I debug the code only "create" method which executes is viewset's method, but it doesn't run "create" method from serializer.
With this code I can't save an "Asiento" neither an "Apunte". What am I doing wrong? Thank you for any answere!
I am using python 2.7 (I can't update it for external reasons) and Django REST Framework 3.3.2.
Ok, I found that my problem was that "asiento" attribute in "Apunte" object can't be null and I wasn't sending it. Now, I have changed "asiento" attribute in "Apunte" object and serializer finally works, and it is no needed "create" method on ViewSet.
Thanks to everyone for your answeres.
First thing you should do in case of invalid serialization is to look at the returned message (serializer.data). It'll help you understand what's going wrong.
My blind guess here is that you're missing the queryset
argument relating to the nested serializer. If not set, DRF will consider those fields as read only.
Edit: After the OP edition, the issue comes from the viewset. You need to call serializer.save()
if the serializer is valid. Have a look at how the CreateMixin does it.
Not sure if thats the solution. But the create
method of a serializer has to return the created object. Try adding return
to your last line
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.