67

I wanted a Django model with 2 foreign keys from the same table. It's an event table which has 2 columns for employees: the 'actor' and the 'receiver'. But I get this error:

Error: One or more models did not validate: tasks.task: Intermediary model TaskEvent has more than one foreign key to Employee, which is ambiguous and is not permitted.

Is there a better way to model this?

I think I'm going to add a TaskEvent_to_Employee table. There will be two records in it, one for each of the two employees related to each TaskEvent. Does anyone know an easier workaround?

Art
  • 2,836
  • 4
  • 17
  • 34
Josh
  • 1,365
  • 3
  • 13
  • 23
  • 1
    Can you provide the Model classes which are giving you this issue? – Jonny Buchanan Feb 25 '09 at 11:08
  • 2
    possible duplicate of [How can I have two foreign keys to the same model in Django?](http://stackoverflow.com/questions/543377/how-can-i-have-two-foreign-keys-to-the-same-model-in-django) – viam0Zah Sep 17 '10 at 18:50
  • 1
    Possible duplicate of [How can I have two foreign keys to the same model in Django?](https://stackoverflow.com/questions/543377/how-can-i-have-two-foreign-keys-to-the-same-model-in-django) – Aaron McMillin Aug 14 '17 at 14:30
  • Definitely is a duplicate, flagged it. – Blairg23 Feb 10 '18 at 03:45
  • @Blairg23 You're 9 years late, but keep up the good work. – Josh Feb 10 '18 at 20:42
  • Well I just saw the issue 2 days ago :P Better late than never. If I found this issue and it's a duplicate, undoubtedly someone else will hit it too trying to find a solution. – Blairg23 Feb 12 '18 at 22:06

5 Answers5

122

I haven't done this yet, but I used inspectdb to generate the models.py file from an existing DB that does exactly that - this is what inspectdb threw back, so it should work:

creator = models.ForeignKey(Users, null=True, related_name='creator')
assignee = models.ForeignKey(Users, null=True, related_name='assignee')

Hope that works for you - if it doesn't I am going to have a problem too.

Technical Bard
  • 4,395
  • 7
  • 31
  • 32
  • 13
    Isn't related_name the link back to the model that contains the attribute using 'related_name', so in the example above example wouldn't you change the related_name's to 'createe', and 'assignor' since if somebody were to access an objects 'assignee' in your example they would get the 'assignor'? – orokusaki Feb 19 '10 at 19:00
  • This is the recommended way to do it. That way, when you're trying to access the model, let's call it `Order` for this example, you can just say `for user in User.objects.all(): created_orders = user.creator.all()`, which will return all created orders for that `User` instance. – Blairg23 Feb 10 '18 at 03:43
  • related_name should be plural – Anthony Sep 18 '19 at 00:50
9

I think what you're looking for is the related_name property on ForeignKeyFields. This will allow you to reference the same table, but give django special names for the relationship.

More Info:

Munim Munna
  • 17,178
  • 6
  • 29
  • 58
Justin Abrahms
  • 1,289
  • 1
  • 12
  • 21
7

Using related_name was my solution:

class Sample(models.model):
    ...

class Mymodel(models.model):
    example1 = models.ForeignKey(Sample, related_name='sample1')
    example2 = models.ForeignKey(Sample, related_name='sample2')
Ghasem
  • 14,455
  • 21
  • 138
  • 171
7

From the error message, it sounds like you're trying to put two foreign keys to the same object on an intermediary table used via the through argument to ManyToManyField, the documentation for which states:

When you set up the intermediary model, you explicitly specify foreign keys to the models that are involved in the ManyToMany relation. This explicit declaration defines how the two models are related.

There are a few restrictions on the intermediate model:

  • Your intermediate model must contain one - and only one - foreign key to the target model (this would be Person in our example). If you have more than one foreign key, a validation error will be raised.
  • Your intermediate model must contain one - and only one - foreign key to the source model (this would be Group in our example). If you have more than one foreign key, a validation error will be raised.
Jonny Buchanan
  • 61,926
  • 17
  • 143
  • 150
-2

The fact that two columns are part of one table implies that the two fields are related, therefor to reference them individually is not ideal. The ForeignKey of your model should be the primary key of the table you are referencing:

event = models.ForeignKey('event')

You would then reference the columns as such:

foo.event.actor
foo.event.receiver

If you wish you could also change the way your class/model references the foreign attributes with properties. In your class you would do the following:

@property
def actor(self):
  return self.event.actor
@property
def receiver(self):
  return self.event.receiver

This would allow you to then call foo.actor and foo.receiver but I believe the longer, foo.event.actor would be more pythonic

awithrow
  • 1,103
  • 9
  • 18