2011-04-18 76 views
6

我有一個樣品形式:的Django的ModelForm(排除在外的領域)

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')) 

形式排除「公司」字段,因爲用戶已經使用用戶界面選擇了這個。

我就準備做:

company = blah 
if form.is_valid(): 
    obj = form.save(commit=False) 
    obj.company = company 
    obj.save() 

的問題是,「公司」和「類型」的組合應該是唯一的(因此「unique_together」)。這是在數據庫中強制執行的,所以django不在乎。 我需要延長這種形式的清潔()方法來檢查唯一這樣:

def clean(self): 
    cleaned_data = self.cleaned_data 
    # check for uniqueness of 'company' and 'type' 

的這裏的問題是,「公司」不存在,因爲它已被排除。 在這種情況下引發表單驗證錯誤的最佳方式是什麼?

- 編輯 這只是爲加入折扣條目。 沒有初始實例。

+0

回答:http://stackoverflow.com/questions/2141030/djangos-modelform-unique-together-validation – gladysbixly 2011-04-18 18:19:43

回答

10

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 Docsoverriding clean for ModelForms

編輯:

你可以做幾件事情要趕非唯一一起進入嘗試。

  1. 在你的窗體中。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: 
         ... 
    
  2. 雛型的清潔方法中使用self.instance檢查唯一性。這裏找到

+0

我明白了。我對Discount()感到困惑。我認爲這是Discount.objects.create()。我的錯。感謝你們倆。 – Dim 2011-04-18 18:42:49

+0

雖然現在可以,但我仍然收到IntegrityError,因爲unique_together上的驗證不會發生,因爲其中一個字段已被排除。 – Dim 2011-04-18 18:53:37

+0

好吧我會編輯我的帖子以包含自定義驗證。 – DTing 2011-04-18 18:55:02

2

你可以試試這個:

discount = Discount(company = blah) 
form = AdminDiscountForm(request.POST, instance=discount) 
if form.is_valid(): 
    discount = form.save() 

而且docs說:默認情況下,清潔()方法驗證標記爲域的獨特性...... unique_together

+0

我應該指出的是,這只是*添加*。根本不需要編輯。 – Dim 2011-04-18 17:02:55

+0

沒關係。您使用默認值集創建實例,然後該實例將採用ModelForm中的所有其他值。 – jammon 2011-04-18 17:06:10

+0

當然,我不能每次都創建一個具有默認值的實例。 unique_together將在某個時刻開始。 – Dim 2011-04-18 17:09:10