224

I'm kind of new to webapps and database stuff in general so this might be a dumb question. I want to make a model ("CategoryModel") with a field that points to the primary id of another instance of the model (its parent).

class CategoryModel(models.Model):
    parent = models.ForeignKey(CategoryModel)

How do I do this? Thanks!

Zags
  • 37,389
  • 14
  • 105
  • 140
sfendell
  • 5,415
  • 8
  • 25
  • 26
  • 3
    Stylistically, I would suggest calling this `parent` instead of `parentId`, since `my_category_model.parent` will be an instance of `CategoryModel`. Django will automatically create a member `parent_id` which will be the primary key of the related model. – Scott Aug 26 '19 at 15:06

4 Answers4

360

You can pass in the name of a model as a string to ForeignKey and it will do the right thing.

So:

parent = models.ForeignKey("CategoryModel")

Or you can use the string "self"

parent = models.ForeignKey("self")
Zags
  • 37,389
  • 14
  • 105
  • 140
Jared Forsyth
  • 12,808
  • 7
  • 45
  • 54
78

You can use the string 'self' to indicate a self-reference.

class CategoryModel(models.Model):
    parent = models.ForeignKey('self')

https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey

Zags
  • 37,389
  • 14
  • 105
  • 140
Brandon Taylor
  • 33,823
  • 15
  • 104
  • 144
  • 12
    I think you mean 'self'. As in the string. self is undefined in this context – Jared Forsyth Mar 08 '13 at 02:28
  • 1
    @Brandon How is 'self' in your answer different from what jared has said in his comment? "i think you mean 'self" !!! . Both are string which is fine according to django docs. ! Any hints – Stryker Nov 02 '16 at 03:06
  • 5
    The difference is that `self` isn't present when defining the model property. If the property were being defined as part of the `__init__()` or another method, it would be, as `self` is always the first positional argument to any instance method of a Python class. – Brandon Taylor Nov 02 '16 at 12:58
22

You also to set null=True and blank=True

class CategoryModel(models.Model):
    parent = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True)

null=True, to allow in database
blank=True, to allow in form validation

markwalker_
  • 12,078
  • 7
  • 62
  • 99
Punnerud
  • 7,195
  • 2
  • 54
  • 44
8

https://books.agiliq.com/projects/django-orm-cookbook/en/latest/self_fk.html

class Employee(models.Model):
    manager = models.ForeignKey('self', on_delete=models.CASCADE)

OR

class Employee(models.Model):
    manager = models.ForeignKey("app.Employee", on_delete=models.CASCADE)

https://stackabuse.com/recursive-model-relationships-in-django/

Hailee
  • 288
  • 1
  • 4
  • 13