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?

Was it helpful?

Solution

From docs of ManyToManyField:

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:

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.

OTHER TIPS

You would have to use self. And since, you have two m2m self relationship you need to add a related_name argument or provide symmetrical=False

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('self', verbose_name="Pro arguments", related_name='my_proargs')
    contraArguments = models.ManyToManyField('self', verbose_name="Contra arguments", related_name='my_contraarg')

The way to do this is to use 'self'

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

From django documentation:

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top