Opened 7 years ago

Closed 12 months ago

#8618 closed New feature (duplicate)

Many-to-many intermediary tables can't have multiple foreign keys to source/target models

Reported by: coda Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords: m2m intermediary validation
Cc: mysliceof314, danny.adair@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The following schema:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=100)
    vacations = models.ManyToManyField('Location', through='Vacation', blank=True)


class Location(models.Model):
    city = models.CharField(max_length=100)
    country = models.CharField(max_length=100)

class Vacation(models.Model):
    person = models.ForeignKey(Person)
    location = models.ForeignKey(Location)
    date = models.DateField()
    travel_agent = models.ForeignKey(Person, related_name='booked_vacations')

doesn't pass validation because "Intermediary model Vacation has more than one foreign key to Person, which is ambiguous and is not permitted."

It looks to me like the only reason for this error is because django doesn't have a way to specify which foreign keys on the intermediary model are relevant (or that there is no default behavior specified).

There's obviously more than one way around this, and probably someone can come up with a nicer example schema than I did. The simplest thing would be to get rid of that validation check, which (i think) would cause django to use the first key found for each model.

Change History (14)

comment:1 Changed 7 years ago by russellm

  • Component changed from Database wrapper to Core framework
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

If you read the ticket (#6095) and mailing list discussions surrounding this feature, this was discussed at the time.

There were a few suggestions on how to do this. Simply removing the check isn't an option - there is no reason to believe that the first foreign key will be the correct one.

Two possible options:

1) Convention: the foreign key _without_ a related field is the field for the M2M relation every time.
2) A new option; something in the Meta class to identify the fields that should be used for the through.

comment:2 Changed 7 years ago by Alex

Another option(which I'm not necessarily endorsing), would be to make through accept a tuple, the first arg is the intermediary model and the second is the name of the fkey to this model, and the third is the name of the fkey to the other model.

comment:3 Changed 7 years ago by Alex

  • milestone set to post-1.0

comment:4 Changed 7 years ago by mysliceof314

  • Cc mysliceof314 added

comment:5 Changed 6 years ago by anonymous

  • milestone post-1.0 deleted

Milestone post-1.0 deleted

comment:6 Changed 6 years ago by emulbreh

Convention: Select the foreign key named to.__name__.lower().

comment:7 Changed 4 years ago by julien

  • Component changed from Core framework to Database layer (models, ORM)

comment:8 Changed 4 years ago by lukeplant

  • Severity set to Normal
  • Type set to New feature

comment:9 Changed 3 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:10 Changed 3 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:11 Changed 2 years ago by danny.adair@…

  • Cc danny.adair@… added

comment:12 Changed 2 years ago by danny.adair@…

1) Convention: the foreign key _without_ a related field is the field for the M2M relation every time.
2) A new option; something in the Meta class to identify the fields that should be used for the through.
[...]
Another option(which I'm not necessarily endorsing), would be to make through accept a tuple, the first arg is the intermediary model and the second is the name of the fkey to this model, and the third is the name of the fkey to the other model.

I find the third option to be the most natural notation. Also, I wonder what notation the first two options would have for an intermediary table that describes more than one M2M relationship...

comment:14 Changed 12 months ago by bmispelon

  • Resolution set to duplicate
  • Status changed from new to closed

Indeed, it seems that this ticket was a duplicate of #14549 which was fixed in c627da0ccc12861163f28177aa7538b420a9d310.

Thanks for the heads up!

Note: See TracTickets for help on using tickets.
Back to Top