Python Django相关字段始终仅在生产上抛出完整性错误
我的django应用程序中有以下两种型号:Python Django相关字段始终仅在生产上抛出完整性错误,python,mysql,django,postgresql,Python,Mysql,Django,Postgresql,我的django应用程序中有以下两种型号: class BaseModel(models.Model): """ Base model """ uuid = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True) created = models.DateTimeField(auto_now_add=True, null=True) modified = mode
class BaseModel(models.Model):
"""
Base model
"""
uuid = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True)
created = models.DateTimeField(auto_now_add=True, null=True)
modified = models.DateTimeField(auto_now=True, null=True)
class Meta:
abstract = True
class BaseBillingModel(BaseModel):
"""
Base billing model with owner field and real_owner method (may reffer to Customer or Profile)
"""
owner = models.UUIDField() # uuid of Profile OR Customer
@property
def real_owner(self):
if self.type == 'customer':
return Customer.objects.get(uuid=self.owner)
if self.type == 'user':
return Profile.objects.get(uuid=self.owner)
class Meta:
abstract = True
class Invoice(BaseBillingModel):
type = models.CharField(_('Invoice type'), max_length=16, choices=INVOICE_PAYMENT_TYPES, default='user')
title = models.CharField(_("Title"), max_length=128, default="")
description = models.CharField(_("Description"), max_length=512, default="")
paid = models.BooleanField(_("Paid"), default=False)
cost = models.DecimalField(_("Total cost"), decimal_places=2, max_digits=10, default=Decimal("0"))
public = models.BooleanField(default=True)
def mark_paid(self):
self.paid = True
self.save()
class InvoiceItem(BaseModel):
invoice = models.ForeignKey(Invoice, null=True, blank=True)
cost = models.DecimalField(_("Cost"), decimal_places=2, max_digits=10, default=Decimal("0"))
quantity = models.IntegerField(_("Quantity"), default=1)
title = models.CharField(_("Title"), max_length=128, default="")
description = models.CharField(_("Description"), max_length=512, default="")
它基本上是一个包含许多发票项目的发票模型。
我使用表单集动态地向发票添加/删除项目。
当我发布web表单时,我迭代项目并计算总成本,然后保存发票
查看代码:
if request.method == 'POST':
invoice_form = InvoiceForm(request.POST)
formset = InvoiceItemFormset(request.POST)
total_forms = int(request.POST.get('form-TOTAL_FORMS'))
for x in range(total_forms):
identifier = "form-{x}-DELETE".format(x=x)
if identifier in request.POST:
deleted_items.append(x)
if request.POST.get('type') == 'customer':
invoice_form.fields['owner_choice'].choices = [(o.uuid.urn[9:],o.company_name) for o in Customer.objects.filter()]
if invoice_form.is_valid() and formset.is_valid():
invoice = invoice_form.save(commit=False)
invoice.owner = invoice_form.cleaned_data.get('owner_choice')
cost = Decimal(0)
for form in formset:
if form not in formset.deleted_forms:
item = form.save(commit=False)
item.invoice = invoice
item.save()
cost += item.cost * item.quantity
invoice.cost = cost
invoice.save()
它可以在我的本地环境中正常工作(MariaDB),正在使用所有项目创建发票。
但是,在后台/生产服务器上,无论我使用的是MySQL还是PostgreSQL,我都会遇到如下错误:
(postgresql)
我不知道该怎么解决这个问题。有什么想法吗?在保存发票项目之前,必须先保存它引用的发票。目前,您的阶段/生产服务器正在检查保存发票项之后但在保存发票之前的外键约束,因此会出现完整性错误 由于您使用的是uuid字段,因此Python将创建主键而不是数据库。因此,您可以通过使用原子装饰器来防止错误。使用
原子
装饰器时,数据库将检查原子块末尾的外键约束,此时发票已保存
from django.db import transaction
transaction.atomic()
def my_view(request):
如果这不起作用,则在保存发票项目之前,您需要确保已保存发票(无
commit=False
)。您可以保存发票项目和发票表单(都使用commit=False
),计算成本,保存发票,然后最后保存发票项目。在保存发票项目之前,必须先保存它引用的发票。目前,您的阶段/生产服务器正在检查保存发票项之后但在保存发票之前的外键约束,因此会出现完整性错误
由于您使用的是uuid字段,因此Python将创建主键而不是数据库。因此,您可以通过使用原子装饰器来防止错误。使用原子
装饰器时,数据库将检查原子块末尾的外键约束,此时发票已保存
from django.db import transaction
transaction.atomic()
def my_view(request):
如果这不起作用,则在保存发票项目之前,您需要确保已保存发票(无
commit=False
)。您可以保存发票项目和发票表单(都使用commit=False
),计算成本,保存发票,然后最后保存发票项目。但我需要先在发票上设置总成本。我的发票模型(post save)上有一个信号,它会向发票所有者发送一封电子邮件,告知总成本。我可以在不触发信号的情况下保存发票吗?另外,为什么它在我的本地数据库上工作?您可以在将发票保存到数据库之前计算成本。听起来MariaDB可能没有检查外键约束(例如MyISAM引擎没有)。我没有任何MariaDB的经验,因此我无法告诉您为什么在开发环境中没有出现错误。如果您已向save()
发送了一个信号,我认为您无法在不触发它的情况下调用save()
。但我需要先在发票上设置总成本。我的发票模型(post save)上有一个信号,它会向发票所有者发送一封电子邮件,告知总成本。我可以在不触发信号的情况下保存发票吗?另外,为什么它在我的本地数据库上工作?您可以在将发票保存到数据库之前计算成本。听起来MariaDB可能没有检查外键约束(例如MyISAM引擎没有)。我没有任何MariaDB的经验,因此我无法告诉您为什么在开发环境中没有出现错误。如果您已将信号吸引到save()
我认为您无法在不触发它的情况下调用save()
。