Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django model with two generic (content_type) foreign keys?

I'm trying to create a mapping table between two generic (content_type) references, one for "agents" and one for "resources".

So I take the usual way I make a generic foreign key :

content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
resource = generic.GenericForeignKey('content_type', 'object_id')

And I try to make a model with two.

agent_content_type = models.ForeignKey(ContentType)
agent_object_id = models.PositiveIntegerField()
agent = generic.GenericForeignKey('agent_content_type', 'agent_object_id')

resource_content_type = models.ForeignKey(ContentType)
resource_object_id = models.PositiveIntegerField()
resource = generic.GenericForeignKey('resource_content_type', 'resource_object_id')

But this now throws up the following errors :

myapp.mymodel: Accessor for field 'resource_content_type' clashes with related field 'ContentType.mymodel_set'. Add a related_name argument to the definition for 'resource_content_type'.

And similar for the agent.

What's going on here? And what should I do?

cheers

phil

like image 524
interstar Avatar asked May 28 '09 10:05

interstar


People also ask

Can a Django model have 2 foreign keys?

First of all, anything is possible. Models can have multiple foreign keys.

Can a model have multiple foreign keys?

A table can have multiple foreign keys based on the requirement.

What is generic ForeignKey in Django?

In Django, a GenericForeignKey is a feature that allows a model to be related to any other model in the system, as opposed to a ForeignKey which is related to a specific one. This post is about why GenericForeignKey is usually something you should stay away from.


1 Answers

Have you tried doing what the error message tells you to do - add a related_name argument?

agent_content_type = models.ForeignKey(ContentType, related_name='mymodel_agent')

Edit: The reason why it happens is that every time you define a foreign key, Django automatically gives the target model an attribute to do the reverse lookup. By default, it gives this the name of the related table + '_set' - so if your article table has an FK to section, section will get an article_set attribute for the reverse lookup.

Now if you have two FKs in the same model pointing at the same target model, Django will try and give them both the foo_set attribute, leading to a collision. Hence the error message, which tells you to set the related_name attribute manually.

like image 82
Daniel Roseman Avatar answered Sep 24 '22 01:09

Daniel Roseman