Login

Unique field inline formset

Author:
dcwatson
Posted:
September 13, 2012
Language:
Python
Version:
Not specified
Score:
1 (after 1 ratings)

This method will return an inline formset class that validates values across the given field are unique among all forms. For instance:

ApprovedUserFormSet = inlineformset_factory(Request, ApprovedUser, formset=unique_field_formset('email'), form=ApprovedUserForm)

Will make sure all ApprovedUser objects created for the Request have unique "email" fields.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def unique_field_formset(field_name):
    from django.forms.models import BaseInlineFormSet
    class UniqueFieldFormSet (BaseInlineFormSet):
        def clean(self):
            if any(self.errors):
                # Don't bother validating the formset unless each form is valid on its own
                return
            values = set()
            for form in self.forms:
                value = form.cleaned_data[field_name]
                if value in values:
                    raise forms.ValidationError('Duplicate values for "%s" are not allowed.' % field_name)
                values.add(value)
    return UniqueFieldFormSet

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 2 weeks ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 10 months, 1 week ago
  5. Help text hyperlinks by sa2812 11 months ago

Comments

monikkinom (on March 6, 2015):

If the errors are not visible in the view, you are probably making the same mistake I made. To display the validation errors in the view, you must add {{ formset.non_form_errors }} to it.

#

dimkoug (on May 24, 2020):

A minor change

def unique_field_formset(field_name): from django.forms.models import BaseInlineFormSet class UniqueFieldFormSet(BaseInlineFormSet): def clean(self): if any(self.errors): # Don't bother validating the formset unless each form is valid on its own return values = set() for form in self.forms: if form.cleaned_data: value = form.cleaned_data[field_name] if value in values: raise forms.ValidationError('Duplicate values for "%s" are not allowed.' % field_name) values.add(value) return UniqueFieldFormSet

#

jrobichaud (on November 16, 2023):

I made these adjustments:

  1. use translations
  2. use the translated label of the field instead of the actual field name.

from django.utils.translation import gettext_lazy as _

def unique_field_formset(field_name): from django.forms.models import BaseInlineFormSet

class UniqueFieldFormSet(BaseInlineFormSet):
    def clean(self):
        if any(self.errors):
            # Don't bother validating the formset unless each form is valid on its own
            return
        values = set()
        for form in self.forms:
            value = form.cleaned_data[field_name]
            if value in values:
                field = form.fields[field_name]
                raise forms.ValidationError(
                    _('Duplicate values for "%(field_name)s" are not allowed.')
                    % {"field_name": field.label}
                )
            values.add(value)

return UniqueFieldFormSet

#

Please login first before commenting.