Escolar Documentos
Profissional Documentos
Cultura Documentos
Aprendendo Django No Planeta Terra Volume1 PDF
Aprendendo Django No Planeta Terra Volume1 PDF
Marinho Brando
1 edio - 2009
Copyright 2008 por Jos Mrio Neiva Brando
reviso
Mychell Neiva Rodrigues
ilustraes e capa
Joo Matheus Mazzia de Oliveira
impresso e acabamento
Lulu.com
Voc pode
copiar, distribuir, exibir e executar a obra
Observaes
Para cada novo uso ou distribuio, voc deve deixar claro para outros
os termos da licena desta obra.
Qualquer uma destas condies podem ser renunciadas, desde que Voc
obtenha permisso do autor.
Nada nesta licena atrapalha ou restringe os direitos morais do autor.
Volume 1
Agradecimentos.............................................................................................................................6
Dicas para o aprendizado...............................................................................................................7
Apresentao.................................................................................................................................9
1. Alatazan chega ao Planeta Terra ..............................................................................................11
2. O que Django? Como isso? ...............................................................................................13
3. Baixando e Instalando o Django .............................................................................................16
4. Criando um Blog maneiro .......................................................................................................23
5. Entendendo como o Django trabalha ......................................................................................39
6. O RSS o entregador fiel .......................................................................................................45
7. Fazendo a apresentao do site com templates .......................................................................64
8. Trabalhando com arquivos estticos .......................................................................................82
9. Pginas de contedo so FlatPages .........................................................................................94
10. Permitindo contato do outro lado do Universo ....................................................................101
11. Deixando os comentrios flurem ........................................................................................117
12. Um pouco de HTML e CSS s faz bem ..............................................................................130
13. Um pouco de Python agora .................................................................................................151
14. Ajustando as coisas para colocar no ar ................................................................................168
15. Infinitas formas de se fazer deploy......................................................................................175
16. Preparando um servidor com Windows ...............................................................................185
17. Preparando um servidor com Linux ....................................................................................205
18. WSGI e Servidores compartilhados ....................................................................................224
Volume 2
Dicas para o aprendizado
19. Signals e URLs amigveis com Slugs
20. Uma galeria de imagens simples e til
21. Organizando as coisas com Tags
22. O mesmo site em vrios idiomas
23. Fazendo um sistema de Contas Pessoais
24. Fazendo mais coisas na aplicao de Contas Pessoais
25. A aplicao de Contas Pessoais sai do backstage
26. Separando as contas pessoais para usurios
27. Funes de usurios
28. Programando com testes automatizados
29. Criando ferramentas para a linha de comando
30. Adentrando a selva e conhecendo os verdadeiros bichos
Volume 1
5
Agradecimentos
H diversas pessoas a agradecer, mas os nomes mais fortes que tenho pra citar
so estes:
Mezinha e Paizinho
Letcia e Tarsila
Miltinho e Verinha
Mychell e Joo Matheus
Andrews Medina, Guilherme Semente e Betty Vogel
Douglas Adams, Felippe e Donaldson Nardi
Os desenvolvedores do Django e do Python
Linus Torvalds e Richard Stallman
As pessoas acima foram decisivas para que esta obra se tornasse real. Todo
agradecimento e dedicatria so poucos diante do que recebi deles.
6
Dicas de Aprendizado
Verso do Django
A verso do Django adotada nesta srie a verso 1.0.2.
Algumas pessoas tm encontrado algumas dificuldades em decorrncia de
usarem uma verso diferente. H diferenas entre verses em aspectos que temos
trabalhado, portanto, use a verso 1.0.2 ou superior.
8
Apresentao
Ol,
nos ltimos anos, tenho investido a maior parte do
meu tempo com o Django.
Eu vinha de uma longa jornada onde segui
firmemente (e nem sempre fielmente ou alegremente)
com o Delphi e o PHP. Mas chegou uma hora que uma
nova tecnologia era necessria - j haviam se passado
quase 10 anos!
A sada foi conhecer as linguagens de programao populares,
colocando alguns princpios em mente:
A tecnologia teria que ser multi-plataforma
A tecnologia teria de ser til para sites e sistemas web
Eu queria ter resultados
Aps meses de namoro com Java e .Net, notei que aquilo no era o que eu
precisava. Ento parti para conhecer outras... TCL, Ruby, Python... opa! No
precisei passar daqui!
Do Python eu cheguei ao Django e ali fiquei.
O Django uma daquelas coisas que voc j tem uma boa impresso na
chegada, mas algumas semanas depois, voc est completamente apaixonado. Hoje,
quase 3 anos depois, eu sinto amor pra vida inteira - ou pelo menos para a curta
vida que as tecnologias costumam levar.
H cerca de um ano atrs, estava para concluir a escrita de um livro
em portugus sobre Django, e percebi que ele no era nada do que eu
queria.
Passei a borracha e resolvi esperar.
9
Ento depois de muitos meses e muitas conversas, percebi que o
melhor caminho seria este.
Eu quero que pessoas comuns aprendam Django, portanto, este o livro
eletrnico que criei para essas pessoas comuns.
Pessoas comuns so pessoas que gostam de passear com a famlia, ouvir
msica, conhecer gente legal e ganhar dinheiro.
T certo que toda pessoa comum tem tambm l suas esquisitices... ento, o
nosso ator principal aqui ser o um aliengena.
Pronto, agora no temos mais problemas com a esquisitice!
10
Captulo 1: Alatazan chega ao Planeta Terra
11
Na sada da primeira aula, Alatazan estava um tanto atordoado com as confusas
definies que ouvira. Ainda no entendia como Arquitetura e Engenharia serviam
para definir quase as mesmas coisas de um assunto, e tambm no entendia pra qu
serviam todos aqueles desenhos, que precisam ser refeitos todos os dias e repetidos
em cdigos e outras formas de repeties... Foi quando ele notou que uma garota e
um rapaz eram os nicos que desciam a rampa, que pareciam se divertir.
Alatazan pensou: "puxa, do qu esses dois esquisitos esto rindo depois de toda
essa tortura? Deve haver algo que eu preciso entender..."
Alatazan se achava no direito de achar os terrqueos esquisitos. Eram todos
diferentes dele, e ele tinha um alto padro de beleza para Katara: um belo topete
(sim, isso tambm ser explicado), olhos de desenho japons, e dois belos dedos em
cada p!
E foi assim que Alatazan conheceu Cartola e Nena, seus parceiros nessa
aventura.
12
Captulo 2: O que Django? Como isso?
Tzzzzt!
A campainha da casa de Cartola tocou, era Alatazan do lado de fora. Ele deu
uma olhadela pela veneziana e correu para abrir a porta.
Vem, estamos fazendo um projeto l dentro, usando uma coisa nova, voc vai
gostar disso.
Para Alatazan todas as tecnologias terrqueas eram novas, mas a alegria de
Cartola j indicava que ela parecia ser um pouco diferente das apresentadas no
curso.
Correram pra dentro e Nena estava sentada ao seu laptop com alguns arquivos
abertos e olhando o resultado de sua "arte" no navegador.
Veja, o Cartola descobriu esse novo jeito de fazer sites. uma tecnologia
chamada Django... d pra fazer muitas coisas diferentes sem muito esforo. O
maior esforo esquecer um pouco do que sabemos hoje pra entender o novo
paradigma.
13
Alm do Django e do Python, voc vai precisar de um banco de dados.
O Banco de Dados onde os dados so guardados. Quando voc est em uma
rodoviria ou aeroporto, existe o guarda-volumes, um local onde voc paga um
valor pra guardar suas coisas por um certo tempo. Quando precisa guardar dinheiro,
voc vai ao banco. O Banco de Dados o lugar certo para guardar dados, e ele
independente do Django.
Os bancos de dados que o Django conhece so o MySQL, PostgreSQL,
SQLite, Oracle e Microsoft SQL Server. Mas ns vamos trabalhar por um bom
tempo s com o SQLite, que o mais fcil deles.
E para ver o seu site ou programa funcionando, voc vai precisar de um
Navegador, que o programa que voc usa para acessar sites da web. Mozilla
Firefox, Microsoft Internet Explorer e Apple Safari so alguns deles. Ns vamos
usar o Firefox por ser o nico destes que funciona tanto no Windows, quanto no
Linux e no Mac. Mas no se preocupe com isso, o navegador o que menos
importa quando se trata de Django.
14
Katara, as coisas costumam ser mais simples do que tm sido na Terra. Isso porque
o povo de l j passou por isso o suficiente pra descobrir que simplificar as coisas
sempre ajuda no resultado final. O que eles no sabem que simplificar evita
cabelos brancos, j que eles no possuem cabelos.
No prximo captulo, vamos baixar e instalar o Django, o Python e o que mais
for necessrio, e dar os primeiros passos para criar o primeiro projeto: um blog, que
Alatazan vai usar para se comunicar com sua famlia.
15
Captulo 3: Baixando e Instalando o Django
16
pra ter certeza de que no esto lhe oferecendo gato por frango. como se voc
quiser um dia fazer diferente e misturar suco de limo com abacate... parece
estranho, mas voc pode fazer isso se quiser (e estranho que algumas pessoas
realmente gostem).
Os caras que fizeram o Django acreditam que todo software (ou pelo menos a
maioria deles) deveria ser livre. Eles ganham dinheiro usando software livre, mas
no impedem que outras pessoas tambm o usem e ganhem dinheiro da mesma
forma, ou at mais.
Mas se o software que voc faz ser livre ou no, isso tambm um direito seu.
Ento ficou fcil de resolver. Voc pode baixar o Django e no pagar nada por
isso. Us-lo e no pagar nada por isso. E pode vender o seu trabalho com ele, e no
repassar nada a eles por isso. S preciso que escreva em algum lugar que seu
software foi escrito usando Django.
O mesmo vale para o Python e para as bibliotecas adicionais que o Django
utiliza.
Baixando e instalando
H vrias formas de se instalar o Django. Algumas muito fceis, outras muito
educativas. Ns vamos seguir pelo caminho que deve ser o mais difcil deles. Isso
porque importante passar por essas etapas para abrir sua mente ao universo
Python e Django, mas caso queira o caminho mais prtico, v direto ao final deste
captulo e veja como fazer.
No Windows
Bom, ento vamos comear pelo Python.
Se voc usa Windows, faa o download do instalador do Python, acessando a
seguinte URL no seu navegador:
http://www.python.org/download/releases/2.5.2/
Aps baixar o arquivo, clique duas vezes sobre ele e clique no boto "Next".
17
Na prxima pgina, a imagem abaixo ser exibida, guarde o caminho indicado
no campo (no caso da imagem abaixo, "C:\Python25\", pois vamos us-lo logo
aps a instalao do Python. Depois dela, siga clicando no boto "Next" at
finalizar.
18
Por fim, importante fazer isso: o Windows no consegue encontrar sozinho o
Python, portanto, preciso dizer a ele onde o Python est. Isso se faz adicionando o
caminho de instalao do Python varivel de ambiente PATH, do Windows.
Pressione as teclas Windows + Pause (a tecla Windows a tecla do logotipo do
Windows).
Na janela aberta, clique na aba "Avanado" e depois disso, no boto Variveis
de ambiente:
19
E ao final do campo "Valor da Varivel", adicione um ponto-e-vrgula e o
caminho que voc memorizou da instalao do Python, como est destacado abaixo.
20
pause
21
Existe um caminho mais fcil?
Sim, existe um caminho bem mais fcil. Como j foi dito l em cima, o processo
acima mais difcil, mas, o melhor para o seu aprendizado.
Se quiser instalar de forma mais fcil, use o DjangoStack. Veja neste site como
faz-lo:
http://marinhobrandao.com/blog/p/djangostack-facil-para-o-
iniciante-aprender-django/
22
Captulo 4: Criando um Blog maneiro
Era uma manh fria, o vento de outono balanava as folhas das poucas rvores
na rua onde Alatazan morava, e algum deixou ali um envelope engraado,
triangular. Para Alatazan, o envelope no era engraado, era exatamente igual aos
envelopes mais usados em Katara.
Ele abriu o envelope e tirou o objeto prateado reluzente, com cheirinho de novo.
Uma das pontas do envelope estava ligeiramente amassada, mas no tinha
problema, pois o papel eletrnico era chamado de papel exatamente por ser flexvel.
Na imagem animada do papel, sua me esbravejava por sua falta de
considerao. Desde sua chegada, Alatazan no havia enviado sequer um "al", mas
mal sabia sua me que por aqui no havia uma agncia do sistema interestelar de
correios.
Mas Katara tem um jeito de acessar a nossa Internet, e ele teve ento a ideia de
criar um blog.
Um blog o jeito mais simples de escrever sobre sua vida. Toda vez que d
vontade de escrever, o sujeito vai l, cria um ttulo e escreve o que quiser, e a
pgina mostra sempre os ltimos itens que ele escreveu.
Porqu um blog?
Um blog fcil e simples de se fazer. E tambm simples de criar novidades.
Hoje vamos deixar o Blog funcionando, a seguir vamos esclarecer umas coisas,
melhorar outras, colocar os RSS, depois vamos aos Comentrios, e assim por
diante. Cada pequeno passo de uma vez, e bem resolvido.
Mas antes de tudo, precisamos resolver uma questo ainda em aberto...
Escolhendo um editor
O Django no se prende a um editor especfico. Existem centenas deles, alguns
com mais recursos, outros mais simples. como modelos de tnis, cada um usa o
23
seu, e h aqueles que preferem sapatos, sandlias, ou andar descalos mesmo. H
ainda aqueles no preferem, mas ainda assim o fazem.
O editor que voc escolhe hoje, pode ser descartado amanh, e o prximo
tambm. No se trata de um casamento, mas sim de uma escolha do momento, at
que voc encontra aquele que se encaixa com o seu perfil.
Ento vamos comear pelo Bloco de Notas, e depois vamos conhecer outros.
24
No Linux ou Mac um pouquinho diferente:
$ cd /Projetos
$ django-admin.py startproject meu_blog
Agora, vamos ver o site funcionando (mesmo que sem nada - ou com quase
nada - dentro). Na pasta do projeto, crie um arquivo chamado "executar.bat" e o
edite com o Bloco de Notas. Dentro dele, escreva o seguinte cdigo:
python manage.py runserver
pause
25
#!/bin/bash
26
Mas isso ainda no nada. Voc ainda no possui nada em seu projeto. Ou pelo
menos, nada que algum possa ver.
Salve o arquivo. Feche o arquivo. Execute o arquivo, clicando duas vezes sobre
ele.
A gerao do banco de dados cria as tabelas e outros elementos do banco de
dados e j cria tambm um usurio de administrao do sistema. Isso acontece
27
porque naquele arquivo settings.py havia uma linha indicando isso (calma, logo
voc vai saber qual).
Sendo assim, ele pergunta pelo nome desse usurio (username), seu e-mail (se
voc digitar um e-mail invlido, ele no vai aceitar) e a senha.
Assim, para ficar mais fcil, informe os dados assim:
Username: admin
E-mail: admin@gmail.com
Password: 1
Password (again): 1
28
Isso aconteceu porque agora voc possui alguma coisa em seu projeto. E quando
voc possui "alguma coisa", qualquer outra coisa que voc no possui
considerada como Pgina no encontrada. Ento, que coisa essa?
A interface de administrao
Na barra de endereo do navegador, localize o endereo:
http://localhost:8000/admin/
29
Voc vai informar o usurio e senha criados no momento da gerao do banco
de dados:
Username: admin
Password: 1
30
Criando a primeira aplicao
Agora, vamos criar uma aplicao, chamada "blog", ela vai ser responsvel
pelas funcionalidades do blog no site. Portanto, crie uma pasta chamada "blog" e
dentro dela crie os arquivos abaixo:
__init__.py
models.py
admin.py
Abra o arquivo models.py com o Bloco de Notas e escreva o seguinte cdigo
dentro:
from django.db import models
class Artigo(models.Model):
titulo = models.CharField(max_length=100)
conteudo = models.TextField()
publicacao = models.DateTimeField()
Opa! Agora vemos ali uma coisa nova: uma caixa da nova aplicao "blog".
Mas como nem tudo so flores, ao clicar no link Artigos, ser exibido um erro,
de banco de dados.
32
Isso acontece porque voc no gerou o banco novamente, depois de criar a nova
aplicao. Ento vamos fazer isso.
Clique duas vezes sobre o arquivo gerar_banco_de_dados.bat e veja o
resultado a seguir:
33
Vamos inserir o primeiro artigo?
Clique sobre o link "Add artigo" e preencha as informaes, clicando por fim
no boto "Save" para salvar.
34
Bom, j temos a interface de administrao do blog funcionando, agora vamos
ao mais interessante!
urlpatterns = patterns('',
(r'^$', 'django.views.generic.date_based.archive_index',
{'queryset': Artigo.objects.all(),
'date_field': 'publicacao'}),
(r'^admin/(.*)', admin.site.root),
)
35
Salve o arquivo. Feche o arquivo. Volte ao navegador, e pressione F5 para
atualizar a pgina, e o resultado ser como este abaixo:
<h1>Meu blog</h1>
{{ artigo.conteudo }}
{% endfor %}
36
</body>
</html>
Este um HTML simples, que percorre a lista de artigos do blog e exibe seu
Ttulo e Contedo.
Ateno: neste momento, importante fechar a janela do MS-DOS (Console ou
Terminal, no Linux ou Mac) onde o Django est rodando, e executar novamente o
arquivo executar.bat. Isto se faz necessrio, pois a primeira vez que adicionamos
um template no site, o que obriga que todo o Django seja iniciado novamente do
zero.
Veja como ficou:
37
sorridente Cartola, batendo em seu ombro e deixando cair um dos fones do
ouvido.
Vamos respirar um pouco, amanh vamos explicar o porqu de cada coisa, e
voc vai compreender cada um desses arquivos criados, editados, modificados,
executados, enfim. Mas isso s depois de um bom suco! - Nena se empolgou
com a vontade de Alatazan, que se empolgou com a empolgao de Nena.
Cartola j era empolgado por natureza.
38
Captulo 5: Entendendo como o Django trabalha
39
Muito bem Ballzer, muito bem.
Isso se repetiu por mais vezes. s vezes o senhor sorria, s vezes no. Pegava
outro cubo, entregava ao Ballzer e assim se seguia...
Eles estavam jogando Bhallz, um complexo jogo muito praticado nas escolas
para adolescentes.
Voltando ao Django...
Na web, as coisas so parecidas.
Imagine que o senhor do outro lado da rua o seu usurio, usando o navegador.
O menino o URL dispatcher.
Os robs mesa so middlewares.
A moa rosada, ao final da mesa, uma view.
O cubo uma requisio (ou HttpRequest).
A coisa que a moa devolveu aos robs uma resposta (ou HttpResponse).
E por fim, o maluco e imprevisvel Ballzer, a prpria Internet.
Ou seja, cada qual sua vez, fazendo seu papel na linha de produo, para
receber um pedido do usurio e retornar uma resposta equivalente, que na
maioria das vezes, uma pgina bonita e colorida.
Entendendo a requisio
Na requisio (ou HttpRequest) h diversas informaes. Uma das informaes
a URL, que composta pelo protocolo, o domnio, a porta (s vezes), o caminho e
os parmetros (s vezes tambm).
Exemplo:
http://localhost:8000/admin/?nome=Mychell&idade=15
Protocolo: http
Domnio: localhost
Porta: 8000
Caminho: /admin/
Parmetros: nome = Mychell e idade = 15
Quando a porta no citada, ento voc deve entender que se trata da porta 80,
40
a porta padro do protocolo HTTP.
Outras informaes que se encontram na requisio so aquelas sobre o
navegador e computador do usurio, como seu IP, sistema operacional, idiomas
suportados, cookies e diversas outras coisas.
O Handler
A primeira coisa que acontece quando a requisio chega ao Django, est no
handler. Essa parte nunca vista ou notada por voc, mas o primeiro passo antes
da requisio chegar aos middlewares, e tambm o ltimo passo antes da resposta
voltar do Django para o usurio final.
Middlewares
Middlewares so pequenos trechos de cdigo que analisam a requisio na
entrada e a resposta na sada. A requisio analisada por eles.
Voc pode determinar quais middlewares estaro na fila mesa para
analisar a requisio e pode at criar os seus prprios middlewares.
Um dos middlewares faz com que toda a segurana e autenticao de usurios
seja feita. Outro adiciona a funo de sesso, uma forma de memorizar o que o
usurio est fazendo para atend-lo melhor. H ainda outro middleware, que
memoriza as respostas no Cache, pois se caso a prxima requisio tenha o mesmo
caminho e os mesmos parmetros, ele retorna a resposta memorizada, evitando o
trabalho de ser processada novamente pela view.
Sendo assim, aps passar por todos esses middlewares, a requisio passa a ter
outras informaes, como qual usurio est autenticado, sesso atual e outras
coisas.
O URL Dispather
Depois de passar pelos middlewares, a requisio analisada pelo URL
Dispatcher, um importante componente do Django que verifica o endereo -
especialmente a parte do caminho - e verifica o arquivo urls.py do projeto para
apontar qual view ser chamada para dar a resposta.
Ah, a view
A view uma funo escrita em Python, e na maioria das vezes, escrita por
voc.
Ela faz isso: recebe uma requisio (HttpRequest) e retorna uma resposta
41
(HttpResponse).
aqui que entra seu trabalho dirio, que analisar uma requisio, fazer algo no
banco de dados e retornar uma pgina.
O Django possui algumas views prontas para coisas que sempre funcionam do
mesmo jeito. Elas so chamadas Generic Views e esto espalhadas por toda parte.
H generic views teis para blogs, para cadastros em geral, para lembrar senha,
autenticar, sair do sistema, redirecionar, enfim, h muitas delas.
Voc no obrigado a usar generic views. Elas esto l para voc us-las se
assim o desejar.
As views escritas por voc devem ser escritas em um arquivo chamado
views.py.
Os arquivos de templates
As pginas no Django so em geral guardadas em Templates, que so arquivos
HTML (ou outro formato) que possuem sua prpria lgica em interpretar quilo que
lhes passado e no final renderizar um HTML, que passado como resposta ao
usurio. No entanto, esta no uma regra, pois muitas vezes no ser retornado um
HTML como resposta. Mas isso ser muito mais esclarecido nos prximos
captulos.
A camada de Modelo
Para armazenar e resgatar informaes do banco de dados, no necessrio ir
at ele e conhecer a linguagem dele (o bom, velho, e cada vez mais sumido SQL).
Voc usa uma ferramenta do Django chamada ORM, que interpreta o seu cdigo,
leva aquilo at o banco de dados, e depois devolve as informaes desejadas.
A parte do cdigo onde voc configura quais so seus modelos de dados e que
tipo de informaes eles devem armazenar, um arquivo chamado models.py.
42
Ento, tudo se resume em MVC
MVC a sigla que resume tudo isso:
Modelo (Model)
Viso (View)
Controle (Controller)
Modelo onde esto as definies dos dados, como eles devem ser
armazenados e tratados. l que voc diz quais campos uma tabela deve ter, seus
tipos e valores padro e se eles so obrigatrios ou no. Dentre outras coisas.
Viso so as funes que recebem requisies e retornam respostas, ao
usurio, a outro computador, a uma impressora ou qualquer outra coisa externa. Ou
seja, as views.
E Controle so todas as coisas que ficam no meio do caminho, como o handler,
os middlewares e o URL dispatcher. A maior parte dessas coisas feita pelo
prprio Django, e voc deve se preocupar pouco ou nada com isso.
E onde entram o banco de dados e os templates?
O banco de dados a camada de persistncia, e no faz parte do MVC, pois no
faz parte do Django em si.
43
Os templates so arquivos utilizados pelas views, so apenas auxiliares, como
uma bolsa utilitria ao lado, que voc usa se quiser ou se precisar.
Passando adiante...
Fascinante tudo isso, no? Meu pai conta que nas fbricas de software mais
antigas trabalhavam com outro conceito, chamado Cliente/Servidor, mas isso
nunca caiu bem na Web, era muito lento...
Os olhos de Nena at brilhavam. Ela adorava essas coisas de conceitos e
arquitetura.
Bom, no muito diferente de jogar Bhallz. Cada pedacinho tem um papel
simples a cumprir. Complicado pegar a coisa toda de uma vez, mas se voc
jogar numa posio de cada vez, vai ver que fcil de jogar... - respondeu um
Alatazan mais aliviado.
Cartola estava um pouco disperso, entretido com seu gadget. Ele o havia
configurado para receber os podcasts do This Week In Django sempre que
houvesse novidades, e havia acabado de chegar um episdio novo.
No prximo captulo, vamos colocar o RSS para funcionar no Blog, e entender
como fcil levar suas novidades s pessoas sem que elas precisem vir at voc.
44
Captulo 6: O RSS o entregador fiel
Ento vamos l?
Para trabalhar com RSS no Django, vamos antes ajustar algumas coisas que
sero necessrias daqui em diante. E o melhor momento para fazer esses ajustes,
agora.
45
muitas) aplicaes.
Uma aplicao um conjunto - de preferncia no extenso - de funcionalidades
com foco em resolver uma questo especfica. Um Blog por exemplo, uma
aplicao.
Todo projeto possui um arquivo chamado settings.py, onde so feitas
configuraes que determinam a sua essncia.
Uma coisa importante para ajustar nas settings do projeto, a TIME_ZONE.
nesta setting que determinamos em que fuso horrio o projeto deve estar adequado.
H uma lista desses fusos horrios no seguinte site:
http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
Essa modificao faz com que a listagem dos artigos seja sempre feita pelo
campo "publicacao". Ali h um detalhe importante: o sinal de menos ( - )
esquerda de 'publicacao' indica que a ordem deve ser decrescente.
Localize esta outra linha:
publicacao = models.DateTimeField()
46
publicacao = models.DateTimeField(
default=datetime.now,
blank=True
)
Isso faz com que no seja mais necessrio informar o valor para o campo de
publicao, pois ele assume a data e hora atuais automaticamente. O argumento
blank indica que o campo pode ser deixado em branco, j que ele vai assumir a
data e hora atuais nesse caso.
Porm, isso no basta.
O elemento datetime no est embutido automaticamente no seu arquivo, e
voc deve traz-lo de onde ele est, para que o Python o use da forma adequada. Do
contrrio, o Python ir levantar um erro, indicando que o objeto datetime no
existe.
Portanto, acrescente a linha a seguir no incio do arquivo, na primeira linha:
from datetime import datetime
class Artigo(models.Model):
class Meta:
ordering = ('-publicacao',)
titulo = models.CharField(max_length=100)
conteudo = models.TextField()
publicacao = models.DateTimeField(
default=datetime.now,
blank=True
)
Algumas coisas sobre Python sero esclarecidas daqui a alguns captulos. Mas
por hora, importante ressaltar que voc deve sempre respeitar a edentao. O
padro mais indicado no Python que seus blocos sejam sempre edentados a cada 4
espaos, portanto, muito cuidado com a tecla de tabulao. No a mesma coisa.
Muito bem. Feitos esses ajustes, vamos ao que realmente interessa.
47
Aplicando RSS dos artigos do blog
A primeira coisa a compreender aqui, que o Django feito por pequenas
partes. E a maior parte dessas pequenas partes no so ativadas quando voc cria
um projeto.
Esse um cuidado essencial para que seu projeto fique o mais leve e compacto
possvel, carregando para a memria e processando somente aquilo que
necessrio. E claro, quem sabe o que necessrio, voc.
As aplicaes especiais que j vm com o Django, so chamadas de contribs, e
aquela que faz o trabalho pesado do RSS chamada de syndication.
Vamos ento editar novamente o arquivo settings.py da pasta do projeto, para
adicionar a aplicao syndication s aplicaes do projeto.
Localize a linha abaixo:
INSTALLED_APPS = (
'blog',
)
Portanto, vamos adicionar a nossa nova URL aps a ltima tupla, para ficar
assim:
urlpatterns = patterns('',
(r'^$', 'django.views.generic.date_based.archive_index',
{'queryset': Artigo.objects.all(),
'date_field': 'publicacao'}),
(r'^admin/(.*)', admin.site.root),
(r'^rss/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': {'ultimos': UltimosArtigos}}),
)
A tupla adicionada indica que a nova URL vai exibir os artigos em formato RSS
na seguinte endereo:
http://localhost:8000/rss/ultimos/
49
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^$', 'django.views.generic.date_based.archive_index',
{'queryset': Artigo.objects.all(), 'date_field': 'publicacao'}),
(r'^admin/(.*)', admin.site.root),
(r'^rss/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': {'ultimos': UltimosArtigos}}),
)
class UltimosArtigos(Feed):
title = 'Ultimos artigos do blog do Alatazan'
link = '/'
def items(self):
return Artigo.objects.all()
Gostou do que viu? No... eu ainda no. Veja que o ttulo e a descrio do
artigo esto como "Artigo object". No est como ns queremos. Vamos l
resolver isso?
Na pasta da aplicao blog, h uma outra pasta, chamada templates. Dentro
dela, voc vai criar mais uma pasta, chamada feeds.
Dentro da nova pasta, vamos criar um template que ser usado para determinar o
ttulo de cada artigo. Ele ser chamado ultimos_title.html. Esse nome se deve
soma do nome desse RSS ( ultimos ) com _title.html, o nome padro para isso que
queremos fazer. Escreva o seguinte cdigo dentro:
{{ obj.titulo }}
51
{{ obj.conteudo }}
52
No entanto, ns podemos fazer isso de uma forma diferente. Faa assim: remova
as seguintes linhas do arquivo feeds.py:
def item_link(self, artigo):
return '/artigo/%d/'%artigo.id
53
class Artigo(models.Model):
class Meta:
ordering = ('-publicacao',)
titulo = models.CharField(max_length=100)
conteudo = models.TextField()
publicacao = models.DateTimeField(
default=datetime.now,
blank=True
)
def get_absolute_url(self):
return '/artigo/%d/'%self.id
O que fizemos agora foi definir um endereo absoluto de URL para artigo, ou
seja, cada artigo tem o seu endereo, e esse endereo til no apenas para o RSS,
mas tambm para outros fins, Veja por exemplo o seguinte endereo:
54
http://localhost:8000/admin/blog/artigo/1/
O resultado :
Notou o link "View on site" em destaque no canto superior direito? Pois bem,
clique sobre ele, e o resultado ser:
56
Bom, j conhecemos esta pgina, certo? Isso quer dizer que essa pgina no
existe.
Esta pgina ser a pgina de um artigo especfico. Ou seja, Alatazan tem um
blog, e na pgina principal do blog so exibidos todos os artigos, porm, cada artigo
possui sua prpria URL - sua prpria pgina. Ento vamos cri-la?
Na pasta do projeto, abra o arquivo urls.py para edio e adicione a seguinte
URL:
(r'^artigo/(?P<artigo_id>\d+)/$', 'blog.views.artigo'),
urlpatterns = patterns('',
(r'^$', 'django.views.generic.date_based.archive_index',
{'queryset': Artigo.objects.all(),
57
'date_field': 'publicacao'}
),
(r'^admin/(.*)', admin.site.root),
(r'^rss/(?P<url>.*)/$',
'django.contrib.syndication.views.feed',
{'feed_dict': {'ultimos': UltimosArtigos}}),
(r'^artigo/(?P<artigo_id>\d+)/$', 'blog.views.artigo'),
)
58
A mensagem diz: "O template 'blog/artigo.html' no existe". Sim, no existe,
mas vamos cri-lo!
Na pasta da aplicao blog, abra a pasta templates, e dentro dela, a pasta blog.
Crie um novo arquivo chamado 'artigo.html' e escreva o seguinte cdigo dentro:
<html>
<body>
Blog do Alatazan
{{ artigo.conteudo }}
</body>
</html>
59
Bom, aconteceu algo errado aqui, no? Veja que no arquivo do template, ns
indicamos as variveis {{ artigo.titulo }} e {{ artigo.conteudo }} para exibirem
respectivamente o ttulo e o contedo do artigo. Mas tudo o que apareceu foi 'Blog
do Alatazan'. Porqu?
Porque para as variveis informadas serem vlidas, preciso que algum
indique que elas existem, e de onde elas vm.
As variveis vlidas para os templates so indicadas a uma parte "oculta" do
processo, chamada Contexto. Para indicar a varivel artigo para o contexto deste
template, vamos modificar a view. Portanto, na pasta da aplicao blog, abra o
arquivo views.py para edio e o modifique, para ficar da seguinte forma:
from django.shortcuts import render_to_response
60
Pronto. Temos uma pgina para o artigo.
Mas antes de terminarmos o captulo, falta fazer uma coisa importante: deixar o
navegador saber que o nosso blog fornece RSS.
Para fazer isso, na pasta da aplicao blog, carregue a pasta templates e dali a
pasta blog. Abra o arquivo artigo_archive.html para edio, e modifique, para
ficar assim:
<html>
<head>
<link rel="alternate" type="application/rss+xml" title="Ultimos
artigos do Alatazan" href="/rss/ultimos/" />
</head>
<body>
<h1>Meu blog</h1>
{{ artigo.conteudo }}
{% endfor %}
61
</body>
</html>
62
Criar as templates para o ttulo e a descrio dos artigos no RSS
Criar a URL e a view do artigo e sua template
Mudar a URL padro do site
Informar variveis ao contexto do template
Fazer o cone do RSS aparecer no navegador
e...
Calma! Voc vai ter um ataque aqui hein... - interferiu Nena - s no v se
esquecer de que no Python, edentao correta obrigao viu... no v
esquecer aquele espao vazio esquerda, seno pau na certa. Trocar espao
por TAB tambm fria...
Os dois coraes de Alatazan pulsavam forte e os trs caram na gaitada, rindo
da situao.
Olha, vamos cada um pra sua casa que agora eu vou dar uma volta por a.
Esse blog est fenho que di, amanh vamos dar um jeito no visual dele.
Cartola disse isso e j foi ajeitando a roupa pra seguir com a sua vida.
63
Captulo 7: Fazendo a apresentao do site com
templates
64
Mas chega de conversa e vamos ao que interessa!
Antes de mais nada, execute o seu projeto, clicando duas vezes no arquivo
executar.bat da pasta do projeto (meu_blog).
No navegador, carregue a pgina inicial:
http://localhost:8000/
65
<head>
<title>Blog do Alatazan</title>
<link rel="alternate" type="application/rss+xml" title="Ultimos
artigos do Alatazan" href="/rss/ultimos/" />
<style type="text/css">
body {
font-family: arial;
background-color: green;
color: white;
}
h1 {
margin-bottom: 10px;
}
h2 {
margin: 0;
background-color: #eee;
padding: 5px;
font-size: 1.2em;
}
.artigo {
border: 1px solid black;
background-color: white;
color: black;
}
.conteudo {
padding: 10px;
}
</style>
</head>
66
<body>
<h1>Blog do Alatazan</h1>
<div class="conteudo">
Publicado em {{ artigo.publicacao }}<br/>
{{ artigo.conteudo }}
</div>
</div>
{% endfor %}
</body>
</html>
67
Opa, visual j melhorou! Mas aquela data de publicao... no ficou boa.
A maioria das modificaes foram estticas, usando CSS e HTML.
A exceo foi a data de publicao, que trata-se da referncia
{{ artigo.publicacao }}, que indica que naquele lugar do HTML, ser exibido o
contedo do atributo publicacao da varivel artigo. Mas ele ficou definitivamente
desagradvel.
H uma forma de melhorar isso, usando um template filter, chamado "date".
Troque o {{ artigo.publicacao }} por {{ artigo.publicacao|date:"d \d\e F \d\e
Y" }} e veja como fica:
O trecho de cdigo que voc acrescentou ( |date:"d \d\e F \d\e Y" ), faz o
seguinte: recebe uma data (ou data/hora, como este caso) e faz o tratamento,
exibindo no seguinte formato: "DIA de MS de ANO", e retorna esse valor
formato em seu lugar - sem modificar a varivel original.
Acontece que o ms est em ingls. Ento isso quer dizer que o todo o site est
preparado para trabalhar na lngua inglesa, o que no o caso de Alatazan, que est
vivendo no Brasil.
68
trecho de cdigo:
LANGUAGE_CODE = 'en-us'
69
O problema com arquivos que no so UTF-8
Ahh, agora est muito mais humano - em Katara isso chamado de "bvio",
mas enfim, no estamos em Katara.
Mas a linguagem ficou estranha, no? "Publicado em 2 dias, 5 horas" no
assim "to" amigvel. Pois ento, no arquivo do template, substitua o em por h.
Salve o arquivo. Porm, possvel que voc tenha um problema agora, veja:
Se este mesmo erro for exibido para voc, porque voc usou um editor que no
salva em formato Unicode por padro. Como o caso do Bloco de Notas.
Dessa forma, voc deve ir at o menu Arquivo -> Salvar como e deixar o
mesmo nome do arquivo, mudando os dois campos abaixo do nome para "Todos os
arquivos" e "UTF-8", respectivamente, como est na imagem abaixo:
70
Agora, ao retornar ao navegador, veja o resultado:
Pronto. Questo dos caracteres especiais resolvida. Da prxima vez que isso
ocorrer, voc j sabe como proceder.
71
Agora observe bem o arquivo de template, e voc pode notar o seguinte trecho
de cdigo:
{% for artigo in latest %}
<div class="artigo">
<h2>{{ artigo.titulo }}</h2>
<div class="conteudo">
Publicado h {{ artigo.publicacao }}<br/>
{{ artigo.conteudo }}
</div>
</div>
{% endfor %}
Veja que o trecho iniciado com {% for artigo in latest %} e finalizado com
{% endfor %}.
Trata-se de um template tag.
Todos os Template Tags iniciam e terminam com {% e %} respectivamente, e
so mais poderosos que qualquer outro elemento em um template, pois possvel
trabalhar com blocos, como o caso desse lao de repetio que aberto pelo
template tag {% for %} e fechado com seu template tag de fechamento {% endfor
%}.
72
Isso acontece, pois a template tag {% include %} inclui um template dentro de
outro. Maneiro, no ? E como esse outro template includo no existe, ele exibiu a
mensagem de erro.
Vamos ento criar esse novo arquivo. Mas pense comigo: o rodap de um
template no deve ser restrito ao blog, mas deve ser do site como um todo,
concorda? Ento dessa vez ns no vamos adicionar esse template pasta de
templates da aplicao blog.
Na pasta do projeto, crie uma nova pasta, chamada "templates" e dentro dela,
crie o arquivo "rodape.html" com o seguinte cdigo dentro:
<div class="rodape">
Por favor no faa contato. Obrigado pela ateno.
</div>
73
# Put strings here, like "/home/html/django_templates" or
# "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
Salve o arquivo.
Agora, ao atualizar seu navegador, o resultado ser este:
74
fazer uma boa prtica j! No incio do arquivo settings.py, acrescente as seguintes
linhas:
import os
PROJECT_ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
Isso faz com que esses caminhos de pastas e arquivos sejam caminhos
completos, e no somente o seu nico nome simples.
Isso faz com que o ttulo do artigo passe a ser um link para sua prpria pgina.
Mas h ainda uma forma melhor de indicar um link, usando a template tag {% url
%}.
Essa template tag bacana, pois flexvel s mudanas. Usando a template tag
{% url %} para indicar um link, voc pode modificar o caminho da URL no
arquivo urls.py e no precisa se preocupar com os vrios links que existem
espalhados pelos templates indicando quela URL, pois eles so ajustados
75
automaticamente. Portanto, modifique o mesmo trecho de cdigo para ficar assim:
<a href="
{% url blog.views.artigo artigo_id=artigo.id %}">
<h2>{{ artigo.titulo }}</h2>
</a>
Observando o que escrevemos, voc vai notar que a template tag indica
primeiramente o caminho da view ( aplicao blog, arquivo views.py, view artigo )
e o argumento artigo_id recebendo o cdigo do artigo ( artigo.id ).
Verificando a URL em questo, veja se reconhece as semelhanas:
(r'^artigo/(?P<artigo_id>\d+)/$', 'blog.views.artigo'),
A herana de templates
Pois bem, falando na pgina do artigo, vamos ver como ela est?
Localize em seu navegador a seguinte URL:
http://localhost:8000/artigo/1/
Como pode ver, a mudana visual que fizemos no template da pgina inicial no
afetou em nada a pgina do artigo. Isso ocorre porque de fato os dois templates so
distintos. Mas existe uma soluo pra isso!
No conceito de Programao Orientada a Objetos h dois elementos
importantes, e algumas vezes conflitantes, chamados herana e composio. No
sistema de templates do Django, voc pode trabalhar com ambos os conceitos,
adotando o mais adequado para cada situao.
Ns j trabalhamos o conceito de composio l atrs, quando voc conheceu a
template tag {% include %}, que trabalha na idia de compr um template
acrescentando outros templates de fim especfico (como apresentar to somente um
rodap, por exemplo) como parte dele.
Agora ento vamos fazer uso da herana.
O conceito de herana trata-se de concentrar uma parte generalizada em um
template que ser herdado por outros, ou seja, estes outros sero uma cpia
daquele, modificando as partes que assim o desejarem. Isso muito til para se
evitar re-trabalho na construo de layouts de pginas.
76
Pois ento vamos ao trabalho.
Na pasta "templates" do projeto ( meu_blog/templates ), crie um novo
arquivo, chamado "base.html", e escreva o seguinte cdigo dentro:
<html>
<head>
<title>
{% block titulo %}Blog do Alatazan{% endblock %}
</title>
<link
rel="alternate"
type="application/rss+xml"
title="Ultimos artigos do Alatazan"
href="/rss/ultimos/"
/>
<style type="text/css">
body {
font-family: arial;
background-color: green;
color: white;
}
h1 {
margin-bottom: 10px;
}
h2 {
margin: 0;
background-color: #eee;
padding: 5px;
font-size: 1.2em;
}
.artigo {
border: 1px solid black;
77
background-color: white;
color: black;
}
.conteudo {
padding: 10px;
}
</style>
</head>
<body>
{% include "rodape.html" %}
</body>
</html>
Voc pode notar que se trata do mesmo cdigo HTML que fizemos no template
"artigo_archive.html", com algumas modificaes. E essas modificaes foram a
remoo de partes do cdigo que eram especficas daquela pgina (uma listagem de
artigos), e a criao de reas potencialmente modificveis. Essas reas so as
template tags {% block %}.
A template tag {% block %} indica que naquele espao aberto por {% block
%} e fechado por {% endblock %}, os templates que herdarem este podem fazer
mudanas adequadas sua realidade.
Salve o arquivo. Vamos agora voltar a editar o template "artigo_archive.html",
da pasta blog/templates/blog e modificar para todo o arquivo ficar assim:
{% extends "base.html" %}
{% block conteudo %}
{% for artigo in latest %}
<div class="artigo">
78
<a href="
{% url blog.views.artigo artigo_id=artigo.id %}">
<h2>{{ artigo.titulo }}
</h2>
</a>
<div class="conteudo">
Publicado h {{ artigo.publicacao|timesince }}<br/>
{{ artigo.conteudo }}
</div>
</div>
{% endfor %}
{% endblock %}
79
{% block h1 %}{{ artigo.titulo }}{% endblock %}
{% block conteudo %}
{{ artigo.conteudo }}
{% endblock %}
Veja que extendemos o mesmo template de herana ( base.html ). Mas desta vez
declaramos os outros blocos, pois precisvamos mudar seus contedos.
O caso do bloco {% block titulo %} especial, pois ele possui um elemento
bastante til aqui, o {{ block.super }}.
O {{ block.super }} uma varivel que carrega o contedo do bloco no template
herdado, e quando ele informado, isso significa que naquele lugar deve ser
mantido o contedo do bloco original. Ou seja, ns mudamos o ttulo da pgina,
mas mantivemos o original, apenas acrescentando esquerda o trecho adicional que
queramos.
Agora salve o arquivo. Feche o arquivo. V at o navegador e veja o resultado:
Gostou do resultado?
Agora podemos representar a herana e composio dos nossos templates da
seguinte forma:
80
Agora, partindo para separar as coisas...
Se eu gostei? Mas claro, isso fascinante, logo logo vou poder colocar meu
blog no ar e...
Num rpido relance, Alatazan interrompeu seu discurso ao ver um vulto passar
pela janela. Ele no identificou aquele movimento rpido, mas algo lhe lembrou
daquela vez que havia conhecido Ballzer, na praa prxima de sua casa, em Katara.
Ele coou a cabea e percebeu que j era tarde. A empolgao o manteve ligado
nas explicaes de Cartola e Nena e agora era a hora de voltar rapidamente para
casa. De outra forma, poderia perder a aula de xadrez daquele dia.
Alatazan, leve esse livro com voc, vai te ajudar a pegar alguns lances mais
comuns de Xadrez - Nena pegou um livro na estante e entregou a ele. - voc vai
notar que cada pea tem uma dinmica diferente, e algumas delas nem se pode
chamar de dinmica, de to limitadas que so... mas cada uma cumpre o seu
papel.
Alatazan agradeceu com um gesto tpico de Katara e se despediu.
No prximo captulo vamos separar algumas coisas do template, aplicar imagens
e conhecer um pouco mais sobre como fazer isso.
81
Captulo 8: Trabalhando com arquivos estticos
Os arquivos estticos
Um site no se resume a pginas em HTML. Ele tambm possui imagens,
arquivos CSS, JavaScript, Flash e outros formatos diversos.
Mas h uma diferena fundamental entre umas e outras partes do site, e isso no
restrito ao tipo de contedo que ser enviado para o navegador, e sim a como
aquele contedo se comporta no site.
Ele dinmico ou esttico?
A pgina inicial do blog apresenta um resultado diferente a cada vez que
criado um novo artigo. Seu contedo poderia variar tambm dependendo do usurio
82
que est autenticado naquela hora. Essa uma pgina dinmica.
J a foto sorridente de Alatazan no canto superior esquerdo do site, ser a
mesma at que algum substitua o arquivo por outro. Ento, ela esttica.
Mas que foto? No h nenhuma foto por l. Ento isso que vamos fazer.
Antes de mais nada, no se esquea de executar o projeto no Django, clicando
duas vezes sobre o arquivo executar.bat da pasta do projeto.
Agora abra o arquivo de template artigo_archive.html, da pasta
**blog/templates/blog para edio, e localize a seguinte linha:
{% block conteudo %}
Salve o arquivo. Feche o arquivo. Essa tag HTML vai exibir uma imagem
chamada foto.jpg no caminho apontado pela varavel {{ MEDIA_URL }}.
A varivel {{ MEDIA_URL }} contm o mesmo valor contido na setting
MEDIA_URL.
Ento vamos agora abrir o arquivo setings.py da pasta do projeto para edio, e
localizar esta setting:
MEDIA_URL = ''
Voc deve ser lembrar de que j usamos essa funo os.path.join() com a
setting PROJECT_ROOT_PATH no mesmo? E ela retorna para a setting
MEDIA_ROOT o caminho completo para a pasta do projeto ( meu_blog ) somada
83
com a subpasta media.
E por fim, ainda temos uma coisa para fazer. Localize a setting
ADMIN_MEDIA_PREFIX e veja como est:
ADMIN_MEDIA_PREFIX = '/media/'
84
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^$', 'django.views.generic.date_based.archive_index',
{'queryset': Artigo.objects.all(),
'date_field': 'publicacao'}),
(r'^admin/(.*)', admin.site.root),
(r'^rss/(?P<url>.*)/$',
'django.contrib.syndication.views.feed',
{'feed_dict': {'ultimos': UltimosArtigos}}),
(r'^artigo/(?P<artigo_id>\d+)/$', 'blog.views.artigo'),
(r'^media/(.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT}),
)
Ou pode usar uma foto sua. Como preferir. O que importa que essa imagem
deve ser do formato JPEG, o nome do arquivo deve ser "foto.jpg", e deve ser
85
colocada na pasta media. Isso porque este o endereo indicado pela tag HTML
desta imagem, l no template.
Feito isso, agora temos a imagem da foto do Alatazan, devidamente salva na
pasta correta e com as todas referncias finalizadas. Vamos ao navegador? Pois
bem, localize no seu navegador a URL principal do blog:
http://localhost:8000/
E veja o resultado:
86
Na pasta do projeto, abra a pasta templates. Nesta pasta, abra o arquivo
base.html para edio, e substitua o seguinte trecho de cdigo:
<style type="text/css">
body {
font-family: arial;
background-color: green;
color: white;
}
h1 {
margin-bottom: 10px;
}
h2 {
margin: 0;
background-color: #eee;
padding: 5px;
font-size: 1.2em;
}
.artigo {
border: 1px solid black;
background-color: white;
color: black;
}
.conteudo {
padding: 10px;
}
</style>
Por este:
<link rel="stylesheet" type="text/css"
href="{{ MEDIA_URL }}layout.css"/>
87
<html>
<head>
<title>
{% block titulo %}Blog do Alatazan{% endblock %}
</title>
<link
rel="alternate"
type="application/rss+xml"
title="Ultimos artigos do Alatazan"
href="/rss/ultimos/"
/>
<link rel="stylesheet" type="text/css"
href="{{ MEDIA_URL }}layout.css"/>
</head>
<body>
{% include "rodape.html" %}
</body>
</html>
88
Opa! Parece que perdemos o nosso visual verde bandeira! Sim, mas vamos
agora criar o arquivo de CSS para voltar ao normal.
Na pasta "media" do projeto, crie um arquivo chamado "layout.css" e escreva
o seguinte cdigo dentro:
body {
font-family: arial;
background-color: green;
color: white;
}
h1 {
margin-bottom: 10px;
}
h2 {
margin: 0;
background-color: #eee;
padding: 5px;
89
font-size: 1.2em;
}
.artigo {
border: 1px solid black;
background-color: white;
color: black;
}
.conteudo {
padding: 10px;
}
90
http://localhost:8000/artigo/1/
91
from django.template import RequestContext
92
interrompeu Nena, muito enftica - e este um ponto bem confuso, s vezes...
Sim, mesmo... um pouco confuso. Mas depois que voc aprende,
simples entender que:
preciso ajustar as settings MEDIA_URL, MEDIA_ROOT e
ADMIN_MEDIA_PREFIX
A setting MEDIA_URL uma URL para a pasta MEDIA_ROOT
preciso criar a pasta media na pasta do projeto
preciso criar a URL ^media/
Toda referncia a arquivos estticos nos templates devem iniciar com
{{ MEDIA_URL }}
Muito bom, muito bom! - foi a vez de Cartola.
Agora que tenho a minha foto na pgina principal, eu estou sentindo falta de
um lugar para falar quem sou eu, e alguma informao a mais...
Sim. Vamos fazer assim: amanh vamos estudar sobre Pginas Planas, pra
isso que elas servem! Agora vamos embora que o calor est nos convidando pra
um passeio l na rua.
93
Captulo 9: Pginas de contedo so FlatPages
'blog',
)
Agora vamos adicionar o middleware que faz todo o trabalho mgico das
FlatPages. Localize a setting MIDDLEWARE_CLASSES ainda no arquivo
settings.py e adicione a seguinte linha:
'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
95
Com o banco de dados gerado, podemos abrir o navegador na URL do admin:
http://localhost:8000/admin/
96
... e ao rolar a barra de rolagem, ainda h este outro campo para informar:
97
Opa! Temos um erro aqui!
Mas simples: para uma FlatPage funcionar, necessrio haver um
template onde ela ser "encaixada".
Portanto, vamos agora pasta do projeto e abrir dali a pasta "templates".
Dentro da pasta "templates", crie uma nova pasta, chamada "flatpages". Dentro
da nova pasta, crie o arquivo "default.html". Abra-o para edio e escreva o
seguinte cdigo dentro:
{% extends "base.html" %}
{% block conteudo %}
98
{{ flatpage.content }}
{% endblock %}
Difcil? Uma baba! Mas h uma coisa feia ali. Lembra-se de que escrevemos um
texto com duas linhas? Sim, mas elas se transformaram em uma s... mas o que
aconteceu?
A resposta simples: o HTML gerado para textos com salto de linha ignora
esses saltos de linha a menos que haja a tag HTML <br/> entre elas. Mas o Django
muito legal, ento h uma soluo mais amigvel para isso.
Volte ao arquivo de template que acabamos de criar e localize a seguinte linha:
{{ flatpage.content }}
99
Pronto! FlatPages so isso que voc acabou de ver!
Chega de mau humor, Alatazan, claro que queremos fazer contato com voc!
Tranquilo, tranquilo hein gente... - falou um Alatazan relaxado.
Tranquilo? Isso at sem graa de to tranquilo - foi a resposta empolgada do
Cartola
, bastou adicionar a aplicao ao projeto, adicionar o middleware e criar
o template. S isso!
E a s ir at o Admin e criar quantas pginas quiser, usando HTML e
nunca se esquecendo de que a URL da Flatpage sempre inicia e termina com a
barra ( / ). - completou Nena.
Agora tem uma coisa esquisita nesse seu blog, cara. Voc deixou um rodap
escrito "Por favor, no faa contato..." no assim que se faz. Porque voc no
cria uma pgina de Contato?
Alatazan olhou para ele como se fosse um daqueles ndios pelados da baa de
Guanabara vendo navios portugueses pela primeira vez.
! isso, vamos fazer uma pgina de contato, ento!
Pois bem, ento isso pessoal!
100
Captulo 10: Permitindo contato do outro lado do
Universo
Salve o arquivo. Feche o arquivo. Agora vamos ao navegador para ver como fica
a pgina principal do site:
http://localhost:8000/
Veja:
Puxa vida, mas que tamanho de erro este? Mas a parte mais importante dessa
mensagem de erro isto:
NoReverseMatch: Reverse for 'meu_blog.views.contato' with
arguments '()' and keyword arguments '{}' not found.
Bom, continuamos com uma mensagem de erro, mas agora ela mudou, veja:
ViewDoesNotExist: Could not import views. Error was: No module
named views
def contato(request):
return render_to_response(
'contato.html',
locals(),
context_instance=RequestContext(request),
103
)
Agora o nosso link funcionou, apesar de ficar um azul perdido no verde. Vamos
ajustar o estilo de nossa pgina para melhorar isso.
Na pasta do projeto, v pasta "media", abra o arquivo "layout.css" para edio
e acrescente esse trecho de cdigo ao final do arquivo:
.rodape {
border: 1px solid black;
background-color: white;
color: gray;
margin-top: 10px;
padding: 10px;
104
}
Agora sim! E agora, ao clicar sobre o link que criamos, veja o que acontece:
105
Bom, nada mais claro: a template "contato.html" no existe.
Agora, v pasta "templates" do projeto e crie um novo arquivo: "contato.html",
com o seguinte cdigo dentro:
{% extends "base.html" %}
{% block conteudo %}
{% if mostrar %}<h3>{{ mostrar }}</h3>{% endif %}
<form method="post">
<table>
{{ form }}
<tr>
<th> </th>
<td><input type="submit" value="Enviar contato"/></td>
</tr>
</table>
</form>
{% endblock conteudo %}
106
Mas como notou, s h o boto "Enviar contato". De volta ao cdigo, veja que
escrevemos uma varivel {{ form }}. esta varivel que vai trazer a mgica para
dentro do template. E como ela no foi declarada na nossa view, bastante natural
que aqui no aparea nada alm do que vemos.
Mas isso no basta, afinal, quem o FormContato ali? Ento agora, localize esta
linha:
from django.template import RequestContext
class FormContato(forms.Form):
nome = forms.CharField(max_length=50)
107
email = forms.EmailField(required=False)
mensagem = forms.Field(widget=forms.Textarea)
class FormContato(forms.Form):
nome = forms.CharField(max_length=50)
email = forms.EmailField(required=False)
mensagem = forms.Field(widget=forms.Textarea)
def contato(request):
form = FormContato()
return render_to_response(
'contato.html',
locals(),
context_instance=RequestContext(request),
)
O que fizemos foi criar um formulrio. Este formulrio tem trs campos: nome,
email e mensagem. O campo "nome" do tipo para receber caracteres, numa
largura mxima de 50 caracteres. O campo "email" do tipo para receber e-mail,
mas no requerido. Por fim, o campo "mensagem" de um tipo livre, que ser
exibido como um Textarea, ou seja, uma caixa de texto maior que a habitual, que
aceita muitas linhas livremente.
Salve o arquivo. Volte ao navegador e pressione F5 para atualizar a pgina de
contato. Veja como ficou:
108
Veja o quanto esse recurso de formulrios dinmicos do Django fantstico!
Temos o nosso formulrio sendo exibido em um piscar de olhos! Mas isso no
basta, pois ele ainda no est funcionando de fato.
Pois ento voltemos ao arquivo "views.py" para localizar a seguinte linha:
form = FormContato()
if form.is_valid():
form.enviar()
mostrar = 'Contato enviado!'
else:
form = FormContato()
110
Voc pode notar que os campos requeridos foram exigidos, e o formato do
campo de E-mail no foi aceito.
A esttica fica por conta do seu CSS.
Agora preencha todos os campos corretamente:
Nome: Mame
E-mail: mamae.do.alatazan@katara.gov
Mensagem: Ol filhinho, sou eu usando o e-mail do trabalho indevidamente
E clique sobre "Enviar contato". Veja o que acontece:
111
texto = """
Nome: %(nome)s
E-mail: %(email)s
Mensagem:
%(mensagem)s
""" % self.cleaned_data
send_mail(
subject=titulo,
message=texto,
from_email=destino,
recipient_list=[destino],
)
class FormContato(forms.Form):
nome = forms.CharField(max_length=50)
112
email = forms.EmailField(required=False)
mensagem = forms.Field(widget=forms.Textarea)
def enviar(self):
titulo = 'Mensagem enviada pelo site'
destino = 'alatazan@gmail.com'
texto = """
Nome: %(nome)s
E-mail: %(email)s
Mensagem:
%(mensagem)s
""" % self.cleaned_data
send_mail(
subject=titulo,
message=texto,
from_email=destino,
recipient_list=[destino],
)
def contato(request):
if request.method == 'POST':
form = FormContato(request.POST)
if form.is_valid():
form.enviar()
mostrar = 'Contato enviado!'
form = FormContato()
else:
form = FormContato()
return render_to_response(
'contato.html',
locals(),
113
context_instance=RequestContext(request),
)
Salve o arquivo. Feche o arquivo. Volte ao navegador e pressione F5. Ele vai
fazer uma pergunta sobre processar dados, devido ao mtodo dessa requisio ter
sido do tipo POST. Confirme a pergunta e veja o resultado:
Isso acontece por que preciso configurar seu projeto com as informaes de
qual servidor SMTP ele deve usar para enviar esta mensagem de e-mail.
Se caso seu servidor de e-mail utilizar conexo segura, acrescente esta linha:
114
EMAIL_PORT = 587
Se caso seu servidor de e-mail utilizar conexo do tipo TLS, acrescente esta
linha tambm:
EMAIL_USE_TLS = True
115
Declarou um mtodo "enviar", que d a ao que queremos ao form;
Esse mtodo formata o texto da mensagem e envia o e-mail, usando uma
funo do Django para isso;
E configurou as settings para envio de e-mails.
Ao todo foram 8 passos para cumprir a nossa misso de hoje! E de quebra
ainda fez um ajuste no visual no rodap.
Alatazan estava em xtase, seu corao da frente clareava o peito, e isso tinha a
ver com sua alegria em chegar at aqui no estudo do Django.
Bom, j que aprendemos tanto assim hoje, amanh vamos criar recursos para
seus usurios enviarem Comentrios em seu blog. Cada artigo vai ter sua prpria
lista de comentrios!
Show de bola!
116
Captulo 11: Deixando os comentrios flurem
117
Ou seja, o trecho de cdigo da setting INSTALLED_APPS fica assim:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
'django.contrib.syndication',
'django.contrib.flatpages',
'django.contrib.comments',
'blog',
)
Voc pode ver que h ali uma nova aplicao chamada "Comments":
118
Devido a uma srie de ajustes que ela sofreu para a verso 1.0, possvel que
em sua verso ela ainda no esteja traduzida por completo para portugus
brasileiro.
Mais frente, voc vai utilizar essa seo do Admin para administrar os
comentrios recebidos, pois tem hora que a pacincia no suficiente para lidar
com algumas liberdades de certos indivduos.
Pois agora vamos ao segundo passo: adicionar uma URL para a aplicao
"comments".
Na pasta do projeto, abra o arquivo "urls.py" para edio e adicione a seguinte
URL ao final da funo patterns():
(r'^comments/', include('django.contrib.comments.urls')),
119
from django.conf import settings
urlpatterns = patterns('',
(r'^$', 'django.views.generic.date_based.archive_index',
{'queryset': Artigo.objects.all(),
'date_field': 'publicacao'}),
(r'^admin/(.*)', admin.site.root),
(r'^rss/(?P<url>.*)/$', \
'django.contrib.syndication.views.feed',
{'feed_dict': {'ultimos': UltimosArtigos}}),
(r'^artigo/(?P<artigo_id>\d+)/$', 'blog.views.artigo'),
(r'^media/(.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT}),
(r'^contato/$', 'views.contato'),
(r'^comments/', include('django.contrib.comments.urls')),
)
Isso vai carregar as template tags da aplicao comments. Agora localize esta
outra linha:
{{ artigo.conteudo }}
120
Acrescente esse trecho de cdigo abaixo dela:
<div class="comentarios">
<h3>Envie um comentario</h3>
E veja o resultado:
121
textarea {
height: 100px;
}
E-mail: garota@escola.com
URL: http://escola.com/garota/
122
Bacana! Ento o envio do comentrio j funcionou! No se preocupe, vamos
mudar o visual dessa pgina a j-j. Agora volte pgina anterior no navegador (
ALT+Esquerda ).
Vamos agora exibir os comentrios do artigo?
Volte ao template "artigo.html" que estvamos editando e localize a seguinte
linha:
<div class="comentarios">
{% load comments %}
124
{% block conteudo %}
{{ artigo.conteudo }}
<div class="comentarios">
<h3>Comentarios</h3>
<h3>Envie um comentario</h3>
</div>
{% endblock %}
125
Primeiro, observe a caixa destacada. Ali ser exibida a pr-visualizao do
comentrio, antes de confirmar o seu envio. Esta opo no obrigatria, voc
pode escolher entre trabalhar com pr-visualizao ou no, e vamos ver como fazer
isso em breve.
Mas o que precisamos fazer agora dar um jeito no visual dessa pgina. Ela no
est nada boa.
Na pasta "templates" da pasta do projeto, crie uma nova pasta "comments".
Dentro da nova pasta crie um arquivo chamado "base.html" e escreva dentro o
seguinte cdigo:
{% extends "base.html" %}
{% block titulo %}
{% block title %}{% endblock %}
{% endblock %}
{% block conteudo %}
{% block content %}{% endblock %}
{% endblock %}
Salve o arquivo.
126
Mas que confuso com tantos blocks! Bom, o que o cdigo acima est fazendo
levar todos os templates da contrib "comments" para estenderem o template do
seu blog, ou seja, eles sero encaixados no seu visual.
Volte ao navegador, pressione F5 - ser feita uma pergunta sobre os dados
enviados, apenas confirme - e veja como ficou:
127
Veja que nesta pgina a mudana no template tambm surtiu efeito. Mas
precisamos ajustar algo aqui. Ao menos um link para a pgina principal
necessria, certo? No podemos deixar uma pgina sem meios para dar
continuidade.
{% block conteudo %}
<p>
Obrigado por enviar seu comentrio, logo vou dar uma olhada!
</p>
128
Agora, s lanar vrios artigos e comentrios para ver como a coisa funciona
bem!
Nos templates que usam template tags de comentrios, tive que carreg-las
com {% load comments %};
Usei as template tags {% render_comment_form %} e {%
get_comment_list %}, para gerar um formulrio e obter os comentrios de
um artigo, respectivamente;
E defini um template "base.html" para ajustar as pginas de comentrios
ao layout do site;
Exatamente! E voc ainda fez um ajuste no CSS para dar uma quebra de
linha nas tags <label>. - Cartola completou.
Joia! Agora posso colocar esse blog no ar!
Mesmo? Voc acha que j est bom pra fazer o deploy? - Nena perguntou, ela
tambm est ansiosa para ver o blog de Alatazan estrear no servidor.
Bom, na verdade ainda quero melhorar o visual do site, mas...
J sei, amanh vamos tirar o dia pra ver HTML e CSS o suficiente para
transformar seu blog com um bom layout!
Ento combinado.
No prximo captulo, vamos trabalhar novamente no layout do site, mas agora
com um foco mais profissional: vamos dar um visual tpico de um blog bem
elaborado ao site do Alatazan, afinal, com tanto estudo, ele merece algo bem
apresentvel e o principal: no ar.
129
Captulo 12: Um pouco de HTML e CSS s faz bem
Alatazan aceitou o convite de Nena para assistir estreia de sua irm mais nova
em um desfile de moda. Estava um pouco frio, mas ainda era cedo, chegaram ao
ginsio cerca de uma hora e meia antes da abertura, pois foi Nena que dirigiu para
levar a irm.
Como estavam por ali, entraram no vestirio com a menina, e acabaram vendo
como a coisa acontece nos bastidores.
engraado como essas coisas parecem uma completa baguna para quem no
do ramo. Panos, fitas, faixas, coisas coloridas, arames e toda sorte de agulhas e
linhas eram s uma frao da variedade de coisas ali, e no comeo as modelos se
pareciam mais com atrizes de picadeiro.
O cheiro de cola imperava no ar, e havia tambm um calorzinho com cheiro de
ferro de passar ligado, do lado direito, prximo cortina.
"Neninha", como Alatazan chama carinhosamente a irm de Nena, seria uma
das ltimas a participar e eles ficaram l dentro o suficiente para ver as primeiras
sarem do vestirio e caminharem para a passarela.
O interessante que depois de toda a arrumao, em questo de segundos a
coisa parece sair de uma situao incompreensvel para uma apresentao louvvel.
A moa que antes parecia um papagaio depenado, j estava agora refinada,
delicada, cheia de glamour.
Ahh, j ia esquecendo... foi nesse dia que Nena e Alatazan estudaram XHTML e
CSS e o resultado foi muito interessante, acompanhe...
{% block meta %}
<meta http-equiv="Content-type"
content="text/html;
charset=utf-8" />
<meta http-equiv="Content-Language" content="pt-br" />
<meta name="keywords"
content="Python, Django, Alatazan, Katara, blog" />
<meta name="description" content="Este o blog do Alatazan, um
katarense aprendendo Django." />
{% endblock meta %}
{% block feeds %}
<link rel="alternate"
type="application/rss+xml"
title="Ultimos artigos do Alatazan"
href="/rss/ultimos/" />
131
{% endblock feeds %}
{% block style %}
<link rel="stylesheet"
type="text/css"
href="{{ MEDIA_URL }}layout.css"/>
{% endblock style %}
{% block scripts %}
{% endblock scripts %}
</head>
<body>
<div id="tudo">
<div id="topo">
{% block topo %}
<div id="foto"> </div>
Blog do Alatazan
{% endblock topo %}
</div>
<div id="menu">
{% block menu %}
{% spaceless %}
<ul>
<li><a href="/">Pagina inicial</a></li>
<li><a href="/sobre-mim/">Sobre mim</a></li>
<li><a href="{% url views.contato %}">Contato</a></li>
</ul>
{% endspaceless %}
{% endblock menu %}
</div>
132
<div class="corpo">
{% block conteudo %}{% endblock %}
</div>
{% include "rodape.html" %}
</div>
</body>
</html>
HTML ou XHTML?
A principal mudana estrutural que fizemos ali foi que samos do HTML para
o XHTML. Isso aconteceu por causa dessas cinco linhas:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="pt-br"
lang="pt-br">
133
ao invs de <br>);
Todas as tags preenchidas devem ser fechadas (ex.: <option>teste</option>
ao invs de <option>teste);
Todos os atributos das tags devem ser abertos e fechados com aspas duplas
(ex.: <p align="center"> ao invs de <p align=center>).
DOCTYPE
O DOCTYPE indica qual o tipo da pgina. Cada tipo implica em um conjunto
de regras diferentes que sero aplicadas pgina quando esta for renderizada.
Os tipos existentes so:
Transitional - o tipo mais flexvel. Permite tags HTML que so marcadas
como deprecated (marcadas como descontinuadas) e permite tambm pginas
que no usem CSS da maneira devida;
Strict - o tipo mais rgido. Aplica todas as regras "ao p da letra";
Bloco "meta"
Voc viu que definimos um {% block meta %}? Pois bem, ali que vamos
descrever tags HTML de meta-definies. As que definimos agora so:
<meta http-equiv="Content-type"
content="text/html;
charset=utf-8" />
134
Esta outra acima define as palavras-chave para busca. O ideal informar entre 5
e 10 palavras-chave, pois isso torna sua pgina mais consistente no momento de
ser indexada por mecanismos de busca como o Google.
No invente de colocar ali 20 ou 30 palavras pensando que isso vai fazer sua
pgina ficar "mais importante". Uma atitude dessa faz as palavras contidas
perderem seu "valor" no momento da busca, e o tiro sai pela culatra.
<meta name="description" content="Este o blog do Alatazan, um
katarense aprendendo Django." />
Divises do layout
div "tudo"
Com esta div, criamos um continer capaz de abranger toda a pgina, assim
podemos delimitar a pgina para ficar mais amigvel a resolues de tela menores,
e tambm com uma aparncia mais agradvel.
div "topo"
o novo continer para o topo da pgina, onde estar a identificao do site,
presente em todas as pginas.
div "menu"
o novo continer para o menu geral do site. dentro dela h uma lista no-
numerada ( <ul> ), que tem cada um de seus itens ( <li> ) como sendo um item do
menu.
div "corpo"
o novo continer para o contedo da pgina.
Bom, agora que tudo foi esclarecido, v ao navegador no seguinte endereo:
http://localhost:8000/
135
E veja como ficou:
Bom, est na cara que no mudou muita coisa n? Mas agora vamos mgica, e
a que voc precisa observar com maior ateno.
Da forma que estruturamos o HTML, podemos ajustar nosso layout para ficar
assim:
136
Para faz-lo, v pasta do projeto e abra a pasta "media". Dali, abra o arquivo
"layout.css" para edio.
Completamente sem estilo CSS, certo? Ok, agora acrescente o seguinte trecho
de cdigo ao arquivo de CSS:
body {
font-family: arial;
background-color: #eee;
color: #333;
}
h1 {
margin: 10px 20px 10px 20px;
}
h2 {
margin: 0;
font-size: 1.2em;
137
}
#tudo {
position: absolute;
background-color: white;
margin: 20px 0 20px -390px;
width: 760px;
left: 50%;
border: 10px solid #aaa;
}
138
Agora j temos uma caixa fixa no centro, certo? Vamos agora acrescentar este
trecho de cdigo:
#topo {
font-size: 3em;
margin: 20px;
}
#topo #foto {
float: right;
background-image: url(/media/foto.jpg);
background-repeat: no-repeat;
background-position: -20px -30px;
width: 56px;
height: 56px;
border: 1px solid #47a;
}
139
Agora j temos o topo da pgina! Agora acrescente mais este:
.corpo {
margin: 20px 20px 0 20px;
}
.rodape {
clear: both;
overflow: hidden;
background-color: #89a;
margin: 20px;
font-size: 0.8em;
color: white;
padding: 10px;
text-align: center;
}
.rodape a {
color: white;
}
140
Pronto, nosso contedo e rodap tambm esto resolvidos! Agora acrescente
mais este trecho de cdigo ao CSS:
/* Menu principal */
#menu {
clear: both;
overflow: hidden;
background-color: #47a;
margin-top: 10px;
height: 26px;
font-size: 0.8em;
font-weight: bold;
color: white;
}
#menu ul {
margin: 0;
padding: 0;
}
#menu ul li {
141
float: left;
list-style: none;
padding: 5px;
}
#menu ul li a:hover {
background-color: #79b;
color: white;
}
Puxa, o nosso menu j virou outro! Agora acrescente mais esse trecho de
cdigo:
/* Artigo do blog */
142
.artigo h2 {
text-decoration: underline;
}
.artigo {
margin: 10px 0 10px 0;
}
.artigo a {
color: black;
}
.conteudo {
padding: 10px;
}
143
form label {
display: block;
}
textarea {
height: 100px;
}
th {
text-align: right;
padding-right: 5px;
}
/* Comentarios */
.comentarios {
border-top: 1px solid silver;
margin-top: 20px;
}
.comentarios hr {
border-width: 0;
height: 1px;
border-top: 1px solid #ddd;
}
144
Pois bem, agora veja como est o nosso CSS depois de tudo:
body {
font-family: arial;
background-color: #eee;
color: #333;
}
h1 {
margin: 10px 20px 10px 20px;
}
h2 {
margin: 0;
font-size: 1.2em;
}
/* Layout */
#tudo {
position: absolute;
145
background-color: white;
margin: 20px 0 20px -390px;
width: 760px;
left: 50%;
border: 10px solid #aaa;
}
#topo {
font-size: 3em;
margin: 20px;
}
#topo #foto {
float: right;
background-image: url(/media/foto.jpg);
background-repeat: no-repeat;
background-position: -20px -30px;
width: 56px;
height: 56px;
border: 1px solid #47a;
}
.rodape {
clear: both;
overflow: hidden;
background-color: #89a;
margin: 20px;
font-size: 0.8em;
color: white;
padding: 10px;
text-align: center;
}
146
.rodape a {
color: white;
}
/* Menu principal */
#menu {
clear: both;
overflow: hidden;
background-color: #47a;
margin-top: 10px;
height: 26px;
font-size: 0.8em;
font-weight: bold;
color: white;
}
#menu ul {
margin: 0;
padding: 0;
}
#menu ul li {
float: left;
list-style: none;
padding: 5px;
}
147
#menu ul li a:hover {
background-color: #79b;
color: white;
}
/* Artigo do blog */
.artigo h2 {
text-decoration: underline;
}
.artigo {
margin: 10px 0 10px 0;
}
.artigo a {
color: black;
}
.conteudo {
padding: 10px;
}
/* Formularios */
form label {
display: block;
}
textarea {
height: 100px;
}
148
th {
text-align: right;
padding-right: 5px;
}
/* Comentarios */
.comentarios {
border-top: 1px solid silver;
margin-top: 20px;
}
.comentarios hr {
border-width: 0;
height: 1px;
border-top: 1px solid #ddd;
}
149
Use unidade "em" para tamanhos de fonte;
Caso queira exibir somente uma parte retangular de uma imagem, crie uma
div com a imagem em background, depois posicione a imagem onde quiser.
Ajustando o rodap
Bom, agora que temos um CSS bem elaborado, vamos fazer um ltimo ajuste.
Na pasta "templates" da pasta do projeto, abra o arquivo "rodape.html" para
edio e o modifique para ficar assim:
<div class="rodape">
Obrigado por passar por aqui. Volte sempre.
</div>
Salve o arquivo. Feche o arquivo. Agora nosso rodap tem uma cara um pouco
mais de... rodap!
150
Captulo 13: Um pouco de Python agora
Cartola estava excitado com o fato do rob ter sido programado em Python, mas
estava achando estranhas algumas linhas de cdigo que tinham erros de lgica
incomuns.
Alatazan j desconfiou logo:
Ballzer, voc andou futricando na programao desse rob? Vai me dizer que
j est me arrumando encrenca?
Ballzer baixou seus olhos, tratou de se esconder um pouco mais atrs da cama
de Cartola e assentiu arrependido.
Voc est me dizendo que esse chimpanz metlico em forma de polvo,
programa em Python? - Cartola perguntou um pouco espantado.
Programar no programa, sabe... mas ele adora mexer nas mesmas coisas que
eu estou mexendo...
Coitadinho, no fala assim com ele, ele seu maior f, Alatazan.
Nena disse isso mas Alatazan reagiu com aquela cara de "no piore as coisas,
por favor".
Bom, ento vamos aproveitar esse momento pra falar sobre algumas coisas
fundamentais do Python. importante saber essas coisas antes de continuar
com o estudo do Django, sabia?
151
para quem gosta de gambiarras, muito pelo contrrio, ela indicada a pessoas que
gostam de se divertir programando, mas fazendo as coisas do jeito certo.
Mas de fato, o Python rompe paradigmas, e que pode ser chamada tambm de
"linguagem multi-paradigmas".
Interpretada ou Compilada?
O Python tambm trabalha com ambos os paradigmas. Quer proteger o cdigo?
Leve somente os arquivos .pyc. Isso vai dificultar o suficiente para quem quiser
explorar suas regras de negcio. Quer trabalhar diretamente nos arquivos de
cdigo-fonte? Basta levar os arquivos .py.
Um cdigo escrito em Python pode ser interpretado de vrias formas:
a forma tradicional, tecnicamente chamada CPython, a forma como temos
trabalhado neste estudo;
o shell interativo do Python, uma interpretao dinmica em shell
semelhante ao prompt do MS-DOS, onde possvel declarar objetos, classes,
funes e fazer outras coisas de forma on-line;
a compilao para classes Java ( arquivos .class ), usando Jython, para ser
executado em mquina virtual JVM;
a compilao para bytecode .Net, usando IronPython, para ser executado em
mquina virtual .Net;
e outras formas de compilao e/ou interpretao para dispositivos de
eletrnica e celulares.
152
Para saber de outras plataformas onde o Python roda, veja esta pgina da Web:
http://www.python.org/download/other/
Aqui, preciso manter alguns cuidados para evitar problemas ao, por exemplo,
executar em um servidor Linux um programa criado e testado em Windows.
As diferenas no so grandes, mas importante ficar de olho nelas. Um caso
clssico o do separador de caminhos de arquivos. No Windows o separador uma
barra invertida ( \ ), nos demais uma barra comum ( / ). Neste caso, voc pode
usar sempre a barra comum ou o elemento os.sep.
Mas raramente essas diferenas chegam a dar dores de cabea, pois o Python j
faz a maior parte para voc.
imprimir_duas_vezes('Tarsila do Amaral')
153
no ir se resolver. preciso adicionar o seguinte cdigo ao arquivo, na primeira
linha:
# -*- coding: utf-8 -*-
def imprimir_duas_vezes(texto):
# Imprime o texto uma vez
print texto
imprimir_duas_vezes('Tarsila do Amaral')
Edentao
Outra caracterstica fundamental do Python, que ele foi pensado para ser
compreendido pelo maior nmero possvel de pessoas. Isso fez com que algumas
definies milenares fossem chutadas para o espao em busca de algo prtico, claro
e que ajudasse tudo isso de forma simptica (neste momento, Ballzer soltou um
sorriso to largo que quase separou seu corpo em dois). A grande sacada foi a
edentao padronizada para todo o cdigo-fonte.
A edentao da linha muda quando esta faz parte de um bloco declarado na
linha anterior.
154
Blocos so sempre iniciados por uma linha que termina com o sinal de dois-
pontos ( : ).
Veja este cdigo novamente, por exemplo:
# -*- coding: utf-8 -*-
def imprimir_duas_vezes(texto):
# Imprime o texto uma vez
print texto
imprimir_duas_vezes('Tarsila do Amaral')
Esta linha define uma nova funo, e inicia o bloco de cdigo que faz parte
dessa nova funo. Da em diante, as linhas so edentadas com 4 espaos da
esquerda para a direita, o que d uma leitura agradvel do cdigo para quem estava
l fora tomando um ar e chegou ali, coando a orelha direita, enquanto mastiga um
palito de dentes ainda do almoo.
A sbita sensao esta:
Sim, claro, j entendi o que esse cdigo faz.
As linhas continuam edentadas at que uma delas volta edentao anterior,
veja:
imprimir_duas_vezes('Tarsila do Amaral')
Ou seja, nenhum espao esquerda. Isso quer dizer que aquele bloco acabou,
aquele trecho de cdigo da funo durou enquanto a edentao estava l, com 4
espaos ou mais esquerda, mas agora que a edentao voltou ao estado inicial,
voltamos ao assunto anterior.
Compreendido?
Use sempre mltiplos de 4 espaos (4, 8, 12, etc.). Nunca utilize tabulao,
pois isso seria desastroso para o cara do palito de dentes, para o seu substituto nas
frias ou para voc mesmo, alguns dias depois. Use sempre 4 espaos para
edentar de bloco em bloco.
155
Conhecendo o Python interativo
Agora, v ao Menu Iniciar e escolha a opo "Executar Programa". Escreva
"python" no campo e clique em "Ok".
No Linux, voc pode executar o Console, digitar "python" e teclar ENTER.
A janela de modo texto do MS-DOS (ou do Console, no Linux) ser aberta com
um prompt assim:
Tipagem
No Python, a tipagem dos dados e objetos dinmica e forte.
"Dinmico" quer dizer que ao uma nova varivel, ou um parmetro de uma
funo, no preciso informar qual o seu tipo, nem mesmo defini-la antes de us-
la. Basta atribuir um valor a ela quando necessrio.
No entanto, internamente todo valor baseado em algum tipo de dado, que por
sua vez uma classe. Uma vez que um valor atribudo a uma varivel, ela passa a
se comportar da forma que a classe daquele valor foi definida para se comportar.
Por isso, ela "forte".
Para ver como isso funciona, volte ao shell interativo e digite a sequncia de
comandos abaixo. Escreva somente as linhas iniciadas por ">>> ", e claro, ignore
o ">>> ", digitando somente o restante da linha.
>>> nome = 'Leticia'
>>> nome
156
'Leticia'
>>> nome.__class__
<type 'str'>
>>> type(nome)
<type 'str'>
2. escrevemos o nome da varivel para que seu valor original seja exibido
na linha de baixo, ou seja: 'Leticia';
3. na linha seguinte, informamos o atributo interno do Python que retorna
a classe daquele objeto, e ele mostrou que o valor contido na varivel
"nome" um tipo bsico de string ( "<type 'str'>" );
4. e na ltima linha usamos uma outra forma de fazer a mesma coisa da
linha anterior.
Agora faa algo semelhante, s que desta forma:
>>> idade = 28
>>> idade
28
>>> idade.__class__
<type 'int'>
Veja que o valor "28" foi interpretado como nmero inteiro ( "<type 'int'>" ).
Veja esses outros:
>>> nota = 8.7
>>> nota
8.6999999999999993
>>> nota.__class__
<type 'float'>
>>> mulher = True
>>> mulher
True
>>> mulher.__class__
<type 'bool'>
>>> nota * idade
157
243.59999999999997
>>> idade * nota
243.59999999999997
Como pode ver, para trabalhar com datas, preciso importar um pacote
chamado "date", de dentro de outro pacote, chamado "datetime".
Importar um pacote ou objeto trata-se de fazer o Python saber que quando
aquele elemento for citado, ele deve ser localizado em uma biblioteca diferente do
mdulo em que voc est agora, e diferente tambm da biblioteca built-in do
Python, que carregada automaticamente.
H outras formas de se importar um pacote ou objeto, veja:
>>> import datetime
>>> datetime.date.today()
datetime.date(2008, 11, 24)
158
J neste ltimo bloco, importamos todos os elementos de "datetime", o que
inclui tambm o elemento "date", ento o usamos logo em seguida.
Acontece, que Alatazan sabe que quando se traz uma manada de elefantes de
uma regio da floresta, e outra manada de elefantes de outra regio da floresta, mas
no se usa nem um papelzinho para dizer que onde vieram, ento a baguna est
definitivamente... feita!
E quando se usa esse famigerado "from algum_lugar import *" e outro "from
outro_lugar import *", acontece a mesma coisa: voc no sabe quem veio, e
tambm no sabe de onde um elemento especfico veio, o que muito ruim.
Portanto no aconselhvel o uso de "import *", a menos que seja em um caso
especfico e simples.
Isso se chama "namespace".
Declarao de classes
Vamos agora declarar uma classe no shell? Pois ento digite as linhas de
cdigo abaixo. As linhas iniciadas com "... " so blocos, portanto, use os 4 espaos
para edentar o bloco.
>>> class Pessoa:
... nome = 'Leticia'
... idade = 28
... nota = 8.7
... mulher = True
... # nao se esqueca da edentacao para continuar o bloco
... def andar(self, passos=10):
... if self.idade > 120:
... print 'Nao foi possivel'
... else:
... print 'Andou %d passos!'%passos
...
>>>
159
aliviadora para aquele mesmo cara do palito.
Em terceiro, voc deve notar que, no shell interativo, quando um bloco tem um
espao em branco entre suas linhas (para manter a esttica e facilidade de leitura),
este deve seguir a mesma edentao, justamente porque seno ele vai pensar que
voc acabou de fechar o bloco, o que no a sua inteno naquele momento. Mas
essa preocupao no necessria quando se est escrevendo cdigo em um
arquivo .py.
160
somente na declarao, e no na execuo do mtodo.
>>> mychell.andar(15)
Andou 15 passos!
Veja s:
Primeiro, declaramos uma nova funo, chamada "inicializador", com os
atributos self, nome, idade, nota e mulher. Os dois ltimos possuem valores
default.
A seguinte linha diz, em outras palavras: "o atributo "self.nota" deve receber o
valor do parmetro "nota" somente se este tiver um valor vlido, do contrrio,
recebe o seu prprio valor para continuar tudo como est".
Neste caso, um valor vlido um valor verdadeiro. Para o Python, os valores
0, False, None, '', (), [] e {} no so verdadeiros.
... self.nota = nota or self.nota
161
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: inicializador() takes at least 3 arguments (1 given)
No cdigo acima, ao instanciar a classe Pessoa, desta vez no foi possvel, pois
o seu inicializador obriga que pelo menos os parmetros sem valor default sejam
informados.
>>> ana = Pessoa('Ana Paula', 8)
Para finalizar essa sequncia, voc deve saber que poderia informar o
inicializador com qualquer outro nome, ou poderia - o que o mais indicado
sempre - simplesmente declarar o mtodo da forma convencional, assim por
exemplo:
class Pessoa:
nome = 'Leticia'
idade = 28
nota = 8.7
mulher = True
Padro de nomenclatura
... que as variveis tenham seus nomes em caixa baixa (letras minsculas), com
as palavras separadas por underscore ( _ ), assim:
nome = 'Marta'
data_nascimento = None
... e que as classes tenham nomes no singular, com a primeira letra de cada
palavra em caixa alta, assim:
class PessoaFisica:
nome = 'Leticia'
Comentrios
... e que comentrios podem ser feitos assim:
# linha comentada que sera ignorada da mesma forma
# que esta outra linha
ou assim:
"""linha comentada que sera ignorada da mesma forma
que esta outra linha"""
163
idade = 20
Pois ao chamar a funo help() para aquela classe ou funo no shell interativo,
aquele comentrio ser interpretado como a documentao da classe. Veja com
seus prprios olhos:
>>> help(Pessoa)
Help on class Pessoa in module __main__:
class Pessoa
| Classe para atribuicao a pessoas do sistema
|
| Data and other attributes defined here:
|
| nome = None
| idade = 20
No fantstico?
NAME
datetime - Fast implementation of the datetime type.
FILE
(built-in)
CLASSES
__builtin__.object
date
datetime
time
164
---- cortamos aqui pois a documentao deste pacote extensa
Ou este:
>>> import urllib
>>> help(urllib)
Help on module urllib:
NAME
urllib - Open an arbitrary URL.
FILE
c:\python25\lib\urllib.py
DESCRIPTION
See the following document for more info on URLs:
"Names and Addresses, URIs, URLs, URNs, URCs", at
http://www.w3.org/pub/WWW/Addressing/Overview.html
See also the HTTP spec (from which the error codes are
derived):
"HTTP - Hypertext Transfer Protocol", at
A funo dir() retorna em uma lista todos atributos e mtodos daquela instncia,
e isso vale tambm para classes.
Portanto, se voc quer saber quais atributos e mtodos a string 'Beatles' possui,
faa isto:
>>> dir('Beatles')
[
165
'__add__', '__class__', '__contains__', '__delattr__',
'__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__',
'__getnewargs__', '__getslice__', '__gt__', '__hash__',
'__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__rmod__', '__rmul__', '__setattr__', '__str__', 'capitalize',
'center', 'count', 'decode','encode', 'endswith', 'expandtabs',
'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower',
'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower',
'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust',
'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines',
'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper',
'zfill'
]
upper(...)
S.upper() -> string
166
Cartola ajustou o volume de seu iPod e prosseguiu:
Vamos resumir a parada:
Python multi-paradigma: orientado a objetos, orientado a aspectos,
procedural, funcional e outros;
pode ser compilado ou interpretado;
roda em qualquer sistema operacional que seja popular;
Python unicode, por isso, preciso informar a codifio do arquivo se
for usar caracteres especiais;
Python constri blocos por edentao, sempre de 4 em 4 espaos;
Pronto! Agora com conceitos bsicos sobre HTML, CSS e Python, podemos
seguir adiante. No prximo captulo, vamos fechar a primeira iterao e partir para
mais aventuras!
167
Captulo 14: Ajustando as coisas para colocar no ar
168
Ento, mo na massa!
Antes de mais nada, execute seu projeto clicando duas vezes sobre o arquivo
"executar.bat" da pasta do projeto.
Primeiro de tudo, abra o arquivo "settings.py" da pasta do projeto para edio.
Vamos pensar as settings do projeto na seguinte diviso:
169
Localize a seguinte linha no arquivo "settings.py":
USE_I18N = True
Ou seja, nosso projeto caiu e parou de funcionar, porque houve um erro do tipo
ImportError no arquivo "settings.py". Isso aconteceu porque o arquivo
importado "local_settings.py" no foi encontrado.
Pois agora volte ao arquivo "settings.py" e modifique o trecho de cdigo que
voc acrescentou para ficar assim:
try:
from local_settings import *
170
except ImportError:
pass
LOCAL = True
DEBUG = True
TEMPLATE_DEBUG = DEBUG
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = os.path.join(PROJECT_ROOT_PATH,'meu_blog.db')
Estas so as settings que fatalmente sero modificadas quando o site for levado
para o servidor, portanto, ao traz-las para c, garantimos que na mquina local elas
permanecero como esto.
Salve o arquivo. Feche o arquivo.
Agora de volta ao arquivo "settings.py", localize esta linha:
DEBUG = True
171
Modifique-a para ficar assim:
DEBUG = False
a nossa URL para arquivos estticos, certo? Remova esse trecho de cdigo.
Agora ao final do arquivo, acrescente as seguintes linhas:
if settings.LOCAL:
urlpatterns += patterns('',
(r'^media/(.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT}),
)
172
from blog.models import Artigo
from blog.feeds import UltimosArtigos
urlpatterns = patterns('',
(r'^$', 'django.views.generic.date_based.archive_index',
{'queryset': Artigo.objects.all(),
'date_field': 'publicacao'}),
(r'^admin/(.*)', admin.site.root),
(r'^rss/(?P<url>.*)/$',
'django.contrib.syndication.views.feed',
{'feed_dict': {'ultimos': UltimosArtigos}}),
(r'^artigo/(?P<artigo_id>\d+)/$', 'blog.views.artigo'),
(r'^contato/$', 'views.contato'),
(r'^comments/', include('django.contrib.comments.urls')),
)
if settings.LOCAL:
urlpatterns += patterns('',
(r'^media/(.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT}),
)
173
ROOT_URLCONF = 'meu_blog.urls'
Esta modificao recomendvel, pois assim seu projeto trabalha de uma forma
transparente em relao PYTHONPATH - o conjunto de pastas reconhecidos
pelo Python em sua mquina virtual para encontrar pacotes e mdulos. Desta
forma, quando seu projeto for lanado ao servidor, vamos adicionar a pasta do
projeto PYTHONPATH e tudo estar resolvido.
Salve o arquivo. Feche o arquivo.
Pronto. Os primeiros passos para levar o projeto ao servidor so esses.
Vamos adiante?
Alatazan perguntou, s pra confirmar:
Ento o projeto tem comportamentos diferentes, dependendo se est no
servidor ou em minha mquina local?
Ao que Cartola respondeu:
Isso, e h um grupo de settings potencialmente adaptveis a essas situaes
diferentes, relacionadas a caminhos de pastas, modo de depurao e outras
coisas assim...
E tem tambm aquelas que so flexveis, pois recebem valores somados a
valores de settings modificadas em linhas de cdigo anteriores ou no arquivo
"local_settings.py".
Por ltimo, h aquelas que dificilmente vo se modificar, pois esto na
estrutura do projeto, como MIDDLEWARE_CLASSES ou
INSTALLED_APPS por exemplo.
Lembrando que o arquivo "settings.py" deve permanecer com as
configuraes ideais para o projeto, ou seja, as que sero usadas caso o arquivo
"local_settings.py" no exista.
O que voc precisa ficar ligado que, ao levar o seu projeto para o servidor,
o arquivo "settings.py" dever permanecer idntico, sem alteraes, pois elas
devem ser feitas apenas no arquivo "local_settings.py". Se ao levar seu projeto
para o servidor, voc fizer mudanas em outras partes do cdigo, muito
provvel que esteja no caminho errado. No se esquea disso!
O bate-bola de Cartola e Nena resumiu rapidamente o aprendizado do dia, e
Alatazan notou aqui uma diferena fundamental de hoje para os dias anteriores:
agora estavam entrando em uma fase mais profissional da coisa.
174
Captulo 15: Infinitas formas de se fazer deploy
175
Na ilustrao acima esto dispostos os elementos de um deploy bsico. Para
cada um desses passos h alternativas variadas para escolher, dependendo da
situao e preferncia dos desenvolvedores e servio de hospedagem.
As caixas em verde (Software de Repositrio e Controle de Verses, FTP e
Fabric) so caminhos os quais voc vai usar para levar os arquivos do projeto para
o servidor. Cada um deles se adequa a uma realidade diferente.
As caixas em rosa (Software servidor web, Cache e Banco de Dados), so
softwares que normalmente so instalados pelo servio de hospedagem em seu
servidor, portanto, caso contrate um servio de hospedagem muito provvel que
esses softwares j vm instalados e configurados.
As caixas em laranja (Interface com o Python/Django e Python, Django e
bibliotecas adicionais) so softwares que (exceto pelo Python em servidores
Linux) normalmente no vm instalados nos servidores e provavelmente tero de
ser instalados e configurados por voc mesmo.
E as caixas em azul (Arquivos estticos e Projeto do site) so os arquivos de
seu projeto. Portanto, pelo menos esses arquivos voc ter de levar para o servidor
para ter seu site no ar.
176
Ambiente de desenvolvimento
Seu ambiente de desenvolvimento (ou de sua equipe) deve estar preparado para
fazer testes e desenvolvimento local e uma ferramenta para enviar seus arquivos
para o servidor, que pode ser de um dos 3 tipos a seguir.
FTP
O uso do FTP tem se tornado cada vez menos recorrente devido falta de
controle e dificuldade para se trabalhar em equipe. Ainda assim, a ferramenta
mais simples e presente nos servidores, conhecida pela maior parte dos
desenvolvedores.
O fato que de uma ou outra forma, nunca se deixa de usar o FTP, mas seu uso
passa a ser para situaes de casos isolados ou emergenciais.
Fabric
Por ltimo, a mais poderosa opo para fazer deploy de projetos em Django se
chama Fabric. Voc pode conseguir mais detalhes sobre ele em seu site oficial:
http://www.nongnu.org/fab/
Banco de Dados
Existem diversos bancos de dados. O Django compatvel oficialmente com 5:
MySQL
PostgreSQL
SQLite
Oracle
Microsoft SQL Server
178
Os primeiros trs so livres, sendo que o MySQL e PostgreSQL so mais
indicados para servidores em produo, pois so poderosos e possuem uma
performance relativamente superior aos demais. Alm disso so plenamente
compatveis com outros softwares livres.
O SQLite mais indicado para ambientes de desenvolvimento, por ser muito
simples e leve, mas no possui uma srie de recursos desejveis para servidores.
J o Oracle e MS SQL Server so softwares proprietrios, que dispem de
verses gratuitas mas limitadas. Tambm so menos compatveis com softwares
livres.
No prximo captulo vamos trabalhar na configurao de um servidor com
MySQL.
Cache
O servio de Cache em um servidor pode variar muito. Muitos servidores j so
oferecidos por empresas de hospedagem com um software de cache, como os
seguintes:
Squid
Varnish
memcached
Ainda que figurem como ferramentas para cache, os trs softwares citados
acima possuem caractersticas e aplicaes diferentes.
H ainda outras formas de fazer cache no Django, usando banco de dados ou
uma pasta do HD. Mas vamos trabalhar a instalao do prximo captulo com
memcached, a mais indicada para esse caso.
179
acordo com o caso.
A maior parte dos servios de hospedagem compartilhada (quando um mesmo
servidor compartilhado por vrios clientes) feita usando FastCGI, mas o
crescimento do WSGI nesse nicho tem sido uma constante. Neste caso, usa-se o
mdulo mod_rewrite do Apache ou funcionalidades semelhantes em outros
servidores web.
J a maior parte dos servidores dedicados e servidores virtualizados so
trabalhados usando mod_python, mas da mesma forma, o crescimento do WSGI
tem substitudo o mod_python pouco a pouco.
Isso se deve facilidade e flexibilidade que o WSGI oferece e ao ganho de
performance que tambm oferece na maior parte dos casos.
Arquivos estticos
Os arquivos estticos so arquivos de imagens, CSS, JavaScript, Flash
Shockwaves e outros. No comum lanar um site sem alguns deles.
Quando se faz o deploy de um projeto, preciso configurar o servidor web para
publicar seus arquivos estticos de forma independente do Django. O Django no
foi construdo para servir arquivos estticos e no vale a pena perder performance
180
com isso.
Outra recomendao importante a separao do servidor web do projeto do
servidor web de arquivos estticos. No necessria a separao entre mquinas
diferentes, o que recomendamos que as configuraes dos servidores web sejam
independentes uma da outra.
A cada vez que uma nova pessoa entra em seu site, uma mquina virtual Python
instanciada para ela, e isso geralmente custa em torno de 15Mb a 30Mb de
memria. Arquivos estticos no precisam nem de um dcimo disso. Se o seu
servidor web for configurado para abrir instncias com pouca memria, sua
mquina virtual Python ser prejudicada, e caso seja configurado para ocupar muita
memria, os arquivos estticos sero os prejudicados.
Portanto, sempre que possvel, crie dois domnios separados, assim por
exemplo: para um site que possui o seguinte domnio:
http://blog-do-alatazan.com/
Projeto do site
O projeto o corao de seu site. Construdo em Django, a nica pea de fato
especfica para o nosso framework. Isso quer dizer que todo o restante do site pode
ser aproveitado da mesma forma para diferentes linguagens e diferentes
frameworks, mas esta especfica para o Django: seu projeto e a configurao
do servidor web para disponibiliz-lo.
181
Esta rvore de arquivos est adequada para o sistema de arquivos do Linux,
Unix e MacOSX, que juntos formam a maioria dos servidores web disponveis em
servios de hospedagem. Entretanto possvel construir uma rvore de pastas
idntica no Windows, exceto pelos links simblicos. Mas isso possvel de
contornar para quem tem prtica com servidores nesse sistema operacional.
Observe que dentro da pasta "django" h duas pastas:
pluggables
Voc deve colocar nesta pasta as aplicaes plugveis extras do projeto, que
veremos mais detalhadamente em um captulo adiante.
Aplicaes plugveis so recursos extras que no so fornecidos pelo Django,
mas por terceiros. H centenas delas na Web, a grande maioria gratuita e livre.
Portanto, esta deve ser a pasta onde essas aplicaes plugveis sero instaladas.
Assim, elas podem ser usadas por vrios projetos em um nico servidor.
projects
Nesta pasta sero instaladas as pastas de projetos. Ou seja, at mesmo se voc
possuir mais de um site em seu servidor, dessa forma suas pastas continuam
182
organizadas.
Mas ateno: ao invs de colocar diretamente a pasta do projeto, crie uma pasta
para o site e dentro desta pasta, coloque a do projeto, pois um site mais do que o
projeto. muito provvel que voc v querer documentar seu site, adicionar alguns
arquivos de histrico e definies, back-ups e outros, portanto, o projeto no se
limita aos arquivos-fonte em Django.
Agora, dentro da pasta do site do projeto, est a pasta do projeto em Django (
meu_blog ). Dentro dela, alm do que j vimos no decorrer dos captulos
anteriores, h ali uma novidade:
deploy
Esta pasta o lugar ideal para se guardar:
os scripts de execuo do projeto (scripts FastCGI e WSGI, por exemplo);
dependencies
Esta pasta deve conter um arquivo chamado README onde voc ir escrever
as dependncias de seu projeto.
Exemplos: se seu projeto trabalha somente na verso 1.0.2 do Django, escreva
isso nesse arquivo. Se seu projeto depende de alguma ferramenta externa como o
ffmpeg, mimms ou Image Magick, escreva tambm. Caso utilize funcionalidades
do campo ImageField, voc vai precisar da biblioteca PIL, portanto, escreva isso.
Sempre de forma explcita, informando a verso utilizada, o porqu e como
deixar isso funcionando no projeto. Isso extremamente importante para que no
se perca no futuro.
183
E agora, vamos ou no configurar um servidor?
Sim, vamos... calma Alatazan, o processo de deploy realmente abrangente,
mas voc vai perceber que na prtica no to complexo quanto parece, pois a
maioria dessas ferramentas pode ser instalada com grande facilidade ou muitas
vezes j vm instaladas nos servios de hospedagem, portanto, atente-se aos
conceitos, pois eles so importantes de se conhecer.
Bom... mas como resumir todo esse aprendizado terico de hoje? - os olhos
de Alatazan estavam um pouco vermelhos e ardiam, pois muito chato ficar
ouvindo outra pessoa falar e no ver exemplos na prtica.
O melhor resumo para hoje so os diagramas, observe-os novamente, e no
se limite a isso. Servidores so evoludos e ajustados ao longo do tempo,
medida que o administrador e o site amadurecem. E para cada tipo de servidor
ou servio de hospedagem h tutoriais com explicaes na web, a basta fazer
uma busca!
Ok, mas amanh vamos configurar um servidor Windows com Apache e
MySQL n?
Sim, vamos fazer isso amanh. Agora hora de relaxar, respirar fundo e
procurar alguma coisa light pra fazer.
184
Captulo 16: Preparando um servidor com Windows
Instalando o Apache
A primeira coisa a se fazer instalar o Apache - de preferncia na verso 2.2.
Para isso v ao site oficial e faa o download do arquivo de instalao:
http://httpd.apache.org/download.cgi
Localize agora um bloco que inicia com "Apache HTTP Server 2.2.11 is the
best available version" ou algo bem semelhante a isso. Nesse bloco h uma lista
das opes mais comuns de download do Apache. Escolha o instalador para
Windows, sem criptografia, que em ingls est assim:
Win32 Binary without crypto (no mod_ssl) (MSI Installer):
Ou quase isso:
186
um ar de indefinio aqui?".
Software um produto dinmico, e software livre quase orgnico e evolui
rapidamente. provvel que ao final deste livro a verso mais recente do Apache
ser outra, e at mesmo do Django. Ou seja, impossvel indicar um caminho
exato para isso hoje, se voc vai us-lo amanh. Portanto fique ligado e observe
que os nmeros da verso podem mudar rapidamente.
Ao final do download, clique duas vezes sobre o arquivo baixado, que ser
executado e a primeira janela ser esta:
187
clicando em "Next" at chegar a esta outra janela:
Observe que desta vez no informamos a porta, pois estamos indicando que ela
deve ser a porta HTTP padro: a 80. Veja o resultado:
188
Viu como fcil ter o Apache funcionando em sua mquina Windows?
Instalando o MySQL
Agora vamos instalar o MySQL, o banco de dados que vamos usar neste
servidor.
Para isso, v ao site oficial de download do MySQL:
http://dev.mysql.com/downloads/mysql/5.1.html#win32
189
Ser requisitado um cadastro gratuito, apenas para fins de propaganda mesmo.
Faa-o (no h outra forma, sorry) e siga para selecionar um dos servidores
"mirrors" para download.
Aps o download, clique duas vezes sobre o arquivo baixado e inicie a
instalao do MySQL no Windows.
190
Prossiga clicando sobre "Next", modificando as opes padro somente se
estiver certo de tal mudana. At chegar a essa tela:
191
Marque a caixa "Include Bin Directory to Windows PATH".
Prossiga clicando em "Next" at esta outra tela:
Determine uma senha difcil de ser quebrada, mas caso tenha dvidas,
simplesmente informe:
Password: "123456"
Confirm: "123456"
Porqu eu sugiro uma senha to fcil de ser quebrada? Simples: para que voc
no o faa!
Prossiga clicando em "Next" at executar a configurao e conclu-la.
Pronto! Agora temos o MySQL rodando em seu servidor Windows!
192
Python e Django
Caso esta mquina no possua Python ou Django, faa a instalao seguindo os
mesmos passos do captulo 3 - Baixando e Instalando o Django - com a diferena
que desta vez no preciso instalar a biblioteca de acesso ao banco de dados
SQLite (pySQLite), pois vamos usar o MySQL.
Aps o download, clique duas vezes sobre o arquivo baixado para instalar o
MySQL for Python no Windows e siga a instalao clicando em "Avanar" at
finalizar.
Instalando o mod_python
Como j foi dito no captulo anterior, o mod_python ainda a forma mais
comum de instalar projetos em Django no Apache em servidores dedicados, mesmo
193
que a opo mais recomendada seja o WSGI.
Neste captulo, vamos trabalhar com o mod_python e em um prximo captulo
ser a vez do WSGI, isso porque importante voc conhecer os dois. Mas no se
esquea que possvel ter qualquer um deles (mod_python, WSGI ou FastCGI)
instalado em Windows ou Linux.
Para fazer o download do mod_python para Windows, carregue a seguinte
pgina em seu navegador:
http://httpd.apache.org/modules/python-download.cgi
Localize o bloco na pgina que comea desta forma (lembrando que a verso
pode variar):
Apache Mod_python 3.3.1 is now available
E abaixo dele, clique sobre o link "Win32 Binaries". Uma lista nada amigvel
ser exibida. Voc deve localizar dentre as opes, o mod_python para a sua
verso do Python ( 2.5 ) e a sua verso do Apache ( 2.2 ), que atualmente esta:
mod_python-3.3.1.win32-py2.5-Apache2.2.exe
Aps o final do download, clique duas vezes sobre o arquivo baixado e prossiga
clicando em "Avanar" at esta janela ser exibida:
194
Agora abra o seguinte arquivo para edio, usando o Bloco de Notas:
C:\Arquivos de programas\Apache Software
Foundation\Apache2.2\conf\httpd.conf
O caminho acima apenas segue a nossa proposta do captulo 15, mas voc pode
trabalhar essa configurao como preferir.
Envie (usando seu meio escolhido) a pasta do projeto ( "meu_blog" ) para
dentro da pasta criada acima.
Agora na pasta do projeto (
"C:\var\django\projects\site_meu_blog\meu_blog" ) abra o arquivo
"local_settings.py" para edio e o modifique para ficar assim:
# Django settings for meu_blog project.
import os
PROJECT_ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
LOCAL = False
DEBUG = False
TEMPLATE_DEBUG = DEBUG
DATABASE_ENGINE = 'mysql'
DATABASE_NAME = 'meu_blog'
DATABASE_HOST = 'localhost'
DATABASE_USER = 'root'
195
DATABASE_PASSWORD = '123456'
Isso vai fazer seu projeto trabalhar como se deve no servidor: sem modo de
depurao ( DEBUG ) e acessando ao banco de dados MySQL. Lembre-se de
informar a setting DATABASE_PASSWORD com a senha correta que voc
informou ao configurar o MySQL.
Uma janela do MS-DOS ser aberta para informar a senha do usurio "root"
no MySQL. Informe a senha ( a que voc escolheu para o lugar de "123456" ),
pressione ENTER, e o shell do MySQL ser aberto:
mysql>
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE settings
PythonDebug On
</Location>
197
O que fizemos ali? Bom, ao abrir uma tag "Location", indicamos que o
Apache deve seguir uma configurao especial para a sua URL raiz.
<Location "/">
A linha seguinte determina que para esta URL deve ser habilitado o suporte ao
Python.
SetHandler python-program
Salve o arquivo.
Reiniciando o Apache
Agora, observe o cone do Apache na bandeja do Windows, prximo ao
relgio, clique sobre ele e escolha a opo "Restart" para reiniciar o Apache e
aplicar a mudana feita.
198
V ao navegador e carregue o endereo do servidor:
http://localhost/
Olha s! Temos o nosso site funcionando no servidor! Mas onde foi parar tudo
aquilo que fizemos de imagens e estilos CSS?
Simples. Lembra-se que a URL '^media/' s reconhecida pelo Django em
ambiente de desenvolvimento? Pois bem, agora temos que configurar o Apache
para reconhec-la. Isto uma tarefa que no tem nenhum intermdio do Django.
apenas um endereo do Apache que aponta para uma pasta no HD. Vamos l?
Volte ao arquivo de configurao do Apache ( "httpd.conf" ) e acrescente o
seguinte trecho de cdigo ao final dele:
Alias /media C:/var/django/projects/site_meu_blog/meu_blog/media
<Directory "C:/var/django/projects/site_meu_blog/meu_blog/media">
Order allow,deny
Allow from all
</Directory>
<Location "/media">
SetHandler None
</Location>
199
Um cuidado especial aqui: muito fcil fugir da sintaxe neste arquivo de
configurao, portanto fique atento aos espaos ou falta deles... um bom exemplo
a parte "allow,deny" que no pode ter um espao antes ou depois da vrgula
O bloco acima faz com que o Apache entenda que ao carregar a URL "/media"
( e URLs "filhas" ), a pasta
"C:/var/django/projects/site_meu_blog/meu_blog/media" deve ser tomada
como base, ou seja, a pasta de arquivos estticos do nosso projeto.
A linha que faz esse trabalho esta:
Alias /media C:/var/django/projects/site_meu_blog/meu_blog/media
Por fim, este ltimo bloco desabilita o Python para a URL /media, para que ela
trabalhe somente com arquivos estticos, sem qualquer interferncia do Django.
<Location "/media">
SetHandler None
</Location>
200
Satisfeito? Mas como pode notar, no temos nenhum artigo publicado, devido a
ser outro banco de dados. Portanto, vamos ao Admin do site para criar os novos
artigos! No navegador, carregue a seguinte URL:
http://localhost/admin/
201
Eta! Mas ns no havamos resolvido o problema dos arquivos estticos?
Sim, mas a URL que resolvemos foi a "/media" - a URL de arquivos estticos
do projeto. Porm, agora se trata do Admin, que um caso especial, e possui seu
prprio caminho para arquivos estticos, com prefixo "/admin_media", informado
na setting "ADMIN_MEDIA_PREFIX".
Portanto, volte ao arquivo de configurao do Apache ( "httpd.conf" ) e
acrescente mais estas linhas ao final:
Alias /admin_media C:/python25/lib/site-packages/django/contrib/admin/media
<Directory "C:/python25/lib/site-packages/django/contrib/admin/media">
Order allow,deny
Allow from all
</Directory>
<Location "/admin_media">
SetHandler None
</Location>
O que fizemos a foi exatamente o mesmo que fizemos para a URL /media, mas
desta vez trabalhamos a URL /admin_media, que direcionada para a pasta de
arquivos estticos da contrib Admin.
Salve o arquivo. Feche o arquivo. Reinicie o Apache.
Agora atualize o navegador e veja como ficou:
202
Pronto! Servidor funcionando, podemos partir para o prximo desafio!
E a, o qu mais?
O qu mais? Meu amigo, estamos no meio da histria, e nem terminamos o
assunto do deploy! Amanh vem a ltima bolacha do pacote.
Cartola encabulou com a energia de Alatazan. Ele no parecia exausto depois da
extensa aula de hoje. Pelo contrrio, Alatazan queria mais, queria saber quais outras
formas de deploy existem, porque essa foi barbada.
Nena, que queria ir embora, puxou a cadeira que estava ao lado, coou a
bochecha, deu uma olhada no relgio e tomou sua vez:
Alatazan, amanh vai ser a minha vez de passar com voc... quero te mostrar
um servidor no Linux e outras coisas diferentes, vamos mudar isso aqui um
pouco que esse ambiente de janelinhas de no a minha praia no... - Nisso ela
olhou irnica para o Cartola, que brigava com seu Mac pra pegar alguns
arquivos do iPod. A resposta veio de bate-pronto.
Hey, quem gosta de janelinha aqui o Alatazan, no sou eu no hein, gosto
de coisa com mais estilo.
Alatazan mexeu sua peruca desalinhado, fez de conta que no ouviu e tratou de
voltar ao assunto:
Bom, ento hoje instalamos um monte de coisas:
Apache 2.2
MySQL 5.1
MySQL for Python 1.2.2
mod_python 3.3.1
Olha, no se prenda s verses secundrias, apenas atenha-se a pegar a
verso estvel mais recente. Geralmente funciona melhor.
E s completando, meu camarada... quando ela fala em verso "secundria",
isso quer dizer que se aparecer um Apache 3.0 ou MySQL 6.0, bom fazer uns
testes antes, pois as verses primrias geralmente mudam muitas coisas...
Ok ok... valeu, j peguei. Por fim..
Configuramos o acesso ao banco de dados no arquivo "local_settings.py"
do servidor;
Criamos o banco de dados no MySQL;
203
Geramos as tabelas do banco de dados pelo Django...
Nena tomou a palavra, j que ela tinha pressa e o Alatazan estava falando
lentamente, como se estivesse saboreando um daqueles churrascos de lagartos de
Katara...
e configuramos o Apache, criando a Location para o projeto e os Alias pra
URLs de arquivos estticos! A foi s reiniciar o Apache e a mgica est feita!
Vamos embora pessoal?
Bacana, amanh ser a vez do Linux! Vai l meu camarada, vou s pegar
essa msica aqui e j vou descendo...
Dito isso, Cartola voltou sua ateno para o computador e os dois saram, se
despedindo do Cad e da priminha que insistia em arrancar seu nariz.
204
Captulo 17: Preparando um servidor com Linux
E para instal-lo em uma mquina virtual, faa sua escolha favorita. Uma boa
opo o VirtualBox:
http://www.virtualbox.org/
Ambos so livres e gratuitos, alis uma coisa bem comum entre todas as
ferramentas que vamos tratar aqui.
O Ubuntu Linux possui uma interface grfica extremamente fcil e amigvel,
entretanto, como muitos servidores Linux no possuem ambiente grfico, vamos
trabalhar constantemente em Console - modo texto semelhante ao Prompt do MS-
DOS.
Neste captulo, assumimos que voc possui conhecimentos bsicos em Linux
suficientes para abrir o Console como pode ver abaixo e ter um editor de sua
preferncia, como gVim, vim, gedit, emacs, nano ou outro qualquer.
206
Instalando o Lighttpd
O Lighttpd um dos servidores web mais leves e rpidos que existem, pois tem
uma estrutura mais simples que o Apache e outros.
Para instalar o Lighttpd, abra uma janela do Console e digite o seguinte
comando:
sudo apt-get install lighttpd
O comando "sudo" solicita sua prpria senha para efeitos de segurana, mas
ele armazena essa senha em memria por algum tempo, portanto voc precisa
digitar sua senha novamente somente se ficar muito tempo em espera.
Confirme a instalao dos pacotes e espere pela concluso da instalao.
Ao concluir, v at seu navegador, e assumindo que esteja trabalhando em
mquina local, carregue a seguinte URL:
http://localhost/
Caso esteja trabalhando em uma mquina remota, digite a URL para o caso.
De qualquer forma, veja como aparece:
Instalando o PostgreSQL
Vamos agora instalar o PostgreSQL, um dos bancos de dados livres mais
robustos e populares.
207
No Console, digite a seguinte linha de comando:
sudo apt-get install postgresql-8.3
208
Observe que estamos trabalhando aqui com dois usurios "postgres"
diferentes: ora trabalhamos no usurio "postgres" do Linux, ora com o usurio de
mesmo nome no PostgreSQL. Um possui vnculo indireto ao outro, mas se tratam
de coisas diferentes. Ao modificar a senha do usurio no PostgreSQL, a senha do
usurio no Linux permanece como estava. Mas isso irrelevante agora, pois esse
usurio s ser usado para acesso a bancos de dados.
Agora, de volta sesso do seu usurio, digite a seguinte linha comando:
psql -U postgres -W
Veja bem: quando acessamos o psql usando uma sesso do usurio "postgres"
do Linux, a autenticao foi aceita sem nem mesmo requisitar senha, mas agora
que usamos uma sesso do seu usurio, mesmo informando a senha correta a
autenticao foi rejeitada. Porqu?
Porque existe uma configurao que determina isso. Vamos mudar essa
configurao. Digite o seguinte comando:
sudo nano /etc/postgresql/8.3/main/pg_hba.conf
Voc pode usar outro editor ao invs do nano, como o vim ou gedit por
exemplo.
Localize agora as seguintes linhas, j prximo ao fim do arquivo:
# Database administrative login by UNIX sockets
local all postgres ident
sameuser
209
Agora ao tentar novamente o seguinte comando, voc ter sucesso:
psql -U postgres -W
Veja o resultado:
Python e Django
O Ubuntu Linux tem o Python como linguagem principal, portanto, voc no
precisa se preocupar em instal-lo, pois ele j vem instalado. O mesmo vale para o
Debian.
Para instalar o Django no Ubuntu Linux - Intrepid Ibex, verso 8.10 - basta
digitar a seguinte linha de comando:
sudo apt-get install python-django
210
http://code.djangoproject.com/svn/django/tags/releases/1.0.2/
django-1.0.2
Aps concluir a instalao do Django, para confirmar que est tudo ok, digite as
seguintes linhas de comando para voltar sua pasta HOME e acessar o shell
interativo do Python:ip
cd ~
python
O resultado dever ser este (ou outro muito semelhante a este, mas sem
mensagem de erro):
'1.0.2 final'
Feito isso, envie a pasta do seu projeto ( "meu_blog" ) para esta pasta do
servidor, em caminho completo:
/var/django/projects/site_meu_blog
Para isso, utilize uma das formas de envio de arquivos abordadas no "captulo
15: Infinitas formas de se fazer deploy" (software de controle de verses, FTP ou
Fabric).
Agora dentro da pasta do projeto no servidor (
212
"/var/django/projects/site_meu_blog/meu_blog/" ), abra o arquivo
"local_settings.py" para edio:
cd meu_blog
nano local_settings.py
LOCAL = False
DEBUG = False
TEMPLATE_DEBUG = DEBUG
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_NAME = 'meu_blog'
DATABASE_HOST = 'localhost'
DATABASE_USER = 'postgres'
DATABASE_PASSWORD = '123456'
FORCE_SCRIPT_NAME = ''
213
"meu_blog", ento devemos cri-lo, certo? Pois o que vamos fazer agora.
No shell, digite a seguinte linha de comando para acessar novamente o shell do
PostgreSQL:
psql -U postgres -W
Essa linha de comando vai criar um novo banco de dados e garantir que sua
codificao de caracteres a 'UTF-8', a mais compatvel com o Django, por ele ser
Unicode.
O resultado desse comando deve ser simplesmente:
CREATE DATABASE
Pronto. Banco de dados criado! Digite esta outra linha de comando para sair do
shell do PostgreSQL:
\q
214
No se preocupe em comparar tudo. Se no houve mensagem de erro porque
deu certo.
Bacana! Estamos caminhando bem! Nosso banco de dados foi criado e agora j
possui as tabelas e outras entidades devidamente geradas pelo Django!
Veja o resultado:
05-auth.conf 10-proxy.conf 10-ssi.conf 10-
userdir.conf
10-cgi.conf 10-rrdtool.conf 10-ssl.conf README
10-fastcgi.conf 10-simple-vhost.conf 10-status.conf
fastcgi.server = (
"/default.fcgi" => (
"main" => (
"socket" => "/tmp/lighttpd-default.sock",
"check-local" => "disable",
"bin-path" =>
"/var/django/projects/site_meu_blog/meu_blog/deploy/default.fcgi",
)
)
)
url.rewrite-once = (
"^(/.*)$" => "/default.fcgi$1"
)
216
)
)
)
E por ultimo, definimos uma URL (em expresso regular que quer dizer:
"todas a partir da barra") para apontar para esse script:
url.rewrite-once = (
"^(/.*)$" => "/default.fcgi$1"
)
Feito.
Acontece, que o script indicado no existe:
/var/django/projects/site_meu_blog/meu_blog/deploy/default.fcgi
Lembre-se de trocar o "nano" pelo seu editor preferido, caso ele no for o
nano.
Agora dentro do novo arquivo, digite as seguintes linhas de cdigo:
#!/usr/bin/python
import sys, os
sys.path.insert(
0, '/var/django/projects/site_meu_blog/meu_blog/'
)
sys.path.insert(
0, '/var/django/projects/site_meu_blog/dependencies/'
)
217
sys.path.insert(
0, '/var/django/pluggables/'
)
os.chdir('/var/django/projects/site_meu_blog/meu_blog/')
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
218
Entendido? Salve o arquivo. Feche o arquivo.
Agora vamos transformar esse arquivo que criamos em executvel:
chmod a+x default.fcgi
Feito isso, vamos reiniciar o Lighttpd para ver o efeito do que fizemos:
sudo /etc/init.d/lighttpd restart
timo! Mas como deve ter percebido, nosso site est tosco. Sem imagens, sem
CSS. Da mesma forma como aconteceu no servidor Windows, isso porque
precisamos agora definir as URLs para arquivos estticos "/media" e
"/admin_media".
Para fazer isso, edite novamente o arquivo de configuraes do Lighttpd.
Assim:
sudo nano /etc/lighttpd/conf-enabled/10-meu_blog.conf
E agora com o arquivo aberto para edio (usando seu editor predileto),
modifique o arquivo para ficar assim:
219
server.modules += ( "mod_fastcgi" )
server.modules += ( "mod_rewrite" )
fastcgi.server = (
"/default.fcgi" => (
"main" => (
"socket" => "/tmp/lighttpd-default.sock",
"check-local" => "disable",
"bin-path" =>
"/var/django/projects/site_meu_blog/blog/deploy/default.fcgi",
)
)
)
alias.url = (
"/media" =>
"/var/django/projects/site_meu_blog/meu_blog/media",
"/admin_media" =>
"/usr/lib/python2.5/site-packages/django/contrib/admin/media/"
)
url.rewrite-once = (
"^(/media/.*)$" => "$1",
"^(/admin_media/.*)$" => "$1",
"^(/.*)$" => "/default.fcgi$1"
)
220
"/media" =>
"/var/django/projects/site_meu_blog/meu_blog/media",
"/admin_media" =>
"/usr/lib/python2.5/site-packages/django/contrib/admin/media/"
)
Misso cumprida!
221
fazido!
Cartola trocou olhares com Nena, deu uma risadinha contida com o canto da
boca... mas no quis corrigir o aliengena e quebrar sua empolgao. Mas foi Nena
que continuou a conversa:
Sim, Alatazan... veja:
Voc instalou o Lighttpd;
e instalou tambm o PostgreSQL e definiu uma senha de acesso ao banco
de dados;
depois voc instalou o Django... em nosso caso usando o apt-get tambm;
instalou o psycopg2 para PostgreSQL no Python;
instalou o flup para FastCGI no Python;
enviou os arquivos do projeto para a pasta correta no servidor;
configurou o "local_settings.py" para tirar o modo de depurao e
configurar o acesso ao banco de dados;
Alatazan deu uma pescada e um arranque com a cabea, se refez e abriu bem os
olhos. Nena continuava:
... criou o banco de dados;
gerou as tabelas no banco de dados;
configurou o Lighttpd para acesso ao projeto;
criou um script de FastCGI no seu projeto;
e configurou as URLs para arquivos estticos!
Depois dessa lista, emendou mais:
Olha, voc notou uma coisa interessante? Para quase tudo, usamos o apt-get
para instalar as coisas. Ele faz isso: baixa o que precisamos, todas as suas
dependncias, configura tudo, move os arquivos nas pastas certas, faz tudo
direitinho...
Estava claro que hoje Nena estava com mais tempo. Com bem mais tempo.
Com muito tempo.
Ahh, j sei! Vamos ver WSGI e servidores compartilhados?
E muito empolgadinha tambm.
Err... vamos fazer isso amanh... tenho minha aula de xadrez...
222
Tudo bem rapaziada... mas enquanto vamos saindo, vou pedir uma coisa
importante pra voc fazer: volte ao assunto do servidor no Windows e compare
com o servidor no Linux. Vai perceber que existem mais semelhanas do que
parece!
223
Captulo 18: WSGI e Servidores compartilhados
224
Baixando e instalando o mod_wsgi para Windows
O mod_wsgi o mdulo de suporte a WSGI para Apache.
Para fazer o download do mod_wsgi para Windows - sem a necessidade de
compilar - v a esta pgina da Web:
http://adal.chiriliuc.com/temp/mod_wsgi-1.0c1-rev_385-win32/
225
Agora escreva o seguinte cdigo no mesmo lugar de onde removeu o anterior:
WSGIScriptAlias / "c:/var/django/projects/site_meu_bl
og/meu_blog/deploy/default.wsgi"
<Directory "c:/var/django/projects/site_meu_blog/meu_blog/deploy/">
Order deny,allow
Allow from all
</Directory>
Como pode ver, fizemos uma referncia para dizer ao Apache que as URLs
iniciadas com uma barra (ou seja: todas, exceto s de arquivos estticos) devem
ser direcionadas para o script WSGI no arquivo "default.wsgi" da pasta "deploy"
do projeto. Veja:
WSGIScriptAlias / "c:/var/django/projects/site_meu_bl
og/meu_blog/deploy/default.wsgi"
226
que... Acontece que este arquivo de script ainda no existe. Portanto, vamos
cri-lo! Se por acaso a mensagem de erro no navegador for algo parecido com
'Forbiden...' continue abaixo, pois esta normalmente a mensagem exibida quando
a pasta de deploy ainda no existe.
PROJECT_ROOT_PATH = os.path.dirname(
os.path.dirname(os.path.abspath(__file__))
)
sys.path.insert(0, PROJECT_ROOT_PATH)
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
import django.core.handlers.wsgi
227
application = django.core.handlers.wsgi.WSGIHandler()
228
isso a! Como pode ver, agora temos o servidor trabalhando em WSGI!
229
alguns caminhos da pasta de documentos, e direcionar o restante para o
Django. Para isso, ele precisa de um mdulo do Apache: p
"mod_rewrite".
Pois bem. Ns vamos agora ajustar o Apache para trabalhar com o mesmo
comportamento de um site de servidor compartilhado.
Ento, para comear, abra o arquivo "httpd.conf" da pasta "C:\Arquivos de
programas\Apache Software Foundation\Apache2.2\conf" para edio.
Localize e remova o seguinte bloco, j no final do arquivo:
WSGIScriptAlias / "c:/var/django/projects/site_meu_blog/meu_b
log/deploy/default.wsgi"
<Directory "c:/var/django/projects/site_meu_blog/meu_blo
g/deploy/">
Order deny,allow
Allow from all
</Directory>
<Directory "C:/var/django/projects/site_meu_blog/meu_blog/media">
Order allow,deny
Allow from all
</Directory>
<Location "/media">
SetHandler None
</Location>
230
Voltamos estaca zero? Nem tanto. Mas agora localize a seguinte linha no
arquivo:
#LoadModule rewrite_module modules/mod_rewrite.so
Order allow,deny
Allow from all
</Directory>
231
E aqui, modificamos a configurao da pasta de documentos para suportar a
configurao do site usando ".htaccess" e scripts WSGI:
<Directory "C:/Arquivos de programas/Apache So
ftware Foundation/Apache2.2/htdocs">
AllowOverride FileInfo
Options ExecCGI MultiViews FollowSymLinks
MultiviewsMatch Handlers
Order allow,deny
Allow from all
</Directory>
232
Isso indica que a pasta foi carregada corretamente e que o Apache a encontra da
forma esperada.
Feito isso, ainda na pasta de documentos ( "C:\Arquivos de
programas\Apache Software Foundation\Apache2.2\htdocs" ), crie o arquivo
".htaccess" com o seguinte cdigo dentro:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /site.wsgi/$1 [QSA,PT,L]
PROJECT_ROOT_PATH = 'C:/var/django/projects/site_meu_blog/meu_blog'
sys.path.insert(0, PROJECT_ROOT_PATH)
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
233
apontado manualmente, sem uso de recursos do Python. Isso porque agora estamos
fora da pasta do projeto e no temos referncia relativa a ela.
Salve o arquivo. Feche o arquivo. Volte ao navegador e carregue a URL do site:
http://localhost/
Pronto! Temos agora o site funcionando novamente, porm desta vez usando
WSGI com rewriting, um recurso fundamental para sites compartilhados.
234
muito tonto - se lembrando das notcias daquela manh.
As notcias que vira na TV eram sobre sinais estranhos e inexplicveis,
deixados no meio de uma plantao de cana. L havia tambm uma toalha para
limpar o suor e uma lmina de um metal desconhecido. As expresses "apocalipse",
"sinais dos tempos" e "prejuzo nesta safra" eram as mais comuns no vocabulrio
do noticirio, mas enfim, isso tabm no lembrava uma zebra. Exceto por aquela
zebra comendo cana no canto superior direito da tela da TV.
Alatazan deu de ombros e continuou seu caminho, lembrando do que aprendeu
hoje, que resumidamente foi:
Configurar um servidor Apache com WSGI, usando mod_wsgi;
Criar script de WSGI na pasta "deploy" do projeto;
Habilitar o mod_rewrite no Apache;
Ativar recursos e sobrecarga na pasta de documentos do Apache, para
suportar scripts WSGI e o arquivo ".htaccess";
Copiar a pasta "media" do projeto para a pasta de documentos;
Criar script de WSGI na pasta de documentos para acessar o projeto.
E foi s isso mesmo! No outro dia, seria a vez de usar signals e URLs
descomplicadas.
235