#

## Django documentation

# 15. Subclassing models

You can subclass another model to create a copy of it that behaves slightly differently.

## Model source code

    from django.core import meta

    # From the "Bare-bones model" example
    from django.models.basic import Article

    # From the "Adding __repr__()" example
    from django.models.repr import Article as ArticleWithRepr

    # From the "Specifying ordering" example
    from django.models.ordering import Article as ArticleWithOrdering

    # This uses all fields and metadata from Article and
    # adds a "section" field.
    class ArticleWithSection(Article):
        section = meta.CharField(maxlength=30)
        class META:
           module_name = 'subarticles1'

    # This uses all fields and metadata from Article but
    # removes the "pub_date" field.
    class ArticleWithoutPubDate(Article):
        class META:
           module_name = 'subarticles2'
           remove_fields = ('pub_date',)

    # This uses all fields and metadata from Article but
    # overrides the "pub_date" field.
    class ArticleWithFieldOverride(Article):
        pub_date = meta.DateField() # overrides the old field, a DateTimeField
        class META:
            module_name = 'subarticles3'
            # No need to add remove_fields = ('pub_date',)

    # This uses all fields and metadata from ArticleWithRepr and
    # makes a few additions/changes.
    class ArticleWithManyChanges(ArticleWithRepr):
        section = meta.CharField(maxlength=30)
        is_popular = meta.BooleanField()
        pub_date = meta.DateField() # overrides the old field, a DateTimeField
        class META:
           module_name = 'subarticles4'

    # This uses all fields from ArticleWithOrdering but
    # changes the ordering parameter.
    class ArticleWithChangedMeta(ArticleWithOrdering):
        class META:
           module_name = 'subarticles5'
           ordering = ('headline', 'pub_date')

    # These two models don't define a module_name.
    class NoModuleNameFirst(Article):
        section = meta.CharField(maxlength=30)

    class NoModuleNameSecond(Article):
        section = meta.CharField(maxlength=30)

## API reference

### ArticleWithSection objects have the following methods:

- `delete()`
- `get_next_by_pub_date()`
- `get_previous_by_pub_date()`
- `save()`

### ArticleWithoutPubDate objects have the following methods:

- `delete()`
- `get_next_by_pub_date()`
- `get_previous_by_pub_date()`
- `save()`

### ArticleWithFieldOverride objects have the following methods:

- `delete()`
- `get_next_by_pub_date()`
- `get_previous_by_pub_date()`
- `save()`

### ArticleWithManyChanges objects have the following methods:

- `delete()`
- `get_next_by_pub_date()`
- `get_previous_by_pub_date()`
- `save()`

### ArticleWithChangedMeta objects have the following methods:

- `delete()`
- `get_next_by_pub_date()`
- `get_previous_by_pub_date()`
- `save()`

### NoModuleNameFirst objects have the following methods:

- `delete()`
- `get_next_by_pub_date()`
- `get_previous_by_pub_date()`
- `save()`

### NoModuleNameSecond objects have the following methods:

- `delete()`
- `get_next_by_pub_date()`
- `get_previous_by_pub_date()`
- `save()`

## Sample API usage

This sample code assumes the above models have been saved in a file `examplemodel.py`.

    >>> from django.models.examplemodel import subarticles1, subarticles2, subarticles3, subarticles4, subarticles5, nomodulenamefirsts, nomodulenameseconds

    # No data is in the system yet.
    >>> subarticles1.get_list()
    []
    >>> subarticles2.get_list()
    []
    >>> subarticles3.get_list()
    []

    # Create an ArticleWithSection.
    >>> from datetime import date, datetime
    >>> a1 = subarticles1.ArticleWithSection(headline='First', pub_date=datetime(2005, 8, 22), section='News')
    >>> a1.save()
    >>> a1

    >>> a1.id
    1
    >>> a1.headline
    'First'
    >>> a1.pub_date
    datetime.datetime(2005, 8, 22, 0, 0)

    # Retrieve it again, to prove the fields have been saved.
    >>> a1 = subarticles1.get_object(pk=1)
    >>> a1.headline
    'First'
    >>> a1.pub_date
    datetime.datetime(2005, 8, 22, 0, 0)
    >>> a1.section
    'News'

    # Create an ArticleWithoutPubDate.
    >>> a2 = subarticles2.ArticleWithoutPubDate(headline='Second')
    >>> a2.save()
    >>> a2

    >>> a2.id
    1
    >>> a2.pub_date
    Traceback (most recent call last):
        ...
    AttributeError: 'ArticleWithoutPubDate' object has no attribute 'pub_date'

    # Retrieve it again, to prove the fields have been saved.
    >>> a2 = subarticles2.get_object(pk=1)
    >>> a2.headline
    'Second'
    >>> a2.pub_date
    Traceback (most recent call last):
        ...
    AttributeError: 'ArticleWithoutPubDate' object has no attribute 'pub_date'

    # Create an ArticleWithFieldOverride.
    >>> a3 = subarticles3.ArticleWithFieldOverride(headline='Third', pub_date=date(2005, 8, 22))
    >>> a3.save()
    >>> a3

    >>> a3.id
    1
    >>> a3.pub_date
    datetime.date(2005, 8, 22)

    # Retrieve it again, to prove the fields have been saved.
    >>> a3 = subarticles3.get_object(pk=1)
    >>> a3.headline
    'Third'
    >>> a3.pub_date
    datetime.date(2005, 8, 22)

    # Create an ArticleWithManyChanges.
    >>> a4 = subarticles4.ArticleWithManyChanges(headline='Fourth', section='Arts',
    ...     is_popular=True, pub_date=date(2005, 8, 22))
    >>> a4.save()

    # a4 inherits __repr__() from its parent model (ArticleWithRepr).
    >>> a4
    Fourth

    # Retrieve it again, to prove the fields have been saved.
    >>> a4 = subarticles4.get_object(pk=1)
    >>> a4.headline
    'Fourth'
    >>> a4.section
    'Arts'
    >>> a4.is_popular == True
    True
    >>> a4.pub_date
    datetime.date(2005, 8, 22)

    # Test get_list().
    >>> subarticles1.get_list()
    []
    >>> subarticles2.get_list()
    []
    >>> subarticles3.get_list()
    []
    >>> subarticles4.get_list()
    [Fourth]

    # Create a couple of ArticleWithChangedMeta objects.
    >>> a5 = subarticles5.ArticleWithChangedMeta(headline='A', pub_date=datetime(2005, 3, 1))
    >>> a5.save()
    >>> a6 = subarticles5.ArticleWithChangedMeta(headline='B', pub_date=datetime(2005, 4, 1))
    >>> a6.save()
    >>> a7 = subarticles5.ArticleWithChangedMeta(headline='C', pub_date=datetime(2005, 5, 1))
    >>> a7.save()

    # Ordering has been overridden, so objects are ordered
    # by headline ASC instead of pub_date DESC.
    >>> subarticles5.get_list()
    [A, B, C]

    >>> nomodulenamefirsts.get_list()
    []
    >>> nomodulenameseconds.get_list()
    []

## Comments

### Rachel Willmer September 1, 2005 at 3:32 a.m.

It might be worth mentioning that if you want the right name to appear in the admin panel, you need to set verbose_name as well as module_name. Otherwise you get the subclass appearing in the admin page, but it uses the superclass name.

### Antonio September 10, 2005 at 7:19 a.m.

This is nice but what if you want to be polymorphic about the calls to Article. That is, what if I want to define a model method say Article.get_layout_size() that does different things depending on which subclass is implementing it. But I do not want to have to grovel through and create specific instances of my model subclasses; that is, all I want to do is articles.get_object(pk=12) and get back an appropriate subclass that I can treat as Article without knowing the implementation subtype. Can I do this somehow?

### Sokolov Yura September 11, 2005 at 1:10 p.m.

I have a lot of classes share same peaces.
One of this peaces:
....time_from=meta.DateTimeField()
....time_to=meta.DateTimeField(default=datetime(3000,1,1,0,0,0))

Another:
....description=meta.TextField()
....def __repr__(self):
........return self.description

Will following code work?
class TimePeriod:
....time_from=meta.DateTimeField()
....time_to=meta.DateTimeField(default=datetime(3000,1,1,0,0,0))
class Description:
....description=meta.TextField()
....def __repr__(self):
........return self.description
class SomeIdent(meta.Model,TimePeriod,Description)
....value=meta.TextField()
class SomeType(meta.Model,Description):
....value=meta.TextField()

Would it be equally (in Some.... behavior) to:
class SomeIdent(meta.Model)
....time_from=meta.DateTimeField()
....time_to=meta.DateTimeField(default=datetime(3000,1,1,0,0,0))
....value=meta.TextField()
....description=meta.TextField()
....def __repr__(self):
........return self.description
class SomeType(meta.Model,Description):
....value=meta.TextField()
....description=meta.TextField()
....def __repr__(self):
........return self.description
?

## Post a comment

Note: Please only use the comments for questions/critcisms/suggestions on the docs; if you experience errors please file a ticket, ask in the IRC channel, or post to the django-users list. Comments will be periodically reviewed, integrated into the documentation proper, and removed.

Your name:

Comment: