Ticket #20098: 20098.2.patch

File 20098.2.patch, 3.6 KB (added by carsten.klein@…, 2 years ago)

Correct handling of unmanaged models and duplicate db_table declaration

  • django/db/models/options.py

    diff --git a/django/db/models/options.py b/django/db/models/options.py
    index d471bba..284a67d 100644
    a b DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering', 
    2323                 'order_with_respect_to', 'app_label', 'db_tablespace',
    2424                 'abstract', 'managed', 'proxy', 'swappable', 'auto_created')
    2525
     26# Lookup table for table names introduced in order to prevent that users from declaring the same table twice
     27db_table_lookup = {}
     28
    2629
    2730@python_2_unicode_compatible
    2831class Options(object):
    class Options(object): 
    121124            self.db_table = "%s_%s" % (self.app_label, self.module_name)
    122125            self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
    123126
     127        # Prevent users from declaring the same table twice, ISSUE #20098
     128        if self.managed:
     129            qname = '%s.%s' % (cls.__module__, cls.__name__)
     130            if self.db_table in db_table_lookup:
     131
     132                raise Exception('db_table "%s" was already declared by "%s" and was redeclared by "%s".'
     133                                % (self.db_table, db_table_lookup[self.db_table], qname))
     134
     135            db_table_lookup[self.db_table] = qname
     136
    124137    def _prepare(self, model):
    125138        if self.order_with_respect_to:
    126139            self.order_with_respect_to = self.get_field(self.order_with_respect_to)
  • tests/regressiontests/admin_scripts/tests.py

    diff --git a/tests/regressiontests/admin_scripts/tests.py b/tests/regressiontests/admin_scripts/tests.py
    index 3bb8bb0..82a512a 100644
    a b class ManageValidate(AdminScriptTestCase): 
    10691069        self.assertNoOutput(err)
    10701070        self.assertOutput(out, '0 errors found')
    10711071
     1072    def test_unmanaged_duplicate_db_table_declaration(self):
     1073        """ISSUE #20098
     1074        manage.py validate must not not raise errors when a project or an app
     1075        declares the same db_table twice using unmanaged model classes.
     1076        """
     1077        self.write_settings('settings.py',
     1078            apps=['admin_scripts.unmanaged_duplicate_db_table_declaration'],
     1079            sdict={'DEBUG': True}
     1080        )
     1081        args = ['validate']
     1082        out, err = self.run_manage(args)
     1083        self.assertNoOutput(err)
     1084        self.assertOutput(out, '0 errors found')
     1085
     1086    def test_duplicate_db_table_declaration_single_app(self):
     1087        """ISSUE #20098
     1088        manage.py validate does not raise errors when a project or an app
     1089        declares the same db_table twice or multiple times for different models
     1090        declared by a single app.
     1091        """
     1092        self.write_settings('settings.py',
     1093            apps=['admin_scripts.duplicate_db_table_declaration_single_app'],
     1094            sdict={'DEBUG': True}
     1095        )
     1096        args = ['validate']
     1097        out, err = self.run_manage(args)
     1098        self.assertOutput(err, 'was redeclared')
     1099
     1100    def test_duplicate_db_table_declaration_multiple_app(self):
     1101        """ISSUE #20098
     1102        manage.py validate does not raise errors when a project or an app
     1103        declares the same db_table twice or multiple times for different models
     1104        declared by different apps.
     1105        """
     1106        self.write_settings('settings.py',
     1107            apps=['admin_scripts.duplicate_db_table_declaration_multiple_app.app1',
     1108                  'admin_scripts.duplicate_db_table_declaration_multiple_app.app2'],
     1109            sdict={'DEBUG': True}
     1110        )
     1111        args = ['validate']
     1112        out, err = self.run_manage(args)
     1113        self.assertOutput(err, 'was redeclared')
     1114
    10721115
    10731116class CustomTestRunner(DjangoTestSuiteRunner):
    10741117
Back to Top