Django Modelform (with field excluded)

I have a sample form:

class AdminDiscountForm(ModelForm): class Meta: model = Discount exclude = ('company',) 

the model she points to is:

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

The form excludes the company field because the user has already selected this using the user interface.

I plan to do:

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

The problem is that the combination of "company" and "type" must be unique (hence "unique_together"). This is done in the database, so django doesn't care. I need to extend the clean () method of this form to check for uniqueness as such:

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

The problem here is that the "company" does not exist because it is excluded. What is the best way to raise the form validation error in this case?

- change This is only for adding discounts. No initial instance.

+6
source share
2 answers

The Jammon method is the one I use. To expand a bit (using your example):

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

This works by creating an instance of your discount model and then linking your form to that instance. This instance is not stored in your db, but is used to bind the form. This related form is relevant to the associated instance company. Then it is sent to your template for completion by the user. When the user submits this form and the form is verified, the model validation check verifies the uniqueness of the unique population defined in the meta.

See Model Validation Docs and overriding clean for ModelForms

change

There are a few things you can do to catch unique recording attempts.

  • Inside form.is_valid (), you can throw an Integrity error:

     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: ... 
  • Use self.instance in a pure model form method to verify uniqueness.

+10
source

You can try the following:

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

And docs say: By default, the clean () method checks for the uniqueness of fields marked as ... unique_together

+2
source

Source: https://habr.com/ru/post/886164/


All Articles