Referência das instâncias de Model¶
Esse documento descreve os detalhes da API Model
. Isso foi feito baseado
no material apresentado nos guias model e
consultas ao banco de datos, então provavelmente
você vai querer ler e entender esses documentos antes de ler este aqui.
Durante essa referência, usaremos os models de exemplo do weblog apresentado no guia de consultas ao banco de dados.
Criando objetos¶
Para criar uma nova instância de um model, somente instancie-o assim como qualquer outra classe Python:
-
class
Model
(**kwargs)¶
Os argumentos são simplesmente os nomes dos campos que você definiu no seu
model. Perceba que instanciando um model você não alterará o banco de dados;
para isso, você precisa do save()
.
Salvando objetos¶
Para salvar um objeto no banco de dados, chame save()
:
-
Model.
save
([force_insert=False, force_update=False])¶
É claro, há algumas legendas; veja as seções abaixo.
A assinatura do método save()
tem mudou nas versões mais novas
(force_insert
e force_update
foram adicionados). Se você está
sobrescrevendo estes métodos, esteja certo do uso correto da assinatura.
Auto-incrementando chaves primárias¶
Se um model possui um AutoField
– uma chave primária que auto-incrementa –
então o valor auto-increment será calculado e salvo como um atributo no seu
objeto, na primeira vez que você chamar o método save()
:
>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b2.id # Retorna None, porque b nao tem um ID ainda.
>>> b2.save()
>>> b2.id # Retorna o ID de seu novo objeto.
Não há meios de dizer qual será o valor do ID antes de você chamar o método
save()
, porque este valor é calculado pelo banco de dados, não pelo Django.
(Por conveniencia, cada modelo possui um AutoField
chamado id
, por
padrão, a menos que você explicitamente especifique primary_key=True
em um
campo. Veja a documentação para AutoField
para saber mais detalhes.
A propriedade pk
¶
-
Model.
pk
¶
Independentemente de saber se você vai definir uma chave primária, ou deixar o
Django fazer isso por você, cada modelo irá ter uma propriedade chamada pk
.
Ela se comporta como um atributo normal dentro do model, mas na verdade é um
alias para qualquer atributo que seja a chave primária de seu model. Você pode
acessar ou setar esse valor, como em qualquer outro atributo, e ele irá
atualizar o campo correto do model.
Especificando explicitamente valores para auto-primary-key¶
Se um modelo tem um AutoField
mas você quer definir um novo ID de objeto
explicitamente quando salva, então defina-o explicitamente antes de salvar,
em vez de confiar na auto-atribuição do ID:
>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b3.id # Retorna 3.
>>> b3.save()
>>> b3.id # Retorna 3.
Se você atribui manualmente, valores para auto-primary-key, esteja certo de não usar um valor de primary-key já existente! Se você criar um novo objeto com um valor de chave primária explicito já existente no banco de dados, o Django irá assumir que você está alternado um dado existente ao invés de criar um novo.
Como mostrado no exemplo acima, blog 'Cheddar Talk'
, neste exemplo o dado
será atualizado no banco de dados:
b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save() # Sobrescreve o blog já existente com ID=3!
Veja Como o Django sabe quando fazer UPDATE vs. INSERT, abaixo, para entender por que isso acontece.
Especificar explicitamente os valores de auto-primary-key é mais usual para salvar objetos em massa, quando você está certo de que não há colisões de chaves primárias.
O que acontece quando você salva?¶
Quando você salva um objeto, o Django executa os seguintes passos:
Emite um sinal pre-save. O sinal
django.db.models.signals.pre_save
é enviado, permitindo qualquer função ouvir o sinal para executar alguma ação personalizada.Pre-processa os dados. Cada campo no objeto é consultado para realização de qualquer modificação dos dados que o campo possa precisar.
A maioria dos campos não fazem pre-processamento – o dado do campo é mantido como está. O pre-processamento é utilizado somente em campos que possuem um comportamento especial. Por exemplo, se seu modelo tem uma
DateField
com umauto_now=True
, o pre-save irá alterar o dado deste campo, assegurando que o campo comtém a data corrente. (Nossa documentação ainda não inclui a lista de todos os campos com este “comportamento especial.”)Prepara os dados para o banco de dados. Cada campo é consultado para prover seu valor corrente em um formato que pode ser escrito no banco de dados. Most fields require no data preparation. Simple data types, such as integers and strings, are ‘ready to write’ as a Python object. However, more complex data types often require some modification.
Por exemplo,
DataFields
usam um objetodatetime
do Python para armazenar o dado. O banco de dados não sabe armazenar objetosdatetime
, então o valor do campo deve ser convertido em uma string compilada no formato de data ISO, para inserção no banco de dados.Insere o dado no banco de dados. O dado pre-processado, preparado, é então composto em um chamada SQL para inserção no banco de dados.
Emite um sinal post-save. O sinal
django.db.models.post_save
é enviado, permitindo qualquer função ouvir o sinal para executar alguma ação personalizada.
Como o Django sabe quando fazer UPDATE vs. INSERT¶
Você pode ter notado que os objetos de banco de dados do Django, utilizam o
mesmo método save()
para criar e atualizar objetos. O Django abstrai a
necessidade de uso do INSERT
ou UPDATE
. Especificamente, quando você
executa save()
, o Django segue este algorítmo:
- Se o atributo chave primária do objeto está setado de forma a ser
considerado
verdadeiro
(ex. um valor que não sejaNone
ou uma string vazia), o Django executa umSELECT
pra averiguar se existe algum dado com esta chave primária. - Se o dado com a chave primária não existe, o Django já existe, o Django
executa uma consulta
UPDATE
. - Se o atributo chave primária do objeto não está setado, ou se está, mas
ela não existe no banco de dados, então o Django executa uma consulta
INSERT
.
O ponto aqui é que você deve ter cuidado para não especificar um valor de chave primária explicitamente ao salvar novos objetos, se você não tem como garantir que o valor não foi utilizado. Para mais sobre esta nuancia, veja Especificando explicitamente valores para auto-primary-key acima e Forçando um INSERT ou UPDATE abaixo.
Forçando um INSERT ou UPDATE¶
Em algumas raras circumstancias, é necessário forçar o método save()
a
executar um SQL INSERT
e não retroceder para fazer um UPDATE
. Ou
vice-versa: atualizar, se possível, mas não inserir uma nova linha. Nestes casos
você pode passar os parametros force_insert=True
ou force_update=True
para o método save()
. Utilizar ambos os parametros é um erro, tendo em vista
que você não irá utilizar ambos, INSERT
e UPDATE
ao mesmo tempo.
Deve ser muito raro você precisar usar estes parâmetros. O Django irá quase sempre fazer a coisa certa e tentar contornar isso irá conduzí-los a erros difíceis de rastrear. Esta funcionalidade é somente para usuários avandaçados.
Deletando objetos¶
-
Model.
delete
()¶ Emite um SQL
DELETE
para um objeto. Este somente deleta o objeto no banco de dados; a instância do Python persistirá, e conterá dados em seus campos.
Outros métodos da instância de um model¶
Alguns métodos de objetos têm propostas especiais.
__str__
¶
-
Model.
__str__
()¶
__str__()
é um “método mágico” do Python que define o que deve ser retornado
se você chamar str()
sobre o objeto. O Django usa str(obj)
(ou a função
relacionada, unicode(obj)
– veja abaixo) em vários lugares, mais
notavelmente como um valor mostrado para renderizar um objeto no site de
administração do Django e como valores inseridos em um template quando é
mostrado um objeto. Por isso, que você deve sempre retornar uma string, legível
para humanos, dos métodos __str__
. Embora ele não seja obrigatório, é
fortemente encorajado (veja a descrição de __unicode__
, abaixo, antes de por
métodos __str__
pra todo lado).
Por examplo:
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def __str__(self):
# Note o uso do django.utils.encoding.smart_str() aqui, por que
# first_name e last_name serão strings unicode.
return smart_str('%s %s' % (self.first_name, self.last_name))
__unicode__
¶
-
Model.
__unicode__
()¶
O método __unicode__()
é chamado quando você executa unicode()
sobre um
objeto. Visto que os backends de banco de dados do Django retornarão strings
Unicode para os atributos de seu model, você naturalmente irá querer escrever um
método __unicode__()
para seu model. O exemplo da seção anterior poderia ser
escrito de maneira mais simples, como:
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
Se você define um método __unicode__()
em seu modelo e não um método
__str__()
, o Django irá automaticamente prover um método __str__()
que
chama o método __unicode__()
e então converte o resultado corretamente para
strings codificadas em UTF-8. Isto é uma prática de desenvolvimento recomendada:
definir somente __unicode__()
e deixar o Django se preocupar com a conversão
das strings quando necessário.
get_absolute_url
¶
-
Model.
get_absolute_url
()¶
Definir um método get_absolute_url()
pra dizer ao Django como calcular a URL
para um objeto. Por exemplo:
def get_absolute_url(self):
return "/people/%i/" % self.id
O Django usa isto em sua interface de administração. Se um objeto define
get_absolute_url()
, a página de edição do objeto terá um link “Veja no site”
que aponta diretamente para a visão pública do objeto, de acordo com o
get_absolute_url()
.
Também, em outros lugares a mais, como no framework de feeds, o uso do get_absolute_url()
como uma
conveniencia para recompensar quem tenha definido o método.
É uma boa prática usar o get_absolute_url()
em templates, ao invés de
escrever a mão as URLs de seus objetos. Por exemplo, este código de template não
é legal:
<a href="/people/{{ object.id }}/">{{ object.name }}</a>
Mas esse código é bem melhor:
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
Note
A string que você retorna do get_absolute_url()
deve conter somente
caracteres ASCII (exigidos pela especificação URI, RFC 2396) que tenham
sido codificados para URL, se necessário. Um template escrito usando
get_absolute_url()
deve ser capaz de utilizar o resultado diretamente
sem a necessidade de qualquer outro tratamento. Você pode desejar usar a
função django.utils.encoding.iri_to_uri()
para ajudá-lo, se você estiver
usando muitas strings unicode.
O decorador permalink
¶
O problema com a solução que descrevemos acima, utilizando o
get_absolute_url()
, é que ela viola ligeiramente os principios DRY: a URL
para este objeto é definida em ambos arquivo URLconf e no modelo.
Você ainda pode dissociar seus modelos do URLconf utilizando o decorador
permalink
:
-
permalink
()¶
Este decorador é passado para a função view, uma lista de parametros posicionais e (opcionalmente) um dicionário de parametros nomeados. o Django então constroi o caminho completo da URL, usando o URLConf, substituindo os parametros que você forneceu dentro da URL. Por exemplo, se seu URLConf contém uma linha como esta:
(r'^people/(\d+)/$', 'people.views.details'),
...seu model pode ter um método get_absolute_url
que parece com isto:
from django.db import models
@models.permalink
def get_absolute_url(self):
return ('people.views.details', [str(self.id)])
Similarmente, se você tem uma entrada no URLConf que pareça isto:
(r'/archive/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', archive_view)
...você poderia referenciá-la usando o permalink()
como a seguir:
@models.permalink
def get_absolute_url(self):
return ('archive_view', (), {
'year': self.created.year,
'month': self.created.month,
'day': self.created.day})
Observe que nós especificamos uma sequencia vazia para o segundo parametro neste caso, porque nós somente queremos passar parametros nomeados, ao invés de posicionais.
Desta forma, você está amarrando a URL absoluta do model com a view que é usada
para mostrá-lo, sem repetir as informações de URL. Você ainda pode usar o método
get_absolute_url
nos templates, como antes.
Em alguns casos, como no caso de uso de generic views, ou no re-uso de views customizadas para múltiplos modelos, especificar a função de view pode confundir o reverse URL matcher (pois múltiplos padrões podem apontar para uma mesma view.)
Para este problema, o Django utiliza padrões de URL nomeados. Usando padrões
de URL nomeados, é possível ter um nome para um padrão, e então referenciar este
nome ao invés da função view. Um padrão de URL nomeado é definida através da
substituição da tupla padrão por uma chamada da função url
):
from django.conf.urls.defaults import *
url(r'^people/(\d+)/$',
'django.views.generic.list_detail.object_detail',
name='people_view'),
...e então usando este nome para fazer a reversão URL ao invés do nome da view:
from django.db.models import permalink
def get_absolute_url(self):
return ('people_view', [str(self.id)])
get_absolute_url = permalink(get_absolute_url)
Mais detalhes sobre padrões de URL nomeadas estão em documentação do URL dispatch.
Métodos extra de instancia¶
Além de save()
, delete()
, um objeto de modelo pode ter qualquer, ou
todos os seguintes métodos:
-
Model.
get_FOO_display
()¶
Para todo campo que possui choices
, o objeto terá um método
get_FOO_display()
, onde FOO
é o nome do campo. Este método retorna o
valor “legível para humanos” do campo. Por exemplo, no seguinte model:
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)
class Person(models.Model):
name = models.CharField(max_length=20)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
...cada instancia de Person
terá um método get_gender_display()
. Exemplo:
>>> p = Person(name='John', gender='M')
>>> p.save()
>>> p.gender
'M'
>>> p.get_gender_display()
'Male'
-
Model.
get_next_by_FOO
(**kwargs)¶
-
Model.
get_previous_by_FOO
(**kwargs)¶
Para todo DateField
e DateTimeField
que não possui null=True
, o
objeto terá os métodos get_next_by_FOO()
e get_previous_by_FOO()
para o
mesmo campo. Este retorna o próximo objeto ou o anterior correspondente ao campo
de data, lançando a exceção apropriada DoesNotExist
se for o caso.
Ambos os métodos aceitam argumentos nomeados opicionalmente, que deve ser no formato descrito em Field lookups.
Note que no caso de valores de datas idénticos, estes métodos irão usar o ID como solução de checagem. Isto garante que nenhum dado será pulado ou duplicado.