3. O que é django
✤ Um framework web desenvolvido com a
liguagem python;
✤ Adota o padrão MVC (Model-View-Controller);
✤ Ênfase em reusabilidade e plugabilidade;
✤ Desenvolvimento ágil;
✤ Baseado no conceito DRY (Don't Repeat
Yourself);
✤ Mapeamento objeto-relacional ORM;
✤ Código aberto (open source). 3
5. O django-admin.py
✤ O django-admin.py deverá estar no “path” do
sistema se você instalou o django via python setup.py.
✤ Se ele não estiver no path, você poderá encontrá-lo
em site-packages/django/bin, onde site-packages é um
diretório dentro da sua instalação do python.
✤ Considere a possibilidade de criar um link simbólico
para o django-admin.py em algum lugar em seu path,
como em /usr/local/bin.
5
6. Criando o projeto
✤ Executando o comando a baixo, será criada a
seguinte estrutura de arquivos do projeto:
python django-admin.py startproject meusite
__Init__.py : Arquivo de configuração para o python
reconhecer a pasta do projeto como um pacote.
manage.py : Script para execução de tarefas
administrativas do projeto.
settings.py : Configurações do projeto.
urls.py : Configuração das URLs do projeto. 6
7. Será que funciona?
✤ Vamos verificar se o projeto funciona. Vá para o
diretório meusite, se você ainda não estiver nele, e rode o
comando “python manage.py runserver 8000”. Você verá a
seguinte saída na sua linha de comando:
Validating models...
0 errors found
Django version 1.3 pre-alpha SVN-13679, using settings 'meusite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
7
8. Testando no navegador
✤ Com o servidor rodando, visite http://127.0.0.1:8000/
com seu navegador Web. Você irá ver a página "Welcome
to Django", em agradáveis tons de azul claro pastel. Ele
funcionou!
8
9. Anote e lembre-se
✤ Uma boa hora para ANOTAR:
✤ NÃO utilize este servidor em nada relacionado a
um ambiente de produção. Este servidor tem como
objetivo ser utilizado apenas durante o desen-
volvimento.
✤ Django é um framework, não um servidor web!
9
10. Banco de dados
✤ Vamos utilizar o banco de dados SQLite para este
projeto. Caso o SQLite não esteja instalado, “sudo apt-get
install sqlite3”. No arquivo settings.py do projeto vamos
fazer as configurações necessárias:
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'meusite.db'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
✤ Aṕos salvar o arquivo execute “python manage.py syncdb”.
LEMBRE-SE de anotar o usuário e a senha do super usuário. 10
11. PySQLite
✤ Dica: Caso o python não possua o módulo do SQLite
instalado “No module named _sqlite3”, você deverá
instalar o pacote “sudo apt-get install python-sqlite” ou
baixar PySQLite do site:
http://code.google.com/p/pysqlite/
✤ Se você fizer download módulo e estiver utilizando
um ambiente Linux, será necessário instalar a lib
“sudo apt-get install libsqlite3-dev” para compilar o
módulo.
11
12. Testando a base de dados
✤ Após configurar a base de dados, podemos
verificar se a estrutura de tabelas está OK.
.../meusite$ sqlite3 meusite.db
SQLite version 3.7.2
Enter ".help" for instructions
sqlite> .schema
✤ Você deverá ver diversas instruções “CREATE
TABLE” referente as tabelas administrativas
necessárias pelo framework.
12
13. Criando uma aplicação
✤ Dentro da pasta meusite criada anteriormente,
execute o comando a seguir. Será criada a seguinte
estrutura de arquivos:
python django-admin.py startapp musicos
__Init__.py : Arquivo de configuração para o python
reconhecer a pasta da aplicação como um pacote.
models.py : Arquivo onde serão definidos os modelos.
views.py : Arquivo que irá conter as views da aplicação.
13
14. Adicionando a aplicação
✤ Vamos editar o settings.py novamente, alterar
a linguagem para “pt-br” e adicionar a
aplicação “musicos“ as apps instaladas.
LANGUAGE_CODE = 'pt-br'
....
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
14
'musicos' )
16. Models
✤ Camada de abstração do banco de dados;
✤ São classes que herdam de django.db.models.
Model;
✤ Definem as entidades do sistema;
✤ Cada atributo de classe do modelo representa
uma coluna do banco de dados.
✤ Já possui diversos tipos de colunas no banco
de dados (ex: INTEGER, VARCHAR).
16
17. Models
from django.db import models
class Artista(models.Model):
nome = models.CharField(max_length=50, null=False)
sobrenome = models.CharField(max_length=50)
data_nascimento = models.DateField(null=False,
db_column='data_de_nascimento')
class Album(models.Model):
artista = models.ForeignKey(Artista)
descricao = models.CharField(max_length=100)
data_lancamento = models.DateField()
valor_venda = models.DecimalField(max_digits=5,
decimal_places=2, null=False)
http://docs.djangobrasil.org/ref/models/fields.html#common-model-field-options 17
http://docs.djangobrasil.org/howto/custom-model-fields.html#howto-custom-model-fields
18. Models
✤ Cada tipo de campo recebe um certo conjunto de
argumentos específicos. 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.
✤ Há um conjunto de argumentos comuns disponí-
veis para todos os tipos de campos. Todos são
opcionais e são totalmente explicados na referência:
http://docs.djangobrasil.org/ref/models/fields.html#common-model-field-options 18
19. Models
✤ 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.
class Meta:
db_table='artista'
19
http://docs.djangobrasil.org/ref/models/options.html#ref-models-options
20. Models
✤ Aṕos editar o arquivo models.py execute novamen-
te “python manage.py syncdb”.
Creating tables ...
Creating table artista
Creating table album
Installing custom SQL ...
Installing indexes ...
No fixtures found.
✤ Note que neste momento as tabelas artista e album
foram criadas. Agora vamos começar a manipular
dados utilizando os modelos criados. 20
21. Models
✤ Para utilizarmos o django ADMIN, vamos editar o
arquivo urls.py que está na pasta do projeto e
remover o comentário das linhas a seguir:
# Remova o comentário das duas próximas linhas para ativar o admin:
# from django.contrib import admin
# admin.autodiscover()
# Uncomment the next line to enable the admin:
# (r'^admin/', include(admin.site.urls)),
✤ Localize estas linhas em seu arquivo urls.py e remova o
comentário das linhas que possuem o # vermelho. 21
22. Models
✤ Também editar o arquivo settings.py que está na
pasta do projeto e remover o comentário da linha a
seguir:
INSTALLED_APPS = (
...
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
…)
#Lembre-se de fazer a sincronização após adicionar uma nova app:
>>> python manage.py syncdb
✤ Localize a propriedade INSTALLED_APPS e remova o
22
comentário da linha que possuem o # vermelho.
23. Models
✤ Para conectar o modelo a interface administrativa,
vamos criar o arquivo admin.py dentro da aplicação
musicos para registrar os modelos que devem ser
manipulados via ADMIN:
from django.contrib import admin
from models import Artista, Album
admin.site.register(Artista)
admin.site.register(Album)
✤ No arquivo admin.py são registrados os modelos que
23
podem ser manipulados pelo ADMIN.
24. Models
✤ Para concluirmos a configuração básica do ADMIN,
vamos editar novamente o arquivo models.py da
aplicação musicos e adicionar uma descrição para
cada classe do modelo:
class Artista(models.Model):
….
def __unicode__(self):
return "%s %s" % (self.nome,self.sobrenome)
class Album(models.Model):
….
def __unicode__(self):
return self.descricao 24
25. Models
✤ Concluídas as alterações básicas necessárias, vamos
testar o ADMIN. Aqui será necessário o usuário e a
senha do superusuário definidas no syncbd.
✤ Acesse com seu navegador http://127.0.0.1:8000/admin/
25
26. Models
✤ Agora utilizaremos o comando “python manage.py
shell“. O manage.py configura o ambiente do projeto
para você. Vamos começar a trabalhar com models:
# Import das classes do model que acabamos de criar. Vamos incluir
>>> from musicos.models import Artista, Album diversos artistas
para melhor ilustrar
os exemplos
# Não há nenhum registro nas tabelas ainda. a seguir.
>>> Artista.objects.all()
# Adicionando o primeiro Artista.
>>> from datetime import datetime
>>> a = Artista(nome='Leandro', sobrenome='zanuz',
data_nascimento=datetime(1980,5,20))
>>> a.save() 26
27. Models
# Note que após salvar o objeto “a” ele passa a possuir um identificador (id).
>>> a.id
# Acessando atributos do objeto.
>>> a.nome
>>> a.sobrenome
# Alterando dados do objeto Artista.
>>> a.sobrenome = 'Zanuz'
>>> a.save()
# Selecionando um objeto Artista específico.
>>> Artista.objects.get(id=1) ou (pk=1)
# Listando todos os objetos Artista cadastrados.
>>> Artista.objects.all()
27
28. Models
✤ Para selecionar registros do banco de dados, você
deverá construir uma QuerySet utilizando as classes do
models.
✤ Uma QuerySet representa uma coleção de objetos de
seu banco de dados. Ela pode conter zero, um ou muitos
filtros (critérios que restringem a coleção baseado em
argumentos fornecidos).
✤ Equivalente ao SQL, a QuerySet representa uma
expressão SELECT, e os filtros são cláusulas limitadoras
como o WHERE ou LIMIT. 28
29. Models
# Também podemos selecionando UM objeto pelo nome e/ou sobrenome.
>>> a = Artista.objects.get(nome='Leandro',sobrenome='Zanuz')
>>> a.id
>>> a = Artista.objects.get(data_nascimento__year = 1980)
>>> a.id
✤ Utilizando filtros em uma QuerySet:
filter(**kwargs)
Retorna uma nova QuerySet contendo somente os objetos que
satisfazem os argumentos especificados.
exclude(**kwargs)
Retorna uma nova QuerySet contento somente os objetos que não
29
satisfazem os argumentos especificados.
30. Models
✤ Para definir as cláusulas WHERE da QuerySet
utilizamos os chamados “field lookups“, que são
palavras chave específicas utilizadas nos métodos
filter(), exclude() e get().
✤ Como utilizar os lookups: field__lookuptype=value
(__ é um duplo underscore).
>>> Artista.objects.filter(data_nascimento__lte='1982-1-1')
SELECT * FROM artista WHERE data_nascimento <= '1982-1-1';
30
http://docs.djangoproject.com/en/dev/ref/models/querysets/#field-lookups
31. Models
# Note que utilizando filtros não ocorre erro ao retornar MAIS DE UM objeto.
>>> Artista.objects.filter(data_nascimento__year=1980)
# Filtrando objetos que o nome inicie com “Lean”.
>>> Artista.objects.filter(nome__startswith='Lean')
[<Artista: Artista object>, <Artista: Artista object>]
# Objetos que o nome inicie com “Lean” e o ano de nascimento seja inferior a 1982.
>>> Artista.objects.filter(nome__startswith='Lean',
data_nascimento__lt='1982-1-1')
# Objetos que o nome inicie com “Lean” e a data de nascimento seja superior ou igual a
# 20/06/1980.
>>> Artista.objects.filter(nome__startswith='Lean',
data_nascimento__gte='1980-6-20')
>>>Artista.objects.filter(nome__startswith='Lean').exclude(
31
data_nascimento__lt='1980-6-20')
32. Models
__exact (Uma comparação exata, case-sensitive)
>>> Artista.objects.get(nome__exact='Leandro')
Equivalente em SQL:
SELECT * FROM artista WHERE nome = 'Leandro';
✤ Quando não for informado um lookup, ou seja, o
argumento não possuir um duplo underscore, o tipo assumido
por padrão será o __exact.
>>> Artista.objects.get(id__exact=4) # explícito
>>> Artista.objects.get(id=4) # __exact está implícito 32
33. Models
__iexact (Uma comparação exata, case-insensitive)
>>> Artista.objects.get(nome__iexact='leAndRo')
Equivalente em SQL:
SELECT * FROM artista WHERE LOWER(nome) = LOWER('leAndRo');
__contains | __icontains (Contendo uma string)
>>> Artista.objects.get(nome__contains='eand')
Equivalente em SQL:
SELECT * FROM artista WHERE nome LIKE '%eand%'; 33
34. Models
__in (Sequência de elementos)
>>> Artista.objects.filter(id__in=(1,3,4))
Equivalente em SQL:
SELECT * FROM artista WHERE id IN (1, 3, 4);;
__startswith | __endswith (Inicie ou termine c/uma string)
>>> Artista.objects.filter(sobrenome__startswith='Zan')
Equivalente em SQL:
SELECT * FROM artista WHERE sobrenome LIKE 'Zan%'; 34
35. Models
✤ Podemos ver um histórico dos SQLs que foram
executado pelo models na base de dados:
# Para visualizar a útima query executada.
>>> from django.db import connection
>>> Artista.objects.create(nome='Leandro',sobrenome='Zanuz',
data_nascimento=datetime(1970,8,25))
>>> print connection.queries[-1]['sql']
# Cache das últimas querys executadas.
>>> print connection.queries
# Gerando uma lista com valores específicos de uma query.
>>> Artista.objects.values_list('nome','sobrenome').filter(pk=1)
35
✤ Não considere o LIMIT 21, é uma propriedade do método __repr__ da QuerySet.
36. Models
✤ Estes foram apenas alguns exemplos do uso
de lookups, para a referência completa acesse:
http://docs.djangoproject.com/en/dev/ref/models/querysets/#field-lookups
✤ Relacionamento de objetos (JOINS).
# Seleciona os Albuns em que o nome do seu Artista inicie com “Lean”.
>>> Album.objects.filter(artista__nome__startswith='Lean')
# Seleciona os Albuns que o nome do seu Artista inicie com “Lean” e o sobrenome
# do Artista não seja NULO e o valor de venda do Album seja maior ou igual a 30.
>>> Album.objects.filter(artista__nome__startswith='Lean',
artista__sobrenome__isnull=False,
valor_venda__gte=30) 36
37. Models
✤ Nos exemplos até agora, utilizamos os filtros para
comparar valores do model com valores constantes,
por exemplo (__gte=30).
✤ Mas como fazemos para comparar valores de um
campo do model com outro campo do mesmo model?
✤ O django prove o objeto F() que permite realizar
comparações entre campos.
# Selecionar os Albuns que a descrição seja igual ao nome do Artista.
>>> from django.db.models import F
37
>>> Album.objects.filter(descricao=F('artista__nome'))
38. Models
✤ Outros exemplos interessantes de QuerySets.
# Selecionando Artistas entre um intervalo de valores (BETWEEN).
>>> Artista.objects.filter(pk__gt=2,pk__lt=5)
# Seleciona os três primeiros objetos de uma QuerySet e após conta os objetos.
>>> Artista.objects.all()[:3].count()
# Seleciona até o décimo Artista, com passo dois (ou seja, de dois em dois).
>>> Artista.objects.all()[:10:2]
# Seleciona os Artistas que o nome contenha 'leandro' e ordene pelo
# sobrenome do Artista de forma decrescente.
>>> a = Artista.objects.filter(nome__icontains='leandro')
.order_by('sobrenome').reverse()
>>> print [(x.nome,x.sobrenome) for x in a] 38
39. Models
✤ QuerySet mais complexas, exemplo “AND e OR”.
# Exemplo utilizando cláusulas AND e OR.
>>> from django.db.models import Q
>>> Artista.objects.filter(Q(nome__istartswith='Lean'),
Q(sobrenome__startswith='Zan')|Q(sobrenome__startswith='Ped'))
✤ Equivalente em SQL:
SELECT * FROM artista WHERE nome LIKE 'Lean%'
AND (sobrenome LIKE 'Zan%' OR sobrenome LIKE 'Ped%')
39
40. Models
✤ Excluindo objetos com models.
# Excluíndo um objeto.
>>> a = Artista.objects.get(pk=1)
>>> a.delete()
# Excluíndo todos os objetos cujo nome começe com 'Lean'.
>>> Artista.objects.filter(nome__istartswith='Lean').delete()
# Excluíndo todos os Artistas.
>>> Artista.objects.all().delete()
✤ Quando o django exclui um objeto, ele executa “ON DELETE
CASCADE”, ou seja, excluirá também qualquer objeto que
possua chave estrangeira apontando para o objeto a ser
40
excluído.
41. Models
✤ Atualizando objetos com models.
# Atualizando um objeto.
>>> a = Artista.objects.filter(pk=2)
>>> a.update(sobrenome='Santos')
# Atualizando o sobrenome de todos os objetos cujo nome seja João ou Fabrício.
>>> a = Artista.objects.filter(Q(nome__exact='João')|Q(nome__exact='Fabrício'))
>>> a.update(sobrenome='Santos')
>>> for x in a:
>>> x.save()
✤ Quando existir múltiplos elementos na Queryset o método
update não executa nenhum método save. Para salvar as alterações
41
deve-se executar o método save para cada elemento da QuerySet.
42. Models
✤ A função extra() permite alterar uma QuerySet
quando for necessário gerar um SQL de grande
complexidade e a sintaxe do django por si só não
oferece condições para tal.
✤ extra() é um hook para injetar cláusulas específicas
em um SQL gerado por uma QuerySet.
✤ Estes lookups “extras” talvez não sejam portáveis
entre diferentes bancos de dados (porque você está
escrevendo SQL explícito) e violando os princípios DRY,
você deve “esquecê-la” sempre que possível. 42
43. Models
✤ Manipulando QuerySets utilizando a função extra():
#Exemplo de utilização do extra, todos os artistas menos alguns específicos.
>>> Artista.objects.all().extra(where=['id NOT IN (3, 4, 5, 20)'])
#Fazendo um sub-select que calcula a media do preço de venda do Album por Artista.
>>> sub_select="SELECT AVG(valor_venda) FROM album AS ab
WHERE ab.artista_id = album.artista_id"
>>> x = Album.objects.extra(select={'soma' : sub_select})
>>> x[0].soma
#Selecionando apenas os Artistas que já possuem Albuns cadastrados.
Artista.objects.extra(where=['EXISTS (SELECT 1 FROM album AS ab WHERE
ab.artista_id = artista.id)'])
43
44. Models
✤ Adicionando métodos próprios a objetos do models
para execução de tarefas específicas.
from django.core.urlresolvers import reverse
from datetime import datetime
class Artista(models.Model):
…
def get_absolute_url(self):
return reverse("visualizar_artista",args=[self.id])
def get_idade_artista(self):
return datetime.now().year - self.data_nascimento.year
44
45. Models
✤ Ainda temos os relacionamentos One-to-one,
Many-to-one e Many-to-many que não abordados
neste treinamento básico.
✤ Documentação e exemplos completos para
estes tipos de relacionamentos estão disponí-
veis nos endereços web abaixo:
http://www.djangoproject.com/documentation/models/one_to_one/
http://www.djangoproject.com/documentation/models/many_to_one/
http://www.djangoproject.com/documentation/models/many_to_many/ 45
47. URL dispatcher
✤ Utilizar URLs limpas e elegantes;
✤ Django permite que você defina as URLs da maneira
que quiser;
✤ Não são necessários .php, .cgi ou outras coisas sem o
menor sentido;
✤ URL (na forma de expressões regulares simples);
✤ Mapeamento das URLs pode ser tão extenso ou curto
quanto necessário.
47
48. URL dispatcher
✤ A seguir um exemplo de configuração das URLs.
from django.conf.urls.defaults import *
urlpatterns = patterns('musicos.views',
(r'^artistas/$', 'listar_artistas'),
url(r'^artista/(d+)/$', 'visualizar_artista',name="visualizar_artista"),
(r'^albuns/$', 'listar_albuns'),
(r'^album/(d+)/$', 'visualizar_album'),
(r'^artista/(d+)/albuns/$', 'listar_albuns_artista'),
)
✤ Vamos adicionar no arquivo urls.py dentro da aplicação
musicos contendo estas URLs. 48
49. URL dispatcher
✤ No urls.py do projeto teremos:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^', include('musicos.urls')),
)
✤ from django.conf.urls.defaults import * disponibiliza a
função patterns().
✤ Para capturarmos um valor da URL, simplesmente
colocamos parênteses em volta dele.
49
50. URL dispatcher
✤ Exemplos de requisição em django:
01 - http://127.0.0.1:8000/artistas/
02 - http://127.0.0.1:8000/artista/leandro/
03 - http://127.0.0.1:8000/artista/4/
✤ 01 - Corresponde ao primeiro elemento da lista de URLs, porque
os padrões são testados seguindo a ordem da lista. O django chama
a função listar_artistas(request).
✤ 02 - Não corresponde a nenhum padrão. O segundo elemento
da lista requer que para o artista seja informado somente dígitos.
✤ 03 - Corresponde ao segundo elemento da lista. O django chama
50
a função visualizar_artista(request, '4').
51. URL dispatcher
✤ Exemplo de URL com grupos nomeados:
urlpatterns = patterns('musicos.views',
(r'^artistas/(?P<codigo>d+)/$', 'visualizar_artista'),
)
✤ Utilizando desta forma, o django chamará a função
visualizar_artista(request, codigo='4'), ou seja, deverá passar os
parâmetros de forma nomeada e não mais posicional como
no exemplo anterior.
✤ Isso significa que a configuração das URLs está um pouco
mais explícita e menos propensa a bugs na ordem dos
argumentos. 51
52. URL dispatcher
✤ Como utilizar a função url():
Sintaxe: url(regex, view, kwargs=None, name=None, prefix='')
Prefixo da View
urlpatterns = patterns('musicos.views',
url(r'^artistas/(?P<codigo>d{4})/$', 'visualizar_artista',name='visualizar_artista'), )
{% url artista 4 %} → utilizando no template por exemplo
✤ Podemos utilizar a função url() no lugar de uma tupla, como um
argumento para patterns(). Isso é conveniente se você quer
especificar um nome a uma URL por exemplo.
✤ O parâmetro prefix tem o mesmo significado que o primeiro
argumento de patterns() e somente é relevante quando você está
52
passando uma string como um parâmetro para a view.
53. URL dispatcher
✤ Em qualquer ponto, seu urlpatterns pode "incluir" outros
módulos URLconf. Isso essencialmente "inclui" um conjunto
de URLs abaixo de outras:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^', include('musicos.urls')),
)
✤ Note que a expressão regular neste exemplo não possui um
$ (caractere que corresponde ao final de string), mas inclui uma /
(barra) no final. Isso porque o django deverá incluir as URLs
contidas neste arquivo de configuração adicional. 53
54. URL dispatcher
✤ O django também possui métodos utilitários
como o reverse() e o resolve() que facilitam o
manuseio das URLs. Veremos na seção views a
seguir um exemplo de suas utilizações.
✤ Referências e maiores informações sobre a
configuração das URLs em django podem ser
encontradas no endereço web abaixo:
http://docs.djangobrasil.org/topics/http/urls.html
54
56. Views
✤ Uma função view, ou somente view, é simples-
mente uma função python que recebe uma
requisição e retorna uma resposta web.
✤ Esta resposta pode ser um conteúdo HTML de
uma página, ou um redirecionamento, ou um
erro 404, ou um documento XML, uma imagem
ou qualquer outro conteúdo, como um arquivo
PDF por exemplo.
56
57. Views
✤ Veja um exemplo simples de view.
from django.http import HttpResponse
import datetime
def listar_artistas(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
✤ Vamos adicionar em nosso arquivo views.py dentro da
aplicação musicos esta função. Ela já possui uma URL
mapeada em particular, configurada no capítulo do URL
dispatcher. 57
58. Views
✤ Sub-classes do HttpResponse:
from django.http import HttpResponse, HttpResponseNotFound
Exemplo de
def funcao(request, codigo): utilização de uma
das sub-classe do
... HttpResponse
if not artista:
return HttpResponseNotFound('Artista não encontrado!')
else:
return HttpResponse(“%s %s”%(a.nome,a.sobrenome))
✤ Retornar códigos de erro HTTP no django é muito fácil. Existem
subclasses do HttpResponse para um número de códigos de status
comuns do HTTP além do 200 (que significa "OK"). Lista completa
de subclasses disponíveis na documentação: 58
http://docs.djangobrasil.org/ref/request-response.html#ref-httpresponse-subclasses
59. Views
✤ Instanciando, manipulando e tratando exceções
de objetos do models através da view.
from django.http import HttpResponse, HttpResponseNotFound
from musicos.models import *
def visualizar_artista(request,codigo):
try:
artista = Artista.objects.get(pk=codigo)
except Artista.DoesNotExist:
return HttpResponseNotFound('Artista %s inexistente!'%(codigo))
return HttpResponse('%s %s' % (artista.nome,artista.sobrenome))
✤ http://127.0.0.1:8000/artista/2/ retorna o nome do Artista (2). 59
61. Templates
✤ A linguagem de template do django foi desig-
nada para estabelecer um equilíbrio entre
facilidade e flexibilidade.
✤ Um template contém variáveis e tags, quando
o template é avaliado essas variáveis são
substituídas por valores.
✤ A seguir um modelo simples que ilustra um
template: 61
62. Templates
<html>
<head><title></title></head>
<body>
{% block conteudo %} Exemplo
“listar_artistas.html”
<h1>{{ titulo }}</h1> deverá estar na
{% for a in artistas %} pasta “templates”
dentro da aplicação
<div> “musicos”
<a href="{{ a.get_absolute_url }}">
{{ a.nome|upper }} : {{ a.get_idade_artista }}
</a>
</div>
{% endfor %}
{% endblock %}
</body>
62
</html>
63. Templates
✤ Alterando a view listar_artistas para retornar o
novo template “listar_artistas.html” definido no
exemplo do anterior.
from django.shortcuts import render_to_response
from musicos.models import Artista
def listar_artistas(request):
dc = dict(titulo="Lista de Artistas",
artistas=Artista.objects.all())
return render_to_response('listar_artistas.html',dc)
✤ Esta view já está disponível em nosso arquivo views.py
63
dentro da aplicação musicos.
64. Templates
✤ Para acessar o valor de uma variável em templates
utilizamos seu nome entre chaves: {{ variavel }}.
Quando um template encontra esta tag ele a avalia e a
substitui pelo valor da variável.
✤ Utiliza-se um ponto (.) para acessar atributos. No
exemplo, {{ artista.nome }} a tag será substituída pelo
atributo nome do objeto artista.
✤ Se for referenciada uma variável que não existe, o
template vai inserir o valor da configuração
TEMPLATE_STRING_IF_INVALID, que é '' (string vazia)
por padrão. 64
65. Templates
✤ Podemos modificar a apresentação dos valores de
variáveis utilizando filtros. A sintaxe dos filtros é
similar a: {{ nome|lower }}. Isso mostra o valor da
variável {{ nome }} após aplicado o filtro lower, que
converte o texto para minúsculas. Utiliza-se o pipe
(|) para aplicar filtros a variáveis.
✤ Filtros podem ser encadeados. A saída de um filtro
é aplicada ao próximo: {{ nome|escape|linebreaks }}.
65
66. Templates
✤ Alguns filtros possuem argumentos. A sintaxe de
um filtro que possui argumentos é similar a: {{ nome|
truncatewords:30 }}. Este filtro irá exibir somente as
primeiras 30 palavras da variável nome.
✤ Os argumentos de filtros que contem espaços
devem ser quoted (entre aspas) , por exemplo, para
inserir em uma lista espaços e virgulas use {{ lista|
join:", " }}.
http://docs.djangoproject.com/en/dev/ref/templates/builtins/ 66
67. Templates
✤ A sintaxe de Tags é: {% tag %}. Tags são mais
complexas do que variáveis: Algumas criam texto na
saída, outras aplicam loops ou lógica.
✤ Algumas Tags requerem que se inicie e termine a
sua declaração: {% tag %} ...conteúdo... {% endtag %}.
✤ Comentários em templates são feitos utilizando a
sintaxe: {# …conteúdo... #}. Por exemplo, para comen-
tarmos uma váriável ou tag:
{{ variável }} → {# variável #} ou {% tag %} → {# tag #} 67
68. Templates
✤ Herança de Template: A mais poderosa – e a mais
complexa – parte da engine de templates do django. A
herança de template possibilita criar uma base
"esqueleto" que contem os elementos mais comuns de
um site e elementos de bloco que serão preenchidos
por conteúdos dinâmicos em certas regiões do
template.
✤ Porém não é difícil entender como a herança de
template funciona, vamos iniciar com um exemplo de
template "pai" denominado "base.html". 68
70. Templates
✤ O template, no qual vamos denominamos base.html,
define um esqueleto HTML simples usado para gerar
uma página web.
✤ Agora será trabalho do template "filho" preencher
os blocos com conteúdo. No exemplo utilizado, a tag
{% block %} define três blocos no qual o template filho
poderá preencher.
✤ Todas as tags block dizem para o template filho que
essas partes de código podem ser sobrescritas. 70
71. Templates
{% extends "base.html" %}
{% block titulo %}Artistas do Site{% endblock %}
{% block conteudo %} Template
“listar_artistas.html”
{% for a in artistas %} (filho) que deverá
<a href="{{ a.get_absolute_url }}"> estender do “base.html”.
{{ a.nome|upper }} : {{ a.get_idade_artista }}
</a><br/>
{% endfor %}
{% endblock %}
✤ A tag {% extends %} é a chave. Ela diz para o template
se "estender" ao outro. Quando o sistema de template
avalia esse template, primeiro ele avalia o templase
base, no caso, "base.html". 71
72. Templates
✤ Template Tags: Em resumo, template tag é uma
declaração (tag) em seu código HTML que executa uma
função python por trás da cortina. Esta função retorna
um trecho de código HTML, ou define um conjunto de
novas variáveis no contexto, permitindo que sejam
manipuladas ou exibidas conforme desejar.
✤ Primeiramente vamos adicionar uma nova pasta
denominada “templatetags” dentro da app musicos. E
vamos adicionar nesta pasta um arquivo “__init__.py”
vazio. Também vamos criar um arquivo “minhastags.py”
dentro da pasta templatetags, ou o nome que preferir. 72
73. Templates
from datetime import datetime
from django.template import Library,Node Template Tag que
from musicos.models import * imprime uma
mensagem de
“Feliz Aniversário”
register = Library() para o Artista.
def exibe_mensagem_aniversario(parser, token):
"""Exibe o nome do Artista se estiver de Aniversário"""
class aux(Node):
def render(self, context):
if context['a'].data_nascimento.strftime('%d-%m') ==
datetime.now().strftime('%d-%m'):
return "Feliz Aniversário"
return ""
return aux()
register.tag('aniversario', exibe_mensagem_aniversario) 73
74. Templates
{% extends "base.html" %}
Adicionando a
{% load minhastags %} Template Tag
{% aniversario %}
{% block titulo %}Artistas do Site{% endblock %} no template que
lista os Artistas.
{% block conteudo %}
{% for a in artistas %}
<a href="{{ a.get_absolute_url }}">
{{ a.nome|upper }} : {{ a.get_idade_artista }} {% aniversario %}
</a><br/>
{% endfor %}
{% endblock %}
✤ Será necessário carregar suas template tags customiza-
das no início do template {% load minhastags %} para que
seja possível incluí-las posteriormente em pontos
74
específicos do seu código HTML.
76. Middlewares
✤ O Middleware é um framework de hook dentro do
processamento de uma requisição/resposta do django.
Ele é um sistema de “plugins”, leve e de baixo nível
para alterar globalmente valores de entrada ou saída.
✤ Cada middleware é responsável por fazer alguma
função específica. Por exemplo, o django inclui um
middleware, XViewMiddleware, que adiciona um
cabeçalho HTTP "X-View" a toda resposta para uma
requisição HEAD.
76
77. Middlewares
✤ Para ativar um novo middleware, adicione-o a lista
MIDDLEWARE_CLASSES no arquivo settings.py do
projeto.
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.doc.XViewMiddleware',
…)
77
78. Middlewares
✤ Na requisição o django aplica os middlewares
process_request() e process_view() na ordem que
estão definidos no MIDDLEWARE_CLASSES, ou seja, de
cima para baixo.
✤ Na reposta, os middlewares process_response() e
process_exception() são aplicados na ordem inversa,
de baixo pra cima.
✤ Você pode imaginar como se fosse uma “cebola”,
onde cada classe middleware é uma "camada" que
envolve a view. 78
80. Middlewares
✤ process_request(self, request): É chamado em cada
request, antes do django decidir qual view executar.
Deve retornar None ou um objeto HttpResponse.
✤ process_view(self, request, view_func, view_args,
view_kwargs): É chamado logo após o django chamar a
view. Deve retornar None ou um objeto HttpResponse.
✤ Enquanto cada middleware retornar None, o django continuará
processando qualquer outro middleware da lista até executar a
view apropriada. Se algum middleware retornar um objeto
HttpResponse, o django não se incomodará em chamar
QUALQUER outra requisição, view ou exceção de middleware. Ele
80
retornará imediatamente o objeto HttpResponse.
81. Middlewares
✤ process_response(self, request, response): Diferen-
temente dos métodos process_request e process_view, o
método process_response() é sempre chamado, mesmo
que os métodos process_request e process_view da mesma
classe middleware foram pulados por causa de um
método de um middleware anterior que retornou um
HttpResponse. Este deve obrigatoriamente retornar um
objeto HttpResponse.
✤ process_exception(self, request, exception): O django
chama process_exception() quando uma view lança uma
exceção. O process_exception() deve retornar um None ou
81
um objeto HttpResponse.
82. Middlewares
✤ Exemplo de um middleware de redirecionamento:
from django.http HttpResponsePermanentRedirect
class RedirectMiddleware:
def process_request(self, request):
# etc...
redirect_url = request.path+'?par1=1&par2=2'
return HttpResponsePermanentRedirect(redirect_url)
Mais sobre middlewares:
http://docs.djangobrasil.org/topics/http/middleware.html
http://www.djangobook.com/en/beta/chapter16/ 82
83. Forms
✤ O forms é uma poderosa biblioteca do django
para criação de formulários.
✤É possível gerar um formulário automatica-
mente através de um model;
✤ As técnicas de validação seguem o tipo do
campo, por exemplo, se for um EmailField, o
django verifica se o que foi digitado pelo usuário
é um endereço de e-mail válido;
http://docs.djangoproject.com/en/dev/ref/forms/fields/#built-in-field-classes 83
85. Forms
✤ Adicionando duas novas URLs para cadastrar e
editar Artistas no urls.py da aplicação musicos:
url(r'^artista/novo/$', 'novo_artista', name="novo_artista"),
url(r'^artista/edita/(?P<codigo>d+)/$', 'edita_artista',
name="edita_artista"),
✤ Existe mais de uma forma de trabalhar com django
forms. Vamos começar fazendo um form manualmente
para entender um pouco melhor a sua estrutura.
✤ A seguir vamos criar um arquivo forms.py dentro da
nossa aplicação musicos. 85
86. Forms
✤ Adicionando a classe FormArtista no arquivo forms.py.
from django import forms
class FormArtista(forms.Form):
nome = forms.CharField(max_length=50)
sobrenome = forms.CharField(max_length=50,required=False)
data_nascimento = forms.DateField(
widget=forms.widgets.DateInput(format="%m/%d/%Y"))
✤ Pode-se perceber no exemplo acima que a estrutura do
form FormArtista é muito similar a da classe models Artista.
86
http://docs.djangoproject.com/en/dev/ref/forms/fields/
87. Forms
✤ Vamos adicionar a view para manipular o novo form.
def novo_artista(request): from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
if request.method == 'POST': from django.core.context_processors import csrf
form = FormArtista(request.POST) from musicos.models import Artista,Album
from musicos.forms import FormArtista
dc = dict(form = form)
if form.is_valid():
a = Artista.objects.create(nome=form.cleaned_data['nome'],
sobrenome=form.cleaned_data['sobrenome'],
data_nascimento=form.cleaned_data['data_nascimento'])
a.save()
return HttpResponseRedirect(reverse("visualizar_artista",args=[a.id]))
else:
dc = dict(form = FormArtista())
dc.update(titulo='Novo Artista')
dc.update(csrf(request)) 87
return render_to_response('form_artista.html',dc)
88. Forms
✤ Adicionamos um novo template “form_artista.html” na
pasta templates da aplicação musicos.
<html>
<head><title></title></head>
<body>
{% block conteudo %}
<h1>{{ titulo }}</h1>
<form method="post" action=".">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="cadastrar" />
</form>
{% endblock %}
88
</body></html>
89. Forms
✤ Finalizados os passos anteriores, deverá estar dispo-
nível o formulário para adicionarmos um novo Artista
através do nosso navegador web. Vamos acessar o
endereço:
http://127.0.0.1:8000/artista/novo/
89
90. Forms
✤ Quando já possuímos um modelo de dados definido
(models.py), podemos criar nossos formulários a partir
das classes do modelo existente.
✤ Vamos alterar a classe FormArtista no arquivo forms.py,
para que o nosso formulário agora seja criado a partir do
modelo de dados da classe Artista.
from django.forms import ModelForm
from musicos.models import Artista
class FormArtista(ModelForm):
class Meta:
model = Artista
90
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/
91. Forms
✤ Agora podemos melhorar a implementação de nossa
view novo_artista. Quando os dados do formulário forem
válidos, podemos executar o metodo save() da instância
formulário, porque o mesmo contém uma Meta class de
Artista.
def novo_artista(request):
…
if form.is_valid():
a = form.save()
return HttpResponseRedirect(reverse("visualizar_artista",args=[a.id]))
…
91
http://www.slideshare.net/scorpion032/python-meta-classes-and-how-django-uses-them
92. Forms
# Cria uma instância do formulário com dados do POST.
form = FormArtista(request.POST)
# Grava um novo objeto Artista com os dados do formulário.
a = form.save()
a.id
# Cria um formulário para edição de um Artista.
a = Artista.objects.get(pk=codigo)
form = FormArtista(instance=a)
# Cria um formulário para editar um Artista utilizando o POST para popular o formulário.
a = Artista.objects.get(pk=codigo)
f = FormArtista(request.POST, instance=a)
f.save() 92
93. Forms
✤ Vamos adicionar a view para alterar Artistas.
def edita_artista(request,codigo):
if request.method == 'POST':
form = FormArtista(request.POST)
dc = dict(form = form)
if form.is_valid():
a = Artista.objects.get(pk=codigo)
f = FormArtista(request.POST, instance=a)
f.save()
return HttpResponseRedirect(reverse("visualizar_artista",args=[a.id]))
else:
dc = dict(form = FormArtista(instance=Artista.objects.get(pk=codigo)))
dc.update(titulo='Edita Artista')
dc.update(csrf(request))
93
return render_to_response('form_artista.html',dc)
94. Forms
✤ Após incluída a view de edição, vamos acessar o
endereço conforme exemplo abaixo e alterar os dados de
um Artista, por exemplo, o id “14”.
http://127.0.0.1:8000/artista/edita/14/
✤ O django forms ainda oferece muito mais recursos para
explorar, os endereços web abaixo apresentam exemplos
e dicas bem interessantes para expandir seus conheci-
mentos.
http://docs.djangoproject.com/en/dev/ref/forms/fields/
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/ 94
95. O que mais?
✤ Alguns tópicos interessantes que não serão abor-
dados neste treinamento básico, mas seguem como
sugestão de pesquisa e complemento do aprendizado:
✤ Signals; ✤ Authentication;
✤ FlatPages; ✤ Internacionalization;
✤ URLs Slugs; ✤ Sessions;
✤ Generic Views; ✤ Testing;
✤ Caching; ✤ Debbuging;
…e outros! 95
96. Bom trabalho!
Obrigado!
Transforme o conhecimento em resultado!
Leandro Zanuz
Twitter: @leandrozanuz
E-mail: lzanuz@ucs.br
96