Django Modelform(带有排除字段)

Dim*_*Dim 9 forms django validation

我有一个示例表格:

class AdminDiscountForm(ModelForm):  
    class Meta:  
        model = Discount  
        exclude = ('company',)
Run Code Online (Sandbox Code Playgroud)

它指向的模型是:

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'))
Run Code Online (Sandbox Code Playgroud)

该表单排除了"公司"字段,因为用户已使用UI选择了此字段.

我打算做一个:

company = blah
if form.is_valid():
    obj = form.save(commit=False)
    obj.company = company
    obj.save()
Run Code Online (Sandbox Code Playgroud)

问题是'company'和'type'的组合应该是唯一的(因此'unique_together').这是在数据库中强制执行的,所以django并不关心.我需要扩展此表单的clean()方法以检查唯一性:

def clean(self):
    cleaned_data = self.cleaned_data
    # check for uniqueness of 'company' and 'type'
Run Code Online (Sandbox Code Playgroud)

这里的问题是'公司'不在那里,因为它被排除在外.在这种情况下,提出表单验证错误的最佳方法是什么?

- 编辑这仅用于添加折扣条目.没有初始实例.

DTi*_*ing 12

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'))
Run Code Online (Sandbox Code Playgroud)

forms.py

class AdminDiscountForm(ModelForm):  
    class Meta:  
        model = Discount  
        exclude = ('company',)
Run Code Online (Sandbox Code Playgroud)

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))
Run Code Online (Sandbox Code Playgroud)

这可以通过创建折扣模型的实例,然后将表单绑定到此实例来实现.此实例不会保存到您的数据库,但用于绑定表单.此绑定表单具有绑定实例的公司值.然后将其发送到您的模板以供用户填写.当用户提交此表单并验证表单时,模型验证检查将检查Meta中定义的唯一一起的唯一性.

Model Validation Docsoverriding clean for ModelForms

编辑:

你可以做一些事情来捕捉非独特的一起进入尝试.

  1. 在你的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:
            ...
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在模型表单的clean方法中使用self.instance来检查唯一性.