Browse Source

Fixed #14305 -- Switched inspectdb to create unmanaged models.

Thanks Ian Kelly for the report and initial patch.
Ramiro Morales 12 years ago
parent
commit
08dc90bccf

+ 4 - 2
django/core/management/commands/inspectdb.py

@@ -40,8 +40,9 @@ class Command(NoArgsCommand):
         cursor = connection.cursor()
         yield "# This is an auto-generated Django model module."
         yield "# You'll have to do the following manually to clean this up:"
-        yield "#     * Rearrange models' order"
-        yield "#     * Make sure each model has one field with primary_key=True"
+        yield "#   * Rearrange models' order"
+        yield "#   * Make sure each model has one field with primary_key=True"
+        yield "#   * Remove `managed = False` lines for those models you wish to give write DB access"
         yield "# Feel free to rename the models, but don't rename db_table values or field names."
         yield "#"
         yield "# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]'"
@@ -224,5 +225,6 @@ class Command(NoArgsCommand):
         to the given database table name.
         """
         return ["    class Meta:",
+                "        managed = False",
                 "        db_table = '%s'" % table_name,
                 ""]

+ 29 - 0
docs/howto/legacy-databases.txt

@@ -49,6 +49,35 @@ Once you've cleaned up your models, name the file ``models.py`` and put it in
 the Python package that holds your app. Then add the app to your
 :setting:`INSTALLED_APPS` setting.
 
+If your plan is that your Django application(s) modify data (i.e. edit, remove
+records and create new ones) in the existing database tables corresponding to
+any of the introspected models then one of the manual review and edit steps
+you need to perform on the resulting ``models.py`` file is to change the
+Python declaration of each one of these models to specify it is a
+:attr:`managed <django.db.models.Options.managed>` one. For example, consider
+this generated model definition:
+
+.. parsed-literal::
+
+      class Person(models.Model):
+          id = models.IntegerField(primary_key=True)
+          first_name = models.ChaField(max_length=70)
+          class Meta:
+	       **managed = False**
+	       db_table = 'CENSUS_PERSONS'
+
+If you wanted to modify existing data on your ``CENSUS_PERSONS`` SQL table
+with Django you'd need to change the ``managed`` option highlighted above to
+``True`` (or simply remove it to let it because ``True`` is its default value).
+
+This servers as an explicit opt-in to give your nascent Django project write
+access to your precious data on a model by model basis.
+
+.. versionchanged:: 1.6
+
+The behavior by which introspected models are created as unmanaged ones is new
+in Django 1.6.
+
 Install the core Django tables
 ==============================
 

+ 15 - 0
docs/ref/django-admin.txt

@@ -288,9 +288,24 @@ needed.
 ``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection
 only works in PostgreSQL and with certain types of MySQL tables.
 
+If your plan is that your Django application(s) modify data (i.e. edit, remove
+records and create new ones) in the existing database tables corresponding to
+any of the introspected models then one of the manual review and edit steps
+you need to perform on the resulting ``models.py`` file is to change the
+Python declaration of each one of these models to specify it is a
+:attr:`managed <django.db.models.Options.managed>` one.
+
+This servers as an explicit opt-in to give your nascent Django project write
+access to your precious data on a model by model basis.
+
 The :djadminopt:`--database` option may be used to specify the
 database to introspect.
 
+.. versionchanged:: 1.6
+
+The behavior by which introspected models are created as unmanaged ones is new
+in Django 1.6.
+
 loaddata <fixture fixture ...>
 ------------------------------
 

+ 10 - 0
tests/regressiontests/inspectdb/tests.py

@@ -140,3 +140,13 @@ class InspectDBTestCase(TestCase):
         self.assertIn("field_field_0 = models.IntegerField(db_column='%s__')" % base_name, output)
         self.assertIn("field_field_1 = models.IntegerField(db_column='__field')", output)
         self.assertIn("prc_x = models.IntegerField(db_column='prc(%) x')", output)
+
+    def test_managed_models(self):
+        """Test that by default the command generates models with `Meta.managed = False` (#14305)"""
+        out = StringIO()
+        call_command('inspectdb',
+                     table_name_filter=lambda tn:tn.startswith('inspectdb_columntypes'),
+                     stdout=out)
+        output = out.getvalue()
+        self.longMessage = False
+        self.assertIn("        managed = False", output, msg='inspectdb should generate unmanaged models.')