[Django]-Django Models ManyToMany and Foreign Key

5👍

If you want to know how many information are linked to each stuff, django will provide a default manager that will allow you to go backwards; for this you don’t need a foreign key in stuff.

class Things(models.Model):
    name = models.CharField(max_length=20)

class Stuff(models.Model):
    name = models.CharField(max_length=20)
    information = models.ManyToManyField('Information')
    things = models.ForeignKey('Things')

class Information(models.Model):
    name = models.CharField(max_length=20)

This model will allow you to do queries like:

  • “What is the information for stuff X ?”
  • “For stuff Y, what information is linked?”
  • “Find me all stuff and information for thing Z

In addition it will allow you have multiple information for each stuff and multiple stuff for each thing.

Writing down these questions at the start will help you develop accurate models without unnecessary links/relations in your database.

0👍

My version of django gives a bit more information:

Error: One or more models did not validate:
foo.stuff: Reverse query name for m2m field 'information' clashes with field 'Information.stuff'. Add a related_name argument to the definition for 'information'.
foo.information: Reverse query name for field 'stuff' clashes with m2m field 'Stuff.information'. Add a related_name argument to the definition for 'stuff'.

Which is probably enough to get you going. Define a related_name for both the ManyToManyField relationship and the ForeignKey relationship from Information to Stuff…

information = models.ManyToManyField('Information', related_name='stuff_many_set')
stuff = models.ForeignKey('Stuff', related_name = 'info_set')

then syncdb will be happy. Of course, you should be sure that you need both the relationships. With the generic entity names here it looks like there may be some confusion.

0👍

Fundamentally you would get an error like this:

$python manage.py syncdb
Error: One or more models did not validate:
t.stuff: Reverse query name for m2m field 'information' clashes with field  'Information.stuff'. Add a related_name argument to the definition for 'information'.
t.information: Reverse query name for field 'stuff' clashes with m2m field 'Stuff.information'. Add a related_name argument to the definition for 'stuff'.

why? simple you have two tables referencing each other, the problem here is that when reverse look ups are applied django will generate the same name, creating a clash.

To fix this issue, like the error states, you need to add related_name this way django knows how to distinguish the different reverse calls.

from django.db import models

class Things(models.Model):
    name = models.CharField(max_length=20)

class Stuff(models.Model):
    name = models.CharField(max_length=20)
    information = models.ManyToManyField('Information', related_name = 'information_information')
    things = models.ForeignKey('Things')

class Information(models.Model):
    name = models.CharField(max_length=20)
    stuff = models.ForeignKey('Stuff', related_name = 'information_stuff')

Sorry Im not very creative with the names, this should work.

Leave a comment