Django Modelform(带有排除字段)
Posted
技术标签:
【中文标题】Django Modelform(带有排除字段)【英文标题】:Django Modelform (with excluded field) 【发布时间】:2011-08-08 01:00:12 【问题描述】:我有一个样本表格:
class AdminDiscountForm(ModelForm):
class Meta:
model = Discount
exclude = ('company',)
它指向的模型是:
class Discount(models.Model):
class Meta:
verbose_name=_('Discount')
verbose_name_plural=_('Discounts')
unique_together = ('company','type')
company = models.ForeignKey(Company)
type = models.CharField(max_length=5, choices=DISCOUNT_CHOICES)
discount = models.DecimalField(max_digits=7, decimal_places=2, verbose_name=_('Discount'))
表单不包括“公司”字段,因为用户已经使用 UI 选择了此字段。
我打算做一个:
company = blah
if form.is_valid():
obj = form.save(commit=False)
obj.company = company
obj.save()
问题是'company' 和'type' 的组合应该是唯一的(因此是'unique_together')。这是在数据库中强制执行的,所以 django 不在乎。 我需要扩展这个表单的 clean() 方法来检查唯一性:
def clean(self):
cleaned_data = self.cleaned_data
# check for uniqueness of 'company' and 'type'
这里的问题是“公司”不在其中,因为它已被排除在外。 在这种情况下引发表单验证错误的最佳方法是什么?
-- 编辑 这仅适用于添加折扣条目。 没有初始实例。
【问题讨论】:
在这里找到答案:***.com/questions/2141030/… 【参考方案1】:Jammon 的方法是我使用的方法。扩展一点(使用您的示例):
models.py
class Discount(models.Model):
class Meta:
verbose_name=_('Discount')
verbose_name_plural=_('Discounts')
unique_together = ('company','type')
company = models.ForeignKey(Company)
type = models.CharField(max_length=5, choices=DISCOUNT_CHOICES)
discount = models.DecimalField(max_digits=7, decimal_places=2, verbose_name=_('Discount'))
forms.py
class AdminDiscountForm(ModelForm):
class Meta:
model = Discount
exclude = ('company',)
views.py
def add_discount(request, company_id=None):
company = get_object_or_404(Company, company_id)
discount=Discount(company=company)
if request.method == 'post':
form = AdminDiscountForm(request.POST, instance=discount)
if form.is_valid():
form.save()
return HttpResponse('Success')
else:
form = AdminDiscountForm(instance=company)
context = 'company':company,
'form':form,
return render_to_response('add-discount.html', context,
context_instance=RequestContext(request))
这是通过创建折扣模型的实例,然后将表单绑定到该实例来实现的。此实例不会保存到您的数据库中,而是用于绑定表单。此绑定表单具有绑定实例的公司的值。然后将其发送到您的模板供用户填写。当用户提交此表单并验证表单时,模型验证检查将检查 Meta 中定义的唯一性的唯一性。
见Model Validation Docs
和overriding clean for ModelForms
编辑:
您可以做一些事情来捕捉非唯一的一起进入尝试。
在您的 form.is_valid() 中,您可以排除这样的完整性错误:
if request.method == 'post':
form = AdminDiscountForm(request.POST, instance=discount)
if form.is_valid():
try:
form.save()
return HttpResponse('Success')
except IntegrityError:
form._errors["company"] = "some message"
form._errors["type"] = "some message"
else:
...
在模型表单的 clean 方法中使用 self.instance 来检查唯一性。
【讨论】:
我明白了。我对 Discount() 感到困惑。我以为是 Discount.objects.create()。我的错。谢谢你们俩。 虽然现在没问题,但我仍然收到 IntegrityError,因为由于其中一个字段已被排除,所以没有发生对 unique_together 的验证。 不需要。我可以以 clean() 方法访问实例吗?我去看看。 所以基本上我可以从 clean() 中访问 self.instance.company 来进行验证。凉爽的。感谢您的帮助! “此外,绑定到模型对象的模型表单实例将包含一个 self.instance 属性,该属性使模型表单方法可以访问该特定模型实例。”,啊,我明白了。好的。用另一种可能的方法编辑帖子。【参考方案2】:你可以试试这个:
discount = Discount(company = blah)
form = AdminDiscountForm(request.POST, instance=discount)
if form.is_valid():
discount = form.save()
docs 说:默认情况下 clean() 方法验证标记为的字段的唯一性... unique_together
【讨论】:
我应该指出,这只是为了添加。根本没有编辑。 没关系。您创建一个设置了默认值的实例,然后该实例采用 ModelForm 中的所有其他值。 我当然不能每次都使用默认值创建一个实例。 unique_together 将在某个时候发挥作用。以上是关于Django Modelform(带有排除字段)的主要内容,如果未能解决你的问题,请参考以下文章