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