[Fixed]-Django Modelform (with excluded field)

15👍

Jammon’s 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, then binding your form to this instance. This instance is not saved to your db but used to bind the form. This bound form has a value for company of the bound instance. It is then sent to your template for the user to fill out. When the user submits this form, and the form is validated, the model validation check will check for uniqueness of the unique together defined in Meta.

See Model Validation Docs and overriding clean for ModelForms

edit:

You can do a couple of things to catch non unique together entry attempts.

  1. Inside your form.is_valid() you can except an Integrity Error like this:

    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. Use self.instance within the model form’s clean method to check for uniqueness.

👤dting

3👍

You could try this:

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

And the docs say: By default the clean() method validates the uniqueness of fields that are marked as … unique_together

👤jammon

Leave a comment