Django Rest Framework Опубликовать вложенные модели - PullRequest
0 голосов
/ 18 октября 2019

У меня есть три связанных модели, и мне нужно сохранить все экземпляры в одной транзакции.

Упрощенная версия моих моделей:

class Recibosventas(models.Model):
    idreciboventa = models.AutoField(primary_key=True)
    idemplea = models.ForeignKey(Empleados, models.DO_NOTHING, db_column='idemplea', blank=True, null=True)
    idempres = models.SmallIntegerField()
    categocompro = models.CharField(max_length=2)
    tipocompro = models.CharField(max_length=1)
    puntoventa = models.SmallIntegerField()
    numero = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = True
        db_table = 'recibosventas'
        unique_together = (('idempres', 'categocompro', 'tipocompro', 'puntoventa', 'numero'),)

class Fondos(models.Model):
    idfondo = models.AutoField(primary_key=True)
    idemplea = models.ForeignKey(Empleados, models.DO_NOTHING, db_column='idemplea', blank=True, null=True)
    idtipofondo = models.ForeignKey('Tiposfondo', models.DO_NOTHING, db_column='idtipofondo')
    idconcepfondo = models.ForeignKey(Conceptosfondos, models.DO_NOTHING, db_column='idconcepfondo')
    idreciboventa = models.ForeignKey('Recibosventas', models.DO_NOTHING, db_column='idreciboventa',  related_name='fondoreciboventa', blank=True, null=True)

    class Meta:
        managed = True
        db_table = 'fondos'

class Movimientosfondos(models.Model):
    idmovimifondo = models.AutoField(primary_key=True)
    idfondo = models.ForeignKey(Fondos, models.DO_NOTHING, db_column='idfondo',  related_name='movimientosfondos', blank=True, null=True)
    iddispon = models.ForeignKey(Disponibilidades, models.DO_NOTHING, db_column='iddispon')

    class Meta:
        managed = True
        db_table = 'movimientosfondos'

serializers.py:

class MovimientosfondosSerializer(serializers.ModelSerializer):
    class Meta:
        model = Movimientosfondos
        fields='__all__' 

class FondosSerializer(serializers.ModelSerializer):
    movimientosfondos = MovimientosfondosSerializer(many=True)

    class Meta:
        model = Fondos
        fields='__all__' 

    def create(self, validated_data):
        with transaction.atomic():
            # Crear la instancia de pedidos de venta
            movimientosfondos_data = validated_data.pop('movimientosfondos')
            fondos = Fondos.objects.create(**validated_data)

            # crear cada instancia de movimientosfondos
            for movimientosfondos_data in movimientosfondos_data:
                movimientosfondos_data['idfondo'] = fondos
                Movimientosfondos.objects.create(**movimientosfondos_data)        

            return fondos

    def update(self, instance, validated_data):
        with transaction.atomic():
            # Crear la instancia de pedidos de venta
            movimientosfondos_data = validated_data.pop('movimientosfondos')

            # Eliminar el detalle de ventas
            for movimientosfondos in (instance.movimientosfondos).all():
                movimientosfondos.delete()

            # crear nuevamente cada instancia de ventasarticulos
            for movimientosfondos_data in movimientosfondos_data:
                movimientosfondos_data['idfondo'] = instance 
                Movimientosfondos.objects.create(**movimientosfondos_data)

            return instance        


class RecibosventasSerializer(serializers.ModelSerializer):        
    fondoreciboventa = FondosSerializer(many=True)

    class Meta:
        model = Recibosventas
        fields='__all__' 

    def create(self, validated_data):
        with transaction.atomic():
            # Crear la instancia de pedidos de venta
            fondosreciboventa_data = validated_data.pop('fondoreciboventa')
            recibosventas = Recibosventas.objects.create(**validated_data)

            # crear cada instancia de fondos
            for fondoreciboventa_data in fondosreciboventa_data:
                fondoreciboventa_data['idreciboventa'] = recibosventas  
                Fondos.objects.create(**fondoreciboventa_data)


            return recibosventas 

    def update(self, instance, validated_data):
        with transaction.atomic():
            # Crear la instancia de pedidos de venta
            fondosreciboventa_data = validated_data.pop('fondoreciboventa')

            for fondoreciboventa in (instance.fondoreciboventa).all():
                fondoreciboventa.delete()

            # crear nuevamente cada instancia de pedidoventasarticulos
            for fondoreciboventa_data in fondosreciboventa_data:
                fondoreciboventa_data['idreciboventa'] = instance 
                Fondos.objects.create(**fondoreciboventa_data)

            return instance  

apiviews:

class FondosList(generics.ListCreateAPIView):
    queryset = Fondos.objects.all()
    serializer_class = FondosSerializer

    def perform_create(self, serializer):
        idemplea = Empleados.objects.get(usuariweb = self.request.user)
        serializer.save(idemplea=idemplea)        


class RecibosventasList(generics.ListCreateAPIView):
    queryset = Recibosventas.objects.all()
    serializer_class = RecibosventasSerializer

    def perform_create(self, serializer):
        idemplea = Empleados.objects.get(usuariweb = self.request.user)
        serializer.save(idemplea=idemplea)

class RecibosventasDetalle(generics.RetrieveDestroyAPIView):
    queryset = Recibosventas.objects.all()
    serializer_class = RecibosventasSerializer  

    def perform_destroy(self, instance):  
        with transaction.atomic():
            # Eliminar el detalle de pedidosventas
            for movimientosfondos in (instance.fondoreciboventa.movimientosfondos).all():
                movimientosfondos.delete()

            instance.fondoreciboventa.delete() 

            # Eliminar el encabezado pedidosventas
            instance.delete()       

class RecibosventasUpdate(generics.UpdateAPIView):
    queryset = Recibosventas.objects.all()
    serializer_class = RecibosventasSerializer       

urls:


urlpatterns = [ 
    path('v1/recibosventas/', RecibosventasList.as_view(), name='recibosventas_list'),
    path('v1/recibosventas/<int:pk>', RecibosventasDetalle.as_view(), name='recibosventas_detalle'),  
    path('v1/recibosventasupdate/<int:pk>', RecibosventasUpdate.as_view(), name='recibosventas_update'), 
]

Я отправляю на API:

{
        "idreciboventa": null,
        "idemplea" : 1,
        "fondoreciboventa": [
            {
                "idfondo": 1,
                "idemplea" : 1,
                "movimientosfondos": [
                    {
                        "idmovimifondo": 1,
                        "idfondo": 1,
                        "iddispon": 9,
                    }
                ],
                "idtipofondo": 1,
                "idconcepfondo": 2,
            }
        ]
        "categocompro": "RC",
        "tipocompro" : "F",
        "puntoventa": 1,
        "numero" : 1,
}

Я получаю следующую ошибку:

Прямое назначение обратной стороне связанного набора запрещено. Вместо этого используйте movimientosfondos.set ().

Я не понимаю, что я делаю неправильно. Кто-нибудь может мне помочь, пожалуйста?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...