Esse documento descreve os detalhes da API Model. Isso foi feito baseado no material apresentado nos guias model e consultas ao banco de dados, 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.
Para criar uma nova instância de um model, somente instancie-o assim como qualquer outra classe Python:
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().
There are three steps involved in validating a model:
All three steps are performed when you call by a model’s full_clean() method.
When you use a ModelForm, the call to is_valid() will perform these validation steps for all the fields that are included on the form. (See the ModelForm documentation for more information.) You should only need to call a model’s full_clean() method if you plan to handle validation errors yourself, or if you have excluded fields from the ModelForm that require validation.
This method calls Model.clean_fields(), Model.clean(), and Model.validate_unique(), in that order and raises a ValidationError that has a message_dict attribute containing errors from all three stages.
The optional exclude argument can be used to provide a list of field names that can be excluded from validation and cleaning. ModelForm uses this argument to exclude fields that aren’t present on your form from being validated since any errors raised could not be corrected by the user.
Note that full_clean() will not be called automatically when you call your model’s save() method, nor as a result of ModelForm validation. You’ll need to call it manually when you want to run model validation outside of a ModelForm.
Example:
try:
article.full_clean()
except ValidationError, e:
# Do something based on the errors contained in e.message_dict.
# Display them to a user, or handle them programatically.
The first step full_clean() performs is to clean each individual field.
This method will validate all fields on your model. The optional exclude argument lets you provide a list of field names to exclude from validation. It will raise a ValidationError if any fields fail validation.
The second step full_clean() performs is to call Model.clean(). This method should be overridden to perform custom validation on your model.
This method should be used to provide custom model validation, and to modify attributes on your model if desired. For instance, you could use it to automatically provide a value for a field, or to do validation that requires access to more than a single field:
def clean(self):
from django.core.exceptions import ValidationError
# Don't allow draft entries to have a pub_date.
if self.status == 'draft' and self.pub_date is not None:
raise ValidationError('Draft entries may not have a publication date.')
# Set the pub_date for published items if it hasn't been set already.
if self.status == 'published' and self.pub_date is None:
self.pub_date = datetime.datetime.now()
Any ValidationError raised by Model.clean() will be stored under a special key that is used for errors that are tied to the entire model instead of to a specific field. You can access these errors with NON_FIELD_ERRORS:
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
try:
article.full_clean()
except ValidationError, e:
non_field_errors = e.message_dict[NON_FIELD_ERRORS]
Finally, full_clean() will check any unique constraints on your model.
This method is similar to clean_fields, but validates all uniqueness constraints on your model instead of individual field values. The optional exclude argument allows you to provide a list of field names to exclude from validation. It will raise a ValidationError if any fields fail validation.
Note that if you provide an exclude argument to validate_unique, any unique_together constraint that contains one of the fields you provided will not be checked.
Para salvar um objeto no banco de dados, chame save():
If you want customized saving behavior, you can override this save() method. See Sobrescrevendo métodos de model predefinidos for more details.
The model save process also has some subtleties; see the sections below.
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.
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.
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 ou 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.
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 um auto_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 objeto datetime do Python para armazenar o dado. O banco de dados não sabe armazenar objetos datetime, 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.
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:
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.
Em algumas raras circunstâncias, é 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.
Sometimes you'll need to perform a simple arithmetic task on a field, such as incrementing or decrementing the current value. The obvious way to achieve this is to do something like:
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold += 1
>>> product.save()
If the old number_sold value retrieved from the database was 10, then the value of 11 will be written back to the database.
This can be optimized slightly by expressing the update relative to the original field value, rather than as an explicit assignment of a new value. Django provides F() expressions as a way of performing this kind of relative update. Using F() expressions, the previous example would be expressed as:
>>> from django.db.models import F
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold = F('number_sold') + 1
>>> product.save()
This approach doesn't use the initial value from the database. Instead, it makes the database do the update based on whatever value is current at the time that the save() is executed.
Once the object has been saved, you must reload the object in order to access the actual value that was applied to the updated field:
>>> product = Products.objects.get(pk=product.pk)
>>> print product.number_sold
42
For more details, see the documentation on F() expressions and their use in update queries.
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.
For more details, including how to delete objects in bulk, see Deletando objetos.
If you want customized deletion behavior, you can override this delete() method. See Sobrescrevendo métodos de model predefinidos for more details.
Alguns métodos de objetos têm propostas especiais.
__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))
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.
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 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:
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.
Além de save(), delete(), um objeto de modelo pode ter qualquer, ou todos os seguintes métodos:
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 instância 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'
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.
Dec 26, 2011