Code

Opened 8 years ago

Closed 8 years ago

#2028 closed defect (fixed)

Since models do not maintain models.py order , Sqlite code breaks on ForeignKeys

Reported by: ant9000@… Owned by: adrian
Component: Core (Other) Version: master
Severity: normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Hello,
I've tried to generate a correct sqlite script for the models.py below:

from django.db import models
class Device(models.Model):
    pass
class Module(models.Model):
    pass
class Die(models.Model):
    pass
class Wafer(models.Model):
    die_type = models.ForeignKey(Die)
class Padpattern(models.Model):
    pass
class Probecard(models.Model):
    pass

and it won't work even if Die is defined before Wafer, since the models get reordered.

Here is a quick and dirty patch to django.db.models.loading that makes it work correctly:

--- loading.py.dist	2006-05-29 09:59:52.078390200 +0200
+++ loading.py	2006-05-29 10:21:42.070052200 +0200
@@ -7,7 +7,10 @@
 
 _app_list = None # Cache of installed apps.
 _app_models = {} # Dictionary of models against app label
-                 # Each value is a dictionary of model name: model class
+                 # Each value is a dictionary with keys 'list', 'dict'
+		  # used to keep track of model name: model class in a sorted fashion
+		  # - 'list' is a sorted list of the models
+		  # - 'dict' associates the model names with their index in 'list'
 
 def get_apps():
     "Returns a list of all installed modules that contain models."
@@ -42,7 +45,9 @@
     """
     app_list = get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish.
     if app_mod:
-        return _app_models.get(app_mod.__name__.split('.')[-2], {}).values()
+        model_entry = _app_models.get(app_mod.__name__.split('.')[-2], {})
+	 model_list  = model_entry.setdefault('list',[])
+	 return model_list
     else:
         model_list = []
         for app_mod in app_list:
@@ -56,13 +61,16 @@
     """
     get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish.
     try:
-        model_dict = _app_models[app_label]
+        model_entry = _app_models[app_label]
     except KeyError:
         return None
 
     try:
-        return model_dict[model_name.lower()]
-    except KeyError:
+	 model_dict = model_entry['dict']
+	 model_idx  = model_dict[model_name.lower()]
+	 model_list = model_entry['list']
+        return model_list[model_idx]
+    except KeyError, IndexError:
         return None
 
 def register_models(app_label, *models):
@@ -73,5 +81,8 @@
         # Store as 'name: model' pair in a dictionary
         # in the _app_models dictionary
         model_name = model._meta.object_name.lower()
-        model_dict = _app_models.setdefault(app_label, {})
-        model_dict[model_name] = model
+        model_entry = _app_models.setdefault(app_label, {})
+	 model_list = model_entry.setdefault('list',[])
+	 model_dict = model_entry.setdefault('dict',{})
+	 model_list.append(model)
+	 model_dict[model_name] = len(model_list)-1

It would probably make sense to implement this hack in a SortedDict class, and use it as the underlying
container for modules.

Your software is great, keep on rocking!
Bye,

Ant9000

Attachments (0)

Change History (2)

comment:1 Changed 8 years ago by anonymous

It's worth noting that according to the sqlite docs, foreign key constraints aren't actually enforced. As such, it's likely not worth controlling the order in which tables are created, if it's only for sqlite's benefit.

comment:2 Changed 8 years ago by mtredinnick

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

As with #2260, I believe this has been fixed at some point in the interim. Can't give an exact changeset, because there are a few that affected this, but the work is done in django/core/management.py to save up any references that refer to tables we haven't created yet and output them at the end.

If the problem is not fixed, please reopen (and post the output of "manage.py sql ..." for this app).

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.