Opened 10 years ago
Last modified 10 years ago
#23931 new Bug
db_manager() method doesn't increment creation_counter
Reported by: | Rhett Garber | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.7 |
Severity: | Normal | Keywords: | |
Cc: | Loic Bistuer | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
Creating a manager with the db_manager() method can cause unexpected behavior. Consider the following:
class MyModel(models.Model): objects = models.Manager() ro_objects = objects.db_manager('ro')
There are certain situations where ro_objects becomes the 'default' manager of the object. Both of these managers have the same 'creation_counter'.
Patch is here:
https://github.com/rhettg/django/compare/db_manager_creation_counter?expand=1
Change History (7)
comment:1 by , 10 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 10 years ago
comment:3 by , 10 years ago
I think it does make sense to allow creation of a manager with db or hints directly rather than relying on the copy behavior.
However,
- That's obviously a bit more involved since BaseManager doesn't currently take any arguments and sub-classing is a really popular pattern. It could conceivable cause problems for people.
- That doesn't mean this patch isn't also correct. I don't think it's appropriate to have any 'copy' patterns that don't increment the creation_counter.
So maybe this patch is appropriate for backporting (since not incrementing the counter is a bug), while adding arguments to init would be a valid for a release?
comment:4 by , 10 years ago
I'm sitting on the fence here.
db_manager()
was designed to generate short-lived managers, not to be assigned as class managers. That said, other short-lived managers (and short-lived fields in custom lookups/expressions for that matter) increase the creation counters (e.g. Category().article_set
) so db_manager()
probably should too, if only for consistency.
However supporting non-empty db
or hints
attributes for long-lived managers is something that would require a fair amount of investigation and some hard design decisions:
- Are these supposed to be default values to be used when nothing else is provided at query time? In that case what about
hints
, should they be merged? Current implementation ofRelatedManager.get_queryset()
completely overrideshints
.
- Are these supposed to be definitive values? Current implementation of
RelatedManager.create|get_or_create|update_or_create()
asks the router directly fordb
and doesn't account that one may be set already on the manager.
If we recognize that long-lived managers can have a db
or hints
state (as it would be the case if we made them __init__()
arguments) then we must define the behavior. Right now setting these may work for some cases, but the behavior is largely undefined as far as Django is concerned.
comment:5 by , 10 years ago
Cc: | added |
---|
comment:6 by , 10 years ago
Patch needs improvement: | set |
---|
comment:7 by , 10 years ago
Sorry I'm not quite following what is happening with this ticket.
Is the conclusion that my change is incorrect because incrementing the creation counter is not the desired behavior?
I looked through the documentation and none of the examples show this as a feature. I'd rather inherit from Manager and pass a
db
attribute along:Given that, maybe the
BaseManager
implementation could acceptdb
andhints
directly.