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: | 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 , 18 years ago
comment:2 by , 18 years ago
Resolution: | → fixed |
---|---|
Status: | new → 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).
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.