Models

Um modelo é a fonte única e definitiva de dados sobre os seus dados. Ele contém os campos e comportamentos essenciais dos dados que você está gravando. Geralmente, cada modelo mapeia para uma única tabela no banco de dados.

O básico:

  • Cada modelo é uma classe Python que extende django.db.models.Model.
  • Cada atributo do modelo representa uma coluna do banco de dados.
  • Com tudo isso, o Django lhe dá uma API de acesso a banco de dados gerada automaticamente, o que é explicado em Fazendo consultas.

See also

Um companheiro para esse documento é o repositório oficial de exemplos de modelo. (Na distribuição do fonte do Django, esses exemplos estão no diretório tests/modeltests.)

Exemplo rápido

Esse modelo de exemplo define uma Person, que tem um first_name e um last_name:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

first_name e last_name são campos do modelo. Cada campo é especificado como um atributo de classe, e cada atributo é mapeado para uma coluna no banco de dados.

O modelo Person acima criaria uma tabela assim:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

Algumas notas técnicas:

  • O nome da tabela, myapp_person, é automaticamente derivado de alguns metadados do modelo, no entanto isto pode ser sobrescrito. Veja Nomes de tabelas abaixo.
  • Um campo id é adicionado automaticamente, mas esse comportamento também pode ser alterado. Veja Campos de chave primária automáticos abaixo.
  • O comando SQL CREATE TABLE nesse exemplo é formatado usando a sintaxe do PostgreSQL, mas é digno de nota que o Django usa o SQL adaptado ao banco de dados especificado no seu arquivo de configurações.

Usando models

Uma vez que já tenha criado seus modelos, o passo final é dizer ao Django para usar estes modelos. Para isto, basta editar seu arquivo settings.py e mudar o INSTALLED_APPS adicionando o nome do módulo que contém seu models.py.

Por exemplo, se os modelos de sua aplicação ficam no módulo mysite.myapp.models (a estrutura de pacote que é criada para uma aplicação pelo script manage.py startapp), o INSTALLED_APPS deve ler, em parte:

INSTALLED_APPS = (
    #...
    'mysite.myapp',
    #...
)

Quando você adicionar novas aplicações ao INSTALLED_APPS, assegure-se de rodar o manage.py syncdb.

Campos

A parte mais importante do modelo – e a única obrigatória – é a lista de campos do banco de dados que ele define. Campos são especificados por meio de atributos de classe.

Exemplo:

class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

class Album(models.Model):
    artist = models.ForeignKey(Musician)
    name = models.CharField(max_length=100)
    release_date = models.DateField()
    num_stars = models.IntegerField()

Tipos de campos

Cada campo no seu modelo deve ser uma instância da classe Field apropriada. O Django usa os tipos das classes para determinar algumas coisas:

  • O tipo de coluna no banco de dados (ex: INTEGER, VARCHAR).
  • O widget a ser usado na interface administrativa do Django, se você a utilizar (ex: <input type="text">, <select>).
  • Os requisitos mínimos para validação, usados no site de administração do Django e nos formulários automaticamente gerados.

O Django é disponibilizado com dezenas de tipos de campos embutidos; você pode encontrar a lista completa em referência de campos do model. Você também pode facilmente escrever seus próprios tipos de campos se os que acompanham o Django não lhe servirem; veja Writing custom model fields.

Field options

Cada tipo de campo recebe um certo conjunto de argumentos específicos (documentados na referência de campos de model). Por exemplo, CharField (e suas subclasses) requerem um argumento max_length que especifica o tamanho do campos VARCHAR que será usado para armazenar os dados.

Também há um conjunto de argumentos comuns disponíveis para todos os tipos de campos. todos são opicionais. Eles são totalmente explicados na refeência, mas aqui há um pequeno sumário dos mais frequentemente usados:

null
Se True, o Django irá gravar valores vazios como NULL no banco de dados. O padrão é False.
blank

Se True, o campo pode ser vazio. o padrão é False.

Note que isso é diferente de null. null é puramente relacionado ao banco de dados, e blank é relacionado com validação. Se um campo tem blank=True, a validação na administração do Django irá permitir a entrada de um valor vazio. Se um campo tem blank=False, o campo será obrigatório.

choices

Um iterável(e.g., uma lista ou tupla) de tupla duplas para usar como escolhas para esse campo. Se fornecido, a administração do Django usará uma caixa de seleção no lugar de um campo de texto padrão e irá limitar as escolhas as opções dadas.

Uma lista de opções é parece com isso:

YEAR_IN_SCHOOL_CHOICES = (
    (u'FR', u'Freshman'),
    (u'SO', u'Sophomore'),
    (u'JR', u'Junior'),
    (u'SR', u'Senior'),
    (u'GR', u'Graduate'),
)

O primeiro elemeno de cada tupla é o verdadeiro valor a ser gravado. O segundo elemento será mostrado pela interface de adminsitração, ou em um ModelChoiceField. Dada uma instância de um objeto de model, o valor mostrado pelo campo choices pode ser acessado usando o método get_FOO_display. Por exemplo:

from django.db import models

class Person(models.Model):
    GENDER_CHOICES = (
        (u'M', u'Male'),
        (u'F', u'Female'),
    )
    name = models.CharField(max_length=60)
    gender = models.CharField(max_length=2, choices=GENDER_CHOICES)
>>> p = Person(name="Fred Flinstone", gender="M")
>>> p.save()
>>> p.gender
u'M'
>>> p.get_gender_display()
u'Male'
default
O valor padrão para o campo. Pode ser também um objeto chamável. Se for um chamável, será chamado a cada vez que um novo objeto for criado.
help_text
Um texto de “ajuda” extra para ser mostrado sob o campo no formulário de objetos do admin. É útil para documentação, mesmo que seu objeto não tenha um formulário administrativo.
primary_key

Se True, esse campo será a chave primária para o modelo.

Se você não especificar primary_key=True <Field.primary_key>` para nenhum campo no seu modelo, o Django adicionará automaticamente um campo IntegerField para ser a chave primária, desta forma, você não precisa configurar o primary_key=True <Field.primary_key>` em qualquer um dos seus campos a menos que você queira sobrescrever o comportamento padrão de chaves primárias. Para saber mais, Campos de chave primária automáticos.

unique
Se True, esse campo deve ser único na tabela.

Novamente, estes são somente descrições curtas das opções mais comuns dos campos. Detalhes completos podem ser encontrados na referência de opções dos campos comuns do model.

Campos de chave primária automáticos

Por padrão, o Django dá a cada model o seguinte campo:

id = models.AutoField(primary_key=True)

Esta é uma chave primária auto incremental.

Se você gostaria de especificar uma chave primária customizada, somente especifique primary_key=True em um dos seus campos. Se o Django ver que você especificou uma :attr:Field.primary_key`, ele não adicionará a coluna id automaticamente.

Cada model requer que exatamente um campo tenha primary_key=True.

Nomes de campos por extenso

Cada tipo de campo, exceto ForeignKey, ManyToManyField e OneToOneField, recebem um primeiro argumento opcional – um nome por extenso. Se o nome por extenso não é informado, o Django criará automaticamente a partir do atributo name do campo, convertendo underscores em espaços.

Nesse exemplo, o nome por extenso é "Person's first name":

first_name = models.CharField("Person's first name", max_length=30)

Nesse exemplo, o nome por extenso é "first name":

first_name = models.CharField(max_length=30)

ForeignKey, ManyToManyField e OneToOneField requerem que o primeiro argumento seja uma classe do modelo, assim usa o argumento verbose_name como um argumento nomeado:

poll = models.ForeignKey(Poll, verbose_name="the related poll")
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(Place, verbose_name="related place")

A convenção é não colocar em caixa alta a primeira letra do verbose_name. O Django irá automaticamente capitalizar a primeira letra quando for necessário.

Relacionamentos

Claramente, o poder dos bancos relacionais reside na capacidade de relacionar tabelas umas as outroas. O Django oferece formas de definir os três tipos de relacionamento mais comuns: muitos-para-um, muitos-para-muitos e um-para-um.

Relacionamentos muitos-para-um

Para definir um relacionamento muitos para um, use ForeignKey. Você o usa como qualquer outro Field`: incluindo-o como um atributo de classe no seu modelo.

O ForeignKey requer um argumento posicional: a classe a qual esse modelo é relacionado.

Por exemplo, se um modelo Car tem um Manufacturer – isso é, um Manufacturer faz múltiplos carros, mas cada Car somente tem um Manufacturer – use as seguintes definições:

class Manufacturer(models.Model):
    # ...

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer)
    # ...

Para criar um relacionamento recursivo – (um objeto que tem um relacionamento muitos para um consigo mesmo) e relacionamentos com models que ainda não foram definidos; veja a referêcia de campos do model para mais detalhes.

É sugerido, mas não obrigatório, que o nome de um campo ForeignKey (manufacturer do exemplo acima) seja o nome do model, em minúsculo. Você pode, é claro, chamar o campo como você quiser. Por exemplo:

class Car(models.Model):
    company_that_makes_it = models.ForeignKey(Manufacturer)
    # ...

See also

Veja o exemplo de relacionamento Muitos-para-um para um exemplo completo.

Os campos ForeignKey também aceitam um número extra de argumentos que são explicados na referência de campos do model. Estas opções ajudam a definir como o relacionamento deve funcionar; todos são opicionais.

Relacionamentos muitos-para-muitos

Para definir um relacionamento muitos-para-muitos, use o ManyToManyField. Você o utiliza como qualquer outro tipo de Field: incluíndo ele como um atributo de classe do seu model.

O ManyToManyField requer um argumento posicional: a classe à qual esse modelo está relacionado.

Por exemplo, se uma Pizza tem múltiplos objetos Topping – isto é, um Topping pode estar em multiplas pizzas e cada Pizza tem várias sobremesas – aqui está como representar isso:

class Topping(models.Model):
    # ...

class Pizza(models.Model):
    # ...
    toppings = models.ManyToManyField(Topping)

Como com ForeignKey, você pode também criar relacionamentos recursivos (um objeto com um relacionamento muitos-para-um para si mesmo) e relacionamentos para models ainda não definidos; veja a referência de campos do model para mais detalhes.

É sugerido, mas não obrigatório, que o nome de um ManyToManyField (toppigns no exemplo acima) esteja no plural, descrevendo o conjunto de objetos model relacionados.

Não importa qual model recebe o ManyToManyField, mas você somente precisa dele em um dos models – não em ambos.

Geralmente, instâncias de ManyToManyField devem ir no objeto que sera editado na internface do admin, se você estiver usando o admin do Django. No exemplo acima, toppings está em Pizza (ao invés de Topping ter um ManyToManyField pizzas) porque é mais natural pensar sobre pizzas tendo sobremesas do que sobremesas tendo várias pizzas. A forma que é mostrada acima, o formulário de Pizza no admin, deixaria os usuários selecionar sobremesas.

See also

Veja o exemplo de relacionamento de model Muitos-para-muitos para um exemplo completo.

Os campos ManyToManyField também aceitam um número extra de argumentos que são explicados na referêcia de campos do model; Estas opções ajudam a definir como o relacionamento deve funcionar; todos são opcionais.

Campos extra sobre relacionamentos muitos-para-muitos

Quando você está somente lidando com relacionamentos muitos-para-muitos simples assim como misturando ou combinando pizzas e sobremesas, um ManyToManyField padrão é tudo que você precisa. Entretanto, algumas vezes você pode precisar associar dados com o relacionamento entre dois models.

Por exemplo, considere o caso de uma aplicação que monitora grupos musicais dos quais músicos pertencem. Há um relacionamento muitos-para-muitos entre uma pessoa e os grupos dos quais ela é um membro, então você poder usar um ManyToManyField para representar este relacionamento. No entanto, há um monte de detalhes sobre a filiação que você pode querer coletar, como a data em que a pessoa se juntou a um grupo.

Para estas situações, o Django permite você especificar o model que será usado para governar o relacionamento muitos-para-muitos. Você pode então colocar campos extra sobre o model intermediário. O model mediador é associado com o ManyToManyField usando o argumento through para apontar o model que agirá como um mediador. Para o nosso exemplo dos músicos, o código pareceria com algo assim:

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __unicode__(self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person)
    group = models.ForeignKey(Group)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

Quando você configura o model intermediário, você explicitamente especifica as chaves extrangeiras para o models que estão envolvidos no relacionamento ManyToMany. Esta declaração explicita define como os dois models serão relacionados.

Há umas poucas restrições no model intermediário:

  • Seu model mediador deve conter uma - e somente uma - chave estrangeira para o model alvo (este seria o Person em nosso exemplo). Se você tiver mais de uma chave estrangeira, um erro de validação será gerado.
  • Seu model mediador deve conter uma - e somente uma - chave estrangeira para o model fonte (este seria o Group no nosso exemplo). Se você tiver mais de uma chave estrangeira, um erro de validação será gerado.
  • A única exceção para isto é o model que term relacionamento muitos-para-muitos, consigo mesmo através de um model intermediário. Neste caso, duas chaves extrangeiras para o mesmo model é permitida, mas elas serão tratadas como dois (diferentes) lados do muitos-para-muitos.
  • Quando se define um relacionamento muitos-para-muitos de u model para ele mesmo, usando um model intermediário, você deve usar symmetrical=False (veja referencia de campos do model).

Agora que você tem configurado seu ManyToManyField para usar seu model mediador (Membership`, neste caso), você está pronto para começar a criar alguns relacionamentos muitos-para-muitos. Você faz isto criando instâncias do model intermediário:

>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
...     date_joined=date(1962, 8, 16),
...     invite_reason= "Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
[<Person: Ringo Starr>]
>>> ringo.group_set.all()
[<Group: The Beatles>]
>>> m2 = Membership.objects.create(person=paul, group=beatles,
...     date_joined=date(1960, 8, 1),
...     invite_reason= "Wanted to form a band.")
>>> beatles.members.all()
[<Person: Ringo Starr>, <Person: Paul McCartney>]

Diferentemente de campos muitos-para-muitos normais, você não pode usar add, create, ou atribuição (i.e.,``beatles.members = [...]``) para criar relacionamentos:

# ISTO NÃO FUNCIONARÁ
>>> beatles.members.add(john)
# NEM ISSO IRÁ
>>> beatles.members.create(name="George Harrison")
# E NEM MESMO ISSO
>>> beatles.members = [john, paul, ringo, george]

Porquê? você não pode simplesmente criar um relacionamento entre um Person e um Group - você precisa especificar todos os detalhes para o relacionamento requerido pelo model Membership. As chamadas simples add, create e atribuição não provem uma forma de especificar estes detalhes a mais. Como um resultado, eles são desabilitados pelos relacionamentos muitos-para-muitos que usam um model mediador. A única forma de criar este tipo de relacionamento é criando instâncias do model intermediário.

O método remove é desabilitado por razões similares. No entanto, o método clear() pode ser usado para remover todo relacionamento muitos-para-muitos para uma instância:

# Beatles have broken up
>>> beatles.members.clear()

Uma vez que você estabeleça o relacionamento muitos-para-muitos criando instâncias de seus models intermediários, você pode emitir consultas. Só que como um relacionamento muitos-para-muitos normal, você pode consultar usando os atributos do model relacionado com o muitos-para-muitos:

# Encontra todos os grupos com o membro cujo nome começa com 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul')
[<Group: The Beatles>]

Como você está usando um model intermediário, você pode também consultar seus atributos:

# Encontre todos os membro do Beatles que entraram depois de 1 Jan 1961
>>> Person.objects.filter(
...     group__name='The Beatles',
...     membership__date_joined__gt=date(1961,1,1))
[<Person: Ringo Starr]

Relacionamentos um-para-um

Para definir um relacionamento um-para-um, use o OneToOneField. Você deve utilizá-lo como qualquer outro Field: incluindo-o como um atributo de classe em seu model.

Este é mais útil sobre a chave primária de um objeto, quando este objeto “extende” outro objeto de alguma forma.

O OneToOneField requer um argumento posicional: a classe para qual o model está relacionado.

Por exemplo, se você construiu um banco de dados de “lugares”, você iria construir um belo padrão, com coisas tipo endereço, telefone, etc. no banco de dados. Então se você esperava construir um banco de dados de restaurantes sobre os lugares, ao invés de repetir e replicar todos esses campos no model Restaurant, você poderia fazer Restaurant ter um OneToOneField para Place (porque um restaurante “é um” lugar; em fato, para manipular isto você normalmente usaria herança, que envolve uma relação um-para-um implícita.)

Como com ForeignKey, um relacionamento recursivo pode ser definido e referenciar models ainda indefinidos; veja a referência de campos do model para mais detalhes.

See also

Veja o exemplo de relacionamento de model um-para-um para um exemplo completo.

Os campos OneToOneField também aceitam um argumento opcional descrito na referência de campos do model.

OneToOneField classes used to automatically become the primary key on a model. This is no longer true (although you can manually pass in the primary_key argument if you like). Thus, it’s now possible to have multiple fields of type OneToOneField on a single model.

As classes OneToOneField são usadas para automaticamente tornar-se a chave primária de um model. Isto já não é verdade ( embora você possa manualmente passar em um argumento primary_key se você quiser). Assim, agora é possível ter vários campos do tipo OneToOneField em um único model.

Models em todos os arquivos

É perfeitamente normal relacionar um model com um de outra aplicação. Para fazer isto, importe o model relacionado no topo do arquivo que contém seu model. Então, é só referenciar para a outra classe model onde você quiser. Por exemplo:

from mysite.geography.models import ZipCode

class Restaurant(models.Model):
    # ...
    zip_code = models.ForeignKey(ZipCode)

Restrições de nome de campos

O Django impõe apenas duas restrições aos nomes de campos do modelo:

  1. Um nome de campo não pode ser uma palavra reservada do Python, porque isso resultaria num erro de sintaxe do Python. Por exemplo:

    class Example(models.Model):
        pass = models.IntegerField() # 'pass' é uma palavra reservada!
    
  2. Um nome de campo não pode conter mais de um underscore em uma linha, devido à forma que a sintaxe de busca de consultas do Django funciona. Por exemplo:

    class Example(models.Model):
        foo__bar = models.IntegerField() # 'foo__bar' tem dois underscores!
    

Essas limitações podem ser trabalhadas, já que o nome do seu campo não precisa necessariamente ser igual ao nome da coluna no seu banco de dados. Veja a opção db_column.

Palavras reservadas do SQL, como join, where ou select, são permitidas como nomes de campos no modelo, porque o Django escapa todos os nomes de tabelas e colunas em cada consulta SQL. Ele usa a sintaxe de quoting do seu banco de dados em particular.

Tipos de campos customizados

Se um dos campos existentes no model não pode ser usado para o que você propõe, ou se você deseja ter vantagem sobre alguma coluna de banco de dados menos comum, você pode criar suas próprias classes de campos. A cobertura total da criação de seus próprios campos é fornecida em Writing custom model fields.

Opções Meta

Forneca seus metadados de model usando uma classe interna class meta, desta forma:

class Ox(models.Model):
    horn_length = models.IntegerField()

    class Meta:
        ordering = ["horn_length"]
        verbose_name_plural = "oxen"

O metadado do model é “qualquer coisa que não seja um campo”, assim como opções de ordenamento (attr:~Options.ordering), nome de tabelas do banco de dados (db_table), ou nomes legíveis-por-humanos no singular ou plural (verbose_name_plural). Nenhum é obrigatório, e adicionar class Meta ao model é completamente opcional.

Uma lista completa de todas as opções possíveis do Meta podem ser encontradas na referência e opções de model.

Métodos do model

Define métodos customizados sobre um model para adicionar funcionalidades a “nível de linha” para seus objetos. Considerando que os métodos Manager são destinados para fazer coisas “table-wide”, os métodos de model devem agir sobre uma instância particular de model.

Esta é uma técnica valiosa para manter a lógica de negócio em um só lugar – o model.

Por exemplo, este model tem uns poucos métodos customizados:

from django.contrib.localflavor.us.models import USStateField

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    birth_date = models.DateField()
    address = models.CharField(max_length=100)
    city = models.CharField(max_length=50)
    state = USStateField() # Yes, this is America-centric...

    def baby_boomer_status(self):
        "Returns the person's baby-boomer status."
        import datetime
        if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
            return "Baby boomer"
        if self.birth_date < datetime.date(1945, 8, 1):
            return "Pre-boomer"
        return "Post-boomer"

    def is_midwestern(self):
        "Returns True if this person is from the Midwest."
        return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')

    def _get_full_name(self):
        "Returns the person's full name."
        return '%s %s' % (self.first_name, self.last_name)
    full_name = property(_get_full_name)

O último método deste exemplo é um property. Leia mais sobre propriedades.

A referência de instância de model tem uma lista completa de métodos automaticamente dados para cada model. Você pode sobrescrever quase todos eles – veja sobrescrevendo métodos de model predefinidos, abaixo – mas há alguns que você irá quase sempre querer definir:

__unicode__()

Um “método mágico” do Python que retorna uma “representação” unicode de qualquer objeto. Isto é o que o Python e o Django irá usar sempre que uma instância de model precisar ser mostrada como uma string. Mais notavelmente, isto acontece quando você mostra um objeto em um um console interativo ou no admin.

Você sempre irá querer definir este método; o padrão não é muito útil.

get_absolute_url()

Este diz ao Django como calcular a URL para um objeto. O Django o usa na sua interface de administraçaõ, e toda vez que precisa descobrir a URL de um objeto.

Qualquer objeto que tem uma URL que o identifica exclusivamente, deve definir este método.

Sobrescrevendo métodos de model predefinidos

Há outro conjunto de métodos do model que encapsulmam um monte de comportamentos de banco de dados que você deseja customizar. Em particular você frequentemente vai querer mudar a forma de funcionamento do save() e delete().

Você é livre para sobrescrever estes métodos (e qualquer outro método do model) para alterar comportamento.

Um caso de uso clássico para sobrecarga de métodos embutidos é se você deseja que algo aconteça sempre que você salva o objeto. Por exemplo (veja save() para documentação e paramêtros aceitos):

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def save(self, force_insert=False, force_update=False):
        do_something()
        super(Blog, self).save(force_insert, force_update) # Call the "real" save() method.
        do_something_else()

Você pode também previnir o salvamento:

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def save(self, force_insert=False, force_update=False):
        if self.name == "Yoko Ono's blog":
            return # Yoko não deve nunca ter seu próprio blog!
        else:
            super(Blog, self).save(force_insert, force_update) # Chama o método save() "real".

É imporante lembrar de chamar o método da superclasse – esse é que é o negócio super(Blog, self).save() – para assegurar que o objeto ainda será salvo no banco de dados. Se você esquecer de chamar o método da superclasse, o comportamento padrão não acontecerá e o banco de dados não será tocado.

Executando SQL customizado

Outra prática comum é escrever consultas SQL personalizadas em métodos do model a nível módulo. Para mais detalhe sobre como usar SQL puro, veja a documentação em usando SQL puro.

Herança de modelos

Herança de models no Django funciona quase igual à forma normal de herança entre classes do Python. A única decisão que você tem de tomar é se você quer que os modelos pai sejam modelos no seu próprio contexto (com suas próprias tabelas de banco de dados), ou se os pais são somente mantenedores de informações comuns que somente serão visíveis através da herança entre modelos.

Freqüentemente, você só quer usar a classe pai para manter informações que você não deseja escrever para cada modelo filho. Esta classe nunca será usada de forma isolada, então classes abstratas de base são o que estiver depois. Entretanto, se você está extendendo uma subclasse de modelo existente (talvez algo de outra aplicação), ou quer que cada modelo tenha sua própria tabela no banco de dados, herança com multi-tabelas é o caminho a seguir.

Classes Abstratas de Base

Uma classe abstrata de base é útil quando você quer colocar alguma informação comum à disposição de vários modelos. Você escreve sua classe de base e coloca abstract=True dentro da classe Meta. Este modelo não será usado para criar qualquer tabela no banco de dados. Em vez disso, quando ele for usado como uma classe abstrata de base por outro modelo, seus campos serão adicionados aos seus modelos filho. É um erro ter campos na classe abstrata de base com o mesmo nome daqueles que a herda (o Django irá lançar uma exceção).

Um exemplo:

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

    class Student(CommonInfo):
        home_group = models.CharField(max_length=5)

O modelo Student possuirá três campos: name, age e home_group. O modelo CommonInfo não pode ser usado como um modelo normal do Django, já que ele é uma classe abstrata de base. CommonInfo não gera uma tabela no banco de dados e nem pode ser instanciado ou salvo diretamente.

Para muitos usos, este tipo de herança de modelo será exatamente o que você quer. Ele fornece uma maneira de fatorar informações comuns ao nível do Python, enquanto ao nível do banco de dados só serão criadas tabelas para os modelos filhos.

Herança de Meta

Quando uma classe abstrata de base é criada, o Django torna qualquer Meta interno da classe que você criou, disponível como um atributo a classe de base. Se uma classe filha não declara sua própria classe Meta, ela irá herdar de seu pai. Se a classe filha quer extender a classe Meta do pai, ela pode. Por exemplo:

class CommonInfo(models.Model):

...

class Meta:
abstract = True ordering = [‘name’]
class Student(CommonInfo):

...

class Meta(CommonInfo.Meta):
db_table = ‘student_info’

O Django faz um ajuste para a classe Meta de uma classe abstrata de base: antes instalando o atributo Meta, e configurando abstract=False. Isto significa que os filhos da classe abstrata de base não se tornam automaticamente classes abstratas. É claro, você pode fazer uma classe abstrata de base que herda outra classe abstrata de base. Você só precisa lembrar de setar explicitamente abstract=True toda vez.

Alguns atributos não fazem sentido serem incluídos na classe Meta de uma classe abstrata de base. Por exemplo, incluindo db_table poderia significar que todos os filhos (que não especificarem seus próprios Meta) poderiam usar a mesma tabela no banco de dados, que é provavelmente o que você não quer.

Herança com Multi-Tabelas

O segundo tipo de herança de modelos suportado pelo Django é quando cada modelo na hierarquia é um modelo em si mesmo. Cada modelo corresponde a sua própria tabela no banco de dados e pode ser consultado e criado individualmente. A relação de herança introduz links entre o modelo filho e cada um de seus pais (por meio de um campo OneToOneField criado automaticamente). Por exemplo:

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField()
    serves_pizza = models.BooleanField()

Todos os campos de Place também estarão disponíveis no Restaurant, apesar de o dado residir em uma tabela diferente no banco de dados. Então ambos são possíveis:

>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")

Se você tem um Place que também é um Restaurant, você pode obter do objeto Place o objeto Restaurant usando a versão minúscula do nome do model:

>>> p = Place.objects.filter(name="Bob's Cafe")
# Se "Bob's Cafe" é um objeto Restaurant, isto irá retornar uma classe filho:
>>> p.restaurant
<Restaurant: ...>

Entretanto, se p no exemplo acima não for um Restaurant (que havia sido criado diretamente como um objeto Place ou foi pai de alguma outra classe), referir-se a p.restaurant poderia gerar um erro.

Meta e herança com multi-tabelas

Nesta situação de herança com multi-tabelas, não faz sentido a classe filha herdar a classe Meta de seus pais. Todas as opções em Meta já teriam sido aplicadas para a classe e aplicá-las de novo normalmente levaria a um comportamento contraditório (isto está em contraste com o caso da classe abstrata de base, onde a classe de base não existe em seu próprio direito).

Então o modelo filho não tem acesso às classes Meta de seus pais. Entretanto, existem uns poucos casos limitados onde o filho herda o comportamento do pai: se o filho não especificar um atributo django.db.models.Options.ordering ou um atributo django.db.models.Options.get_latest_by, ele os herdará de seus pais.

Se o pai tem um ordenamento e você não quer que o filho o tenha, você pode explicitar com uma lista vazia:

class ChildModel(ParentModel):
    ...
    class Meta:
        # Remove o ordenamento dos pais
        ordering = []

Herança e relações reversas

Porque a herança com multi-tabelas usa um campo implícito OneToOneField para ligar o filho ao pai, é possível mover propriedades do pai para o filho, como no exemplo acima. Entretanto, isso usa o nome que é o valor padrão related_name para relações django.db.models.fields.ForeignKey e django.db.models.fields.ManyToManyField. Se você está colocando estes tipos de relações sobre uma subclasse de outro modelo, você deve especificar o atributo related_name em cada campo. Se você esquecer, o Django gerará um erro quando você rodar o validate ou syncdb.

Por exemplo, usando a classe Place novamente, vamos criar outra subclasse com um ManyToManyField:

class Supplier(Place):
    # Você deve especificar o related_name em todas as relações.
    customers = models.ManyToManyField(Restaurant,
            related_name='provider')

Herança múltipla

Da mesma forma que as subclasses do Python, é possível para um modelo do Django ter herança de múltiplos modelos pais. Mantenha em mente a aplicação da resolução normal de nomes do Python. A primeira classe de base em que um nome particular aparece (ex: Meta) será utilizada. Nós paramos de procurar assim que encontramos um nome. Isso significa que se os múltiplos pais possuem uma classe Meta, somente o primeiro será usado. Todos os outros serão ignorados.

Geralmente você não necessita de herança múltipla. O principal caso de uso onde isso se torna comum é para classes ‘’mix-in’‘: adicionando um campo ou método extra em particular para cada classe que herdar do mix-in. Tente manter suas hierarquias o mais simples possível, para que você não trave batalhas para descobrir de onde vem uma certa informação.

“Esconder” nomes de campos não é permitido

Numa classe normal do Python, é admissível para uma classe filha sobrescrever qualquer atributo de sua classe pai. No Django, isto não é permitido para atributos que são instâncias de Field (pelo menos, não neste momento). Se a classe base tem um filho chamado author, você não pode criar outro campo para o model chamado author em qualquer classse que herde da classe base.

Sobrescrever campos no model pai conduz a dificuldade em áreas como inicialização de novas instâncias (especificando que os campos são inicializados no Model.__init__) e serialização. Estas são funcionalidades que a herança de classes normal do Python não consegue lidar da mesma forma, então a diferença entre a herança de model do Django e herança de classes do Python não é meramente arbitrária.

Esta restrição somente se aplica aos atributos que são instâncias do Field. Atributos normais do Python podem ser sobrescritos se você desejar. Ele também se aplita apenas ao nome do atributo como Python o vê: se você está manualmente especificando o nome da coluna do banco de dados, você pode ter o nome da coluna aparecendo em ambas uma filha e um model antecessor para herança muiti-tabela (elas são colunas em duas tabelas diferentes no banco de dados).

Django will raise a FieldError exception if you override any model field in any ancestor model. O Django irá lançar uma exceção FieldError se você sobrescrever qualquer campo em qualquer model antecessor.