#11369 closed (fixed)
verbose_name_plural not inherited if base class is abstract.
Reported by: | Beetle_B | Owned by: | Ramiro Morales |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.0 |
Severity: | Keywords: | verbose_name_plural, inheritance, abstract | |
Cc: | mueen@…, bronger@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Perhaps this is desired behavior. However, I think the docs should mention this explicitly.
The situation where this arose is that I was creating a CategoryBase class (abstract), which was a bit barebones. I then subclassed this to get a number of derived classes (all abstract as well) - because I have different use cases (some need an HTML description, which will be formatted using Textile or Markdown, etc). Then for one particular app, I needed one of these, so I subclassed (without making it an abstract class).
I had set verbose_name_plural in the Meta of the original CategoryBase class. This did not get inherited...
In summary:
CategoryBase --> CategoryMarkup --> Category
where all but Category were abstract classes.
Anyway, I'm not arguing it should be inherited - will leave that up to you to decide. I just feel that if it isn't, it should be reflected in the docs for abstract base classes.
Attachments (1)
Change History (18)
comment:1 by , 15 years ago
Cc: | added |
---|
comment:2 by , 15 years ago
comment:3 by , 15 years ago
It's not obvious from those docs.
It explicitly states that Meta options are inherited if you don't define a Meta class. It then goes on to say that some options aren't (giving the examples of db_table and abstract). That's about it. Are we supposed to guess whether verbose_name_plural is inherited?
db_table is obvious.
abstract is not that obvious, which is why it was explicitly explained.
Likewise, I think stuff like verbose_name_plural is not obvious.
(Unless I'm missing something else from the docs...)
comment:4 by , 15 years ago
Component: | Uncategorized → Documentation |
---|---|
Triage Stage: | Unreviewed → Accepted |
The documentation should explicitly state what properties are/are not inherited.
comment:5 by , 15 years ago
Some tests I've performed trying to understand this ticket (also available at http://dpaste.de/45tH/), the <django.utils.functional.__proxy__ object
hints this is getting handled by the string_concat
calls in django.db.models.options.Option.contribute_to_class
:
# models.py from django.db import models class CategoryBase(models.Model): class Meta: abstract = True verbose_name_plural = u'CategoryBase verbose_name_plural' class Category(CategoryBase): title = models.CharField(max_length=100) #---------------------- >>> from t11369.models import Category >>> c = Category(title=u'Title A') >>> c.save() >>> print Category._meta.verbose_name_plural CategoryBase verbose_name_plural >>> print c._meta.verbose_name_plural CategoryBase verbose_name_plural #====================== # models.py from django.db import models class CategoryBase(models.Model): class Meta: abstract = True verbose_name_plural = u'CategoryBase verbose_name_plural' class CategoryMarkup(CategoryBase): class Meta: abstract = True verbose_name_plural = u'CategoryMarkup verbose_name_plural' class Category(CategoryMarkup): title = models.CharField(max_length=100) #---------------------- >>> from t11369.models import Category >>> c = Category(title=u'Title A') >>> c.save() >>> print Category._meta.verbose_name_plural CategoryMarkup verbose_name_plural >>> print c._meta.verbose_name_plural CategoryMarkup verbose_name_plural #====================== # models.py from django.db import models class CategoryBase(models.Model): class Meta: abstract = True verbose_name_plural = u'CategoryBase verbose_name_plural' class CategoryMarkup(CategoryBase): class Meta: abstract = True class Category(CategoryMarkup): title = models.CharField(max_length=100) #---------------------- >>> from t11369.models import Category >>> c = Category(title=u'Title A') >>> c.save() >>> print Category._meta.verbose_name_plural <django.utils.functional.__proxy__ object at 0xb75a76ec> >>> print c._meta.verbose_name_plural <django.utils.functional.__proxy__ object at 0xb75a76ec>
comment:6 by , 15 years ago
Component: | Documentation → Database layer (models, ORM) |
---|
As can be seen above, problem occurs when there is one or more intermediate abstract classes between the one containing the verbose_name_plural
definition and the non-abstract one.
In the example posted by the OP, the CategoryMarkup
model needs to define its own inner Meta
class basause it has to explicitely specify it is a abstract class. Then, if it is desired it inherits the verbose_name_plural
attribute from CategoryBase
we need to make sure it extends its Meta inner class by subclassing it:
class CategoryBase(models.Model): class Meta: abstract = True verbose_name_plural = u'CategoryBase verbose_name_plural' class CategoryMarkup(CategoryBase): class Meta(CategoryBase.Meta): abstract = True #...
OP didn´t paste his models se we don't know if he was taking this in account.
But even if this usage error isn't present in user's models there is a Django bug (Category.verbose_name_plural
values shown are <django.utils.functional.proxy... as above and they evaluate to "Categorys" in the admin). IMHO it should treat
verbose_name_plural in a way consistent with
verbose_name`. I'm changing the component field of this ticket accordingly.
by , 15 years ago
Attachment: | 11369-r11267.diff added |
---|
comment:7 by , 15 years ago
Has patch: | set |
---|
follow-up: 12 comment:8 by , 15 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
OP here.
Here's how I remember it (I have the code, but it may have been modified since then):
There's one (perhaps important) difference:
class CategoryBase(models.Model): class Meta: abstract = True verbose_name_plural = u'CategoryBase verbose_name_plural' class CategoryMarkup(CategoryBase): class Meta(CategoryBase.Meta): abstract = True class Category(CategoryMarkup): title = models.CharField(max_length=100)
The difference is that the intermediate abstract model (CategoryMarkup)'s Meta is subclassing the Meta of the parent. This was as per the docs...
In any case, your examples are illuminating. So normally, verbose_name_plural is inherited from an abstract base class that defines it?
The point of this bug report was that the docs should state explicitly what is or is not inherited. Your examples have, in a sense, confused me, and is suggesting an inconsistent behavior (in which case a separate ticket needs to be opened). On the one hand, it is inherited (if the immediate parent defines it). On the other, it is not (even when the intermediate abstract class's Meta is inheriting directly from the parent's Meta).
comment:9 by , 15 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:10 by , 15 years ago
Owner: | set to |
---|---|
Status: | new → assigned |
comment:11 by , 15 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
I don't know what I'm doing "wrong", but somehow this keeps getting assigned to me. Trying to reset...
comment:12 by , 15 years ago
Replying to Beetle_B:
OP here.
Here's how I remember it (I have the code, but it may have been modified since then):
...
The difference is that the intermediate abstract model (CategoryMarkup)'s Meta is subclassing the Meta of the parent. This was as per the docs...
Correct.
In any case, your examples are illuminating. So normally, verbose_name_plural is inherited from an abstract base class that defines it?
Correct.
The point of this bug report was that the docs should state explicitly what is or is not inherited.
Oops, sorry. From the tracking of the ticket history I had understood this ticket was initially opened to report the mis-behavior and later changed to be about the docs, that's why I changed is component to ORM.
Your examples have, in a sense, confused me, and is suggesting an inconsistent behavior (in which case a separate ticket needs to be opened). On the one hand, it is inherited (if the immediate parent defines it). On the other, it is not (even when the intermediate abstract class's Meta is inheriting directly from the parent's Meta).
Correct, and the patch solves it, the regression test case added shows this with an very similar example: It fails without the patch and works after applying it.
Anyway, if the patch (or another solution) is committed to solve the problem that Django is treating the verbose_name_plural
in a way different to verbose_name
when abstract model inheritance is involved then there won't be any special cases to document (apart for the cases already covered: abstract
is not inherited and db_table
is but it won't make any sense). That is, all the meta model options are inherited just like in the non-abstract scenario and IMHO there won't be any need to explicitely list them.
comment:13 by , 15 years ago
Owner: | set to |
---|---|
Status: | new → assigned |
comment:14 by , 14 years ago
Cc: | added |
---|
comment:15 by , 14 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
comment:16 by , 14 years ago
comment:17 by , 14 years ago
I exterience the very same problem with "ordering" instead of "verbose_name_plural". Is this related?
I think this can be marked as invalid.
http://docs.djangoproject.com/en/dev/topics/db/models/#meta-inheritance