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

Python 如何使用Django Rest框架有效地关联模型,python,django,python-3.x,serialization,django-rest-framework,Python,Django,Python 3.x,Serialization,Django Rest Framework,我正在尝试创建一个应用程序来保存商店的帐户。每次将发票上载到系统时,它必须在另一个名为“products”的表中创建产品,但如果产品已经存在,则只需更新价格和数量 每张发票可以有多个产品 我应该如何建议表之间的关系?。一对多,一对一,多对多 是否有任何方法可以在每张发票上创建产品列表来表示关系?。供应商可以提供多种产品 是否有一种方法可以在不创建重复项的情况下在产品表中创建记录?。如果在输入新发票时更新了库存中的价格和数量,则无需多次使用同一产品 例如,要输入的发票具有以下信息: 数 列表项

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

每张发票可以有多个产品

  • 我应该如何建议表之间的关系?。一对多,一对一,多对多

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

  • 是否有一种方法可以在不创建重复项的情况下在产品表中创建记录?。如果在输入新发票时更新了库存中的价格和数量,则无需多次使用同一产品

  • 例如,要输入的发票具有以下信息:

    • 列表项
    • 提供者
    • 产品:(列表)
      • 产品a
      • 产品b
      • 产品c
    • 总数
    • 日期
    如果存在产品A,发票必须更新库存中的价格和数量

    如果产品C不存在,发票必须创建产品

    到目前为止,我所拥有的是:

    发票/型号.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
    
    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)
    
    发票/序列化程序.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
    
    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)
    
    库存/型号.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
    
    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)
    

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

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


    如果将发票行项目存储在单独的模型中,则发票将有一个ForeignKey字段,产品将有另一个ForeignKey字段,以及数量和价格字段。当您有一张特定的发票时,您可以获取其行项目。

    在这种情况下,我将创建一个具有重复值的表,假设一张发票输入100个块,另一张发票输入50个块,那么该表中将有2条记录,第一条记录有100个块,第二条记录有50个块。我的问题是发票表与产品表之间应该有什么样的关系,以便在创建发票时更新产品而不是创建新产品,我不知道这是否正确,或者我是否应该创建一个包含重复产品的表,并根据该表更新销售表。我认为我不太理解您的问题,尤其是关于“因此,在创建发票时,它是在更新产品,而不是创建新产品”的部分。这里有一个不同问题的答案。除了“product”表和“order”表之外,它还有一个“product_order”表,这就是我所说的表示发票行项目的意思。在这种情况下,它应该是多对多关系,一张发票有多个产品,并使用该发票计算产品的数量和价值。但是如何防止发票创建同一物品的多个记录?请原谅我的英语,但它不是我的语言。(我应该发送数据库的图表吗?@kruboSure,如果你有一个结构图,你可以将它添加到你的问题中。还可以解释一个具体的例子,比如,如果用户输入{example},系统应该如何响应?