Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Model validation on update in django

I've created a model called Term and a validator for it, like this:

from django.db import models
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError


def validate_insensitive_exist(value):
            exists = Term.objects.filter(word__iexact = value.lower()).exists()
            if exists == True:
                    raise ValidationError("This term already exist.")


class Term(models.Model):
        word = models.CharField(max_length=200, unique=True, validators=[validate_insensitive_exist])
        related_term = models.ManyToManyField("self", null=True, blank=True)
        def __unicode__(self):
                return self.word
        def natural_key(self):
                return self.word

What this validator does is to raise an exception when I try to add a term that already exists (in lower or uppercase), and it's working fine. My problem is that when I try to edit an existing term (just to put a character in upper or lowercase - but the word is the same), an exception is raised because in fact i'm trying to add a word that already exists, being itself. What I want is to validate the new word that I enter against all the other terms, ignoring the word that was in the first place and that I'm actually changing.

Can anyone help me with that?

like image 532
Falcoa Avatar asked Mar 10 '15 14:03

Falcoa


People also ask

How Django knows to update VS insert?

The doc says: If the object's primary key attribute is set to a value that evaluates to True (i.e. a value other than None or the empty string), Django executes an UPDATE. If the object's primary key attribute is not set or if the UPDATE didn't update anything, Django executes an INSERT link.

What is __ str __ In Django model?

str function in a django model returns a string that is exactly rendered as the display name of instances for that model.

How does Django validate data?

Django provides built-in methods to validate form data automatically. Django forms submit only if it contains CSRF tokens. It uses uses a clean and easy approach to validate data. The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class.

How do I update a field in Django?

Use update_fields in save() If you would like to explicitly mention only those columns that you want to be updated, you can do so using the update_fields parameter while calling the save() method. You can also choose to update multiple columns by passing more field names in the update_fields list.


1 Answers

You can't use a validator for this, because a validator only has access to the value, not to the model instance that you are trying to validate.

You can define a clean method for your model, and exclude the current instance from the queryset.

class Term(models.Model):
    word = models.CharField(max_length=200, unique=True)
    related_term = models.ManyToManyField("self", null=True, blank=True)


    def clean(self):
        other_terms = Term.objects.filter(word__iexact=self.word.lower())
        if self.pk:
            other_terms = other_terms.exclude(pk=self.pk)
        if other_terms.exists():
            raise ValidationError("This term already exists.")
like image 168
Alasdair Avatar answered Oct 13 '22 10:10

Alasdair