#14948 closed (fixed)
Broken routers in 1.2.4: type object 'ModelBase' has no attribute '_meta'
Reported by: | shell_dweller | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.2 |
Severity: | Keywords: | router, ManyToManyField, blocker, regression | |
Cc: | s.kuzmenko@…, django@…, fwenzel@…, james@…, conrad666@…, typeshige@…, brian@…, django@…, hgeerts@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
There is a problem with using routers in the latest security release 1.2.4. The details are somewhat murky for a lay person but here's the gist of it:
- The site has a routing scheme setup as described in http://docs.djangoproject.com/en/1.2/topics/db/multi-db/#using-routers
- Attempt to save any model with a ManyToManyField fails in router when trying to execute db_for_write:
def db_for_write(self, model, **hints): if model._meta.app_label == 'my_app_label': return 'my_db_name' return None
Error message is "type object 'ModelBase' has no attribute '_meta'".
It seems that the error occurs in django/db/models/fields/related.py, line 624 where self.through.__class__
returns ModelBase whereas prior to 1.2.4 it used to be a user defined class.
Here's the stack trace:
[ snip ] File "/usr/lib/python2.4/site-packages/django/forms/models.py", line 375, in save fail_message, commit, construct=False) File "/usr/lib/python2.4/site-packages/django/forms/models.py", line 87, in save_instance save_m2m() File "/usr/lib/python2.4/site-packages/django/forms/models.py", line 83, in save_m2m f.save_form_data(instance, cleaned_data[f.name]) File "/usr/lib/python2.4/site-packages/django/db/models/fields/related.py", line 1144, in save_form_data setattr(instance, self.attname, data) File "/usr/lib/python2.4/site-packages/django/db/models/fields/related.py", line 730, in __set__ manager.clear() File "/usr/lib/python2.4/site-packages/django/db/models/fields/related.py", line 506, in clear self._clear_items(self.source_field_name) File "/usr/lib/python2.4/site-packages/django/db/models/fields/related.py", line 624, in _clear_items db = router.db_for_write(self.through.__class__, instance=self.instance) File "/usr/lib/python2.4/site-packages/django/db/utils.py", line 134, in _route_db chosen_db = method(model, **hints) File "/path/to/my/app/routers.py", line 10, in db_for_write if model._meta.app_label == 'my_label': AttributeError: type object 'ModelBase' has no attribute '_meta'
Attachments (3)
Change History (24)
comment:1 by , 14 years ago
Cc: | added |
---|
comment:2 by , 14 years ago
(assuming you have created a registered a router that uses "model._meta.object_name", of course)
comment:3 by , 14 years ago
Cc: | added |
---|
I can confirm this. A simple workaround would probably be to catch this in the router, but this would be a duct-tape fix.
comment:4 by , 14 years ago
Cc: | added |
---|
comment:5 by , 14 years ago
Cc: | added |
---|
comment:6 by , 14 years ago
Cc: | added |
---|
comment:7 by , 14 years ago
milestone: | → 1.3 |
---|---|
Triage Stage: | Unreviewed → Accepted |
Ok - this is a pretty major regression.
comment:8 by , 14 years ago
Cc: | added |
---|
comment:9 by , 14 years ago
Keywords: | blocker regression added |
---|
comment:11 by , 14 years ago
Cc: | added |
---|
follow-up: 13 comment:12 by , 14 years ago
This bug broke my site when I upgraded to 1.2.4, forcing me to roll back to 1.2.1 (after being deluged hundreds of errors in a few minutes). I am surprised more people haven't spoken up. Thanks for the hard work.
comment:13 by , 14 years ago
Replying to intrepidweb:
This bug broke my site when I upgraded to 1.2.4, forcing me to roll back to 1.2.1 (after being deluged hundreds of errors in a few minutes). I am surprised more people haven't spoken up. Thanks for the hard work.
You should be able to at least upgrade to 1.2.3 without encountering this problem.
comment:14 by , 14 years ago
The router check on rel.through may have been broken for some time but was hidden because the ConnectionRouter catched it's AttributeError
We can thank the following ticket for showing us this bug: http://code.djangoproject.com/ticket/14870
The patch cannot be reverted since the router call is broken and needs to be fixed.
On my project the error was raised in a different code path.
File "/home/harm/django12/django/core/management/commands/loaddata.py", line 174, in handle obj.save(using=using) File "/home/harm/django12/django/core/serializers/base.py", line 168, in save setattr(self.object, accessor_name, object_list) File "/home/harm/django12/django/db/models/fields/related.py", line 730, in __set__ manager.clear() File "/home/harm/django12/django/db/models/fields/related.py", line 506, in clear self._clear_items(self.source_field_name) File "/home/harm/django12/django/db/models/fields/related.py", line 624, in _clear_items db = router.db_for_write(self.through.__class__, instance=self.instance) File "/home/harm/django12/django/db/utils.py", line 134, in _route_db chosen_db = method(model, **hints) File "/home/harm/lascon/lascon/router.py", line 18, in db_for_write if model._meta.app_label == 'exact' and model._meta.object_name != 'ExactProfile': AttributeError: type object 'ModelBase' has no attribute '_meta'
comment:15 by , 14 years ago
Cc: | added |
---|
by , 14 years ago
Attachment: | django-1.2-router_related_accessor.patch added |
---|
patch with testcase for django-1.2, trunk will need to be patched as well
comment:16 by , 14 years ago
Has patch: | set |
---|
comment:17 by , 14 years ago
comment:18 by , 14 years ago
Patch needs improvement: | set |
---|
Actually the fix for #13668 is a subset of the fixes proposed here. What would be needed to close this ticket is a test case for the django/db/models/base.py modifications, currently the tests proposed in the patch attached to this ticket, passes irrespective of if the changes to that file are present.
by , 14 years ago
Attachment: | 14948-1.2.X-r15186.diff added |
---|
Patch by Harm Geerts updated to 1.2.x banch status as of now
by , 14 years ago
Attachment: | django-1.2-router_related_accessor-2.patch added |
---|
new patch based on changes from #13668 with tests to cover changes in django.db.models.base
comment:19 by , 14 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
(In [15207]) [1.2.X] Fixed #14948 -- Fixed a couple of cases where invalid model classes were passed to the database router when collecting reverse foreign key and many to many relationships. Thanks shell_dweller for the report and Harm Geerts for the patch.
This also enhances tests added in r15186.
Code in SVN trunk doesn't suffer from this problem because it was refactored in r14507.
Same problem here - an easy way to reproduce: