Opened 3 years ago

Closed 3 years ago

#29092 closed Bug (wontfix)

Clashing table name checks don't account for database routers

Reported by: Elizaveta Kishchukova Owned by: nobody
Component: Database layer (models, ORM) Version: 1.11
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Elizaveta Kishchukova)

This code results in errors during integrity checks when there are apps using models with same m2m table name.

in django/db/models/fields/related.py, lines 1441-1453:

    def _check_table_uniqueness(self, **kwargs):
        if isinstance(self.remote_field.through, six.string_types) or not self.remote_field.through._meta.managed:
            return []
        registered_tables = {
            model._meta.db_table: model
            for model in self.opts.apps.get_models(include_auto_created=True)
            if model != self.remote_field.through and model._meta.managed
        }    
        m2m_db_table = self.m2m_db_table()
        model = registered_tables.get(m2m_db_table)
        # The second condition allows multiple m2m relations on a model if
        # some point to a through model that proxies another through model.
        if model and model._meta.concrete_model != self.remote_field.through._meta.concrete_model:

Example:

Set up:
app1.SomeModel with table name "some_table_name" (using database 1)
app2.SomeModel with table name "some_table_name" (using database 2)
app1.Y with field xs = models.ManyToManyField('X', through='SomeModel')
app2.Y with field xs = models.ManyToManyField('X', through='SomeModel')

ERRORS: 
app1.Y.xs: (fields.E340) The field's intermediary table 'some_table_name' clashes with the table name of 'app2.SomeModel'.
app2.Y.xs: (fields.E340) The field's intermediary table 'some_table_name' clashes with the table name of 'app1.SomeModel'.

Notice how it compares models of different apps. This dictionary ought to at least use something like 'database.table_name' or 'app_name.table_name' for key.

Change History (3)

comment:1 Changed 3 years ago by Elizaveta Kishchukova

Description: modified (diff)

comment:2 Changed 3 years ago by Tim Graham

Component: UncategorizedDatabase layer (models, ORM)

If I understand correctly, the only thing preventing the tables from clashing in your case is the database router. I'm not sure if it's worth trying to have this check consult database routers. This doesn't seem like a common setup, so the best solution might be for you to add that check to SILENCED_SYSTEM_CHECKS.

comment:3 Changed 3 years ago by Tim Graham

Resolution: wontfix
Status: newclosed
Summary: Issues with ManyToMany Models for different apps with same table namesClashing table name checks don't account for database routers
Type: UncategorizedBug

Feel free to reopen and offer a patch for evaluation if you think the implementation is straightforward. I guess any solution can't be perfect since we won't have access to the instance hint at check time.

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