How to define a Django model with a reference to itself?
Question: I'm new to Django and currently write an application, where users can enter
their opinions on some topic.

Every opinion A may have zero or more opinions, which support A and several
(zero or more) opinions, which refute A.

I tried to create a model for this and wrote a `models.py` file like this:

    
    
    from django.db import models
    
    # Create your models here.
    class Opinion(models.Model):
        id = models.AutoField(primary_key=True)
        contents = models.CharField(max_length=256)
        source = models.CharField(max_length=256)
        proArguments = models.ManyToManyField(Opinion, verbose_name="Pro arguments")
        contraArguments = models.ManyToManyField(Opinion, verbose_name="Contra arguments")
    

When I run `python manage sqlall`, I get following error:

    
    
      File "D:\dev\history-site\history_site\opinions\models.py", line 4, in <module>
        class Opinion(models.Model):
      File "D:\dev\history-site\history_site\opinions\models.py", line 8, in Opinion
        proArguments = models.ManyToManyField(Opinion, verbose_name="Pro arguments")
    
    NameError: name 'Opinion' is not defined
    

How can I fix this error?


Answer: From [docs of
`ManyToManyField`](https://docs.djangoproject.com/en/dev/ref/models/fields/#ref-
manytomany):

> Requires a positional argument: the class to which the model is related.
> This works exactly the same as it does for `ForeignKey`, including all the
> options regarding recursive and lazy relationships.

Which
[says](https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey):

> To create a recursive relationship -- an object that has a many-to-one
> relationship with itself -- use `models.ForeignKey('self')`.

So:

    
    
    proArguments = models.ManyToManyField("self", verbose_name="Pro arguments")
    contraArguments = models.ManyToManyField("self", verbose_name="Contra arguments")
    

I'm slightly wondering about your data model if arguments are considered
opinions as well, but that's another matter.

