代码之家  ›  专栏  ›  技术社区  ›  alejandrohtadinom

如何使用Django-Rest框架有效地关联模型

  •  0
  • alejandrohtadinom  · 技术社区  · 6 年前

    我正在尝试创建一个应用程序来保存商店的帐户。每次将发票上载到系统时,必须在另一个名为“产品”的表中创建产品,但如果产品已经存在,则只需更新价格和数量。

    每张发票可以有多个产品

    1. 是否有任何方法可以在每张发票上创建产品列表来表示这种关系?。一个供应商可以提供多个产品。

    2. 有没有一种方法可以在不创建重复项的情况下创建产品表中的记录?。如果一次更新的产品数量与发票中的数量相同,则不必输入新的存货。

    例如,要输入的发票包含以下信息:

    • 列表项
    • 供应商
      • 产品a
      • 产品c
    • 总计
    • 日期

    如果产品A存在,发票必须更新库存中的价格和数量。

    到目前为止,我只有:

    发票/模型.py :

    from django.db import models
    
    from product.models import Product
    from sales.models import PaymentMethod
    
    
    class Supplyer(models.Model):
        """
        Proveedor de servicios o productos
        """
    
        rif = models.CharField(max_length=255)
        name = models.CharField(max_length=255)
        phone = models.CharField(max_length=255)
        email = models.EmailField()
    
        def __str__(self):
            return '{} - {}'.format(self.name, self.rif)
    
    
    class Invoice(models.Model):
        """
        Clase que controla las facturas ingresadas al sistema
        """
    
        ref = models.CharField(max_length=255)
        supplyer = models.OneToOneField(Supplyer, on_delete=models.CASCADE)
        items = models.ManyToManyField(Product)
        total = models.DecimalField(max_digits=14, decimal_places=2)
        paymnet_method = models.OneToOneField(PaymentMethod, on_delete=models.CASCADE)
        date = models.DateField(auto_now_add=True, auto_now=False)
    
        def __str__(self):
            return '{} - {} - {}'.format(self.supplyer, self.date, self.ref)
    

    :

    from rest_framework.serializers import ModelSerializer
    from invoice.models import Supplyer, Invoice
    from stock.models import Product
    from stock.serializers import ProductSerializer
    
    
    class SupplyerSerializer(ModelSerializer):
        """
        Clase que controla los proveedores de productos o servicios
        """
    
        class Meta:
            model = Supplyer
            fields = ('rif', 'name', 'phone', 'email')
    
    
    class InvoiceSerializer(ModelSerializer):
        """
        Clase que controla las facturas de proveedores.
    
        Esta clase tiene un metodo crear propio para poder crear productos cuando
        se carga la factura, y si el producto ya existe, debe actualizar el costo
        del producto en el inventario
        """
    
        # Llamada al serializador de productos
        product_serializer = ProductSerializer(many=True)
    
        # Llamada al serializador de proveedores
        supplyer_serializer = SupplyerSerializer()
    
        class Meta:
            model = Invoice
            fields = ('ref', 'supplyer_serializer', 'product_serializer', 'total', 'payment_method', 'date')
    
        def create(self, validated_data):
            """
            Este metodo sobre escribe el metodo de crear instancia por defecto del
            serializador, esto nos permite crear un producto y actualizar el
            precio al momento de cargar la factura al sistema.
    
            self: llamada al metodo
            validated_data: Datos validados por el serializador
            """
    
            # lista de productos o servicios en la factura
            products_obj = validated_data.pop('items')
    
            # Cargar la factura a la base de datos
            invoice = Invoice.objects.create(**validated_data)
    
            # Iterar por la lista de productos de la factura
            for product in products_obj:
                Product.objects.create(products_obj)
    
            return invoice
    
        def update(self, instance, validated_data):
            """
            Este metodo actualiza las facturas y productos asociados a ella
    
            self: llamada al metodo
            instance: instancia u objeto a modificar
            validated_data: datos validados por el serializador
            """
    
            # Se obtienen los datos de los productos en la factura
            products_obj = validated_data.pop('items')
            products = (instance.product_serializer).all()
            products = list(products)
    
            # Se selecciona la factura y se actualizan los datos
            instance.ref = validated_data.get('ref', instance.ref)
            instance.supplyer = validated_data.get('supplyer', instance.supplyer)
            instance.total = validated_data.get('total', instance.total)
            instance.payment_method = validated_data.get('payment_method', instance.payment_method)
    
            # Iterar pro la lista de productos
            for product_data in products_obj:
                # Dentro del bucle se atualizan los datos de los productos
                product = products.pop(0)
                product.name = product_data.get('name', product.name)
                product.description = product_data.get('description', product.description)
                product.price = product_data.get('price', product.price)
                product.save()
    
            return instance
    

    股票/模型.py :

    from django.db import models
    
    
    class Product(models.Model):
        name = models.CharField(max_length=255)
        description = models.CharField(max_length=255)
        price = models.DecimalField(max_digits=12, decimal_places=2)
    
    
    class Stock(models.Model):
        item    = models.OneToOneField(Product, on_delete='CACADE')
        package = models.CharField(max_length=255)
        unity   = models.IntegerField()
        date    = models.DateTimeField(auto_now=True)
        value   = models.DecimalField(max_digits=12, decimal_places=2)
        cost   = models.DecimalField(max_digits=12, decimal_places=2)
        qty     = models.IntegerField()
    
        def __str__(self):
            return '{}'.format(self.date)
    
    0 回复  |  直到 6 年前
        1
  •  0
  •   krubo    6 年前

    看起来您需要另一个模型来表示发票的行项目,包括数量和价格。例如,如果发票1包含50公斤砖块和100公斤水泥,那么发票2包含20公斤砖块和20公斤水泥,您希望如何记录这两项记录?

    在您当前的型号中,产品“砖块”可以链接到发票1和发票2,但是没有地方存储每张发票上列出的不同数量的砖块。

    如果您将发票行项目存储在单独的模型中,则发票将具有一个ForeignKey字段,而产品将具有另一个ForeignKey字段,以及数量和价格字段。当你有一个具体的发票,你可以 follow the relationship backwards 获取其行项目。

    推荐文章