Opened 18 years ago

Closed 18 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 Holovaty
Component: Core (Other) Version: dev
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

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

Change History (2)

comment:1 by anonymous, 18 years ago

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 by Malcolm Tredinnick, 18 years ago

Resolution: fixed
Status: newclosed

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).

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