Escolar Documentos
Profissional Documentos
Cultura Documentos
Aprendendo Django Vol 1
Aprendendo Django Vol 1
Marinho Brando
1 edio - 2009
Todos os direitos reservados por Jos Mrio Neiva Brando E-mail: marinho@aprendendodjango.com www.aprendendodjango.com
Licena
Esta obra e seus personagens so licenciados sob a licena Creative Commons Atribuio-Uso No-Comercial-Vedada a Criao de Obras Derivadas 2.5 Brasil ( http://creativecommons.org/licenses/by-nc-nd/2.5/br/ ). As premissas bsicas desta licena so que:
Voc pode
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.
O autor desta obra e de seus personagens Jos Mrio Neiva Brando (codinome "Marinho Brando"). A autoria das ilustraes de Joo Matheus Mazzia de Oliveira. A reviso e edio do texto de Mychell Neiva Rodrigues.
Sumrio
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
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.
Dicas de Aprendizado
Antes de entrar de cabea na leitura do livro, bom manter em mente alguns princpios que vo facilitar a compreenso, manter a calma em alguns momentos e fortalecer o aprendizado. Veja abaixo:
anos para serem criadas de forma que voc possa usar facilmente agora. Esse valor s tem essa fora e dinmica porque o Django software livre.
Conhecimento. O seu conhecimento do Django e de conceitos aprofundados de Web, Programao Orientada a Objetos e Bancos de Dados faz TODA a diferena. Python. uma linguagem de fcil compreenso, no burocrtica e prtica. Muito prtica. Isso evita que seu crebro se perca em interpretar coisas e smbolos que no precisaria interpretar e mantenha o foco na soluo.
Portanto, no existem atalhos, nem vida fcil, mas voc pode facilitar as coisas e se divertir com isso, usando as ferramentas certas, e agindo com foco e persistncia. Ento, numa bela manh vai perceber que est produzindo com qualidade e rapidez, por seus prprios mritos.
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.
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!
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
H poucas semanas, Alatazan estava numa nave de transporte em massa vinda de Katara. Katara (que significa "ns resolvemos" em seu idioma mais popular) um planeta no muito distante, que gira em torno de um sol gelado e azul claro*. L existe a tradio de enviar seus jovens para outros planetas, com o fim de passar um tempo ali aprendendo seus costumes e dando um tempo para os pais que querem ter uma folga das manias desses jovens. Alatazan escolheu o Planeta Terra depois de consultar no Google Sky e achar bonitinha a forma rechonchuda, molhada e quentinha da Terra. E assim, veio parar aqui atravs de uma coisa que parece um prato cheio de lmpadas coloridas. Sim, eles conseguem acesso nossa internet, e voc saber em breve como fazem isso. Algumas semanas depois de chegar Terra, Alatazan percebeu que o nosso pequeno planeta estava em polvorosa com aquilo que chamvamos de "Engenharia de Software". Ele ainda no compreendeu como haveria uma engenharia para uma coisa mole e sem forma, mas Alatazan otimista, sempre. E sabe que vai resolver esse enigma. Depois de resolver a questo de sua reluzente careca com uma peruca bacana (apesar do amarelo ser um tom de amarelo incomum para cabelos), Alatazan tambm procurou resolver uma questo menos importante mas muito chata: seus documentos. Com documentos que o fizeram se tornar menos esquisito aos olhos dos terrqueos, Alatazan conseguiu uma vaga em um curso da tal "Engenharia de Software". Logo percebeu que no havia engenheiro de software algum, na verdade os profissionais da engenharia de software eram chamados de muitos nomes, como "analistas", "arquitetos", "projetistas", "desenvolvedores", "codificadores", "homologadores", "enroladores", enfim, eram muitos ttulos, no muito claros, e Alatazan ainda no entendia bem para qu serviam tantos nomes para se realizar atividades to parecidas.
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
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
Quando Alatazan chegou Terra, sua pequena nave foi enviada da nave maior, e ao chegar, chocou-se ao cho, meio desajeitada, e pareceu acertar algum que passeava com seu cachorrinho. Alatazan saiu de dentro um pouco desajeitado e uma velhinha lhe ofereceu um suco. Ele adorou aquilo, e agora, na casa de Cartola, ele tomava um suco de tangerina pra refrescar um pouco antes de retomar descoberta do Django. Do nada, ele soltou essa: Quem inventou o suco? Sei l, algum que estava sentindo calor, h muito tempo atrs... Quem foi eu no sei, mas ainda bem que ele contou a receita pra algum, seno teria ido dessa pra melhor com sua ideia guardada e deixando um monte de gente fadada ao cafezinho. A fruta de preo baixo, fcil de comprar, a receita livre para qualquer um, s ter um pouquinho de tempo, gua, liquidificador, acar, essas coisas... bom demais! Vou levar isso pra Katara e vou ficar rico fazendo sucos... E depois dessas divagaes, eles voltaram ao computador. Como que se consegue o Django? - Alatazan j foi logo indagando ao Cartola...
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:
Na caixa de seleo "Variveis do Sistema" clique duas vezes sobre o item "Path".
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.
Pronto! O Python est pronto para uso. Agora vamos ao Django! Na pgina a seguir voc encontrar alguns meios para instalar o Django.
http://www.djangoproject.com/download/
Vamos instalar o tarball da verso 1.0. Tarball um arquivo compactado que termina com ".tar.gz" e precisa de um programa de descompresso para ser aberto. Para o Windows, o 7-Zip um software (tambm livre) que faz isso pra voc. Faa o download da seguinte pgina e instale em sua mquina:
http://www.7-zip.org/
Voltando ao Django, localize "Django-1.0.tar.gz" na pgina de Download do Django citada acima. Faa o download do arquivo e descompacte onde bem quiser. Dentro da pasta criada - que provavelmente vai se chamar "Django-1.0") voc vai criar um novo arquivo, chamado "instalar.bat", edite usando o Bloco de Notas e escreva dentro o seguinte cdigo:
python setup.py install
20
pause
Feche, salve, e clique duas vezes para executar. Feito isso, o Django estar instalado. Agora vamos seguir para o ltimo passo: instalar a biblioteca do banco de dados SQLite. O SQLite um banco de dados simples, sem muitos recursos. ideal para o ambiente de criao e desenvolvimento. No d pra fazer muitas coisas com ele, mas voc dificilmente vai precisar de fazer muitas coisas enquanto cria seu site. Para o Django trabalhar em conjunto com o SQLite, preciso apenas instalar uma biblioteca, chamada pySQLite, e nada mais. Ento, v at a pgina seguinte e faa o download do tarball (cdigo-fonte, com extenso .tar.gz).
http://oss.itsystementwicklung.de/trac/pysqlite/#Downloads
Se a instalao do pySQLite apresentar erros de compilao no Windows, tente instalar com um dos instaladores executveis disponveis na pgina de download acima. Isso s vezes ocorre por consequncia de algum tipo de incompatibilidade entre compiladores. Aps o download, faa o mesmo que fez com o Django: 1. descompacte usando o 7-zip
21
Alatazan respirou aliviado. Apesar da sopa de letrinhas, a coisa no parecia to complicada. ento tudo se resume a instalar 3 coisas: o Python, o Django e o pySQLite. que so feitos de forma que os princpios do software livre sejam preservados: usando outros softwares livres - completou Nena e ento, o que vamos fazer amanh? vamos criar o seu primeiro projeto. Voc j tem alguma idia do que quer fazer? sim, quero dar um jeito de mandar mensagens para a minha famlia, mostrar como tem sido a minha vida por aqui, o que tenho descoberto, algumas fotos dos tnis da Rua 9...
22
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
Pronto, agora feche essa janela e vamos voltar pasta do projeto, em c:\Projetos\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
Nota: no Linux e no MacOSX o equivalente aos arquivos .BAT so os arquivos .sh. A diferena que eles no suportam o comando "pause" e devem iniciar com a seguinte linha:
25
#!/bin/bash
Voc deve tambm definir a permisso de execuo ao arquivo usando o comando chmod +x ou usando a janela de Propriedades do arquivo.
Salve o arquivo. Feche o arquivo. Execute o arquivo clicando duas vezes sobre ele.
26
Mas isso ainda no nada. Voc ainda no possui nada em seu projeto. Ou pelo menos, nada que algum possa ver.
1. A linha que comea com DATABASE_ENGINE, deve ficar com DATABASE_ENGINE = 'sqlite3' 2. A linha que comea com DATABASE_NAME, deve ficar com DATABASE_NAME = 'meu_blog.db' 3. E logo abaixo da linha que possui 'django.contrib.sites', acrescente outra linha com 'django.contrib.admin', O arquivo de URLs do projeto
Salve o arquivo. Feche o arquivo. Agora edite o arquivo urls.py, tambm com o Bloco de Notas, fazendo as seguintes modificaes:
1. Na linha que possui # from django.contrib import admin, remova o "# " do incio - no se esquea de remover o espao em branco 2. Na linha que possui # admin.autodiscover(), remova o "# " do incio 3. Na linha que possui # (r'^admin/(.*)', admin.site.root),, remova o "# " do incio
Salve o arquivo. Feche o arquivo. Agora vamos gerar o banco de dados (isso mesmo!).
chamado
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
Ao exibir a frase Pressione qualquer tecla para continuar. . ., feche a janela volte ao navegador, pressione F5 pra ver como ficou.
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:
30
Salve o arquivo. Feche o arquivo. Agora abra o arquivo admin.py com o Bloco de Notas e escreva dentro:
from django.contrib import admin from models import Artigo admin.site.register(Artigo)
31
Salve o arquivo. Feche o arquivo. Vamos voltar pasta do projeto (meu_blog), e editar novamente o arquivo settings.py, fazendo o seguinte:
1. Abaixo da linha que possui 'django.contrib.admin', acrescente outra linha com 'blog',
Salve o arquivo. Feche o arquivo. E agora volte ao navegador, pressionando a tecla F5:
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:
Agora, ao voltar ao navegador e atualizar a pgina com F5, a pgina ser carregada da maneira desejada:
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!
Ao tentar carregar a URL http://localhost:8000/ em seu navegador, ser exibida aquela pgina amarela com Pgina no encontrada, se lembra? Pois ento agora vamos criar uma pgina para responder quando aquela URL for chamada. Na pasta do projeto (meu_blog), abra o arquivo urls.py para editar, e modifique para ficar da seguinte maneira:
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin: 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), )
35
Salve o arquivo. Feche o arquivo. Volte ao navegador, e pressione F5 para atualizar a pgina, e o resultado ser como este abaixo:
Isso acontece porque ainda falta um arquivo em HTML para exibir as informaes do Blog, que chamamos de Template. Vamos cri-lo? Ok, abra a pasta blog, contida na pasta da projeto (onde j esto os arquivos __init__.py, models.py e admin.py), crie uma pasta chamada "templates" e dentro dela crie outra pasta, chamada "blog". Por fim, dentro da nova pasta criada, crie novo arquivo chamado "artigo_archive.html" e escreva o seguinte cdigo dentro:
<html> <body>
<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
Quando ainda era criana, Alatazan andava pela rua alegremente quando zuniu uma bola de metal cheia de braos perto de sua cabea. Na verdade no eram muitos braos, eram apenas dois mesmo. A bola de metal era uma espcie de rob de modelo antigo. Seus circutos pareciam no funcionar muito bem, mas ele emanava um sorriso arregalado, num jeito espalhafatoso que Alatazan gostou. Um homem gritou:
39
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
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
Cartola obcecado por informao: l notcias de poltica, esportes e economia, sites com artigos sobre robtica, receitas de comida senegalesa e blogs de nerds de renome. Nena no deixa por menos, mas ela gostava mesmo de entretenimento. Acessa blogs de celebridades, ao mesmo tempo que curte cada novidade sobre metodologias geis. Alatazan percebeu que seria complicado concorrer o precioso tempo de seus leitores com essa gente toda, ento logo ele notou que precisa mudar seu blog para publicar seus textos em formato RSS. RSS no se trata da sociedade conservadora mais risonha de Katara. RSS somente um formato que segue os padres do XML, mas que foi criado para carregar informaes como Ttulo, Data de Publicao e Contedo (dentre outras) de artigos. Qualquer site que lance esse tipo de informao, pode publicar seu contedo tambm em forma de RSS e assim seus leitores usam programas como o Google Reader para serem avisados sempre que houver novidades. RSS tambm muito til para Podcasts e ainda para exportar e importar esse mesmo tipo de informao. E claro, o Django j vem com isso pronto, sem dor e com bons recursos!
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
Na pasta do projeto (meu_blog), abra o arquivo settings.py no editor e localize a seguinte linha:
TIME_ZONE = 'America/Chicago'
Este apenas um exemplo. Caso no esteja na zona de fuso horrio da cidade de So Paulo, v at o site citado acima, encontre o seu fuso horrio, e ajuste a TIME_ZONE para cdigo respectivo. Salve o arquivo. Feche o arquivo.
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
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
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
No Python, toda expresso que divida entre sinais de vrgula ( , ) e contido entre parnteses, chamada de Tupla. Trata-se de uma lista que no ser modificada enquanto o projeto estiver em execuo. INSTALLED_APPS uma tupla, onde indicamos todas as aplicaes do projeto. Todos os itens contidos ali tero um tratamento especial no seu projeto, indicando classes de modelo de dados (tabelas para o banco de dados), views e outras informaes contidas em seus arquivos models.py, views.py, admin.py, dentre outros. Vamos portanto, adicionar ao final da tupla a aplicao 'django.contrib.syndication', a nossa estrela principal aqui. Portanto, agora a tupla vai ficar assim:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', 'django.contrib.syndication',
'blog', )
No necessrio que a ordem seja exatamente esta, mas recomendvel que se separe as aplicaes contribs das demais aplicaes, sempre que possvel.
48
Salve o arquivo. Feche o arquivo. Agora vamos adicionar uma URL para este nosso RSS. Localize o arquivo urls.py da pasta do projeto e abra-o para edio. Neste arquivo, cada tupla informada dentro da funo patterns() indica um padro de URL. Veja como est abaixo:
urlpatterns = patterns('', (r'^$', 'django.views.generic.date_based.archive_index', {'queryset': Artigo.objects.all(), 'date_field': 'publicacao'}), (r'^admin/(.*)', admin.site.root), )
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),
A tupla adicionada indica que a nova URL vai exibir os artigos em formato RSS na seguinte endereo:
http://localhost:8000/rss/ultimos/
No se esquea da importncia dessa palavra ultimos, pois ela que identifica o nosso RSS (sim, podemos ter diversos RSS diferentes em um mesmo site). Mas ainda no suficiente, pois o UltimosArtigos um estranho ali. Se voc rodar o sistema agora, vai notar uma mensagem de erro, pois esse elemento UltimosArtigos realmente no existe. Pois ento, na linha superior iniciada com urlpatterns, vamos adicionar a seguinte linha:
from blog.feeds import UltimosArtigos
49
# Uncomment the next two lines to enable the admin: 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}}), )
Pois bem. Salve o arquivo. Feche o arquivo. Vamos seguir para a derradeira tarefa antes de ver o nosso RSS funcionando: na pasta da aplicao blogs, crie um novo arquivo chamado feeds.py, e escreva o seguinte cdigo dentro:
from django.contrib.syndication.feeds import Feed
50
ver o resultado disso! Primeiro, execute o seu projeto, clicando duas vezes sobre o arquivo executar.bat da pasta do projeto. Agora localize o seguinte endereo em seu navegador:
http://localhost:8000/rss/ultimos/
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 }}
Salve o arquivo. Feche o arquivo. Crie um novo arquivo, chamado ultimos_description.html, e escreva o seguinte cdigo dentro:
51
{{ obj.conteudo }}
Salve o arquivo. Feche o arquivo. V ao navegador e pressione a tecla F5 para ver como ficou.
Que tal agora? Est melhor? Ok, vamos conhecer um pouco mais do que fizemos. O atributo title recebeu o valor 'Ultimos artigos do blog do Alatazan', que ttulo deste RSS. O atributo link recebeu o valor '/', indicando que o endereo na web equivalente a este RSS o do caminho '/', que somado ao protocolo ('http'), domnio ('localhost') e porta ('8000'), fica assim:
http://localhost:8000/
O mtodo def items(self) carrega uma lista de artigos. A linha return Artigo.objects.all() indica que este mtodo vai retornar no RSS todos os objetos da classe Artigo (em ordem decrescente pelo campo publicacao, lembra-se?). E o mtodo def item_link(self, artigo) retorna, para cada artigo, seu endereo na web, que definimos para ser o caminho '/artigo/' somado ao id do artigo, mais uma barra ( / ) ao final, que no fim da histria vai ficar assim, por exemplo, para um artigo de id 57:
http://localhost:8000/artigo/57/
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
Salve o arquivo. Feche o arquivo. Aps um F5 no navegador, na URL do RSS, veja o resultado:
A mensagem de erro completa esta: Give your Artigo class a get_absolute_url() method, or define an item_link() method in your Feed class. Veja que ele sugere a criao do mtodo item_link (que acabamos de remover) ou do mtodo get_absolute_url() na classe Artigo. Vamos fazer isso? Na pasta da aplicao blog, abra o arquivo models.py para edio e ao final da classe Artigo (o final do arquivo) adicione as seguintes linhas de cdigo:
def get_absolute_url(self): return '/artigo/%d/'%self.id
53
Salve o arquivo. Feche o arquivo. De volta ao navegador, atualize a pgina com F5 e veja que voltamos ao normal!
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:
Hummm... no saiu como queramos... Mas isso aconteceu pelo seguinte motivo: O Django possui suporte a mltiplos sites em um nico projeto. Isso quer dizer que se voc tem um projeto de blog, voc pode ter os blogs do Cartola, do Alatazan e da Nena, todos eles usando o mesmo projeto, ainda que trabalhem com
55
informaes distintas. Isso s vezes muito til. Quando um projeto criado, ele recebe um "site" padro, que tem o endereo http://example.com, justamente para voc modificar e deixar como quiser. Ento vamos mudar isso para http://localhost:8000/, certo? Carregue o endereo do admin no navegador:
http://localhost:8000/admin/
Na caixa 'Sites', clique no item 'Sites'. Na pgina carregada, clique sobre 'example.com', e modifique, substituindo 'example.com' para 'localhost:8000', assim:
Clique no boto Save. Feche a janela de execuo do Django e execute novamente o arquivo executar.bat da pasta do projeto. Volte URL anterior ( http://localhost:8000/admin/blog/artigo/1/ ), clique em "View on site" e o resultado ser este:
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'),
# Uncomment the next two lines to enable the admin: from django.contrib import admin admin.autodiscover()
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'), )
Salve o arquivo. Feche o arquivo. Volte ao navegador, pressione a tecla F5 e observe que a mensagem mudou:
Essa mensagem indica que a URL informada ( http://localhost:8000/artigo/1/ ) realmente existe, mas que no foi encontrada a view 'blog.views.artigo'. Isso acontece porque a view realmente no existe. Ainda! Agora, na pasta da aplicao blog, crie um novo arquivo, chamado views.py e escreva o seguinte cdigo dentro:
from django.shortcuts import render_to_response
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>
Salve o arquivo. Feche o arquivo. V ao navegador e carregue a pgina principal de nosso site:
http://localhost:8000/
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
Alatazan levantou cedinho, correu at a geladeira e buscou um doce de goiaba. Aquilo era muito bom e ele devorava cada pedacinho, como se fossem os deliciosos lagartos que vendem nas panificadoras de sua cidade natal. Ele ligou a TV. Sempre achou muito engraada aquela forma primitiva de entretenimento. No programa educativo daquela manh, estavam apresentando como funciona a linha de fabricao e montagem de automveis. Qualquer um sabe - isso, aqui na Terra, claro - que um automvel movido pela fora de seu motor, que faz um (ou ambos) de seus eixos girar, e isso faz as rodas levarem o carro frente. H diversas outras partes fundamentais em um veculo, e elas so compostas uma por uma, at que no fim da linha de montagem, passam a ser feitos ajustes, pinturas e encaixes com um propsito tambm muito importante: o conforto do motorista e o visual do carro. No h nada de agradvel em dirigir um automvel com cadeiras de ferro ou observar um carro sem os devidos acabamentos. A situao do blog de Alatazan mais ou menos essa: funciona mas est longe de ser uma beleza.
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/
Voc levaria a srio um site assim? Alatazan tambm no. Ento vamos criar um CSS para melhorar isso. CSS significa Cascading Style Sheet. Por alguma razo mrbida, Alatazan se lembrou da sociedade RSS de Katara, que se refere a "Rarams Sarabinis Sarados". O significado do nome dessa sociedade conservadora e risonha no era conhecido nem mesmo por seus seguidores, j que era conservada da mesma forma (e por sinal desorganizada) h tantos milnios que o significado se perdeu por l. Alatazan voltou sua ateno ao CSS e notou que isso no tinha nada a ver com aquilo. E prosseguiu. Aproveitando o devaneio de Alatazan, a partir de agora, para facilitar a nossa comunicao, vamos usar o caminho de pastas de forma mais compacta, certo? Partindo da pasta do projeto (meu_blog), em blog/templates/blog abra o arquivo artigo_archive.html, e o modifique de forma que fique assim:
<html>
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; }
66
<body>
<h1>Blog do Alatazan</h1>
</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'
Como deve ter notado, a mudana foi de "english-unitedstates" para "portuguese-brazil". Salve o arquivo. Feche o arquivo. Volte ao navegador, pressione a tecla F5 e:
Pronto! Agora estamos falando a mesma lngua! Nota: d uma olhadinha na interface de administrao ( http://localhost:8000/admin/ ) para ver que agora tudo est em bom portugus brasileiro. Mas ainda assim, aquela data ficou ruim, pois no possui horas, e ficou um tanto burocrtica. Vamos fazer algo mais bacana? Voltando ao arquivo do template ( artigo_archive.html ) substitua o trecho | date:"d \d\e F \d\e Y" por |timesince, salve o arquivo e veja como fica:
69
70
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>
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 %}.
Salve o arquivo. Feche o arquivo. V ao navegador e atualize com F5. Veja o resultado:
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. )
A tupla TEMPLATE_DIRS indica as pastas onde podem ser encontrados templates para o projeto, alm daquelas que j so automaticamente localizadas dentro das aplicaes. O Django no incentiva o uso exagerado dessas pastas "extra" de templates, pois entendemos que a maior partes deles deve ser concentrada em suas devidas aplicaes, mas em muitas vezes inevitvel possuir alguns arquivos-chave numa dessas pastas. Modifique o trecho de cdigo para ficar assim:
TEMPLATE_DIRS = ( 'templates', )
No entanto, h uma coisa desagradvel aqui. O caminho 'templates' no um caminho absoluto, e isso pode te levar a ter diversos problemas. Vamos portanto
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
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'),
Notou o fator de ligao? Observe os elementos blog.views.artigo e artigo_id. Salve o arquivo. Feche o arquivo. E agora, ao carregar a pgina no navegador novamente, voc vai notar o link para a pgina no 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; }
77
<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" %}
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 %}
Puxa! Diminuiu bastante, no foi? Sim, e o que fizemos foi exatamente o oposto do template base.html: removemos as partes generalizadas e levadas para o template herdado e deixamos somente as partes especficas desse template. Note a template tag {% extends "base.html" %} no incio do template. ela quem diz que este template ser uma extenso daquele que criamos ( base.html ). Essa template tag deve sempre estar posicionada no incio do template. A partir do momento em que um template extende outro, qualquer cdigo que estiver fora de uma template tag {% block %} ser ignorado. Portanto, veja que o trecho de cdigo especfico desse template foi colocado dentro do bloco {% block conteudo %}. Os demais blocos no foram declarados ou citados porque nesta pgina no precisamos modific-los. Salve o arquivo. Feche o arquivo. E ao atualizar o navegador com F5, verifique que o visual da pgina inicial permanece o mesmo. Agora vamos fazer o mesmo trabalho no template artigo.html da pasta blog/templates/blog. Abra esse arquivo para edio e modifique para ficar assim:
{% extends "base.html" %}
79
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
81
O que sensibiliza Alatazan desde que chegou Terra que ns humanos possumos uma virtude que tambm importante em Katara. Seres orgnicos possuem individualidade. Cada flor, mesmo sendo da mesma espcie e da mesma planta, possui um tamanho diferente, um tom de cor particular. - dizia ele consigo mesmo enquanto tomava um sorvete na praa. O sorvete caiu no cho e balanou a cabea. Mas continuou: Cada pessoa tem um jeito diferente de agir, uma importncia particular para o todo, e tratar a todos como se fossem iguais seria desperdiar o que cada um tem de melhor... Agora um ou dois pombos mexiam no sorvete espalhado pelo cho. Filosofias parte, Alatazan se levantou e seguiu para a casa de Cartola. Vamos l meu amigo, hoje dia de estudar outra pea importante na engrenagem do site
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, **blog/templates/blog para edio, e localize a seguinte linha:
{% block conteudo %}
da
pasta
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 = ''
A setting MEDIA_URL tem a funo de indicar o endereo que contm arquivos estticos do projeto. Isso no indica que seja possvel ter apenas um. Em grandes projetos necessrio haver mais caminhos para arquivos estticos, ento so tomados outras prticas para isso. Mas sempre que possvel, recomendvel ter apenas um lugar que fornea esses arquivos. E o caminho mais indicado o /media/. Portanto, modifique essa linha para ficar assim:
MEDIA_URL = '/media/'
Esta setting indica o caminho no HD onde esto os arquivos estticos. Modifique esta setting para ficar assim:
MEDIA_ROOT = os.path.join(PROJECT_ROOT_PATH, 'media')
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/'
Esta setting indica o caminho para os arquivos estticos do Admin - a interface automtica de administrao do Django. Acontece que ela est apontando exatamente para o mesmo caminho que a setting MEDIA_URL e isso vai dar em conflito. Ento a modifique para ficar assim:
ADMIN_MEDIA_PREFIX = '/admin_media/'
Voc deve estar se perguntando "mas se estas so as melhores prticas, ento porqu essas settings j no vm dessa forma?". Ahn... melhores prticas uma expresso muito forte. E este assunto trata de variaes diversas em projetos distintos. Digamos que estas sejam as melhores prticas para sites pequenos ou sites em desenvolvimento. Mas ainda assim no so as nicas boas prticas para isso. Portanto, o Django tenta ser o mais discreto possvel, deixando essa deciso para voc. Salve o arquivo. Feche o arquivo. Acha que s isso? No . O caminho que indicamos setting MEDIA_URL no existe no arquivo urls.py e como este um ambiente de desenvolvimento, temos isso a fazer ali: abrir o arquivo urls.py para edio e adicionar a seguinte URL:
(r'^media/(.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
settings
MEDIA_URL
Mas o elemento settings.MEDIA_ROOT ali no vai funcionar, pois preciso dizer quem o "settings" em questo. Portanto, localize a seguinte linha no arquivo:
from django.conf.urls.defaults import *
84
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}), )
Salve o arquivo. Feche o arquivo. Pronto, j temos a URL funcionando. Mas agora precisamos ter uma pasta "media" na pasta do projeto, com o arquivo foto.jpg dentro, certo? Ento v at a pasta do projeto e crie a pasta media. A foto do Alatazan esta:
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:
Bacana! Agora temos uma imagem posicionada em nosso layout! possvel que haja uma dvida em sua cabea agora: "mas o Django s suporta imagens JPEG?" No. isso no est sob poder do Django. O Django suporta qualquer imagem ou outro formato de arquivo esttico, seja ele Shockwave Flash (.swf), imagens (.gif, .jpg, .png e outras), mdia digital (.mp3, .wma, .ogg e outras), JavaScript (.js), CSS (.css) ou qualquer outro formato de arquivo esttico. Essa uma definio que no depende do Django, mas sim de seu servidor e navegador que vo trabalhar com esses arquivos. Agora vamos fazer outra modificao: separar o CSS do template, e criar um arquivo esttico para conter somente o CSS. Vamos?
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; }
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; }
89
font-size: 1.2em; }
Notou que exatamente o mesmo que removemos do template base.html, exceto pela ausncia das tags <style>? Pois agora salve o arquivo. Feche o arquivo. Volte ao navegador e veja que o visual do site voltou ao normal:
90
http://localhost:8000/artigo/1/
Opa! Onde foi parar o estilo CSS desta pgina? Acontece que esta pgina vem que uma view que foi feita manualmente por voc, e esta no possui um contexto que contenha um valor para a varivel {{ MEDIA_URL }}, e isso fez com que sua referncia ficasse vazia, perdendo seu estilo. Mais pra frente vamos ver isso em detalhes, mas agora, vamos nos atentar e resolver o problema. Na pasta da aplicao "blog", abra o arquivo views.py para edio, e modifique o arquivo para ficar da seguinte forma:
from django.shortcuts import render_to_response from django.template import RequestContext
91
Essas modificaes fazem com que algumas variveis especiais (incluindo a {{ MEDIA_URL }}) sejam vlidas nos templates. Salve o arquivo. Feche o arquivo. V ao navegador, atualize com F5 e veja o resultado:
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
Folheando o livro de Xadrez que Nena lhe emprestou, Alatazan notou aquelas sees de informaes do livro, como uma breve biografia do autor, na contracapa, e a pgina onde haviam seus agradecimentos. Na ltima pgina do livro havia tambm um texto promocional de outros livros do mesmo autor, sua fotografia e um carto da loja onde o livro havia sido comprado. comum haver esse tipo de pginas na maior parte dos sites. Isso porqu voc precisa dizer quem , do que se trata e outros assuntos relacionados para dar solidez e demonstrar transparncia ao seu usurio. Seu legado importante.
94
'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',
Salve o arquivo. Feche o arquivo. Agora vamos gerar o banco de dados para ver o efeito que isso causou em nosso projeto. Na pasta do projeto, clique duas vezes sobre o arquivo gerar_banco_de_dados.bat que deve executar da seguinte forma:
95
Clique no link "Adicionar" direita da palavra "Pginas Planas" e adicione uma nova URL da seguinte forma:
96
... e ao rolar a barra de rolagem, ainda h este outro campo para informar:
Ou seja, informe os seguintes valores para os respectivos campos: URL: /sobre-mim/ Ttulo: Sobre mim Contedo: esteja livre para informar o texto como quiser, mas faa questo que esse texto tenha mais de uma linha Sites: localhost:8000 Uma informao importante aqui: no se esquea da barra ( / ) no incio e no final do campo URL. Isso importante para que o middleware consiga casar a URL com a FlatPage, ok? Pois bem, agora clique sobre o boto "Salvar" e carregue no navegador o seguinte endereo:
http://localhost:8000/sobre-mim/
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 %}
Salve o arquivo. Volte ao navegador e pressione a tecla F5 para atualizar. Veja como ficou:
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 }}
Salve o arquivo. Feche o arquivo. V ao navegador, atualize a pgina e veja como ficou:
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
Shhheeeght! Pzzt! SShhhptt! Tzing! Pzzziiitt! Pam-pararampam. Pam! Pam L estava Alatazan em sua nave, uns 500 km acima do cho, j quase no limite da atmosfera, tentando regular o canal para fazer contato com seu planeta. O sistema de comunicao de sua nave utiliza dobradura de nvel 6 no espao, com envergadura de 70 a 90 e isso pode ser seriamente afetado quando h uma tempestade de asteroides nas redondezas. No faz muito tempo que Katara descobriu o rdio como uma simples soluo para comunicaes a grandes distncias, e foi tambm nesta poca que eles souberam da existncia do Planeta Terra e de nossa Internet. Nessa hora ficou ainda mais evidente que Alatazan no podia viver isolado em seu espao, preciso ter um meio para receber contato de outras pessoas, no importa quo distante elas estejam. Ento, naquele dia eles criaram:
101
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.
Bastante evidente, certo? No existe uma URL para a view localizada em *'meu_blog.views.contato', isso que ele est dizendo.
102
Vamos criar essa URL ento: abra o arquivo "urls.py" da pasta do projeto para edio e insira esta linha ao final da chamada patterns():
(r'^contato/$', 'views.contato'),
Bom, continuamos com uma mensagem de erro, mas agora ela mudou, veja:
ViewDoesNotExist: Could not import views. Error was: No module named views
Em outras palavras: no possvel importar* o mdulo views, pois ele no existe. Pois ento vamos cri-lo. Na pasta do projeto ( meu_blog ), crie um novo arquivo chamadado views.py e escreva o seguinte cdigo dentro:
from django.shortcuts import render_to_response from django.template import RequestContext
103
Salve o arquivo. Feche o arquivo. Voc deve ter estranhado que criamos um novo arquivo views.py na pasta do projeto, ao invs de usar o arquivo views.py da pasta da aplicao blog. que esta no uma funcionalidade do blog, e sim do site como um todo. Devemos lembrar que o projeto pode ter mais coisas no futuro, alm do seu blog. Portanto, um arquivo views.py na pasta do projeto para funes que so especficas do projeto faz bastante sentido. Mas ento, de volta ao navegador, pressione F5 e veja como ficou:
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
Salve o arquivo. Feche o arquivo. Volte ao navegador, pressione F5 e veja como ficou:
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" %}
<tr> <th> </th> <td><input type="submit" value="Enviar contato"/></td> </tr> </table> </form> {% endblock conteudo %}
Salve o arquivo. Feche o arquivo. Ufa! Bastante coisa, no verdade? O que fizemos a foi declarar, alm dos blocks habituais, um formulrio para o envio da mensagem de contato. De volta ao navegador, veja como ficou a pgina de contato:
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
107
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()
Esse nosso cdigo faz o seguinte: Se o mtodo dessa request do tipo POST, entende-se que o usurio clicou sobre o boto "Enviar contato". Isso faz sentido porque o carregamento padro de pginas utiliza o mtodo do tipo GET. Ou seja, somente quando o usurio clica no boto, e desde que a tag <form> do template possui um argumento
109
method="post", essa linha ser vlida; Neste caso, a varivel "form" recebe a instncia do formulrio "FormContato", contendo os valores enviados no request.POST. Esses valores so aqueles que o usurio informou no formulrio. Feito isso, o formulrio passa por uma validao ( form.is_valid() ). nesse momento que ele verifica se os campos requeridos foram todos preenchidos, e se todos os campos foram preenchidos corretamente de acordo com seus tipos (por exemplo: um endereo de e-mail no pode ter um formato diferente do habitual que conhecemos); Se a validao seguir com sucesso, chamado o mtodo form.enviar(), que enviar a mensagem; Por fim, mostrada uma mensagem que avisa ao usurio que a mensagem foi enviada com sucesso. No caso de qualquer coisa dessas acima no sair da forma esperada, as devidas mensagens de erro ou validao sero exibidas. Salve o arquivo. Volte ao navegador. E faa o seguinte: Preencha apenas o campo "E-mail", com um e-mail invlido Clique sobre o boto "Enviar contato" sem preencher os demais campos. Veja como ficou:
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:
Puxa, mas o que isso agora? Anime-se! Isso um bom sinal, pois significa que chegamos ao ponto no cdigo onde tudo foi validado e o mtodo form.enviar() no foi encontrado.
111
texto = """ Nome: %(nome)s E-mail: %(email)s Mensagem: %(mensagem)s """ % self.cleaned_data
Agora substitua o trecho 'alatazan@gmail.com' pelo seu e-mail. Mas afinal, o que esse mtodo gigantesco faz? Ele define um ttulo para o e-mail, que ser enviado para voc; Ele define que o destino desse e-mail ser o seu e-mail; Ele define o texto desse e-mail com as informaes preenchidas pelo usurio, usando a sintaxe de formatao de strings do Python; E por fim, ele envia um e-mail ( funo send_mail() ) com esses dados. No Python, para informar uma string com mais de uma linha, voc pode usar trs aspas duplas ou simples, como por exemplo """esta aqui""". Mas o mtodo send_mail no foi devidamente importado. Portanto, v ao incio do arquivo e acrescente a seguinte linha:
from django.core.mail import send_mail
112
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
if form.is_valid(): form.enviar() mostrar = 'Contato enviado!' form = FormContato() else: form = FormContato()
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
Pronto! Mais uma pgina virada em nossa caminhada! Partindo para outra forma de receber contato... Caramba! Quando eu vi o formulrio com os campos na pgina depois de escrever menos de 10 linhas de cdigo, fiquei espantado! Sim, e veja, o que voc fez, num resumo rpido foi isso: Declarou um link para a pgina de contato usando a template tag {% url %}; Criou uma view para a pgina de contato; Criou um novo template para a view de contato. Nele foi criado um <form>; Declarou uma classe de Form e seus campos; Definiu na view uma condio que verifica se o usurio clicou sobre o boto de enviar para efetuar o envio do e-mail;
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
Alatazan estava bebendo um copo d'gua no intervalo da aula, quando uma garota chegou at ele. Ela segurava um copo com refrigerante e comia um pastel. Oi, desculpe, mas seu brao est sujo aqui oh. Alatazan deu uma olhada em seu cotovelo, mas a nica coisa que havia ali eram as listras habituais dos katarenses. Um pouco constrangido e sem saber como explicar moa, ele gaguejou, antes que outra garota, que parecia ser amiga dela, se aproximou rindo. No acredito... no sua tonta, mancha, de nascena, voc est fazendo o menino ficar com vergonha aqui... presta ateno! E riu um pouco mais... Alatazan deu uma risadinha meio de meia boca e deu um jeito de sair dali... no queria entrar naquele "debate". Depois de pensar um pouco, ele percebeu que isso tinha seu lado bom. No final das contas, essa liberdade de expresso acaba sendo positiva e bem-vinda.
117
'blog', )
Temos agora uma nova aplicao no projeto: comments. Salve o arquivo. Feche o arquivo. Agora atualize o banco de dados, clicando duas vezes sobre o arquivo "gerar_banco_de_dados.bat" da pasta do projeto. Uma janela do MS-DOS ser exibida mostrando o seguinte resultado:
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')),
A funo include() inclui as URLs de outro arquivo na URL em questo. Neste caso, as URLs do mdulo 'django.contrib.comments.urls' so includas na URL '^comments/'. Na prtica, se no mdulo 'django.contrib.comments.urls' houver uma URL '^post/$', o Django junta uma coisa outra e entende que possui uma URL '^comments/post/$' apontando para tal. Isso feito para todas as URLs encontradas no mdulo includo ('django.contrib.comments.urls'). uma soluo prtica para dividir as URLs quando o arquivo se torna muito extenso, e tambm muito prtico quando voc quer separar as coisas para que suas aplicaes se tornem mais flexveis. Agora, o arquivo "urls.py" ficou assim:
from django.conf.urls.defaults import *
119
# Uncomment the next two lines to enable the admin: 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}), (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
E veja o resultado:
Opa, a est um formulrio de contato completo! Mas o que ns fizemos ali? A template tag {% render_comment_form for artigo %} gera um formulrio dinmico de comentrios para o objeto "artigo". Lembra-se do Form que trabalhamos no ltimo captulo? Mas ele ficou meio deformando, no? Um pouco de CSS vai fazer bem pra esse layout. Da pasta do projeto, entre em "media", abra o arquivo "layout.css" para edio e acrescente o seguinte trecho de cdigo ao final do arquivo:
form label { display: block; }
121
Salve o arquivo. Feche o arquivo. Volte ao navegador, atualize e veja como ficou:
Agora vamos preencher o formulrio de comentrio para ver o que acontece? Preencha assim:
Nome: Garota da Escola E-mail: garota@escola.com URL: http://escola.com/garota/ Comentrio: Parabns pelo blog!
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">
{% get_comment_list for artigo as comentarios %} {% for comentario in comentarios %} <div class="comentario"> Nome: {{ comentario.name }}<br/> {% if comentario.url %}URL: {{ comentario.url }} {% endif %}<br/> {{ comentario.comment|linebreaks }} <hr/> </div> {% endfor %}
Salve o arquivo. Volte ao navegador, atualize a pgina do artigo e veja como ficou:
123
J melhorou, no ? Pois olha o que fizemos: ns declaramos a template tag {% get_comment_list for artigo as comentarios %} que obtm todos os comentrios que existem para o objeto "artigo" e os coloca na varivel "comentarios". Depois, com a varivel em mos, ns fazemos um lao nela, usando a template tag {% for comentario in comentarios %}, ou seja, todo o trecho de cdigo que est entre as template tags {% for %} e {% endfor %} ser repetido a cada comentrio. Se houverem 5 comentrios na lista, ento ser repetido 5 vezes, uma para cada comentrio, que representado pela varivel "comentario". Por fim, a template tag {% if comentario.url %} sigfinica que o trecho de cdigo que est entre ela e a template tag {% endif %} s deve ser mostrado se o comentrio possuir o campo "url" preenchido. Agora, o template "artigo.html" completo est assim:
{% extends "base.html" %}
{% load comments %}
124
{% get_comment_list for artigo as comentarios %} {% for comentario in comentarios %} <div class="comentario"> Nome: {{ comentario.name }}<br/> {% if comentario.url %}URL: {{ comentario.url }} {% endif %}<br/> {{ comentario.comment|linebreaks }} <hr/> </div> {% endfor %}
<h3>Envie um comentario</h3>
</div> {% endblock %}
Agora observe que no formulrio do template, existe tambm um boto "Preview". Ele faz o seguinte: ao invs de enviar o comentrio, ele apenas exibe o resultado para que o usurio veja como vai ficar antes de enviar. Isso til para que ele tenha uma segunda chance de ajustar algo no texto. Mas chega de explicaes! A funo de pr-visualizao do comentrio Escreva um novo comentrio, clique sobre o boto "Preview" e veja o que acontece:
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" %}
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:
J melhorou, n? Agora, clique no boto "Post" para publicar esse comentrio. Veja:
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>
Salve o arquivo. Feche o arquivo. Volte ao navegador, atualize e veja como ficou:
128
Agora, s lanar vrios artigos e comentrios para ver como a coisa funciona bem!
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.
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
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...
130
muito menos a disposio de arquivos estticos. Estamos falando de apresentao visual, a roupagem esttica que o site precisa receber antes de ser apresentado ao usurio. No a nossa inteno fazer desse um trabalho visual para ganhar algum prmio, e sim, conhecer um pouco do assunto. Antes de mais nada, execute seu projeto, clicando duas vezes no arquivo "executar.bat" da pasta do projeto. Pois bem, vamos comear pelo template mais bsico de nosso site. Aquele que todos extendem: o "base.html", da pasta "templates" do projeto. Abra esse arquivo para edio e o modifique para ficar assim:
<!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" > <head> <title>{% block titulo %}Blog do Alatazan{% endblock %}</title>
{% 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 %}
<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
{% include "rodape.html" %}
Salve o arquivo. Assegure-se de que est salvando o arquivo no padro UTF-8. Mas quanta coisa hein? Como pode notar, modificamos o template em grande parte, portanto, vamos falar das mudanas por partes.
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">
O XHTML uma evoluo do HTML, que obedece a regras melhor definidas. Isso a torna potencialmente mais rpida e melhor compreendida por navegadores e mecanismos de busca. As principais novidades que o XHTML oferece so:
A pgina deve iniciar com uma declarao de DOCTYPE; A tag <html> deve possuir um namespace e definio de idioma; Ela case sensitive, ou seja, letras maisculas e minsculas so consideradas diferentes; Todas as tags devem ser declaradas em letras minsculas (ex.: <body> ao invs de <BODY>); Todas as tags vazias devem ser fechadas com uma barra ao final (ex.: <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"; Frameset - aplica regras especficas para frames e tambm possui a mesma flexibilidade da Transitional;
Namespace e idioma O padro que definimos aponta o XML namespace "http://www.w3.org/1999/xhtml", que define o documento como compatvel com o padro de XHTML definido pelo W3C em 1999. Alm disso, definimos o idioma como "pt-br"
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" />
Esta acima define o padro de caracteres utf-8, ou seja, Unicode, o conjunto de caracteres que suporta os mais importantes alfabetos do mundo.
<meta http-equiv="Content-Language" content="pt-br" />
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." />
Esta acima define a descrio da pgina. Os mecanismos de busca (como o Google) a utilizam para sua descrio quando sua pgina listada nos resultados de uma busca.
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 nonumerada ( <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
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; }
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
.rodape { clear: both; overflow: hidden; background-color: #89a; margin: 20px; font-size: 0.8em; color: white; padding: 10px; text-align: center; }
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 li {
141
#menu ul li a:link, #menu ul li a:visited, #menu ul li a:active { padding: 5px; text-decoration: none; color: white; }
Puxa, o nosso menu j virou outro! Agora acrescente mais esse trecho de cdigo:
/* Artigo do blog */
142
143
/* Comentarios */
144
Pois bem, agora veja como est o nosso CSS depois de tudo:
body { font-family: arial; background-color: #eee; color: #333; }
/* Layout */
145
background-color: white; margin: 20px 0 20px -390px; width: 760px; left: 50%; border: 10px solid #aaa; }
#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; }
.corpo {
.rodape { clear: both; overflow: hidden; background-color: #89a; margin: 20px; font-size: 0.8em; color: white; padding: 10px; text-align: center; }
146
/* 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 li a:link, #menu ul li a:visited, #menu ul li a:active { padding: 5px; text-decoration: none; color: white; }
147
/* Artigo do blog */
/* Formularios */
148
/* Comentarios */
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
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.
com
nome
imprimir_duas_vezes('Tarsila do Amaral')
Salve o arquivo. V Prompt do MS-DOS (ou no Console do Linux), localize a pasta onde voc salvou o arquivo e execute:
python testar_caracteres.py
Isso acontece porque o seu comentrio da linha 5 possui um "" acentuado, veja:
# aqui que imprime outra vez
153
imprimir_duas_vezes('Tarsila do Amaral')
Isso importante, pois o Python foi criado em solo americano por um holands e utilizado por pessoas do mundo inteiro, o que inclui brasileiros, gregos, russos, chineses, japoneses, coreanos, indianos, isrealenses e muitos outros, cada qual com seus caracteres particulares e outros em comum. Portanto, o Python deve suportar a todos eles, suas particularidades e aquilo que h em comum entre eles.
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 doispontos ( : ). Veja este cdigo novamente, por exemplo:
# -*- coding: utf-8 -*-
imprimir_duas_vezes('Tarsila do Amaral')
O Python segue as linhas do arquivo de cima para baixo at encontrar a seguinte linha:
def imprimir_duas_vezes(texto):
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
Pois bem, este o Python interativo. importante conhec-lo, pois constantemente fazemos tarefas de administrao de projetos usando esta ferramenta, que muito prtica tambm para o aprendizado.
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 usla. 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
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
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)
Observe que aqui, ns importamos o pacote "datetime" inteiro. Ento, para us-lo, precisamos informar todo o caminho para a funo today().
>>> datetime = __import__('datetime') >>> datetime.date.today() datetime.date(2008, 11, 24)
Neste outro bloco, importamos o pacote "datetime" da mesma forma, s que agora seu nome foi informado dentro de uma string. Isso til para se importar pacotes quando seus nomes sero conhecidos somente em tempo de execuo.
>>> from datetime import * >>> 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
Puxa, fizemos um bocado de coisas a. Primeiro, voc deve ter notado que a cada incio de um novo bloco, mais 4 espaos devem acrescentar edentao e o contrrio tambm verdadeiro. Em segundo, declaramos alguns atributos para a classe (nome, idade, nota e mulher) j com valores iniciais. Isso no obrigatrio, mas d uma clareza
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.
Primeiro, instanciamos a classe Pessoa e atribumos essa instncia varivel "mychell". Depois atribumos valores a seus atributos, para modificar os valores iniciais. E por ltimo, executamos o mtodo andar. Na primeira execuo do mtodo, no informamos um valor para o parmetro passos, ento o valor assumido foi 10. Veja:
>>> mychell.andar() Andou 10 passos!
Na segunda execuo, informamos um valor para o parmetro. Observe que o parmetro self foi completamente ignorado. Isso porqu ele deve ser informado
160
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
J na linha abaixo, a coisa bem parecida, mas o valor do parmetro "mulher" s ser atribudo ao atributo "self.mulher" caso ele no seja None, ou seja, seu valor default.
... self.mulher = mulher is not None or self.mulher
importante perceber aqui, que o que estamos fazendo atribuir os valores informados para os parmetros opcionais somente se estes foram realmente informados, pois None seu valor default, e indica que ele no foi informado. Na segunda parte, atribumos a funo classe, como se fosse um atributo, de nome __init__, mas como ela uma funo, o Python a atribui como mtodo. Agora veja a seguir:
>>> ana = Pessoa()
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)
Agora fizemos do jeito certo, atribuindo o nome 'Ana Paula' e a idade 8. Ao imprimir os valores dos atributos na tela, eles so exibidos, at mesmo o atributo "mulher", que permaneceu com seu valor default.
>>> ana.nome 'Ana Paula' >>> ana.idade 8 >>> ana.mulher True
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
def __init__(self, nome, idade, nota=None, mulher=None): self.nome = nome self.idade = idade self.nota = nota or self.nota self.mulher = mulher is not None or self.mulher
def andar(self, passos=10): if self.idade > 120: print 'Nao foi possivel'
162
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"""
E muito aconselhvel que todas as funes e classes tenham um comentrio no incio do bloco, assim:
class Pessoa: """Classe para atribuicao a pessoas do sistema""" nome = None
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 | | | | | | nome = None idade = 20 Data and other attributes defined here: Classe para atribuicao a pessoas do sistema
No fantstico?
FILE (built-in)
164
Ou este:
>>> import urllib >>> help(urllib) Help on module urllib:
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
Isso muito til e ajuda bastante. E to til quanto a funo help() a funo dir(), veja
>>> dir(Pessoa) ['__doc__', '__init__', '__module__', 'andar', 'idade', 'mulher', 'nome', 'nota']
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' ]
Novamente: o Python fantstico! Com muita empolgao, rumo ao deploy Alatazan ficou fascinado, e Ballzer, como era de se esperar, comeou a formular suas aventuras futuras.
Puxa, evidentemente o Python mais do que isso, mas s em saber disso muito do que j fizemos e vamos fazer nos prximos dias se esclareceu de forma to... pythonica! Meu camarada, muito, muito bacana programar em Python. E o mais interessante que as coisas so realmente simples, veja que muito fcil casar classes com funes de formas variadas. por isso que existem tantos frameworks criados em Python!
166
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; O shell interativo uma mo-na-roda em muitas situaes; a tipagem de dados no Python dinmica e forte; faa tudo explcito e use namespaces; classes tambm so objetos, e mtodos devem ser declarados sempre com self sendo o primeiro parmetro;
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
Nesse dia, caiu uma chuva daquelas que no tm nada a ver com o tempo nem com a poca. Alatazan nem sabia disso, pois estava no planeta h poucas semanas. Mas ele sentiu um gostinho de vingana quando viu os panfletos de gs, supermercado, me-desanto e outros mais derretendo na caixinha de correios. Definitivamente: se havia uma coisa chatssima na Terra eram esses malditos panfletos. Alatazan compreendeu mais rpido que ningum a ideia de "colocar no ar". Em Katara, h empresas de publicidade que colocam milhares de propagandas no ar todos os dias. O problema que essas propagandas so pequenos robs que se parecem com moscas, e ficam em grupos de 5 ou 6 por ali, perto dos portes como se no quisessem nada, assobiando e praticando um voo manjado. Quando o infeliz morador sai de sua casa, atacado por eles com as mais variadas propagandas. s vezes essas pessoas entram em ataque de nervos e passam um bom tempo tentando acertar os robs com tapas ou jornais, mas nunca se resolve, e no outro dia a mesma coisa. O pai de Alatazan trabalha na fbrica onde esses robs so feitos, na seo onde eles so treinados, e ali eles usam uma capa frgil, resistente a coisa nenhuma. Depois do treinamento eles recebem uma capa resistente e flexvel, que no permite que se derretam quando a chuva cai. S depois disso, podem ser colocados 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:
H algumas settings que so muito relativas ao ambiente ao qual seu projeto est no momento. Vamos dar o exemplo mais simples: o estado de DEBUG. Esta setting s deve ter valor True em ambientes de teste ou desenvolvimento, nunca em produo. Outras settings j so resultado de uma definio fixa, somada a outra setting do caso citado acima. Um bom exemplo a setting MEDIA_ROOT que seria sempre a mesma pasta "media" da pasta do projeto, mas a pasta do projeto pode estar em um caminho no ambiente de desenvolvimento e em outro no servidor. E h ainda as settings que dificilmente mudam, como INSTALLED_APPS por exemplo. A definio de quais settings so flexveis e quais no o so variam de acordo com o projeto, mas em geral h um ponto divisor no arquivo "settings.py" que se adapta maioria dos casos.
169
Na maioria dos projetos, esta a ltima linha de um grupo de settings que variam muito de acordo com a situao atual do projeto. Abaixo desta linha esto aquelas settings que se ajustam a elas, ou que no se ajustam a nada. Portanto, vamos acrescentar um novo trecho de cdigo abaixo dessa linha:
from local_settings import *
Salve o arquivo e v janela do MS-DOS (ou Console, no caso do Linux) onde o projeto est rodando. Veja o que aconteceu:
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
Salve o arquivo. Execute o projeto novamente, clicando duas vezes sobre o arquivo "executar.bat" da pasta do projeto. No Python, o try/except um recurso que permite que voc faa uma tentativa, e caso essa tentativa resulte em erro, voc pode tratar esse erro sem que seu software seja afetado ou paralisado. Em outras palavras ns tentamos importar todas as settings do arquivo "local_settings.py", mas caso ocorra algum erro de importao ( ImportError ), a situao ser ignorada e o interpretador do Python deve seguir adiante como se nada tivesse acontecido. Veja que apenas erros de importao esto sendo suportados aqui, ou seja, qualquer outro tipo de erro ter o comportamento padro de levantar uma exceo. O erro de importao mais comum o de o arquivo no existir. O raciocnio o seguinte: todas as settings do arquivo "local_settings.py" sero importadas, substituindo o valor das settings que esto acima desse trecho de cdigo. Se elas no tiverem sido declaradas no "local_settings.py", permanecem como esto. Agora, na pasta do projeto, crie um novo arquivo chamado "local_settings.py" com o seguinte cdigo dentro:
import os PROJECT_ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
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
Ao mudar a setting DEBUG para False, desativamos o estado de depurao do projeto em suas configuraes padro, mas elas permanecero funcionando localmente, pois no arquivo "local_settings.py" elas foram mantidas como estavam. Ok, por agora isso suficiente. Salve o arquivo. Feche o arquivo. Agora abra o arquivo "urls.py" da pasta do projeto para edio e localize o seguinte techo de cdigo:
(r'^media/(.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
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}), )
O que fizemos a foi o seguinte: a URL '^media/' s deve existir se o projeto estiver em mquina local, ou seja, na sua mquina, em ambiente de desenvolvimento. Isso importante, pois o Django no foi feito para servir arquivos estticos em servidores. No servidor esta tarefa deve ser deixada para um software que foi criado para isso: um servidor web, como o Apache, Lighttpd, IIS ou outro. Agora o arquivo urls.py ficou assim:
from django.conf.urls.defaults import * from django.conf import settings
# Uncomment the next two lines to enable the admin: from django.contrib import admin admin.autodiscover()
172
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')), )
Salve o arquivo. Feche o arquivo. A diviso que trabalhamos no arquivo "settings.py", que voc pde observar no diagrama, simples de se fazer e poderosa. Pois seguindo essa linha de raciocnio possvel no s configurar o projeto para diferenciar o servidor em produo de seu ambiente de desenvolvimento, como til tambm para ambientes de homologao e testes, situaes de um projeto em mais de um servidor ou de mltiplos sites em um s projeto. Tire um tempo para pensar nisso, observe o arquivo "settings.py" com ateno e note aquilo que poderia variar em situaes distintas. Se for necessrio, mova a setting desejada para antes ou depois do trecho de cdigo que importa o mdulo "local_settings.py". Agora, para concluir, abra novamente o arquivo "settings.py" do projeto e localize a seguinte linha:
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
Prximo a onde Alatazan viveu sua infncia h uma cidade chamada Konnibagga, que foi construda dentro de uma ilha, no meio de um lago. Devido sua populao ser extremamente dinmica, atravs dos sculos dezenas de pontes foram construdas para atravessar o lago at a ilha. Haviam pontes compridas, pontes curtas, pontes gratuitas, pontes com pedgio, pontes bonitas e feias, resistentes e frgeis, largas e estreitas. Um dia um homem sugeriu que se fossem atravessadas todas as pontes em sequncia, entrando e saindo da cidade, seria possvel desenhar um girassol com o traado do percurso. Acontece que em Katara no existem girassis e ningum compreendeu qual era o fundamento para tal sugesto. O homem foi ento contratado pela prefeitura para construir mais pontes por um lucro maior desde que parasse de falar nessa ideia, e assim ele realmente parou com isso, construiu muitas pontes e com o dinheiro fez uma viagem transatlntica apesar de l tambm no haver um Atlntico para atravessar.
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/
Seu uso se resume a construir um pequeno script, chamado de fabfile, que determina as regras para se atualizar servidores em grande nmero, realizando algumas tarefas relacionadas a isso. No se trata de uma opo vantajosa para a maioria do sites que esto presentes em somente um servidor, mas para ambientes mais complexos se trata de uma grande vantagem.
177
Cada um deles possui uma forma diferente de se configurar para trabalhar com o Django. No prximo captulo vamos trabalhar a configurao do Apache, o mais popular e comum deles.
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/
Dessa forma voc pode configurar o servidor web de formas diferentes, otimizando cada um de acordo com seu caso. Voc pode inclusive separar para softwares servidores web diferentes se preferir. Exemplo: Apache para o projeto em Django e Lighttpd para arquivos estticos.
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); e outros scripts e arquivos relacionados ao deploy no servidor, como por exemplo um arquivo com a lista de cron jobs, que so tarefas agendadas para servidores Linux/Unix/MacOS X.
No mesmo nvel da pasta do projeto h outra pasta aqui: 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
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
Um ndio passou em seu cavalo a galopes entre duas rochas. Havia poeira no ar, e tambm havia o cheiro da poeira, o Sol castigava a poeira, e a terra vermelha socada por sculos de pouca chuva e muito vento, fazia desenhos atravs do deserto, com muita poeira. Os desenhos serpenteavam por aqui e ali, e pelas serpentes, ora passavam cavalos, ora passavam rios, ora passava uma criana chorando no colo de sua me, segurando firme seu iPod. O ndio de pele vermelha - no se sabe se era devido ao Sol, devido terra avermelhada da regio ou devido sua timidez naquele momento - galopou novamente at uma lagoa, entregou peixes boca de um golfinho, montou seu cavalo novamente e rumou a um celeiro, atravessando por uma janela larga e alta, e... Opa! Voltando os olhos novamente quele menino que no para de chorar, agora sentado com sua me, assistindo aos colegas terminarem a pea, morrendo de inveja porque no ia ganhar os aplausos do teatro e nem o novssimo MelecaBoy verde, uma nova mania gosmenta da sesso de desenhos, e... enfim, isso nem interessa... Ao final, Cadu correu at Cartola, tirou uma onda, curtiu seu momento de ator-mirim e voltou a rodopiar por ali. Mas Alatazan ainda estava um pouco ligado no assunto do servidor para o dia seguinte...
185
Windows. Os procedimentos so semelhantes nos dois sistemas operacionais, e a parte mais importante - a configurao para ter seu projeto funcionando - realmente muito parecida entre ambos, portanto seu aprendizado ser til em qualquer caso, mas agora vamos ao trabalho! Voc pode usar a mesma mquina que tem usado para estudar o Django, pois no se tratam de recursos conflitantes. Esta uma situao bastante normal para intranets e sistemas em redes locais.
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:
Clique no link para fazer o download. Enquanto o download feito, sua mente deve estar se perguntando "porqu h
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
Preencha os respectivos valores para os campos. Caso no saiba o que preencher ali, preencha da seguinte forma: Network Domain: "localhost" Server Name: "localhost" Administrator's E-mail Address: "seu_email@qualquercoisa.com" Modifique o campo "Administrator's E-mail Address" de acordo com seu prprio e-mail e siga adianta clicando em "Next" at finalizar. Ao finalizar a instalao, verifique o cone do Apache na bandeja do Windows, prximo ao relgio:
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
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
A verso mais indicada a verso 5.1. Na opo "Windows Essentials (x86)", clique no link "Pick a mirror".
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.
Siga clicando no boto "Next" at finalizar a instalao. Ao final ser exibida uma nova janela para configurao do MySQL (que por sinal muito semelhante s janelas de instalao).
190
Prossiga clicando sobre "Next", modificando as opes padro somente se estiver certo de tal mudana. At chegar a essa tela:
Escolha a segunda opo ( "Best Support for Multilingualism" ). Isso vai tornar a codificao de caracteres padro em "UTF-8", a que melhor se relaciona com o Django, e evitar alguma eventual chatice alguns dias frente. Prossiga clicando em "Next" at chegar a esta 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.
Faa o download do mysql-python na opo "MySQL-python-1.2.2.win32py2.5.exe". Da mesma forma que as instalaes anteriores, a verso atual pode variar para cima (1.2.3, 1.3 ou 2.0 por exemplo):
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
Localize uma linha que inicia com "LoadModule" e acrescente a seguinte linha abaixo dela:
LoadModule python_module modules/mod_python.so
Salve o arquivo. Feche o arquivo. Na verdade voc vai encontrar muitas linhas assim, mas no se preocupe. Se acrescentar a nova linha abaixo de qualquer uma delas, estar no lugar correto. E agora voc tem o mod_python instalado em seu servidor Windows.
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 "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__))
( arquivo
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>
196
Feche a janela do MS-DOS e v pasta do projeto. Clique duas vezes sobre o arquivo "gerar_banco_de_dados.bat" para gerar as tabelas para o novo banco de dados em MySQL. agora que vamos saber se a nossa configurao est correta:
Informe os dados solicitados ( Username, E-mail, Password e Password again ) da mesma forma que fizemos no captulo 4 ( Criando um blog maneiro ), com username "admin" e password "1". Aps finalizar a gerao do banco de dados, feche a janela e... ... pronto! Mais um passo dado! Temos o projeto e o MySQL conversando naturalmente at aqui!
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
Esta linha abaixo indica a PYTHONPATH que o Python deve obedecer na mquina virtual que ser aberta para esta URL. No caso, atribumos a pasta do projeto ( 'c:/var/django/projects/site_meu_blog/meu_blog' ), acrescentada do que j estava antes na PYTHONPATH ( sys.path ), seguindo a sintaxe do prprio Python para isso.
PythonPath "['c:/var/django/projects/site_meu_blog/meu_blog'] + sys.path"
Na linha seguinte determinamos que o Apache deve utilizar o handler do Django para atender s requisies atravs do Python neste caso.
PythonHandler django.core.handlers.modpython
E aqui declaramos uma varivel de ambiente que determina o mdulo que contm as settings do projeto. Observe que se indicamos a pasta do projeto PYTHONPATH, ento todos os mdulos ( arquivos com extenso ".py" ) que esto na pasta do projeto podem agora ser informados com seu nico nome, pois eles esto na PYTHONPATH sem nenhum pacote intermedirio. Na prtica, estamos passando o arquivo "settings.py" para o Django .
SetEnv DJANGO_SETTINGS_MODULE settings
Por fim, definimos o estado de depurao para a mquina virtual do Python. Como estamos ainda em processo de colocar o site no ar, prudente manter essa configurao. Quando o site estiver em pleno funcionamento, recomendvel que esta linha seja removida.
PythonDebug On
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
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
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
Mas isso no suficiente, pois preciso dar permisso pasta indicada, portanto, este bloco abaixo d a permisso necessria:
<Directory "C:/var/django/projects/site_meu_blog/meu_blog/media"> Order allow,deny Allow from all </Directory>
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>
Salve o arquivo. Reinicie o Apache, usando o cone na bandeja do Windows na opo "Restart" para aplicar a mudana que fizemos. Voltando ao navegador, pressione F5 e veja como ficou:
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
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
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
Naquela noite ao chegar sua casa, Nena abriu uma nova mquina virtual com o Ubuntu Linux em seu laptop. No queria usar sua instalao oficial cheia de coisas j instaladas. Alatazan por sua vez aproveitou a passagem de uma nave-gal de Katara pelo nosso sistema solar para dar uma passadinha por l (atrs de Jpiter) e buscar algumas coisas que sua me mandou. A definio mais comum da palavra "me" em nossa galxia de "aquela que serve, protege, regula e manda pra voc um monte de coisas inteis que um dia com febre e assaduras voc descobre que no eram to inteis assim". Claro que a me de Alatazan no foge definio, e nas caixas que mandou esto alguns pacotinhos com... por exemplo: uma caixinha de cuecas refrescantes, um spray do p que refresca as cuecas por algum tempo, uma chave-polvo para desentalar o spray de vez em quando e uma alga-area para alimentar a chavepolvo. Ao sair de Katara, Alatazan se sentiu aliviado por no ser mais obrigado a usar as tais cuecas a guardou as poucas que trouxe em algum lugar no fundo da nave. Mas agora, cansado de desenhar silhuetas desconfortveis para o ventilador, ele estava com uma assadura na virilha, o que fazia com que andasse desajeitado, parecendo um E.T. e no sabia mais onde as cuecas estavam. Por isso, os pacotes de sua me foram bastante tranquilizadores.
205
PostgreSQL, no bem por a... o bom conhecer sistemas operacionais diferentes, bancos de dados diferentes, servidores web diferentes e assim por diante. Para colocar em prtica o nosso servidor em Linux, no se esquea de que preciso ter o controle total do sistema, do contrrio no ser possvel instalar os softwares que vamos instalar nem mesmo configur-los. Portanto, a recomendao que agora voc use sua instalao do Ubuntu em mquina local ou em uma mquina virtual, como Alatazan o fez. Neste captulo vamos trabalhar no universo Ubuntu/Debian, que esto entre as distribuies mais populares do Linux. Para fazer o download do Ubuntu, v at esta pgina:
http://www.ubuntu.com/
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 MSDOS. 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
Confirme a instalao dos pacotes e aguarde pela concluso. Assim como aconteceu com o Lighttpd, ao concluir a instalao, o PostgreSQL j iniciado. Agora, precisamos definir uma senha para o usurio "postgres" para ter acesso ao banco de dados. Portanto, digite agora as seguintes linhas de comando:
sudo su postgres psql
Este o shell cliente do PostreSQL, onde possvel realizar qualquer operao SQL de definio de modelo de dados, consulta a dados, persistncia e tarefas de manuteno, enfim, muito poderoso. Para alterar a senha do usurio "postgres" do PostgreSQL, digite a seguinte linha de comando:
alter user postgres with password '123456';
No se esquea de trocar a senha '123456' pela de sua preferncia. O resultado na linha abaixo ser este:
ALTER ROLE
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
Ao solicitar a senha, digite a senha informada no lugar de '123456' criada agora h pouco. Veja a mensagem de erro que ser exibida:
psql: FATAL: autenticao do tipo Ident falhou para o usurio "postgres"
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 sameuser postgres ident
O que esta linha faz e determinar que o usurio "postgres" do PostgreSQL s pode ser autenticado caso esteja acessando do servidor local, com o usurio equivalente do sistema operacional (ou seja, o usurio "postgres" do Linux). Vamos portanto liberar a autenticao deste usurio por outros (como o seu prprio usurio por exemplo). Para isso, modifique as linhas para ficar assim:
# Database administrative login by UNIX sockets local all postgres password
Salve o arquivo. Feche o arquivo. Agora de volta ao shell, reinicie o servio do PostgreSQL com a seguinte linha de comando:
sudo /etc/init.d/postgresql-8.3 restart
209
Veja o resultado:
Pronto! Agora temos o PostgreSQL funcionando em nosso servidor, da forma apropriada ao que precisamos.
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
Aps confirmar e concluir a instalao, seu servidor j ter o Django na verso 1.0 - no mnimo - devidamente instalada. J nas demais verses do Ubuntu Linux, isso no recomendvel, pois a maioria delas ainda tem esse pacote em uma verso antiga do Django ( 0.96 ). Portanto neste caso, para instalar o Django, faa assim: Primeiro instale o Subversion, com a seguinte linha de comando:
sudo apt-get install subversion
210
http://code.djangoproject.com/svn/django/tags/releases/1.0.2/ django-1.0.2
Isso vai baixar o cdigo-fonte da ltima reviso da verso 1.0.2 do Django, usando o Subversion - um software de controle de verses. Aps concluir o download, entre na nova pasta "django-1.0.2" e instale o Django:
cd django-1.0.2 sudo python setup.py install
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
E agora, fora da pasta de instalao do Django e dentro do shell interativo, digite estas linhas de comando:
import django django.get_version()
O resultado dever ser este (ou outro muito semelhante a este, mas sem mensagem de erro):
'1.0.2 final'
Agora saia do shell interativo, pressionando Control+D. Pronto! Agora temos o Django numa verso bacana funcionando em nosso servidor!
Pronto! Aps confirmar e concluir a instalao, j temos a biblioteca de acesso ao PostgreSQL funcionando no Python em nosso servidor!
211
biblioteca do Python responsvel pela compatibilidade com o FastCGI. Para isso, digite a seguinte linha de comando:
sudo apt-get install python-flup
Lembre-se de trocar o "SEU_USUARIO" nas duas linhas de comando pelo nome do seu usurio atual. As linhas de comando vo: 1. Criar a pasta onde vamos colocar nossas coisas em Django, usando o superusurio do sistema operacional; 2. Assumir o seu prprio usurio como dono da nova pasta; 3. Assumir o seu prprio grupo como dono dela; 4. Acessar a pasta. Agora cria a sequncia de pastas:
mkdir projects cd projects mkdir site_meu_blog
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
),
abra
arquivo
DATABASE_ENGINE = 'postgresql_psycopg2' DATABASE_NAME = 'meu_blog' DATABASE_HOST = 'localhost' DATABASE_USER = 'postgres' DATABASE_PASSWORD = '123456'
FORCE_SCRIPT_NAME = ''
Da mesma forma que no captulo anterior, desabilitamos o modo de depurao, mas desta vez preparamos o projeto para trabalhar com o PostgreSQL, ao invs do MySQL. No v se esquecer de ajustar a setting "DATABASE_PASSWORD" com a senha que escolheu para o lugar de "123456". O principal ponto a ser observado nessa modificao trata-se desta linha:
FORCE_SCRIPT_NAME = ''
Ela ter o papel de ocultar o nome interno do script do FastCGI, e caso no seja informada, o site muito provavelmente se comportar de forma instvel em suas URLs. Salve o arquivo. Feche o arquivo.
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
Agora, precisamos gerar as tabelas do banco de dados, lembra-se? S para nos certificar, digite a linha de comando abaixo para se posicionar na pasta do projeto:
cd /var/django/projects/site_meu_blog/meu_blog
Depois de dadas as informaes solicitadas (Username, E-mail, Password e Password again), o resultado deve ser este:
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 userdir.conf 10-cgi.conf 10-fastcgi.conf 10-proxy.conf 10-rrdtool.conf 10-simple-vhost.conf 10-ssi.conf 10-ssl.conf 10-status.conf 10README
Esses arquivos so pr-configurados para determinadas utilidades. uma dessas coisas feitas para ajudar quem est configurando o servidor. Mas ns vamos criar um novo, completamente vazio. Abra um novo arquivo "10-meu_blog.conf"
215
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",
) ) )
Determinar um caminho interno do servidor apontando para um script do projeto (alem de determinar o caminho para o arquivo de socket):
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" ,
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" )
Salve o arquivo. Feche o arquivo. Agora precisamos ativar essa configurao. Para isso, vamos criar um link simblico para representar o arquivo "10-meu_blog.conf" na pasta que define as configuraes ativadas.
sudo ln -s /etc/lighttpd/conf-available/10-meu_blog.conf ../confenabled/
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
217
sys.path.insert( 0, '/var/django/pluggables/' )
Resumindo, o que fizemos nesse outro arquivo de script foi isso: Possibilitamos que este arquivo seja executvel, e dizemos ao Linux que ele deve ser interpretado pelo Python:
#!/usr/bin/python
Agora um pequeno trick necessrio e a definio da varivel de ambiente "DJANGO_SETTINGS_MODULE" apontando o mdulo que contm as settings do projeto, que por sua vez ser localizada na PYTHONPATH que acabamos de definir:
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
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", ) ) )
url.rewrite-once = ( "^(/media/.*)$" => "$1", "^(/admin_media/.*)$" => "$1", "^(/.*)$" => "/default.fcgi$1" )
Observe que fizemos as seguintes modificaes: Primeiro, acrescentamos dois "apelidos", dizendo ao Lighttpd que tais URLS ("/media" e "/admin_media") devem apontar para as respectivas pastas no HD. Ou seja: so URLs simples para pastas de arquivos estticos e devem fazer exatamente isso: retornar arquivos estticos do HD no caminho definido. Observe com ateno a pasta "/usr/lib/python2.5/sitepackages/django/contrib/admin/media/" pois ela pode ser diferente em seu sistema operacional se por acaso ele usar a verso 2,4 do Python como padro.
alias.url = (
220
As demais linhas que acrescentamos criam URLs com suas respectivas expresses regulares para os "apelidos" de arquivos estticos, veja:
"^(/media/.*)$" => "$1", "^(/admin_media/.*)$" => "$1",
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
Houve uma poca em que restavam poucos planetas e satlites prximos a Katara para serem habitados, e as pessoas perderam seu interesse por alguns deles em especial, talvez devido falta de atmosfera, proximidade de Katara, falta de gua ou qualquer outra desculpa que viesse cabea. Isso no foi bom para os negcios de algumas empresas. Foi por isso que a Bangla Oportunidades Interplanetrias lanou o slogan "s para escolhidos a dedo". A parte do dedo no foi muito bem compreendida a princpio, mas ser um escolhido parecia ser bastante recompensador. As sesses para escolha de novos clientes eram caracterizadas, dentre outras coisas, por avaliar eventos aleatoriamente e escolher aqueles que se esqueciam de parar de bater palmas ao final dos aplausos. Ou mesmo aqueles que batiam palmas sozinhos. Atualmente a comunidade dos moradores do satlite Katara-E o resultado disso, e formada por uma populao extremamente altrusta. Seus moradores compartilham suas casas, compartilham suas roupas, compartilham seus copos, suas mulheres, seus maridos, suas crianas e suas cuecas, especialmente as sujas. s vezes ocorrem algumas distraes como consequncia disso, mas no interessa qual seja o desfecho, no final tudo comemorado com uma boa cervejada e um enterro festivo.
224
Escolha a opo mais adequada sua verso. No caso que temos trabalhado (Apache 2.2 e Python 2.5), a verso a escolher esta:
mod_wsgi_py25_apache22
Faa o download do arquivo "mod_wsgi.so". Ele deve ser colocado na seguinte pasta do HD:
C:\Arquivos de programas\Apache Software Foundation\Apache2.2\modules
Isto vai habilitar o mod_wsgi no seu Apache. Agora localize este trecho de linhas:
<Location "/"> SetHandler python-program PythonPath "['c:/var/django/projects/site_meu_blog/meu_blog'] + sys.path" PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE settings PythonDebug On </Location>
Remova-o. Ou se preferir, copie para um bloco de notas para consultar depois se precisar.
225
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"
J no segundo bloco, ns definimos a permisso para que o Apache acesse a pasta deste script:
<Directory "c:/var/django/projects/site_meu_blog/meu_blog/deploy/"> Order deny,allow Allow from all </Directory>
Salve o arquivo. Feche o arquivo. Reinicie o Apache pelo cone na bandeja do Windows, prximo ao relgio.
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.
E agora dentro da pasta "deploy", crie um arquivo chamado "default.wsgi", com o seguinte cdigo dentro:
import os, sys
import django.core.handlers.wsgi
227
application = django.core.handlers.wsgi.WSGIHandler()
Agora observe o que fizemos: Na primeira linha simplesmente importamos os pacotes de sistema operacional e de sistema do Python.
import os, sys
No bloco seguinte, ns encontramos a pasta do projeto (uma acima da pasta do script), inserimos seu caminho no incio da PYTHONPATH e definimos o mdulo de settings para o Django:
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'
Por fim, importamos o handler do Django para trabalhar com WSGI e declaramos a varivel "application" atribuda de uma instncia do handler, veja:
import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
O WSGI trabalha sempre procurando pela varivel "application" no script em questo. Portanto, no mude este nome, ele fundamental. Salve o arquivo. Feche o arquivo. Reinicie o Apache pelo cone na bandeja do Windows, volte ao navegador, atualize com F5 e veja como ficou:
228
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"
230
Voltamos estaca zero? Nem tanto. Mas agora localize a seguinte linha no arquivo:
#LoadModule rewrite_module modules/mod_rewrite.so
Isso vai ativar o "mod_rewrite" no Apache. Agora acrescente esse trecho ao final do arquivo:
AddHandler wsgi-script .wsgi
<Directory "C:/Arquivos de programas/Apache Softw are Foundation/Apache2.2/htdocs"> AllowOverride FileInfo Options ExecCGI MultiViews FollowSymLinks MultiviewsMatch Handlers
Veja s o que fizemos: Aqui ns vinculamos uma extenso de arquivo ao formato de script de WSGI:
AddHandler wsgi-script .wsgi
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
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]
Vamos detalhar o que essas linhas significam? Veja: Ativamos o rewriting da pasta de documentos. A partir desse ponto as URLs so direcionadas de acordo com as regras abaixo desta linha:
RewriteEngine On
Dizemos que se o caminho da URL requisitada existir na pasta de documentos, ela ter prioridade sobre o Django. esta linha que d vida pasta "media" trabalhando com arquivos estticos.
RewriteCond %{REQUEST_FILENAME} !-f
Dizemos que todas as demais URLs (que no existirem enquanto arquivos da pasta) sero repassadas ao nosso projeto em Django. Representado por um script da pasta de documentos, chamado "site.wsgi".
RewriteRule ^(.*)$ /site.wsgi/$1 [QSA,PT,L]
Salve o arquivo. Feche o arquivo. Como pode notar, o arquivo de script "site.wsgi" de fato no existe. Pois ento, ainda na pasta de documentos, crie um novo arquivo chamado "site.wsgi" com o seguinte cdigo dentro:
import os, sys
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
Este script muito semelhante ao que criamos no incio do captulo, mas o caminho do projeto ( "C:/var/django/projects/site_meu_blog/meu_blog" )
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