Opened 8 years ago

Closed 8 years ago

#27264 closed Bug (needsinfo)

Model Meta is overwriten by abstract parent class

Reported by: luxcem Owned by: nobody
Component: Database layer (models, ORM) Version: 1.10
Severity: Normal Keywords: models meta inheritance
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Tim Graham)

class Something:

foo = 'foo'

Hi, it seems to be an actual django bug, the example at the address
https://docs.djangoproject.com/en/1.10/topics/db/models/#meta-inheritance
does not work correctly,


  from django.db import models

    class BaseCategory(models.Model):
        title = models.CharField(max_length=100)

        class Meta:
            abstract = True
            ordering = ['title']

    class Category(BaseCategory):

        name = models.CharField(max_length=100)

        class Meta(BaseCategory.Meta):
            ordering = ['name']
            db_table = 'sample'

Category.Meta.ordering is equal to title, Category.Meta.db_table is
undefined and Category.Meta.abstract is correctly set to false, in fact
Category.Meta is of type BaseCategory.Meta.

A stranger behavior is when abstract = True is added to the subclass :


  class Category(BaseCategory):

        name = models.CharField(max_length=100)

        class Meta(BaseCategory.Meta):
            abstract = True
            ordering = ['name']
            db_table = 'sample'

Now the behavior is correct (if abstract was not set) :
Category.Meta.db_table = 'sample', Category.Meta.ordering = name but
Category.Meta.abstract = False, Category.Meta is of type Category.Meta

So additionally it is impossible to create an abstract class inheriting
an abstract class.

Tested with django 1.8, 1.9, 1.10, 1.10.1 and python 2.7, 3.4

Change History (7)

comment:1 by luxcem, 8 years ago

Description: modified (diff)

comment:2 by Tim Graham, 8 years ago

Django uses values from the process meta, e.g. Category._meta.db_table, not Category.Meta. Could you be more specific about the problems you encounter when using the models?

in reply to:  2 comment:3 by luxcem, 8 years ago

Replying to Tim Graham:

Django uses values from the process meta, e.g. Category._meta.db_table, not Category.Meta. Could you be more specific about the problems you encounter when using the models?

I see, Category._meta is correct and I'll be using this instead of Meta, but anyway it seems that the Meta inheritance behavior is not standard, for example with another subclass :

from django.db import models

class BaseCategory(models.Model):
    title = models.CharField(max_length=100)

    class Meta:
        abstract = True
        ordering = ['title']

    class Something:
        foo = 'foo'

class Category(BaseCategory):

    name = models.CharField(max_length=100)

    class Meta(BaseCategory.Meta):
        ordering = ['name']
        db_table = 'sample'

    class Something(BaseCategory.Something):
        bar = 'bar'
>>> Category.Meta
<class 'core.models.BaseCategory.Meta'>
>>> Category.Something
<class 'core.models.Category.Something'>
>>> Category.Something.bar 
'bar'
>>> Category.Something.foo
'foo'
>>> Category.Meta.db_table
Traceback (most recent call last):
  File "<ipython-input-6-6545a8699b54>", line 1, in <module>
    Category.Meta.db_table
AttributeError: type object 'Meta' has no attribute 'db_table'

>>> Category.Meta.ordering
['title']

comment:4 by luxcem, 8 years ago

Description: modified (diff)

comment:5 by Tim Graham, 8 years ago

Description: modified (diff)

Why is it a problem?

in reply to:  5 comment:6 by luxcem, 8 years ago

Replying to Tim Graham:

Why is it a problem?

While it's not an actual problem, it is a very conter intuitive and unexpected behavior.

comment:7 by Tim Graham, 8 years ago

Resolution: needsinfo
Status: newclosed

If you want to provide a patch showing that it can be fixed without breaking anything, feel free to reopen the ticket. I guess the relevant code might be Options.contribute_to_class().

Note: See TracTickets for help on using tickets.
Back to Top