Models - Django

 

Recomendação de boas práticas




Lista de opções


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

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)


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.

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)

Referência para campos do Model



Relacionamentos


Relacionamentos muitos-para-um

Para definir um relacionamento muitos para um, use ForeignKey.

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

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

class Carro(models.Model):
fabrica= models.ForeignKey(Fabrica)
# ...


Relacionamentos muitos-para-muitos

Para definir um relacionamento muitos-para-muitos, use o ManyToManyField


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)


OBS - Não importa qual model recebe o ManyToManyField, mas você somente precisa dele em um dos models – não em ambos.
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)



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>]


Atenção

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.



Relacionamentos um-para-um


Para definir um relacionamento um-para-um, use o OneToOneField

In this example, a Place optionally can be a Restaurant:

from django.db import models

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


class Restaurant(models.Model):
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
primary_key=True,
)
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)

class Waiter(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
name = models.CharField(max_length=50)


Opções Meta

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

class Animal(models.Model):
especie = models.CharFieldField()

class Meta:
ordering = ["especie"]
verbose_name_plural = "animais"



SQL Puro


Se sua consulta é puramente uma operção de leitura de dados, nenhum commit é requerido. Por exemplo:

def my_custom_sql(self):
from django.db import connection, transaction
cursor = connection.cursor()

# Operação de modificação de dado - commit obrigatório
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
transaction.commit_unless_managed()

# Operação de recebimento de dado - não é necessário o commit
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
row = cursor.fetchone()

return row


Fazendo consultas

Uma vez que você tenha criado seus data models, o Django automaticamente lhe dá uma API de abstração de banco de dados que permite você criar, receber, atualizar e deletar objetos.


Criando objetos

Para representar dados de uma tabela de banco de dados em objetos Python, o Django usa um sistema intuitivo: Uma classe model representa uma tabela de banco de dados, e uma instância dessa classe representa um dado em particular dentro da tabela.


Assumimos que os models estão em mysite/blog/models.py, aqui tem um exemplo:

>>> from mysite.blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()

Salvando mudanças de objetos

Para salvar mudanças de um objeto que já existe no banco de dados, use save().
Dado uma instância b5 do Blog que já está salvo no banco de dados, este exemplo muda seu nome e o atualiza no banco de dados:

>> b5.name = 'New name'
>> b5.save()

Salvando campos ForeignKey e ManyToManyField

Atualizar um campo ForeignKey funciona exatamente da mesma forma como salvar um campo normal; simplesmente atribuindo um objeto do tipo certo ao campo em questão:

>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()

Atualizar um ManyToManyField funciona um pouco diferente; usa o método add() sobre o campo para adicionar um dado a relação:

>> joe = Author.objects.create(name="Joe")
>> entry.authors.add(joe)


Recebendo todos os objetos

A forma mais simples de receber objetos da tabela é obtendo todos eles. Para fazer isso, use o método all() de um Manager:

>>> all_entries = Entry.objects.all()

O método all() retorna um QuerySet` de todos os objetos do banco de dados.

Recebendo objetos específicos com filtros

O QuerySet raiz fornecido pelo Manager descreve todos os objetos na tabela de banco de dados. Geralmente, contudo, você precisará selecionar somente um conjunto de objetos.


Por exemplo, para obter um QuerySet de entradas de blog do ano 2006, use o filter() desta forma:

Entry.objects.filter(pub_date__year=2006)

Filtros encadeados

O resultado de refinar uma QuerySet é, em si, um QuerySet, então é possível encadear refinamentos juntos. Por exemplo:

>>> Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.now()
... ).filter(
... pub_date__gte=datetime(2005, 1, 1)
... )

QuerySets são lazy

Os QuerySets are lazy – o ato de criar um QuerySet não envolve qualquer atividade de banco de dados. Você pode empilhar filtros juntos ao longo do dia, e o Django não os executa no banco de dados até que o QuerySet seja avaliado. Dê uma olhada nesse exemplo:

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.now())
>>> q = q.exclude(body_text__icontains="food")
>>> print q

Embora isso pareça como três hits no banco de dados, de fato o banco de dados foi consultado somente na última linha (print q).


Outros métodos do QuerySet

Na maior parte do tempo você usará all(), filter() e exclude() quando você precisar pesquisar por objetos no banco de dados. Entretanto, isso não é tudo que há; veja a Referência de API do QuerySet para uma lista completa de todos os vários métodos do QuerySet.

Limitando QuerySets

Use a sintaxe de array-slicing do Python para limitar seu QuerySet com um certo número de resultados. Este é o equivalente as clausulas SQL LIMIT e OFFSET.

Por exemplo, isso retorna os primeiros 5 objetos (LIMIT 5):

>>> Entry.objects.all()[:5]

Isso retorna do sexto ao décimo objeto (OFFSET 5 LIMIT 5):

>>> Entry.objects.all()[5:10]


Para receber um único objeto ao invés de uma lista (e.g. SELECT foo  FROM bar  LIMIT 1), use um index simples ao invés de um slice. Por exemplo, isso retorna a primeira Entry do banco de dados, depois de ordenar as entradas alfabéticamente pelos cabeçalhos:

>>> Entry.objects.order_by('headline')[0]


Campos de pesquisa

Campos de pesquisa são como você especifica o cerne de uma clausula WHERE. Eles são especificado como argumento nomeados para o método filter() do QuerySet.

Os argumentos básicos de pesquisa tem a forma campo__tipodepesquisa=valor. (Isso é um underscore duplo). Por exemplo:

>>> Entry.objects.filter(pub_date__lte='2006-01-01')

é traduzido para o seguinte SQL:

SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

Pesquisas que abrangem relacionamentos

O Django oferece um poderoso e intuitovo meio de “seguir” relacionamentos numa pesquisa, preocupando-se com os JOINs SQL por vocês automaticamente, por trás das cenas. Para abranger um relacionamento, é só usar o nome dos campos relacionados atráves dos models, separados por dois underscores, até que você obtenha os campos que você deseja.

Este exemplo recebe todos os objetos Entry com um Blog cujo name seja 'Beatles Blog':

>>> Entry.objects.filter(blog__name__exact='Beatles Blog')


Atalho para pk

Por conveniência, o Django fornece um atalho para pesquisas com pk, que significa “chave primária”.

No exemplo Blog model, a chave primária é o campo id, então estas três regras são equivalente:

>>> Blog.objects.get(id__exact=14) # Forma explicita
>>> Blog.objects.get(id=14) # __exact é implícito
>>> Blog.objects.get(pk=14) # pk implica em id__exact

O uso de pk não é limitado a consultas __exact – qualquer termo de consulta pode ser combinado com pk para executar uma consulta sobre a chave primária de um model:

# Pega as entradas dos blogs com id 1, 4 e 7
>>> Blog.objects.filter(pk__in=[1,4,7])

# Pega todas as entradas do blog com id > 14
>>> Blog.objects.filter(pk__gt=14)

Pesquisas com pk também podem funcionar através de joins. Por exemplo, estas três regras são equivalentes:

>>> Entry.objects.filter(blog__id__exact=3) # Froma explicita
>>> Entry.objects.filter(blog__id=3) # __exact é implícito
>>> Entry.objects.filter(blog__pk=3) # __pk implica em __id__exact

 

Comparando objetos

Para comparar duas instâncias de model, é só usar o operador de comparação padrão do Python, dois sinais de igual: ==. Por trás das cenas, o que é comparado é a chave primária dos dois models.

Usando o exemplo Entry acima, as duas declarações a seguir são equivalentes:

>>> some_entry == other_entry
>>> some_entry.id == other_entry.id

Se uma chave primária de um model não é chamada de id, não tem problema. As comparações sempre usaram a chave primária, seja lá como for chamada. Por exemplo, se uma chave primária de um model é chamada name, estas duas declarações são equivalentes:

>>> some_obj == other_obj
>>> some_obj.name == other_obj.name

Deletando objetos

O método delete, convenientemente é chamado delete(). Este método deleta imediatamente o objeto e não retorna valor. Exemplo:

e.delete()

Você pode também deletar objetos em grupos. Todo QuerySet tem um método delete(), que deleat todos os seus membros.

Por exemplo, isso deleta todos os objetos Entry com um pub_date do ano 2005:

Entry.objects.filter(pub_date__year=2005).delete()



from django.db.models import Q
criterion1 = Q(question__contains="software")
criterion2 = Q(question__contains="java")
q = Question.objects.filter(criterion1 & criterion2)


Chaves compostas


The unique_together clause is directly translated to the SQL unique index. And you can only set those on columns of a single table, not a combination of several tables.

Sets of field names that, taken together, must be unique:

unique_together = [['driver', 'restaurant']]

class MyModel(models.Model):
field1 = models.CharField(max_length=50)
field2 = models.CharField(max_length=50)
class Meta:
unique_together = ('field1', 'field2',)


Custom User Django




Boas práticas





Como posso ver as consultas SQL que o Django está executando?


Assegure-se que sua configuração do Django DEBUG está configurada para True. Então faça isso:

>>> from django.db import connection
>>> connection.queries
[{'sql': 'SELECT polls_polls.id, polls_polls.question, polls_polls.pub_date FROM polls_polls',
'time': '0.002'}]


“connection.queries” só está disponível se nas configurações a variável DEBUG for True. É uma lista de dicionários em ordem de execução da querie. Cada dicionário possui o seguinte:

``sql`` -- The raw SQL statement
``time`` -- How long the statement took to execute, in seconds.


connection.queries incluem todas as instruções SQL - INSERTs, UPDATEs, SELECTs etc. Cada vez que seu aplicativo atinge o banco de dados a consulta será gravada.





Ver mais





Referência

Comentários

Postagens mais visitadas deste blog

Weasyprint

Django Mask with JQuery Mask Plugin