pupil
pupil

Reputation: 328

How to set django model field value based-on value of other field in the same Model

I want to assign a NullBooleanField value to always oppose other field value in the same model, except for None. From models below, i want to make sure if the value of scam is True, the value of whitelist can not also be True. But if scam is None, whitelist allowed to also set to None. The expected criteria is one of the followings:

  1. If scam is True, the allowed value of whitelist is False or None
  2. If scam is False, the allowed value of whitelist is True or None
  3. If scam is None, the allowed value of whitelist is True or False or None

So, how to make sure scam is always the opposite of whitelist?

This is my class model:

class ExtendHomepage(models.Model):
    "extending homepage model to add more field"
    homepage = models.OneToOneField(Homepage)

    # True if the website is a scam, False if not, None if not sure
    scam = models.NullBooleanField(blank=True, null=True)

    # True if the webpage is already inspected, False if not 
    inspected = models.BooleanField(default=False)

    # True if the website is already reported, False if not yet 
    reported =  models.NullBooleanField(blank=True, null=True)

    # True if the website response is 200, else it is False
    access =  models.BooleanField(default=True)

    # True if the web should be whitelist, False if should not, None pending
    whitelist =  models.NullBooleanField(blank=True, null=True)

Upvotes: 2

Views: 2240

Answers (2)

M.javid
M.javid

Reputation: 6637

You can make a property getter and setter for this necessity similar below code:

class ExtendHomepage(models.Model):
    "extending homepage model to add more field"
    homepage = models.OneToOneField(Homepage)

    # True if the website is a scam, False if not, None if not sure
    scam = models.NullBooleanField(blank=True, null=True)

    # True if the webpage is already inspected, False if not 
    inspected = models.BooleanField(default=False)

    # True if the website is already reported, False if not yet 
    reported =  models.NullBooleanField(blank=True, null=True)

    # True if the website response is 200, else it is False
    access =  models.BooleanField(default=True)

    # True if the web should be whitelist, False if should not, None pending

    __whitelist = models.NullBooleanField(blank=True, null=True)

    @property
    def whitelist(self):
        if self.scam is not None and self.scam == self.__whitelist:
            # this if block is not necessary but for 
            # check if content changed directly in database manager
            # then assign None value to this attribute
            self.__whitelist = None
        return self.__whitelist

    @whitelist.setter
    def whitelist(self, value):
        self.__whitelist = value
        if self.scam is not None and self.scam == self.__whitelist:
            self.__whitelist = None

Upvotes: 2

Paulo Scardine
Paulo Scardine

Reputation: 77251

I'm not sure I understood your criteria, but you can use validation:

def clean(self):
    if self.scam and self.whitelist:
        raise ValidationError("Can't set whitelist and scam simultaneously.")
    if self.scam is False and self.whitelist is False:
        raise ValidationError("Negate either whitelist or scam or none.")

Update your question with a truth table so we can understand what you want.

Upvotes: 1

Related Questions