1

I have the following model:

class Category(models.Model):
    name = models.CharField(max_length=255)
    parent = models.ForeignKey('self', related_name='children')

My question is that how I could prevent model to referencing itself (same object). Object should be only able to point to other categories but not to itself ('dogs' can have parent 'animals' but can't have parent 'dogs')

m5seppal
  • 1,186
  • 3
  • 15
  • 31

2 Answers2

2

You can override the save method to throw an exception:

def save(self, *args, **kwargs):
    if self.parent and self.parent.name == self.name:
        raise ValidationError('You can\'t have yourself as a parent!')
    return super(Category, self).save(*args, **kwargs)
Ben
  • 6,687
  • 2
  • 33
  • 46
  • This wont work. Since self.parent has attribute `id` where `self` still dont.You can do `self.parent.name == self.name` – itzMEonTV Apr 09 '17 at 21:08
  • Thanks guys, I'm on the right track now. But latter won't work either, it gives AttributeError if there is no parent (it's not mandatory field) so I added "if self.parent and self.parent.name == self.name:". Now it works but the illegal value is still shown in admin multiple choice dropdown. How I could make sure that no form etc. ever suggest that value for the user? Please edit that post at least to fix the AttributeError part and I'll accept it then. – m5seppal Apr 10 '17 at 04:10
  • 1
    From what I know, validation should be done in `clean()` or `clean_fields()` method https://docs.djangoproject.com/en/3.1/ref/models/instances/#validating-objects – hashlash Sep 28 '20 at 16:50
1

For UI one can restrict using limit_choices_to: https://docs.djangoproject.com/en/4.0/ref/models/fields/#django.db.models.ForeignKey.limit_choices_to

bhdnx
  • 430
  • 7
  • 5