Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django unique model fields validation in form

I have a model with a few unique fields and I'm writing a form for it. I found some reference to the [validate_unique][1] method that should check for uniqueness on fields when you call it but my form .is_valid() always returns True.

My testcase:

class ServerFormTest( TestCase ):
    def setUp( self ):
        self.server = Server.objects.create( host = "127.0.0.1", name = "localhost" )

    def test_unique_name(self):
        form = ServerForm({
            'name': 'localhost',
            'host': '127.0.0.1'
        })

        self.assertFalse( form.is_valid( ) )

and my form:

class ServerForm( forms.ModelForm ):
    class Meta:
        model = Server
        fields = ('name', 'host')

    def clean( self ):
        self.validate_unique()
        return self.cleaned_data

server model:

class Server( models.Model ):
    host = models.GenericIPAddressField( blank = False, null = False, unique = True )
    name = models.CharField( blank = False, null = False, unique = True, max_length = 55 )
like image 528
Romeo Mihalcea Avatar asked Jul 01 '15 00:07

Romeo Mihalcea


2 Answers

validate_unique is a Model method.

Running the superclass clean method should take care of model uniqueness checks given a ModelForm.

class MyModelForm(forms.ModelForm):    
    def clean(self):
        cleaned_data = super(MyModelForm, self).clean()
        # additional cleaning here
        return cleaned_data

There is a warning on the django docs specifically about overriding clean on ModelForms, which automatically does several model validation steps.

like image 178
Yuji 'Tomita' Tomita Avatar answered Oct 09 '22 06:10

Yuji 'Tomita' Tomita


simple way to achieve uniqueness to a field, just use "unique=True" in the model field. Example:

email = models.EmailField(verbose_name=_('Email'), max_length=255, unique=True)

phone = models.CharField(verbose_name=_('Phone Number'), max_length=14, unique=True)

But if you really want to achieve this through form, or situation demands it, for example, in the above code section, here phone number is a character field. uniqueness is difficult to achieve here because for the system 0171-xxxxxxx and 0171xxxxxxx are different numbers but actually they are same. It can be easily validated through form's clean_phone method. Here the digit is parsed from the string(character field) before checking uniqueness.

    def clean_phone(self):
        phone = self.cleaned_data.get("phone")
        # parse digits from the string
        digit_list = re.findall("\d+", phone)
        phone = ''.join(digit_list)
        
        if CustomUser.objects.filter(phone=phone).exists():
            raise forms.ValidationError("phone number is already exists")
        return phone

like image 32
Mithun Biswas Avatar answered Oct 09 '22 05:10

Mithun Biswas