2011-04-18 4 views
6

У меня есть образец формы:Джанго 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

ответ

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

Это работает путем создания экземпляра вашей модели скидок, а затем привязать форму к этому экземпляру. Этот экземпляр не сохраняется в вашем db, но используется для привязки формы. Эта связанная форма имеет значение для компании связанного экземпляра. Затем он отправляется на ваш шаблон для заполнения пользователем. Когда пользователь отправляет эту форму и форма проверяется, проверка проверки модели проверяет уникальность уникального вместе, определенного в мета.

См Model Validation Docs и overriding 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.objects.create(). Виноват. Спасибо вам обоим. – Dim

+0

Пока это нормально, я все равно получаю IntegrityError, поскольку проверка на unique_together не происходит, потому что одно из полей было исключено. – Dim

+0

Хорошо, я отредактирую свое сообщение, чтобы включить пользовательскую проверку. – DTing

2

Вы можете попробовать это:

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

И docs сказать: По умолчанию метод чистой() проверяет уникальность полей, которые помечены как ... unique_together

+0

Я должен отметить, что это только для * добавление *. Нет редактирования вообще. – Dim

+0

Все нормально. Вы создаете экземпляр с установленными значениями по умолчанию, а затем этот экземпляр принимает все остальные значения, которые находятся в ModelForm. – jammon

+0

Несомненно, я не могу просто создать экземпляр со значениями по умолчанию каждый раз. unique_together собирается в какой-то момент ударить. – Dim

Смежные вопросы