Opened 12 years ago
Closed 4 years ago
#19040 closed New feature (wontfix)
Allow declaring a model Manager class inside the model class
Reported by: | Owned by: | ||
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | model manager |
Cc: | jelena.kutalovskaja@… | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
It is not possible to have a models' Manager-class defined on the models' class-level this way:
class Post(models.Model): title = models.CharField(max_length=50) slug = models.SlugField(max_length=50, blank=True, unique=True) body = models.TextField(blank=True) pub_date = models.DateTimeField(blank=True) mod_date = models.DateTimeField(blank=True) tags = models.ManyToManyField(Tag) class Meta: ordering = ['pub_date'] # Newest first class Manager(models.Manager): def by_slug(self, slug): slug = slug.strip().lower() return self.get(slug=slug) objects = Manager() def __unicode__(self): return self.title def save(self, *args, **kwargs): self.slug = self.slug or generate_slug(self.title) self.pub_date = self.pub_date or timezone.now() self.mod_date = timezone.now() return super(Post, self).save(*args, **kwargs)
I got the following error:
Traceback (most recent call last): File "C:\Users\niklas\Desktop\blog_project\manage.py", line 10, in <module> execute_from_command_line(sys.argv) File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\core\management\__init__.py", line 443, in execute_from_command_line utility.execute() File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\core\management\__init__.py", line 382, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\core\management\base.py", line 196, in run_from_argv self.execute(*args, **options.__dict__) File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\core\management\base.py", line 231, in execute self.validate() File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\core\management\base.py", line 266, in validate num_errors = get_validation_errors(s, app) File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\core\management\validation.py", line 30, in get_validation_errors for (app_name, error) in get_app_errors().items(): File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\db\models\loading.py", line 158, in get_app_errors self._populate() File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\db\models\loading.py", line 64, in _populate self.load_app(app_name, True) File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\db\models\loading.py", line 88, in load_app models = import_module('.models', app_name) File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\utils\importlib.py", line 35, in import_module __import__(name) File "C:\Users\niklas\Desktop\blog_project\blog\models.py", line 48, in <module> class Post(models.Model): File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\db\models\base.py", line 99, in __new__ new_class.add_to_class(obj_name, obj) File "C:\Python27\lib\site-packages\django-1.4.1-py2.7.egg\django\db\models\base.py", line 219, in add_to_class value.contribute_to_class(cls, name) TypeError: Error when calling the metaclass bases unbound method contribute_to_class() must be called with Manager instance as first argument (got ModelBase instance instead)
Change History (9)
comment:1 by , 12 years ago
Cc: | added |
---|---|
Triage Stage: | Unreviewed → Design decision needed |
Version: | 1.4 → master |
comment:2 by , 12 years ago
I'd prefer this structure. If the manager was usable with other models as well, I'd admit putting it outside of and give it a meaningful name. But if it is only used for one model, putting it directly into the class makes the most sense to me.
Why should I have
Post PostManager PostAdmin
when it would also be possible to have the following:
Post Post.Manager Post.Admin
(haven't yet tried it with the django.contrib.admin.ModelAdmin
class)
comment:3 by , 12 years ago
It's a nice feature to have, it also allow to override the model Manager and Admin objects against Post.Manager and Post.Admin instead of PostAdmin and PostManager which is my style of programming but might not be yours.
The overhead is at instanciation time.
The real question is whether it is good pratice to somewhat couple the model with its manager and admin in regard of separation of concerns.
The OP is right «But if it is only used for one model, putting it directly into the class makes the most sense to me.»
comment:5 by , 12 years ago
Triage Stage: | Design decision needed → Accepted |
---|
comment:6 by , 10 years ago
Cc: | added |
---|---|
Owner: | changed from | to
Status: | new → assigned |
comment:7 by , 9 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
Summary: | models.Manager on class-level of models.Model does not work → Allow declaring a model Manager class inside the model class |
Type: | Bug → New feature |
comment:8 by , 9 years ago
Cc: | removed |
---|
comment:9 by , 4 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
Triage Stage: | Accepted → Unreviewed |
After 8 years with no suggestion, I'm going to close this as wontfix. For me, Simon's initial reaction was the right one.
Happy to reconsider if a proposal does turn up, but pending such...
Is there a reason you why can't define the
Manager
subclass out of theModel
subclass definition?Unless you can provide a good reason to so, I'm inclined toward marking this ticket as wontfix since fixing it implicates adding some method inspection in
ModelBase.add_to_class
. Marking as DDN to get someone else review.IMO it's not worth the overhead.