O que é Django?

Propaganda
Tabeladeconteúdos
Introdução
1.1
Comofuncionaainternet?
1.2
Introduçãoàlinhadecomando
1.3
InstalaçãodoPython
1.4
EditordeCódigo
1.5
IntroduçãoaoPython
1.6
OqueéDjango?
1.7
InstalaçãodoDjango
1.8
Criandoumprojeto
1.9
ModelosdoDjango
1.10
Administração
1.11
Implantação!
1.12
Urls
1.13
Views-horadecriar!
1.14
IntroduçãoaHTML
1.15
DjangoORM(Querysets)
1.16
Dadosdinâmicosnostemplates
1.17
Templates
1.18
CSS-Deixemaisbonito
1.19
Estendendoostemplates
1.20
Ampliesuaaplicação
1.21
Formulários
1.22
Domínio
1.23
Oquevemdepois?
1.24
2
Introdução
TutorialDjangoGirls
EstetrabalhoélicenciadosobalicençaCreativeCommonsAttribution-ShareAlike4.0.Paraverumacópiadesta
licença,visitehttps://creativecommons.org/licenses/by-sa/4.0/
Translation
ThistutorialhasbeentranslatedfromEnglishtoPortuguesebyagroupofawesomevolunteers.
Specialthanksforhelpgoesoutto:
AdailtondoNascimentoAdamVictorNazarethBrandizziAntonioLuisAnnandaSousaAdjamiltonJuniorBernardoFontes
CamillaAchuttiCarlaSuarezCleitonLimaclemente.jnrdanieltexEricHidekiFlavioBarrosFabioC.BarrionuevodaLuz
ffabiorjGabrielaCavalcantedaSilvaLeandroSilvaAraujoLucasMagnum1pedroJoaoLuizLorencetti
KatyannaMouraKleberCPinheiroLeandroBarbosaLeonardoAlvesdosSantosMarcelRibeiroDantasjoepreludian
RafaelBiagionideFazioPabloPalaciosPauloAlemRaonyGuimaresCorreodoCarmoLisboaCardenasVivianMacedo
WillieLawrence*RicardoManhãesSaviiWow!<3<3
Introdução
Vocêjásentiucomoseomundofossecadavezmaissobretecnologiaequedealgumaformavocêtenhaficadopratrás?
Vocêjáimaginoucomoseriacriarumwebsitemasnuncatevemotivaçãosuficienteparacomeçar?Vocêjápensouqueo
mundodosoftwareécomplicadodemaisatéparatentarfazeralgumacoisasozinho?
Bem,nóstemosboasnotíciasparavocê!Programaçãonãoétãodifícilquantopareceenósqueremostemostraroquão
divertidopodeser.
Estetutorialnãoirátetransformarmagicamenteemumprogramador.Sevocêquerserbomnissoprecisademesesou
atémesmoanosdetreinoeprática.Masnósqueremostemostrarqueaprogramaçãooucriaçãodewebsitesnãoétão
complicadaquantoparece.Nóstentaremosexplicarosdiferentespedaçostãobemquantopudermos,talquevocênãose
sintaintimidadopelatecnologia.
Nósesperamosconseguirfazervocêamaratecnologiatantoquantonósamamos!
Oquevocêiráaprenderduranteotutorial?
Quandovocêtiverterminadootutorialvocêteráumaaplicaçãowebsimplesefuncional:seupróprioblog.Nósvamos
mostrarcomocolocá-loonline,paraqueoutrosvejamseutrabalho!
Eleseparecerá(maisoumenos)comisso:
3
Introdução
Sevocêseguirotutorialporcontaprópriaenãotiverumtreinadorparaajudaremcasodequalquerproblema,nós
temosumchatparavocê:
1.Nóspedimosaosnossostreinadoreseparticipantesanteriorespara
acessaremládetemposemtemposeajudaremoutroscomotutorial!Nãotenhamedodefazersuaperguntalá!
OK,vamospelocomeço...
Sobreotutorialecontribuições
EstetutorialémantidoporDjangoGirls.Sevocêencontrarquaisquererrosouquiseratualizarotutorial,porfavorsigaas
orientaçõesdecontribuição.
Gostariadenosajudaratraduzirotutorialparaoutros
idiomas?
nomomento,astraduçõesestãosendomantidasnaplataformacrowdin.comem:
https://crowdin.com/project/django-girls-tutorial
Seoseuidiomanãoestálistadonocrowdin,porfavoropenanewissueinformandooidiomaparaquepossamos
adicioná-lo.
4
Introdução
5
Comofuncionaainternet?
Comofuncionaainternet
Estecapítuloéinspiradonapalestra"ComoaInternetfunciona"deJessicaMcKellar
(http://web.mit.edu/jesstess/www/).
ApostamosquevocêusaaInternettodososdias.Masvocêsaberealmenteoqueacontecequandovocêdigitaum
endereçocomohttps://djangogirls.orgemseunavegadorepressiona'Enter'?
Aprimeiracoisaquevocêprecisaentenderéqueumsiteésóummontedearquivossalvosemumdiscorígido.Assim
comoseusfilmes,músicasoufotos.Noentanto,existeumapartequeéexclusivaparasites:essaparteincluicódigode
computadorchamadoHTML.
Sevocênãoestiverfamiliarizadacomprogramação,podeserdifícilcompreenderoHTMLnocomeço,masseunavegador
web(comooChrome,Safari,Firefox,etc)amaele.NavegadoresWebsãoprojetadosparaentenderessecódigo,seguir
suasinstruçõeseapresentartodosessesarquivosdequeseusiteéfeito,exatamentedojeitoquevocêquerqueeles
sejamapresentados.
Igualàtodososarquivos,osarquivosHTMLprecisamserarmazenadosemumdiscorígido.Paraainternet,nósusamos
especiaisepoderososcomputadoreschamadosdeservidores.Elesnãotêmtela,mouseouteclado,porquesuafinalidade
principaléarmazenardadoseservi-los.Éporissoqueelessãochamadosdeservidores..--porqueelesservemavocê,
dados.
OK,masvocêquersabercomoquêainternetseparece,certo?
Fizemosumdesenhopravocê!Veja:
Pareceumabagunça,nãoé?Naverdadeéumarededemáquinasconectadas(osservidoresmencionadosacima).
Centenasdemilharesdemáquinas!Muitos,muitosquilômetrosdecabosportodoomundo!Paraveroquãocomplicadaa
interneté,vocêpodevisitarumsite(http://submarinecablemap.com/)quemostraummapacomoscabossubmarinos.
Aquiestáumscreenshotdosite:
6
Comofuncionaainternet?
Fascinante,não?Mas,obviamente,nãoépossívelterumfioconectadoatodamáquinaligadanainternet.Logo,para
chegaremumamáquina(porexemploaquelaondehttps://djangogirls.orgestásalva)nósprecisamospassaruma
requisiçãoatravésdemuitasemuitasmáquinasdiferentes.
Separececomisso:
7
Comofuncionaainternet?
Imaginequequandovocêdigitahttps://djangogirls.org,vocêenviaumacartaquediz:"QueridoDjangoGirls,eudesejover
ositedjangogirls.org.Envieelepramim,porfavor!"
Suacartavaiparaaagênciadoscorreiosmaispróximadevocê.Depoisvaiparaoutraqueéumpoucomaispertodeseu
destinatário,depoisparaoutraeoutra,atéqueelasejaentregueaoseudestino.Oúnicodiferencialéquesevocêenviar
cartas(pacotesdedados)comfreqüênciaparaomesmolugar,cadacartapodepassarpordiferentesagênciasde
correios(roteadores),dependendodecomoelassãodistribuídasemcadaagência.
8
Comofuncionaainternet?
Sim,ésimplesassim.Vocêenviamensagenseesperaalgumaresposta.Claro,aoinvésdepapelecanetavocêusabytes
dedados,masaideiaéamesma!
Aoinvésdeendereçoscomonomedarua,cidade,códigopostalenomedopaís,nósusamosendereçosIP.Primeiroseu
computadorpedeaoDNS(DomainNameSystem-SistemadeNomedeDomínio)paratraduzirdjangogirls.orgparaum
endereçoIP.Ofuncionamentodelesepareceumpoucocomasantigaslistastelefônicasondevocêpodeolharparao
nomedapessoaquequerentraremcontatoeacharoseunúmerodetelefoneeendereço.
Quandovocêenviaumacarta,elaprecisatercertascaracterísticasparaserentreguecorretamente:umendereço,selo,
etc.Vocêtambémusaumalinguagemqueoreceptadorcompreende,certo?Omesmoacontececompacotesdedados
quevocêenviaparaverumsite:vocêusaumprotocolochamadoHTTP(HypertextTransferProtocol-Protocolode
TransferênciadeHipertexto).
Então,basicamente,quandovocêtemumsite,vocêprecisaterumservidor(máquina)ondeeleficahospedado.O
servidorestáàesperadequaisquerrequisiçõesrecebidas(cartasquesolicitamaoservidoroenviodoseusite)eele
enviadevoltaseusite(emoutracarta).
ComoesteéumtutorialdeDjangovocêvaiperguntaroqueoDjangofaz.Quandovocêenviaumarespostanemsempre
vocêquerenviaramesmacoisaparatodomundo.Serámuitomelhorsesuascartasforempersonalizadas,diferenciada
paraapessoaqueacaboudeescreverparavocê,certo?ODjangoajudavocêacriaressaspersonalizadase
interessantescartas:).
Chegadefalar,éhoradecriar!
9
Introduçãoàlinhadecomando
Introduçãoàlinhadecomando
Éemocionante,não?!Vocêvaiescreversuaprimeiralinhadecódigoempoucosminutos:)
Deixe-nosapresentá-loaoseuprimeironovoamigo:alinhadecomando!
Asetapasaseguirmostrarãoavocêcomousarajanelapretaquetodososhackersusam.Podeparecerumpouco
assustadornocomeço,masrealmenteéapenasumpromptesperandoporcomandosdevocê.
Qualéalinhadecomando?
Ajanela,quenormalmenteéchamadadelinhadecomandoouinterfacedelinhadecomando,éumaplicativo
baseadoemtextoparavisualização,manipulaçãoemanuseiodearquivosemseucomputador(comoporexemplo,o
WindowsExplorerouoFindernoMac,masseminterfacegráfica).Outrosnomesparaalinhadecomandosão:cmd,CLI,
prompt,consoleouterminal.
Abraainterfacedelinhadecomando
Paracomeçaralgunsexperimentos,precisamosabriranossainterfacedelinhadecomandoprimeiro.
Windows
VáemIniciar→TodososProgramas→Acessórios→Promptdecomando.
MacOSX
Applications→Utilities→Terminal.
Linux
ProvavelmentevocêvaiacharemApplications→Accessories→Terminal,masissodependedoseusistemaoperacional.
QualquercoisaésóprocurarnoGoogle:)
Prompt
Agoravocêdeveverumajanelabrancaoupretaqueestáàesperadeseuscomandos.
SevocêestiveremMacounumLinux,vocêprovavelmenteveráum``$,comoeste:
$
NoWindows,éumsinalde >,comoeste:
>
Cadacomandoseráantecedidoporestesinaleumespaço,masvocênãoprecisadigitá-lo.Seucomputadorfaráissopor
você:)
Apenasumapequenanota:noseucaso,talvezháalgocomo C:\Users\ola>ou Olas-MacBookAir:~ola$antes
dosinaldopromptistoestará100%correto.Nestetutorialnósapenassimplificaremoseleparaomínimo.
10
Introduçãoàlinhadecomando
Seuprimeirocomando(YAY!)
Vamoscomeçarcomalgosimples.Digiteoseguintecomando:
$whoami
ou
>whoami
DepoisteclaEnter.Essaénossasaída:
$whoami
olasitarska
Comovocêpodever,ocomputadorsóapresentouseunomedeusuário.Elegante,né?:)
Tentedigitarcadacomando,nãocopiarecolar.Vocêvaiselembrarmaisdessaforma!
OBásico
Cadasistemaoperacionaltemoseupróprioconjuntodeinstruçõesparaalinhadecomando,entãosecertifiquequevocê
estáseguindoasinstruçõesdoseusistemaoperacional.Vamostentar,certo?
Pastaatual
Serialegalsaberemquepastaestamosagora,certo?Vamosver.Digiteoseguintecomandoseguidodeumenter:
$pwd
/Users/olasitarska
SevocêestivernoWindows:
>cd
C:\Users\olasitarska
Provavelmentevocêvaiveralgoparecidonasuamáquina.Umvezquevocêabrealinhadecomandovocêjácomeçana
pastaHome.
Nota:'pwd'significa'printworkingdirectory'.
Listandoarquivosepastas
Entãooquetemnele?Serialegaldescobrir.Vamosver:
$ls
Applications
Desktop
Downloads
Music
...
Windows:
11
Introduçãoàlinhadecomando
>dir
DirectoryofC:\Users\olasitarska
05/08/201407:28PM<DIR>Applications
05/08/201407:28PM<DIR>Desktop
05/08/201407:28PM<DIR>Downloads
05/08/201407:28PM<DIR>Music
...
Entraremoutrapasta
TalvezagentequeiraentrarnanossapastaDesktop?
$cdDesktop
Windows:
>cdDesktop
Vejaserealmenteentramosnapasta:
$pwd
/Users/olasitarska/Desktop
Windows:
>cd
C:\Users\olasitarska\Desktop
Aquiestá!
Dicadeprofissional:sevocêdigitar cdDeapertaratecla tabnoseuteclado,alinhadecomandoirápreencher
automaticamenteorestodonomeparaquevocêpossanavegarrapidamente.Sehouvermaisdeumapastaque
comececom"D",aperteatecla tabduasvezesparaobterumalistadeopções.
Criandoumapasta
QuetalcriarumdiretórioDjangoGirlsnasuaáreadetrabalho?Vocêpodefazerassim:
$mkdirdjangogirls
Windows:
>mkdirdjangogirls
Estecomandovaicriarumapastacomonome djangogirlsnonossodesktop.Vocêpodeverificarseeleestálá,sóde
olharnasuaáreadetrabalhoouexecutandoumcomando ls(MacouLinux)ou dir(Windows)!Experimente:)
Dicadeprofissional:Sevocênãoquiserdigitaromesmocomandováriasvezes,tentepressionar setaparacimae
setaparabaixonotecladoparapercorrercomandosusadosrecentemente.
Exercite-se!
12
Introduçãoàlinhadecomando
Umpequenodesafioparavocê:nasuamaisnovapastacriada djangogirlscrieumaoutrapastachamada teste.Use
oscomandos cde mkdir.
Solução:
$cddjangogirls
$mkdirteste
$ls
teste
Windows:
>cddjangogirls
>mkdirteste
>dir
05/08/201407:28PM<DIR>teste
Parabéns!:)
Limpando
Nãoqueremosdeixarumabagunça,entãovamosremovertudooquefizemosatéagora.
PrimeiroprecisamosvoltarparaapastaDesktop:
$cd..
Windows:
>cd..
Fazendo cdpara ..nósmudaremosdodiretórioatualparaodiretóriopai(quesignificaodiretórioquecontémo
diretórioatual).
Vejaondevocêestá:
$pwd
/Users/olasitarska/Desktop
Windows:
>cd
C:\Users\olasitarska\Desktop
Agoraéhoradeexcluirodiretório djangogirls.
Atenção:Aexclusãodearquivosusando del, rmdirou rméirrecuperável,significandoArquivosexcluídosvão
emboraparasempre!Então,tenhacuidadocomestecomando.
$rm-rdjangogirls
Windows:
>rmdir/Sdjangogirls
djangogirls,Temcerteza<S/N>?S
13
Introduçãoàlinhadecomando
Pronto!Paratercertezaqueapastafoiexcluída,vamoschecar:
$ls
Windows:
>dir
Saindo
Porenquantoéisso!Agoravocêfecharalinhadecomandocomsegurança.Vamosfazerdojeitohacker,certo?:)
$exit
Windows:
>exit
Legal,né?:)
Sumário
Aquivaiumalistadealgunscomandosúteis:
Comando
(Windows)
Comando(MacOS/
Linux)
Descrição
Exemplo
exit
exit
Fechaajanela
exit
cd
cd
Mudaapasta
cdtest
dir
ls
Listaaspastaseos
arquivos
dir
copy
cp
Copiaumarquivo
copyc:\test\test.txt
c:\windows\test.txt
move
mv
Moveumarquivo
movec:\test\test.txt
c:\windows\test.txt
mkdir
mkdir
Criaumapasta
mkdirtestdirectory
del
rm
Deletaumapastae/ou
arquivo
delc:\test\test.txt
Estessãoapenasalgunsdospoucoscomandosquevocêpodeexecutaremsualinhadecomando,masvocênãovai
usarmaisnadadoqueistohoje.
Sevocêestivercurioso,ss64.comcontémumareferênciacompletadecomandosparatodosossistemasoperacionais.
Pronto?
VamosmergulharnoPython!
14
InstalaçãodoPython
VamoscomeçarcomPython
Finalmentechegamosaqui!
Masprimeiro,vamosfalarumpoucosobreoqueoPythoné.Pythonéumalinguagemdeprogramaçãomuitopopularque
podeserusadaparacriarsites,jogos,softwarescientíficos,gráficosemuito,muitomais.
OPythonéorigináriodadécadade1980eseuprincipalobjetivoéserlegívelporsereshumanos(nãoapenasmáquinas!),
porissoeleparecemuitomaissimplesdoqueoutraslinguagensdeprogramação.Issofazelemaisfácildeaprender,mas
nãoseengane,Pythontambémémuitopoderoso!
InstalaçãodoPython
EstesubcapítuloébaseadoemumtutorialcriadoporGeekGirlsCarrots(https://github.com/ggcarrots/djangocarrots)
DjangoéescritoemPython.NósprecisamosdeleparafazerqualquercoisaemDjango.Vamoscomeçarcomsua
instalação!NósqueremosquevocêinstaleoPython3.4,entãosevocêtemqualquerversãoanterior,vocêvaiprecisar
atualizá-la.
Windows
VocêpodebaixaroPythonparaWindowsnowebsitehttps://www.python.org/downloads/release/python-343/.Depoisde
fazerodownloaddoarquivo*.msi,vocêprecisaexecutá-lo(dandoumduplo-cliquenele)eseguirasinstruções.É
importantelembrarocaminho(apasta)ondevocêinstalouoPython.Elaseráútildepois!
Cuidadocomumacoisa:nasegundateladoassistentedeinstalação,marcado"Customize",certifique-sevocêrolarpara
baixoeescolhaaopção"Adicionarpython.exeparaocaminho",comoem
15
InstalaçãodoPython
Linux
ÉmuitoprovávelquevocêjátenhaoPythoninstaladoeconfigurado.Paratercertezaseeleestáinstalado(equalasua
versão),abraumterminaledigiteoseguintecomando:
$python3--version
Python3.4.2
SevocênãotemoPythoninstaladoouquerumaversãodiferente,vocêpodeinstalá-lodaseguintemaneira:
Ubuntu
Digiteoseguintecomandonoterminal:
sudoapt-getinstallpython3.4
Fedora
Useoseguintecomandonoterminal:
sudoyuminstallpython3.4
openSUSE
Useoseguintecomandonoterminal:
sudozypperinstallpython3
OSX
Vocêprecisaacessarositehttps://www.python.org/downloads/release/python-342/ebaixaroinstaladordoPython:
downloaddoinstaladorMacOSX64-bit/32-bitDMG,
Dêumduplo-cliqueparaabri-lo,
Dêumduplo-cliquenoPython.mpkgparaexecutaroinstalador.
VerifiqueseainstalaçãofoibemsucedidaabrindooTerminaledigitandoocomando python3:
$python3--version
Python3.4.2
Sevocêtiverqualquerdúvidaousealgumacoisadeuerradoevocênãosabeoquefazer-porfavorpergunteaoseu
instrutor!Àsvezes,ascoisasnãoestãoindobemeémelhorpedirajudaaalguémcommaisexperiência.
16
EditordeCódigo
EditordeCódigo
Vocêestáprestesaescreversuaprimeiralinhadecódigo,entãoéhoradebaixarumeditordecódigo!
Existemmuitoseditoresdiferenteseemgrandeparteseresumeapreferênciapessoal.Amaioriadosprogramadores
Pythonusaascomplexas,masextremamentepoderosasIDEs(IntegratedDevelopmentEnvironments,ouemportuguês,
AmbientededesenvolvimentoIntegrado),taiscomoPyCharm.Parauminiciante,entretanto,estasIDE'ssãomenos
convenientes;nossasrecomendaçõessãobemmaissimples,porém,igualmentepoderosas.
Nossassugestõesestãoabaixo,massinta-selivreparaperguntaraoseucoachquaissãoassuaspreferências-assim
vaisermaisfácilobteraajudadeles.
Gedit
Geditéumeditoropen-source,gratuito,disponívelparatodosossistemasoperacionais.
Baixeaqui
SublimeText3
SublimeText3éumeditormuitopopularcomumperíododeavaliaçãogratuita.Éfácildeinstalareusar,eestádisponível
paratodosossistemasoperacionais.
Baixeaqui
Atom
AtoméumnovoeditordecódigocriadopeloGitHub.Eleégratuito,open-source,fácildeinstalarefácildeusar.Está
disponívelparaWindows,OSXeLinux.
Baixeaqui
Porqueestamosinstalandoumeditordecódigo?
Vocêdeveestarseperguntandoporqueestamosinstalandoessesoftwareeditordecódigoespecialaoinvésdeusaralgo
comoWordouBlocodeNotas.
Primeiroéquecódigoprecisasertextosemformatação,eoproblemacomprogramascomoWordeTexteditéqueeles
naverdadenãoproduzemtextosemformatação,elesfazem"richtext"(comfonteseformatação),usandoformatos
personalizadoscomoRTF.
Asegundarazãoéqueeditoresdecódigosãoespecializadosemeditarcódigo,entãoelespodemoferecerrecursosúteis,
comorealcedecódigocomcoresdeacordocomoseusignificado,ouautomaticamentefecharcitaçõesparavocê.
Nósvamosverissoemaçãodepois.Embrevevocêteráseueditordecódigocomoumadassuasferramentasfavoritas.
:)
17
IntroduçãoaoPython
IntroduçãoaoPython
PartedestecapítuloébaseadonosTutoriaisdeGeekGirlsCarrots(https://github.com/ggcarrots/django-carrots).
Vamosescreverumpoucodecódigo!
InterpretadorPython
ParacomeçarabrincarcomPythonnósprecisamosabrirumalinhadecomandonoseucomputador.Vocêjádevesaber
comofazerisso--vocêaprendeuissonocapítuloIntroduçãoàLinhadeComando.Assimqueestiverpronto,sigaas
instruçõesabaixo.
NósqueremosabriroPythonnumterminal,entãodigite python3etecleEnter.
$python3
Python3.4.2(...)
Type"copyright","credits"or"license"formoreinformation.
>>>
SeuprimeirocomandoPython!
DepoisdeexecutarocomandoPython,opromptmudoupara >>>.Paranós,issosignificaqueporenquantosó
utilizaremoscomandosnalinguagemPython.Vocênãoprecisadigitar >>>-OPythonfaráissoporvocê.
SevocêdesejasairdoconsoledoPython,apenasdigite exit()ouuseoatalho Ctrl+ZnoWindowse Ctrl+Dno
Mac/Linux.Entãovocênãovaivermaiso >>>.
MasagoranãoqueremossairdalinhadecomandodoPython.Queremosaprendermaissobreele.Vamos,então,fazer
algomuitosimples.Porexemplo,tentedigitaralgumaoperaçãomatemática,como 2+3eaperteEnter.
>>>2+3
5
Incrível!Vêcomoarespostasimplesmenteaparece?OPythonconhecematemática!Vocêpodetentaroutroscomandos
como:- 4*5- 5-1- 40/2
Divirta-secomissoporumtempoedepoisvolteaqui:).
Comovocêpodever,oPythonéumaótimacalculadora.Sevocêestáseperguntandooquemaisvocêpodefazer...
Strings
Quetaloseunome?Digiteseuprimeironomeentreaspas,dessejeito:
>>>"Ola"
'Ola'
Vocêacaboudecriarsuaprimeirastring!Stringéumsequênciadecaracteresquepodemserprocessadapelo
computador.Astringsempreprecisainiciareterminarcomomesmocaractere.Estepodeseraspasduplas( ')ou
simples( ")-elasdizemaoPythonqueoqueestádentrodelaséumastring.
Stringspodemserjuntadas.Tenteisto:
18
IntroduçãoaoPython
>>>"Oi"+"Ola"
'OiOla'
Vocêtambémpodemultiplicarstringsporumnúmero:
>>>"Ola"*3
'OlaOlaOla'
Sevocêprecisacolocarumaapóstrofedentrodesuastring,existemduasmaneirasdefazer.
Usandoaspasduplas:
>>>"Correndo'ladeiraabaixo"
"Correndo'ladeiraabaixo"
ouescapandoapóstrofocomumabarrainvertida( \):
>>>"Correndo\'ladeiraabaixo"
"Correndo'ladeiraabaixo"
Legal,hein?Paraverseunomeemletrasmaiúsculas,bastadigitar:
>>>"Ola".upper()
'OLA'
Vocêacaboudeusarafunção uppernasuastring!Umafunção(como upper())éumconjuntodeinstruçõesqueo
Pythonrealizaemumdeterminadoobjeto( "Ola"),semprequevocêchamarporele.
Sevocêquersaberonúmerodeletrasdoseunome,existeumafunçãoparaissotambém!
>>>len("Ola")
3
Seperguntandoporquealgumasvezesvocêchamafunçõescomum .nofimdeumastring(como "Ola".upper())e
algumasvezesvocêprimeirochamaafunçãocolocandoastringnosparênteses?Bem,emalgunscasos,funções
pertencemaobjetos,como upper(),quesópodeserutilizadaemstrings.Nessecaso,nóschamamosafunçãode
método.Outrasvezes,funçõesnãopertencemanadaespecíficoepodemserusadasemdiferentestiposdeobjetos,
assimcomo len().Éporissoquenósestamosfornecendo "Ola"comoumparâmetroparaafunção len.
Sumário
OK,chegadestrings.Atéagoravocêaprendeusobre:
oprompt-digitarcomandos(códigos)nointerpretadorPythonresultaemrespostasemPython
númerosestrings-noPython,númerossãousadosparamatemáticaestringsparaobjetosdetexto
operadores-como+e*,combinamvaloresparaproduzirumnovovalor
funções-comoupper()elen(),executamaçõesnosobjetos.
Issoéobásicosobretodasaslinguagensdeprogramaçãoquevocêaprende.Prontoparaalgomaisdifícil?Apostamos
quesim!
Erros
Vamostentaralgonovo.Podemosobterotamanhodeumnúmerodamesmaformaquepodemosencontrarotamanhodo
nossonome?Digite len(304023)epressioneEnter:
19
IntroduçãoaoPython
>>>len(304023)
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
TypeError:objectoftype'int'hasnolen()
Temosnossoprimeiroerro!Eledizqueobjetosdotipo"int"(inteiros,apenasnúmeros)nãotêmnenhumcomprimento.
Entãooquepodemosfazeragora?Talvezpossamosescrevernossonúmerocomoumastring?Stringstêmum
comprimento,certo?
>>>len(str(304023))
6
Funcionou!Usamosafunção strdentrodafunção len. str()convertetudoparastrings.
Afunção strconverteascoisasemstrings
Afunção intconverteascoisasemnúmerosinteiros
Importante:podemosconverternúmerosemtexto,masnósnãopodemos,necessariamente,convertertextoem
números-oque int('hello')querdizer?
Variáveis
Umconceitoimportantenaprogramaçãoéoconceitodevariáveis.Umavariávelnãoénadamaisdoqueumnomepara
algumacoisa,detalformaquevocêpossausá-lamaistarde.Osprogramadoresusamessasvariáveisparaguardar
dados,parafazerseuscódigosmaislegíveiseparanãoterqueselembrarsempreoquealgumascoisassignificam.
Digamosquequeremoscriarumanovavariávelchamada nome:
>>>nome="Ola"
Vê?Éfácil!Ésófazer:nomeigualaOla.
Comovocêpercebeu,seuprogramanãoretornounadacomofezanteriormente.Entãocomosabemosqueavariável
realmenteexiste?Simplesmentedigite nomeetecleEnter:
>>>nome
'Ola'
Yippee!Suaprimeiravariável!:)Vocêsemprepodemudaroseuvalor:
>>>nome="Sonja"
>>>nome
'Sonja'
Vocêpodeusá-latambémemfunções:
>>>len(nome)
5
Incrívelnão?Claro,variáveispodemserqualquercoisa,entãopodemsernúmerostambém!Tenteisso:
>>>a=4
>>>b=6
>>>a*b
24
20
IntroduçãoaoPython
Mas,esedigitarmosonomeerrado?Vocêconsegueadivinharoqueaconteceria?Vamostentar!
>>>city="Tokyo"
>>>ctiy
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
NameError:name'ctiy'isnotdefined
Umerro!Comovocêpodever,PythontemdiferentestiposdeerroseesteéchamadoNameError.Pythondaráesteerro
sevocêtentarusarumavariávelquenãofoidefinidaainda.Sevocêencontraresseerrodepois,vejasenoseucódigose
vocênãodigitouonomedeumavariávelerrado.
Brinquecomissoporumtempoevejaoquevocêconseguefazer!
Afunçãoprint
Tenteisso:
>>>nome='Maria'
>>>nome
'Maria'
>>>print(nome)
Maria
Quandovocêapenasdigita nome,ointerpretadorPythonrespondecomarepresentaçãocomostringdavariável'name',
quesãoasletrasM-a-r-i-a,entreaspassimples.Quandovocêdiz print(nome),Pythonvai"imprimir"oconteúdoda
variávelnatela,semasaspas,oqueémaispuro.
Comoveremosmaistarde, print()tambéméútilquandoqueremosimprimiralgodentrodefunções,ouquando
queremosimprimiralgoemváriaslinhas.
Listas
Alémdestringseinteiros,oPythontemtodosostiposdiferentesdeobjetos.Vamosapresentarumchamadolista.Listas
sãoexatamenteoquevocêachaqueelassão:elassãoobjetosquesãolistasdeoutrosobjetos:)
Váemfrenteecrieumalista:
>>>[]
[]
Sim,estaéumalistavazia.Nãoémuito,nãoé?Vamoscriarumalistadosnúmerosdaloteria.Comonãoqueremosficar
repetindoocódigotodootempovamoscriarumavariávelparaela:
>>>loteria=[3,42,12,19,30,59]
Tudocerto,nóstemosumalista!Oquepodemosfazercomisso?Vamosverquantosnúmerosdeloteriaexistemnesta
lista.Vocêtemideiadequalfunçãodeveusarparaisso?Vocêjásabedisso!
>>>len(loteria)
6
Sim! len()podetedaronúmerodeobjetosquefazempartedeumalista.Umamãonaroda,não?Vamosorganizarisso
agora:
21
IntroduçãoaoPython
>>>loteria.sort()
Issonãoretornanada,apenastrocaaordememqueosnúmerosaparecemnalista.Vamosimprimirissooutravezevero
queacontece:
>>>print(loteria)
[3,12,19,30,42,59]
Comovocêpodever,osnúmerosnanossalistaestãoordenadosdomenorparaomaior.Parabéns!
Talvezagentequeirainverteressaordem?Vamosfazerisso!
>>>loteria.reverse()
>>>print(loteria)
[59,42,30,19,12,3]
Molezané?Sevocêquiseradicionaralgumacoisaàsualista,vocêpodefazeristodigitandooseguintecomando:
>>>loteria.append(199)
>>>print(loteria)
[59,42,30,19,12,3,199]
Sevocêquisermostrarapenasoprimeironúmerovocêpodeusaríndices.Umíndiceéumnúmeroquedizondeumitem
dalistaestá.Oscomputadoresgostamdeiniciaracontagempor0,entãooprimeiroobjetotemíndice0,opróximotem
índice1eporaívai.Tenteisso:
>>>print(loteria[0])
59
>>>print(loteria[1])
42
Comovocêpodever,vocêpodeacessardiferentesobjetosnasualistausandoonomedalistaeoíndicedoobjetodentro
doscolchetes.
Pordiversãoextra,tentealgunsoutrosíndices:6,7,1000,-1,-6ou-1000.Vejasevocêconseguepreveroresultado
antesdetentarocomando.Osresultadosfazemsentido?
VocêpodeencontrarumalistadetodososmétodosdisponíveisnestecapítulonadocumentaçãodoPython:
https://docs.python.org/3/tutorial/datastructures.html
Dicionários
Umdicionárioésemelhanteaumalista,masvocêpodeacessarvaloresatravésdeumachaveaoinvésdeumíndice.
Umachavepodeserqualquerstringounúmero.Asintaxeparadefinirumdicionáriovazioé:
>>>{}
{}
Issomostraquevocêacaboudecriarumdicionáriovazio.Hurra!
Agora,tenteescreveroseguintecomando(tentesubstituircomassuasprópriasinformaçõestambém):
>>>participante={'nome':'Ola','pais':'Polonia','numeros_favoritos':[7,42,92]}
Comessecomando,vocêacaboudecriarumavariávelchamada participantcomtrêsparesdechave-valor:
22
IntroduçãoaoPython
Achave nomeapontaparaovalor 'Ola'(umobjeto string),
paisapontapara 'Polonia'(outra string),
e numeros_favoritosapontampara [7,42,92](uma listcomtrêsnúmerosnela).
Vocêpodechecaroconteúdodechavesindividuaiscomasintaxe:
>>>print(participante['nome'])
Ola
Veja,ésimilaraumalista.Masvocênãoprecisalembraroíndice-apenasonome.
OqueacontecesepedirmosaoPythonovalordeumachavequenãoexiste?Vocêconsegueadivinhar?Vamostentare
descobrir!
>>>participante['idade']
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
KeyError:'idade'
Olha,outroerro!EsseéumKeyError.Pythonébastanteprestativoetedizqueachave 'idade'nãoexistenesse
dicionário.
Quandousarumdicionarioouumalista?Bem,umbompontopararefletir.Penseemumasoluçãoantesdeolhara
respostanapróximalinha.
Vocêprecisadeumasequênciaordenadadeitens?Useumalist.
Vocêprecisaassociarvalorescomchaves,assimvocêpodeprocurá-loseficientemente(pelachave)maistarde?Use
umdictionary.
Dicionários,comolistas,sãomutáveis,ouseja,quepodemsermudadosdepoisquesãocriados.Vocêpodeadicionar
novosparesdechave/valorparaodicionárioapóssuacriação,como:
>>>participante['linguagem_favorita']='Python'
Comoaslists,usarométodo len()emdicionáriosretornaonúmerodepareschave-valornodicionario.Váemfrentee
digiteocomando:
>>>len(participante)
4
Esperoqueagorafaçasentidoatéagora.:)Prontaparamaisdiversãocomdicionários?Pulenapróximalinhaparacoisas
incríveis.
Vocêpodeusarocomando pop()paradeletarumitemnodicionario.Digamos,sevocêquerexcluiraentrada
correspondenteachave 'numeros_favoritos',bastadigitaroseguintecomando:
>>>participante.pop('numeros_favoritos')
>>>participante
{'pais':'Polonia','linguagem_favorita':'Python','nome':'Ola'}
Comovocêpodevernoretorno,oparchave-valorcorrespondenteàchave'numeros_favoritos'foiexcluído.
Alémdissovocêpodemudarovalorassociadocomumachavejácriadanodicionário.Digite:
>>>participante['pais']='Alemanha'
>>>participante
{'pais':'Alemanha','linguagem_favorita':'Python','nome':'Ola'}
23
IntroduçãoaoPython
Comovocêpodever,ovalordachave 'pais'foialteradode 'Polonia'para 'Alemanha'.:)Emocionante?Hurra!Você
acaboudeaprenderoutracoisaincrível.
Sumário
Incrível!Agoravocêsabemuitosobreprogramação.Nestaúltimapartevocêaprendeusobre:
erros-agoravocêsabecomolereentendererrosqueaparecemseoPythonnãoentenderumcomandoquevocê
deu
variáveis-nomesparaobjetosquepermitemvocêprogramarfacilmenteedeixarseucódigomaislegível
listas-listasdeobjetosarmazenadosemumaordemespecífica
dicionários-objetosarmazenadoscomopareschave-valor
Empolgado(a)paraopróximopasso?:)
Comparecoisas
Grandepartedaprogramaçãoconsisteemcompararcoisas.Oqueémaisfácildecomparar?Números,éclaro.Vamos
vercomoissofunciona:
>>>5>2
True
>>>3<1
False
>>>5>2*2
True
>>>1==1
True
>>>5!=2
True
DemosaoPythonalgunsnúmerosparacomparar.Comovocêpodever,Pythonpodecompararnãosónúmerosmas
tambémresultadosdemétodos.Legal,hein?
Vocêestáseperguntandoporquecolocamosdoissinaisdeigual ==ladoaladoparacompararseosnúmerossão
iguais?Nósusamosumúnico =paraatribuirvaloresavariáveis.Vocêsempre,sempreprecisacolocardois ==se
quiserverificarseascoisassãoiguais.Tambémépossívelafirmarqueascoisassãodesiguaisentresi.Paraisso,
usamososímbolo !=,conformemostradonoexemploacima.
DêaoPythonmaisduastarefas:
>>>6>=12/2
True
>>>3<=2
False
>e <sãofáceis,masoque >=e <=significam?Leiaelesdaseguinteforma:
x >ysignifica:xémaiorquey
x <ysignifica:xémenorquey
x <=ysignifica:xémenorouigualay
x >=ysignifica:xémaiorouigualay
Fantástico!Quermais?Tenteisto:
24
IntroduçãoaoPython
>>>6>2and2<3
True
>>>3>2and2<1
False
>>>3>2or2<1
True
VocêpodedaraoPythonquantosnúmerosparacompararquantovocêquiser,eelevaitedarumaresposta!Espertinho,
certo?
and-sevocêusarooperador and,ambasascomparaçõesterãoqueserverdadeirasparaquetodoocomandoseja
verdadeiro
or-sevocêusarooperador or,apenasumadascomparaçõesprecisaserverdadeiraparaqueocomandotodo
sejaverdadeiro
Jáouviuaexpressão"compararmaçãscomlaranjas"?VamostentaroequivalenteemPython:
>>>1>'django'
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
TypeError:unorderabletypes:int()>str()
Aquivemosqueassimcomonaexpressão,Pythonnãoécapazdecompararumnúmero( int)eumastring( str).Em
vezdisso,elemostrouumTypeErrorenosdissequeosdoistiposnãopodemsercomparadosjuntos.</p>
Booleano
Acidentalmente,vocêaprendeusobreumnovotipodeobjetoemPython.Échamadodebooleano--eprovavelmenteo
tipomaisfácilqueexiste.
Existemapenasdoisobjetosbooleanos:-True(verdadeiro)-False(falso)
MasparaoPythonentenderisso,vocêprecisasempreescreverTrue(primeiraletramaiúscula,comorestodasletrasem
minúsculo).true,TRUE,tRUEnãovaifuncionar--sóTrueécorreto.(OmesmoseaplicaaoFalse,claro.)
Booleanospodemservariáveistambém!Veja:
>>>a=True
>>>a
True
Vocêtambémpodefazerdessejeito:
>>>a=2>5
>>>a
False
Pratiqueedivirta-secomosvaloresbooleanos,tentandoexecutarosseguintescomandos:
TrueandTrue
FalseandTrue
Trueor1==1
1!=2
Parabéns!Booleanossãoumdosrecursosmaisinteressantesnaprogramação,evocêacaboudeaprendercomousá-los!
Salvá-lo!
25
IntroduçãoaoPython
Atéagoranósescrevemostodonossocódigoemuminterpretadorpython,quenoslimitaaumalinhadecódigoemum
momento.Programasnormaissãosalvosemarquivoseexecutadospelonossointerpretadordelinguagemde
programaçãooucompilador.Atéagorajácorremosnossosprogramasdeumalinhadecadaveznointerpretador
Python.Nósvamosprecisardemaisdeumalinhadecódigoparaaspróximastarefas,entãoprecisaremosrapidamente:
SairdointerpretadorPython
Abriroeditordecódigodesuaescolha
Salvaralgumcódigoemumnovoarquivopython
Executá-lo!
ParasairdointerpretadorPythonqueestamosusando,simplesmentedigiteafunção exit():
>>>exit()
$
Issovaicolocá-lanopromptdecomando.
Anteriormente,nósescolhemosumeditordecódigodaseçãodoeditordecódigo.Nósprecisamosabriroeditoragorae
escreveralgumcódigoemumnovoarquivo:
print('Hello,Djangogirls!')
NotaVocêdeveobservarqueumadascoisasmaislegaissobreeditoresdecódigo:cores!NoconsoledoPython,
tudoeradamesmacor,masagoravocêdeveverqueafunçãode Imprimiréumacordiferentedasequênciade
caracteresnoseuinterior.Issoéchamadode"realcedesintaxe",eéumaajudamuitoútilquandoestá
programando.Percebaacordascoisasevocêvaiobterumadicaparaquandovocêesquecerdefecharuma
seqüênciadecaracteres,oufazerumerrodedigitaçãoemumnomedepalavra-chave(como defemumafunção,
queveremosabaixo).Estaéumadasrazõespelasquaisquenósusamosumeditordecódigo:)
Obviamente,vocêéumdesenvolvedorpythonbastanteexperienteagora,entãosinta-selivreparaescreverumcódigo
quevocêaprendeuhoje.
Agoratemosdesalvaroarquivoedêumnomedescritivo.Vamoschamaroarquivopython_intro.pyesalve-oemseu
desktop.Podemosnomearoarquivotudooquequisermos,oimportanteaquiétercertezaqueoarquivoterminanopy,
istodiznossocomputador,queéumarquivoexecutáveldepythonePythonpodeexecutá-lo.
Comoarquivosalvo,éhoradeexecutá-lo!Usandoashabilidadesquevocêaprendeunaseçãodelinhadecomando,use
oterminalaltereosdiretóriosparaodesktop.
EmumMac,ocomandoseráparecidocomisto:
cd~/Desktop
NoLinux,seráassim(apalavra"Desktop"podesertraduzidoparaseuidioma):
cd~/Desktop
Enowindows,vaiserassim:
cd%HomePath%\Desktop
Sevocêficarpreso,sópedirajuda.
Emseguida,usaroPythonparaexecutarocódigonoarquivoassim:
$python3python_intro.py
Hello,Djangogirls!
26
IntroduçãoaoPython
Tudobem!Vocêacaboudeexecutarseuprimeiroprogramaempythonquefoisalvoemumarquivo.Sesenteótima?
Vocêpodeagorapassarparaumaferramentaessencialnaprogramação:
if...elif...else
Muitascoisasnocódigosópodemserexecutadassedeterminadascondiçõesforematendidas.ÉporissoqueoPython
temalgumacoisachamadadeclaraçãoif.
Substituaocódigonoarquivopython_intro.pyparaisto:
if3>2:
Sesalvouesteeelefoiexecutado,nósveríamosumerrocomoeste:
$python3python_intro.py
File"python_intro.py",line2
^
SyntaxError:unexpectedEOFwhileparsing
Pythonesperaquenósforneçamosmaisinstruçõesqueserãosupostamenteexecutadascasoacondição 3>2venhaa
serverdadeira(ou Truenessecaso).VamostentarfazeroPythonimprimir"Itworks!".Altereoseucódigonoseuarquivo
python_intro.pyparaisto:
if3>2:
print('Itworks!')
Vocêpercebeuqueidentamosapróximalinhacom4espaços?PrecisamosfazerissoparaqueoPythonsaibaqual
códigoseráexecutadoseoresultadoforTrue.Vocêpodefazercom1espaço,masquasetodososprogramadoresPython
fazemcom4paradeixarascoisasarrumadas.Umúnicotabtambémvaicontarcomo4espaços.
Salvá-loeexecutenovamente:
$python3python_intro.py
Itworks!
Esenão?
Nosexemplosanteriores,ocódigofoiexecutadosomentequandoascondiçõeseramverdade.MasoPythontambémtem
instruções elife else:
if5>2:
print('5érealmentemaiorque2')
else:
print('5nãoémaiorque2')
Quandoforexecutadoiráimprimir:
$python3python_intro.py
5érealmentemaiorque2
Se2forumnúmeromaiordoque5,entãoosegundocomandoseráexecutado.Fácil,né?Vamosvercomofuncionao
elif:
27
IntroduçãoaoPython
name='Sonja'
ifname=='Ola':
print('HeyOla!')
elifname=='Sonja':
print('HeySonja!')
else:
print('Heyanonymous!')
eexecutado:
$python3python_intro.py
HeySonja!
Viuoqueaconteceu?
Sumário
Nosúltimostrêsexercíciosvocêaprendeu:
compararascoisas-emPython,vocêpodecompararascoisasusandoosoperadores >, >=, ==, <=, <eo
and, or
Booleano-umtipodeobjetoquesótemumdosdoisvalores: Trueou False
Salvandoarquivos-armazenamentodecódigoemarquivosassimvocêpodeexecutarprogramasmaiores.
if...elif...else-instruçõesquepermitemquevocêexecuteocódigosomentesedeterminadascondiçõesforem
atendidas.
Éhoradaúltimapartedestecapítulo!
Suasprópriasfunções!
Selembradefunçõescomo len()quevocêpodeexecutarnoPython?Bem,boasnotícias,agoravocêvaiaprendera
escreversuasprópriasfunções!
UmafunçãoéumasequênciadeinstruçõesqueoPythondeveexecutar.CadafunçãoemPythoncomeçacomapalavrachave def,seguidodeumnomeparaafunçãoeopcionalmenteumalistadeparâmetros.Vamoscomeçarcomuma
funçãosimples.Substituaocódigonopython_intro.pycomoseguinte:
defhi():
print('Hithere!')
print('Howareyou?')
hi()
Ok,nossaprimeirafunçãoestápronta!
Vocêpodeseperguntarporqueescrevemosonomedafunçãonaparteinferiordoarquivo.IstoéporquePythonlêo
arquivoeexecutadecimaparabaixo.Então,parausaranossafunção,temosdeescrevê-lonaparteinferior.
Vamosexecuta-loagoraeveroqueacontece:
$python3python_intro.py
Hithere!
Howareyou?
Issofoifácil!Vamosconstruirnossaprimeirafunçãocomparâmetros.Usaremosoexemploanterior-umafunçãoquediz
'hi'paraquemoexecuta-comumname:
28
IntroduçãoaoPython
defhi(name):
Comovocêpodever,agorademosumparâmetrochamado nameparanossafunção:
defhi(name):
ifname=='Ola':
print('HiOla!')
elifname=='Sonja':
print('HiSonja!')
else:
print('Hianonymous!')
hi()
Comovocêpodever,nósprecisamoscolocardoisespaçosantesdafunção print,porque ifprecisasaberoquedeve
acontecerquandoacondiçãoforatendida.Vamosvercomoissofuncionaagora:
$python3python_intro.py
Traceback(mostrecentcalllast):
File"python_intro.py",line10,in<module>
hi()
TypeError:hi()missing1requiredpositionalargument:'name'
Oops,umerro.Felizmente,Pythonnosforneceumamensagemdeerrobastanteútil.Eladizqueafunção hi()(aquela
quedeclaramos)temumargumentoobrigatório(chamado name)equenósesquecemosdepassá-loaochamarafunção.
Vamoscorrigi-lonaparteinferiordoarquivo:
hi("Ola")
eexecutenovamente:
$python3python_intro.py
HiOla!
Esemudarmosonome?
hi("Sonja")
eexecutá-lo:
$python3python_intro.py
HiSonja!
Agora,oqueachaquevaiacontecersevocêescreveroutronomelá?(SemserOlaouSonja)Experimentá-loeverse
vocêestácerto.Eledeveimprimiristo:
Hianonymous!
Istoéincrível,não?Dessamaneiravocênãoprecisaserepetir(DRY-don'trepeatyourself,ouemportuguês,nãose
repita)cadavezqueformudaronomedapessoaqueafunçãopretendecumprimentar.Eéexatamenteporissoque
precisamosdefunções-vocênuncaquerrepetirseucódigo!
Vamosfazeralgomaisinteligente..--existemmaisquedoisnomes,eescreverumacondiçãoparacadaumseriadifícil,
certo?
29
IntroduçãoaoPython
defhi(name):
print('Hi'+name+'!')
hi("Rachel")
Vamoschamarocódigoagora:
$python3python_intro.py
HiRachel!
Parabéns!Vocêacaboudeaprenderacriarfunções:)!
Laços
Jáéaúltimaparte.Foirápido,não?:)
Comomencionamos,osprogramadoressãopreguiçosos,nãogostamderepetirasmesmascoisas.Programaçãofala
sobrecomoautomatizarascoisas,entãonãoqueremoscumprimentarcadapessoapeloseunomemanualmente,certo?
Éaíondeoslaçosvemacalhar.
Aindaselembradaslistas?Vamosfazerumalistadegarotas:
girls=['Rachel','Monica','Phoebe','Ola','You']
Queremoscumprimentartodaselaspelosseusnomes.Temosafunção hiparafazerisso,entãovamosusá-laemum
loop:
fornameingirls:
O forsecomportadamesmaformaqueo if,ocódigoabaixoessesdoisprecisamserrecuadosquatroespaços.
Aquiestáocódigocompletoqueserásalvonoarquivo:
defhi(name):
print('Hi'+name+'!')
girls=['Rachel','Monica','Phoebe','Ola','You']
fornameingirls:
hi(name)
print('Nextgirl')
equandoexecutá-lo:
$python3python_intro.py
HiRachel!
Nextgirl
HiMonica!
Nextgirl
HiPhoebe!
Nextgirl
HiOla!
Nextgirl
HiYou!
Nextgirl
Comovocêpodever,tudooquevocêvaicolocardentrodeumainstrução forcomespaçoserárepetidoparacada
elementodalista girls.
Vocêtambémpodeusaro foremnúmerosusandoafunção range:
30
IntroduçãoaoPython
foriinrange(1,6):
print(i)
Queiriaimprimir:
1
2
3
4
5
rangeéumafunçãoquecriaumalistadenúmerosqueseseguemumapósooutro(essesnúmerossãodadosporvocê
comoparâmetros).
NotequeosegundodessesdoisnúmerosnãoestáincluídonalistaqueoPythonmostrou(em range(1,6),contade1a
5,maso6nãoéincluído).
Sumário
Éisso.Vocêétotalmentedemais!Nãoétãofácil,entãovocêdevesesentirorgulhosadesimesma.Estamos
definitivamenteorgulhosasdevocêporterchegadoatéaqui!
Talvezvocêqueirabrevementefazeralgomais-espreguiçar,andarumpouco,descansarosolhos-antesdeirparao
próximocapítulo.:)
31
OqueéDjango?
OqueéDjango?
Djangoéumframeworkgratuitoedecódigoabertoparaacriaçãodeaplicaçõesweb,escritoemPython.Éumframework
web,ouseja,éumconjuntodecomponentesqueajudaadesenvolversitesdeformamaisrápidaemaisfácil.
Veja,quandovocêestáconstruindoumsite,vocêsempreprecisaumconjuntosimilardecomponentes:umamaneirade
lidarcomaautenticaçãodousuário(inscrever-se,realizarlogin,realizarlogout),paineldegerenciamentoparaoseusite,
formulários,uploaddearquivos,etc.
Felizmenteparavocê,hámuitotempo,outraspessoasnotaramváriassemelhançasnosproblemasenfrentadospelos
desenvolvedoreswebquandoestãocriandoumnovosite,entãoelesuniram-seecriaramosframeworks(Djangoéum
deles)quelhedãocomponentesprontos,quevocêpodeusar.
Frameworksexistemparasalvá-lodeterquereinventararodaeajudamaaliviarasobrecargaquandovocêestá
construindoumnovosite.
Porquevocêprecisadeumframework?
ParaentenderoqueDjangoénaverdade,precisamosolharmaisdepertoosservidores.Aprimeiracoisaéqueoservidor
precisasaberoquevocêquerparaservi-loumapáginadaWeb.
Imagineumacaixadecorreio(porta)queémonitoradaporcartasrecebidas(requisição).Issoéfeitoporumservidorweb.
Oservidorweblêacartaeenviaumarespostacomumapáginaweb.Mas,quandovocêquerenviaralgumacoisavocê
precisaterumconteúdo.EoDjangoéaquiloquevailheajudaracriaresseconteúdo.
Oqueacontecequandoalguémsolicitaumsitedoseu
servidor?
QuandochegaumarequisiçãoparaoservidorwebelaépassadaparaoDjangoquetentadescobrirdoqueelasetrata.
Primeiroelepegaumendereçowebetentadescobriroquefazer.EssaparteéfeitapelourlresolverdoDjango.(Note
queoendereçodeumsitesechamaURL-UniformResourceLocator,emportuguêsLocalizadordeRecursosUniforme,
dessaformaonomeurlresolver,ouresolvedordeurls,fazsentido).Issonãoémuitointeligente-levaàumalistade
padrõesetentacorresponderaURL.ODjangoverificapadrõesdecimaparabaixoesealgoécorrespondido,passaa
solicitaçãoparaafunçãoassociada(queéchamadaview).
Imagineumcarteirocomumacarta.Elaestáandandopelaruaeverificacadanúmerodecasacomaqueestánacarta.
Seelecorresponder,elacolocaacartalá.Éassimquefuncionaourlresolver!
Todasascoisasinteressantessãofeitasdentrodaview:podemosdarumaolhadanobancodedadosparaprocurar
algumasinformações.Talvezousuárioqueiramudaralgonosdados?Comoumacartadizendo:"Porfavormudea
descriçãodomeuemprego."-aviewchecasevocêtempermissãoparafazerissoeentãoatualizaadescriçãodo
empregopravocê,enviandoemseguidaumamensagem:"Feito!".EntãoaviewgeraumarespostaeoDjangopode
enviá-laparaonavegadordocliente.
Claro,adescriçãoacimaémuitosimplificada,masvocênãoprecisasaberdetalhestécnicosainda.Terumaideiageraljá
ésuficiente.
Entãoemvezdemergulharemmuitosdetalhes,nóssimplesmentevamoscomeçarcriandoalgocomoDjangoe
aprenderemostodasaspartesimportantesaolongodocaminho!
32
InstalaçãodoDjango
InstalaçãodoDjango
PartedestecapítuloébaseadonostutoriaisdoGeekGirlsCarrots(https://github.com/ggcarrots/django-carrots).
Partedestecapítuloébaseadonodjango-marcadortutoriallicenciadosobreCreativeCommonsAttributionShareAlike4.0InternationalLicense.Otutorialdodjango-marcadoréprotegidopordireitosautoraisporMarkus
Zapke-Gründemannetal.
Ambientevirtual
AntesdeinstalarmosoDjango,nósiremosinstalarumaferramentaextremamenteútilqueiráajudaramanterseu
ambientededesenvolvimentoarrumadoemseucomputador.Épossívelignorarestepasso,maseleéaltamente
recomendado.Começarcomamelhorconfiguraçãopossíveltesalvarádemuitosproblemasnofuturo!
Então,vamoscriarumambientevirtual(tambémchamadoumvirtualenv).IssoisolarásuaconfiguraçãoPython/Django
emumabaseporprojeto,significaquequaisquermudançasquefizeremumwebsitenãoafetaráquaisqueroutras
aplicaçõesqueestiverdesenvolvendoaparte.Arrumado,certo?
Tudooquevocêprecisafazeréencontrarumdiretórionoqualvocêdesejacriaro virtualenv;SeudiretórioHome,por
exemplo.NoWindowspodeparecercomo C:\Usuário\Nome(onde Nomeéonomedoseulogin).
Paraestetutorialusaremosumnovodiretório djangogirlsdoseudiretóriohome:
mkdirdjangogirls
cddjangogirls
Nósvamosfazerumvirtualenvchamado myvenv.Oformatogeraldessecomandoé:
python3-mvenvmyvenv
Windows
Paracriarumnovo virtualenv,vocêprecisaabriroconsole(Nósfalamossobreissoalgunscapítulosatrás,lembra-se?)e
executar C:\Python34\python-mvenvmyvenv.Seráalgoparecidocomisto:
C:\Usuário\Nome\djangogirls>C:\Python34\python-mvenvmyvenv
onde C:\Python34\pythonéodiretórioemquevocêpreviamenteinstalouPythone myvenvéonomedasua virtualenv.
Vocêpodeusarqualqueroutronome,massempreuseminúsculasesemespaços,acentosoucaracteresespeciais.
Tambéméumaboaideiamanteronomecurto-vocêiráreferenciarmuitoaele!
LinuxeOSX
Criarum virtualenvtantonoLinuxcomoOSXésimplescomoexecutar python3-mvenvmyvenv.Seráalgoparecido
comisto:
~/djangogirls$python3-mvenvmyvenv
myvenvéonomedasua virtualenv.Vocêpodeusarqualqueroutronome,maspermaneçaemcaixabaixa(minúsculas)
enãouseespaçosentreosnomes.Tambéméumaboaideiamanteronomecurto-vocêiráreferenciarmuitoaele!
33
InstalaçãodoDjango
NOTA:IniciaroambientevirtualnoUbuntu14.04assimretornaráoseguinteerro:
Error:Command'['/home/eddie/Slask/tmp/venv/bin/python3','-Im','ensurepip','--upgrade','--default-pip']'
returnednon-zeroexitstatus1
Paracontornaresseproblema,useocomando virtualenv.
~/djangogirls$sudoapt-getinstallpython-virtualenv
~/djangogirls$virtualenv--python=python3.4myvenv
Trabalhandocomovirtualenv
Ocomandoacimacriaráumdiretóriochamado myvenv(ousejaonomequevocêescolheu)quecontémonosso
ambientevirtual(basicamenteumconjuntodediretóriosearquivos).Tudooquequeremosporenquantoéiniciá-lo
executando:
C:\Usuário\Nome\djangogirls>myvenv\Scripts\activate
noWindows,ou:
~/djangogirls$sourcemyvenv/bin/activate
noOSXenoLinux.
Lembre-sedesubstituir myvenvcomseunomeescolhidodo virtualenv!
NOTE:àsvezes source(fonte)podenãoestardisponível.Nessescasos,tentefazerisso:
~/djangogirls$.myvenv/bin/activate
Vocêvaisaberquetemum virtualenvfuncionandoquandoveropromptnoseuconsoleseparecercom:
(myvenv)C:\Usuário\Nome\djangogirls>
ou:
(myvenv)~/djangogirls$
Percebaqueoprefixo (myvenv)aparece!
Aotrabalhardentrodeumambientevirtual, pythoniráautomaticamentesereferiraversãocorretaparaquepossautilizar
pythonemvezde python3.
Ok,nóstemostodasasdependênciasimportantesnolugar.FinalmentepodemosinstalaroDjango!
InstalandooDjango
Agoraquevocêtemasua virtualenviniciado,vocêpodeinstalarDjangousando pip.Noconsole,execute pipinstall
django==1.8.5(Percebaqueusamosumduplosinaldeigual: ==).
34
InstalaçãodoDjango
(myvenv)~$pipinstalldjango==1.8.5
Downloading/unpackingdjango==1.8.5
Installingcollectedpackages:django
Successfullyinstalleddjango
Cleaningup...
noWindows
SevocêreceberumerroaochamaropipnaplataformaWindowsporfavor,verifiqueseocaminhodoprojeto
contémespaços,acentosoucaracteresespeciais(exemplo, C:\Users\UserName\djangogirls).Sesimporfavor
movaparaoutrolugarsemespaços,acentosoucaracteresespeciais(sugestãoé: C:\djangogirls).Apósa
mudança,porfavortentenovamenteocomandoacima.
NoLinux
SevocêreceberumerroaochamarpipnoUbuntu12.04porfavorexecute python-mpipinstall-U--forcereinstallpipparacorrigirainstalaçãodopipnovirtualenv.
Éisso!Agoravocêestá(finalmente)prontoparacriarumaaplicaçãoDjango!
35
Criandoumprojeto
SeuprimeiroprojetoDjango!
PartedestecapítuloébaseadonostutoriaisdoGeekGirlsCarrots(https://github.com/ggcarrots/django-carrots).
Partedestecapítuloébaseadonodjango-marcadortutoriallicenciadosobreCreativeCommonsAttributionShareAlike4.0InternationalLicense.Otutorialdodjango-marcadoréprotegidopordireitosautoraisporMarkus
Zapke-Gründemannetal.
Nósvamoscriarumblogsimples!
Oprimeiropassoparacriá-loécomeçarumnovoprojetodeDjango.Basicamente,istosignificaquevamosexecutar
algunsscriptsfornecidospeloDjangoqueirácriaroesqueletodeumprojetoDjangoparanós:umbandodediretóriose
arquivosqueusaremosmaistarde.
OsnomesdealgunsarquivosediretóriossãomuitoimportantesparaoDjango.Nãorenomeieosarquivosqueestamos
prestesacriar.Moverparaumlugardiferentetambémnãoéumaboaidéia.Djangoprecisamanterumadeterminada
estruturaparasercapazdeencontrarcoisasimportantes.
Lembre-sequetudonovirtualenv.Sevocênãovêumprefixo (myvenv)emseuconsole,vocêprecisaativaro
virtualenv.NósexplicamoscomofazerissonocapítuloinstalaçãodoDjangonapartetrabalhandocom
virtualenv.Vocêpodefazerissodigitandooseguintecomando: myvenv\Scripts\activatenoWindowsou
myvenv/bin/activatenoMacOS/Linux.
NotaVerifiquequevocêincluiuoponto( .)nofinaldocomando,éimportanteporquedizoscriptparainstalaro
Djangoemseudiretórioatual.
Noconsole,vocêdeveexecutar(Lembre-sedequevocênãopodedigitar ~/djangogirls$(myvenv),OK?):
(myvenv)~/djangogirls$django-adminstartprojectmysite.
noWindows:
(myvenv)C:\Users\Name\djangogirls>pythonmyvenv\Scripts\django-admin.pystartprojectmysite.
Django-adminéumscriptqueirácriarosdiretóriosearquivosparavocê.Agora,vocêdeveterumdiretórioestruturaque
separececomisso:
djangogirls
├───manage.py
└───mysite
settings.py
urls.py
wsgi.py
__init__.py
manage.pyéumscriptqueajudacomagestãodosite.Comissoseremoscapazesdeiniciarumservidordewebno
nossocomputadorseminstalarnada,entreoutrascoisas.
Oarquivo settings.pycontémaconfiguraçãodoseusite.
Lembraquandofalamossobreumcarteiroverificandoondeentregarumacarta?arquivo urls.pycontémumalistados
padrõesusadospor urlresolver.
Vamosignorarosoutrosarquivosporagora-nósnãovamosmudá-los.Aúnicacoisaalembrarénãoexcluí-lospor
acidente!
36
Criandoumprojeto
Configurando
Vamosfazeralgumasalteraçõesno mysite/settings.py.Abraoarquivousandooeditordecódigoquevocêinstalou
anteriormente.
Seriabomterahoracorretanonossosite.Váparaa<wikipediatimezoneslistecopieseufusohorário.(porexemplo.
America/Sao_Paulo)
Emsettings.py,localizealinhaquecontém TIME_ZONEemodifiqueparaescolherseuprópriofusohorário:
TIME_ZONE='America/Sao_Paulo'
Modifique"America/Sao_Paulo",conformeocaso
Nóstambémprecisaramosadicionarumcaminhoparaarquivosestáticos(nósvamosdescobrirtudosobrearquivos
estáticoseCSSmaistardenotutorial).Desçaatéofinaldoarquivoelogoabaixodaentrada STATIC_URL,adicioneum
novoumchamado STATIC_ROOT:
STATIC_URL='/static/'
STATIC_ROOT=os.path.join(BASE_DIR,'static')
Instalaçãodeumbancodedados
Háváriossoftwaresdebancodedadosdiferentesquepodearmazenardadosparaoseusite.Nósvamosusaropadrão,
sqlite3.
Istojáestáconfiguradonestapartedoseuarquivo mysite/settings.py:
DATABASES={
'default':{
'ENGINE':'django.db.backends.sqlite3',
'NAME':os.path.join(BASE_DIR,'db.sqlite3'),
}
}
Paracriarumbancodedadosparaonossoblog,vamosfazeroseguintenoconsole.Digite: pythonmanage.pymigrate
(precisamosestarnodiretórioquecontémoarquivo manage.py djangogirls).Seissodercerto,vocêdeveveralgocomo
isto:
(myvenv)~/djangogirls$pythonmanage.pymigrate
Operationstoperform:
Applyallmigrations:admin,contenttypes,auth,sessions
Runningmigrations:
Applyingcontenttypes.0001_initial...OK
Applyingauth.0001_initial...OK
Applyingadmin.0001_initial...OK
Applyingsessions.0001_initial...OK
Eestápronto!Horadeiniciaroservidorwebeversenossositeestáfuncionando!
Vocêprecisaestarnodiretórioquecontémoarquivo manage.py(odiretório djangogirls).Noconsole,nóspodemos
iniciaroservidorwebexecutandoo pythonmanage.pyrunserver:
(myvenv)~/djangogirls$pythonmanage.pyrunserver
Agoratudoquevocêprecisafazeréverificarseseusiteestásendoexecutado-abraseunavegador(Firefox,Chrome,
Safari,InternetExplorerouoquevocêusa)edigiteoendereço:
37
Criandoumprojeto
http://127.0.0.1:8000/
Oservidorwebvaiassumirseupromptdecomandoatévocêpará-lo:paradigitarmaiscomandosouabrirumanova
janeladoterminal(enãoseesqueçadeativarseuvirtualenvneletambém),oupararoservidordeweb,alternandode
voltaparaajanelanaqualestáexecutandoepressionandoCTRL+C-botõesdecontroleeCjuntos(noWindows,você
podeterquepressionarCtrl+Break).
Parabéns!Vocêcriouseuprimeirositeeoexecutouusandoumservidordeweb!Nãoéimpressionante?
Prontoparaopróximopasso?Estánahoradecriaralgumconteúdo!
38
ModelosdoDjango
ModelosdoDjango
Agoraoquenósqueremoscriaréalgoquearmazenetodosospostsnonossoblog.Masparafazerissoprecisamos
aprenderumpoucomaissobrecoisaschamadas objetos.
Objetos
Existeumconceitonaprogramaçãochamado ProgramaçãoOrientadaàObjetos(POO).Aideiaéqueaoinvésdeescrever
tudocomoumachatasequênciadeinstruçõesdeprogramaçãopodemosmodelarascoisasedefinircomoelasinteragem
umascomasoutras.
Entãooqueéumobjeto?Éumacoleçãodepropriedadeseações.Istopodeparecerestranho,masvamoslhedarum
exemplo.
Sequeremosmodelarumgatonóscriaremosumobjeto Gatoquepossuialgumaspropriedades,porexemplo cor,
idade, humor(bom,mau,sonolento;)), dono(queéumobjetodaclasse Pessoaou,casosejaumgatoderua,essa
propriedadeévazia).
Eentãoo Gatotemalgumasações: ronronar, arranharou comer(noqualvamosdaraogatoalguma ComidaDeGato,
quepoderiaserumobjetoseparadocompropriedades,como sabor).
Gato
-------cor
idade
humor
dono
ronronar()
arranhar()
comer(comida_de_gato)
ComidaDeGato
-------sabor
Então,basicamente,aideiaédescrevercoisasreaisnocódigocompropriedades(chamadasde propriedadesdoobjeto)
eações(chamadasde métodos).
Comonósiremosmodelaraspostagensdoblogentão?Queremosconstruirumblog,certo?
Precisamosresponderàpergunta:oqueéumapostagemdeblog?Quepropriedadesdeveter?
Bem,comcertezanossoblogprecisadealgumapostagemcomoseuconteúdoeumtítulo,certo?Tambémseriabom
saberquemaescreveu-entãoprecisamosdeumautor.Finalmente,queremossaberquandoapostagemfoicriadae
publicada.
Post
-------title
text
author
created_date
published_date
Quetipodecoisapodeserfeitacomumapostagem?Serialegalteralgum métodoquepubliqueapostagem,nãoé
mesmo?
Entãoprecisamosdeummétodochamado publicar.
39
ModelosdoDjango
Comojásabemosoquequeremosalcançar,podemoscomeçaramodelagememDjango!
ModelodoDjango
Sabendooqueumobjetoé,nóscriaremosummodelonoDjangoparaapostagemdoblog.
UmmodelonoDjangoéumtipoespecialdeobjeto-eleésalvoemum bancodedados.Umbancodedadoséuma
coleçãodedados.Obancodedadoséumlocalemquevocêvaisalvardadossobreusuários,suaspostagens,etc.
UsaremosumbancodedadoschamadoSQLiteparaarmazenarasnossasinformações.Esteéoadaptadordebancode
dadospadrãoDjango--elevaiserosuficienteparanósnestemomento.
Vocêpodepensaremummodelodebancodedadoscomoumaplanilhacomcolunas(campos)elinhas(dados).
Criandoumaaplicação
Paramantertudoarrumadovamoscriarumaplicativoseparadodentrodonossoprojeto.Émuitobomtertudoorganizado
desdeoinício.Paracriarumaplicativoprecisamosexecutaroseguintecomandonoconsole(apartirdodiretório
djangogirlsondeestáoarquivo manage.py):
(myvenv)~/djangogirls$pythonmanage.pystartappblog
Vocêvainotarqueumnovodiretório blogécriadoequeeleagoracontémumnúmerodearquivos.Nossosdiretóriose
arquivosnonossoprojetodevemseparecercomeste:
djangogirls
├──mysite
|__init__.py
|settings.py
|urls.py
|wsgi.py
├──manage.py
└──blog
├──migrations
|__init__.py
├──__init__.py
├──admin.py
├──models.py
├──tests.py
└──views.py
DepoisdecriarumaplicativotambémprecisamosdizeraoDjangoquedeveusá-lo.Fazemosissonoarquivo
mysite/settings.py.Precisamosencontraro INSTALLED_APPSeadicionarumalinhacom 'blog',logoacimado ).É
assimqueoprodutofinaldeveficarassim:
INSTALLED_APPS=(
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
)
CriandoomodeloPostdonossoblog
Noarquivo blog/models.pydefinimostodososobjetoschamados Modelos-esteéumlugaremquevamosdefinirnossa
postagemdoblog.
40
ModelosdoDjango
Vamosabrir blog/models.py,removatudodeleeescrevaocódigocomoeste:
fromdjango.dbimportmodels
fromdjango.utilsimporttimezone
classPost(models.Model):
author=models.ForeignKey('auth.User')
title=models.CharField(max_length=200)
text=models.TextField()
created_date=models.DateTimeField(
default=timezone.now)
published_date=models.DateTimeField(
blank=True,null=True)
defpublish(self):
self.published_date=timezone.now()
self.save()
def__str__(self):
returnself.title
Certifique-sedeterusadodoiscaracteres( _)emcadaladodo str.Aquelescaracteressãousados
freqüentementeemPythoneàsvezesoschamamosde"dunder"(abreviaçãode"double-underscore"ou"duplo
sublinhado").
Éassustador,não?Masnãosepreocupe,vamosexplicaroqueestaslinhassignificam!
Todasaslinhascomeçandocom fromou importsãolinhasqueadicionamalgunspedaçosdeoutrosarquivos.Então
aoinvésdecopiarecolarasmesmascoisasemcadaarquivo,podemosincluiralgumaspartescom from...import....
classPost(models.Model):-estalinhadefineonossomodelo(éum objeto).
classéumapalavra-chaveespecialqueindicaqueestamosdefinindoumobjeto.
Postéonomedonossomodelo,podemoslhedarumnomediferente(maséprecisoevitarosespaçosembrancoe
caracteresespeciais).Semprecomeceumnomedeclassecomumaletramaiúscula.
models.ModelsignificaqueoPostéummodelodeDjango,entãooDjangosabeelequedevesersalvonobancode
dados.
Agorapodemosdefiniraspropriedadesquediscutimos: titulo, texto, data_criacao, data_publicacaoe autor.Para
issoprecisamosdefinirumtipodecampo(éumtexto?Éumnúmero?Umadata?Umarelaçãocomoutroobjeto,por
exemplo,umusuário?).
models.CharField-assimécomovocêdefineumtextocomumnúmerolimitadodecaracteres.
models.TextField-esteéparatextoslongossemumlimite.Seráidealparaumconteúdodepostdeblog,certo?
models.DateTimeField-esteéumadataehora.
models.ForeignKey-esteéumlinkparaoutromodelo.
Nósnãovamosexplicarcadapedaçodecódigoaqui,poisissolevariamuitotempo.Vocêdeveolharadocumentaçãodo
DJangosevocêquisersabermaissobrecamposdoModelecomodefinircoisasalémdestasdescritasacima
(https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types).
Quetal defpublish(self):?Éexatamenteonossométodode publishquefalávamosantes. def,significaquese
tratadeumfunção/método. publishéonomedométodo.Vocêpodealterar,sequiser.Aregraéqueusamosletras
minúsculasesublinhadosemvezdeespaçosembranco(ouseja,sevocêquerterummétodoquecalculaopreçomédio,
vocêpoderiachamá-lo calculate_average_price).
Métodosmuitasvezes returnalgo.Háumexemplodeque,nométodo __str__.Nessecenário,quandochamamos
__str__()teremosumtexto(string),comumtítulodoPost.
Sealgoaindanãoestáclarosobremodelos,sinta-selivreparapediroseutreinador!Sabemosqueémuitocomplicado,
especialmentequandovocêaprenderoquesãoobjetosefunçõesaomesmotempo.Masesperoqueelesepareceum
poucomenosmágicaparavocêagora!
41
ModelosdoDjango
Criandotabelasparanossosmodelosnobancodedados
Oúltimopassoéadicionarnossonovomodeloparanossobancodedados.PrimeirotemosquefazeroDjangosaberque
nóstemosalgumasmudançasemnossomodelo(sócriamosisso),digite pythonmanage.pymakemigrationsblog.Será
algoparecidocomisto:
(myvenv)~/djangogirls$pythonmanage.pymakemigrationsblog
Migrationsfor'blog':
0001_initial.py:
-CreatemodelPost
Djangopreparaumarquivodemigraçãoquetemosdeaplicaragoraparanossobancodedados,tipo pythonmanage.py
migrateblog,asaídadeveser:
(myvenv)~/djangogirls$pythonmanage.pymigrateblog
Operationstoperform:
Applyallmigrations:blog
Runningmigrations:
Applyingblog.0001_initial...OK
Viva!NossomodelodePostestáagoraemnossobancodedados,seriaumprazervê-lo,certo?Saltarparaopróximo
capítuloparaveroaspectodoseuPost!
42
Administração
Administração
Paraadicionar,editareremoverpostagensquenóscriamosusaremosoDjangoadmin.
Vamosabriroarquivo blog/admin.pyesubstituirseuconteúdopor:
fromdjango.contribimportadmin
from.modelsimportPost
admin.site.register(Post)
Comovocêpodever,nósimportamos(incluímos)omodeloPostdefinidonocapítuloanterior.Paratornarnossomodelo
visívelnapáginadeadministração,nósprecisamosregistrá-locom: admin.site.register(Post).
OK,horadeolharparaonossomodelodePost.Lembre-sedeexecutar pythonmanage.pyrunservernoconsolepara
executaroservidorweb.Váparaonavegadoredigiteoendereçohttp://127.0.0.1:8000/admin/Vocêveráumapáginade
loginassim:
Parafazerloginvocêprecisacriarumsuperuser-umusuárioquepossuicontrolesobretudodosite.Volteparaoterminal
edigite pythonmanage.pycreatesuperuser,pressioneenteredigiteseunomedeusuário(caixabaixa,semespaço),
endereçodee-mailepasswordquandoelesforemrequisitados.Nãosepreocupequevocênãopodeverasenhaque
vocêestádigitando-éassimquedeveser.Sódigitá-laepressione'Enter'paracontinuar.Asaídadeveparecercomessa
(ondeUsernameeEmaildevemserosseus):
(myvenv)~/djangogirls$pythonmanage.pycreatesuperuser
Username:admin
Emailaddress:[email protected]
Password:
Password(again):
Superusercreatedsuccessfully.
Volteparaaonavegadorefaçalogincomascredenciaisdesuperuserquevocêescolheu,vocêdevevisualizaropainel
decontroledoDjangoadmin.
43
Administração
Váparaaspostagenseexperimenteumpoucocomelas.Adicionecincoouseispostagens.Nãosepreocupecomo
conteúdo-vocêpodecopiarecolaralgumtextodestetutorialparaoconteúdoparaeconomizartempo:).
Certifique-sequepelomenosduasoutrêspostagens(masnãotodas)têmadatadepublicaçãodefinida.Issoseráútil
depois.
SevocêquisersabermaissobreoDjangoadmin,vocêdeveconferiradocumentaçãodoDjango:
https://docs.djangoproject.com/en/1.8/ref/contrib/admin/
Esteéprovavelmenteumbommomentoparatomarumcafé(ouchocolate)oualgoparacomerparareporasenergias.
VocêcriouseuprimeiromodelodeDjango-vocêmereceumpoucodedescanso!
44
Implantação!
Implantação!
NotaOcapítuloseguintepodeseràsvezesumpoucodifícildepassar.Persistaetermine-o;Implantaçãoéuma
parteimportantedoprocessodedesenvolvimentodewebsite.Estecapítuloestálocalizadonomeiodotutorialpara
queseututorpossalheajudarcomoprocessoligeiramentecomplexodecolocarseusiteonline.Istosignificaque
vocêaindapodeterminarotutorialporcontaprópriasevocêcontinuaremoutromomento.
Atéagoranossositesóestavadisponívelnoseucomputador,agoravocêvaiaprendercomopublicarelenainternet!A
implantaçãoéoprocessodepublicaçãodoseuaplicativonaInternetdetalformaqueaspessoaspossam,finalmente,ver
seuaplicativo:).
Comovocêaprendeu,umwebsiteprecisaestarlocalizadonumservidor.Existemmuitosprovedores,masiremosutilizaro
quetemumprocessodedeployrelativamentesimples:PythonAnywhere.PythonAnywhereégratuitoparaaplicações
pequenasquenãopossuemmuitosvisitantes,entãoserásuficienteparavocêporenquanto.
OoutroserviçoexternoqueusaremoséGitHub,queéumserviçodehospedagemdecódigo.Existemoutros,masquase
todososprogramadorespossuemumacontanoGitHubatualmenteeagoravocêtambém!
UsaremosoGitHubcomoumtrampolimparatransportarnossocódigoparaoPythinAnywhere.
Git
Gité"sistemadecontroledeversão"usadopormuitosprogramadores-umsoftwarequecontrolamudançasnosarquivos
aolongodotempoparaquevocêpossarecuperarversõesespecíficasdepois.Umpoucocomo"controlarmudanças"no
MicrosoftWord,masmuitomaispoderoso.
InstalandooGit
Windows
VocêpodebaixarGitemgit-scm.com.Vocêpodeapertar"nextnextnext"emtodosospassosexcetoum;noquintopasso
chamado"AdjustingyourPATHenvironment",escolha"RunGitandassociatedUnixtoolsfromtheWindowscommandline"(aopçãodebaixo).Alémdisso,opadrãoestáótimo.CheckoutestiloWindows,commitUnix-stylelinhasde
confirmaçãoestábom.
MacOS
BaixarGitgit-scm.comesigaasinstruções.
Linux
Seelejánãoestiverinstalado,Gitdeveestardisponívelatravésdeseugerenciadordepacotes,entãotente:
sudoapt-getinstallgit
#or
sudoyuminstallgit
ComeçandonossorepositórionoGit
Gitcontrolaasalteraçõesparaumdeterminadoconjuntodearquivosnoquechamamosderepositóriodecódigo(ou
"repo").Vamoscomeçarumparanossoprojeto.Abraoconsoleeexecuteessescomandos,nodiretório djangogirls:
45
Implantação!
Nota:Verifiqueoseudiretóriodetrabalhoatualcomum pwd(OSX/Linux)ouocomando cd(Windows)antesde
inicializarorepositório.Vocêdeveestarnapasta djangogirls.
$gitinit
InitializedemptyGitrepositoryin~/djangogirls/.git/
$gitconfiguser.name"YourName"
[email protected]
Inicializarorepositóriogitéalgoquesóprecisamosfazerumavezporprojeto(evocênãoteráquere-introduzironome
deusuárioee-mailnuncamais)
Gitirácontrolarasalteraçõesparatodososarquivosepastasnestediretório,masexistemalgunsarquivosquequeremos
ignorar.Fazemosissoatravésdacriaçãodeumarquivochamado .gitignorenodiretóriobase.Abraseueditorecrieum
novoarquivocomoseguinteconteúdo:
*.pyc
__pycache__
myvenv
db.sqlite3
.DS_Store
Esalvecomo .gitignorenapastadenívelsuperior"djangogirls".
Nota:Opontonoiníciodonomedoarquivoéimportante!Sevocêestátendoalgumadificuldadeemcriá-la(Macs
nãogostamdecriararquivosquecomeçamcomumpontoatravésdoFinder,porexemplo),useorecurso"SaveAs"
noseueditorquesemprefunciona.
Éumaboaidéiaparausarumcomandode gitstatusantesde gitaddousemprequevocênãotivercertezadeque
seráfeito,paraevitarsurpresas(porexemplo,serãoadicionadosarquivoserradosoucommitados).Ocomando git
statusretornainformaçõessobretodososarquivoscontrolado/modificado/encenado,statusderamoemuitomais.O
outputdevesersemelhantea:
$gitstatus
Onbranchmaster
Initialcommit
Untrackedfiles:
(use"gitadd<file>..."toincludeinwhatwillbecommitted)
.gitignore
blog/
manage.py
mysite/
nothingaddedtocommitbutuntrackedfilespresent(use"gitadd"totrack)
Efinalmentenóssalvamosnossasalterações,Váparaoseuconsoleeexecuteestescomandos:
$gitadd--all.
$gitcommit-m"MyDjangoGirlsapp,firstcommit"
[...]
13fileschanged,200insertions(+)
createmode100644.gitignore
[...]
createmode100644mysite/wsgi.py
EmpurrandoonossocódigoparaGitHub
46
Implantação!
VáparaGitHub.comecadastreumanovaegratuitacontadeusuário.Emseguida,crieumnovorepositório,edêonome
"my-first-blog".Deixeo"initialisewithaREADME"desmarcado,deixeaopção.gitignoreembranco(jáfizemosisso
manualmente)ealicençacomoNone.
NotaOnome my-first-blogéimportante--vocêpoderiaescolheroutracoisa,masvamosusá-lomuitasvezesnas
instruçõesabaixoevocêteriaquesubstituí-locadavez.Éprovavelmentemaisfácilficarcomonome my-firstblog.
Natelaseguinte,vocêserámostradaacloneURLdoseurepo.Escolhaaversão"HTTPS",copie,evamoscolá-lono
terminalembreve:
AgoraprecisamosligarorepositórioGitnoseucomputadorcomonoGitHub.
$gitremoteaddoriginhttps://github.com/<your-github-username>/my-first-blog.git
$gitpush-uoriginmaster
47
Implantação!
DigiteseuGitHubusernameesenha,evocêdeveveralgocomoisto:
Usernamefor'https://github.com':hjwp
Passwordfor'https://[email protected]':
Countingobjects:6,done.
Writingobjects:100%(6/6),200bytes|0bytes/s,done.
Total3(delta0),reused0(delta0)
Tohttps://github.com/hjwp/my-first-blog.git
*[newbranch]master->master
Branchmastersetuptotrackremotebranchmasterfromorigin.
SeucódigoagoraestánoGitHub.Váeconfira!Vocêsaberáqueestáemboacompanhia-Django,oDjangoGirlsTutorial
emuitosoutrosgrandesprojetosdesoftwaredefonteabertatambémhospedamseucódigonoGitHub:)
CriaçãodenossoblogemPythonAnywhere
Emseguida,éhoradeseinscreverparaumacontagratuitade"Beginner"naPythonAnywhere.
www.pythonanywhere.com
Nota:aoescolherseunomedeutilizadoraqui,tenhaemmentequeaURLdoseublogteráoformulário
yourusername.pythonanywhere.com,entãoescolhaseunicknameouonomedoqueéoblog.
PullingourcodedownonPythonAnywhere
QuandovocêseinscreveparaPythonAnywhere,vocêélevadoaoseupaineldecontroleoupágina"Consoles".Escolhaa
opçãoiniciaroconsole"Bash"--queéaversãoPythonAnywheredeumconsole,comoaquelanoseuPC
Nota:PythonAnywhereébaseadoemLinux,assimsevocêestivernoWindowsoconsolevaiparecerumpouco
diferentedoqueestánoseucomputador.
VamospuxarnossocódigodeGitHubemPythonAnywhereatravésdacriaçãodeum"clone"dorepo.Digiteoseguinte
paraoconsolenaPythonAnywhere:
$gitclonehttps://github.com/<your-github-username>/my-first-blog.git
IstopuxaráumacópiadoseucódigoparaPythonAnywhere.Confiradigitando:
$treemy-first-blog
my-first-blog/
├──blog
│├──__init__.py
│├──admin.py
│├──migrations
││├──0001_initial.py
││└──__init__.py
│├──models.py
│├──tests.py
│└──views.py
├──manage.py
└──mysite
├──__init__.py
├──settings.py
├──urls.py
└──wsgi.py
CriandoumvirtualenvnaPythonAnywhere
Assimcomofezemseuprópriocomputador,vocêpodecriarumvirtualenvnaPythonAnywhere.NoconsoleBash,digite:
48
Implantação!
20:20~$cdmy-first-blog
20:20~$virtualenv--python=python3.4myvenv
Runningvirtualenvwithinterpreter/usr/bin/python3.4
[...]
Installingsetuptools,pip...done.
20:20~$sourcemyvenv/bin/activate
(mvenv)20:20~$pipinstalldjangowhitenoise
Collectingdjango
[...]
Successfullyinstalleddjango-1.8.5whitenoise-2.0
Coletadearquivosestáticos.
Vocêestavaimaginandooqueé"whitenoise"?Éumaferramentaparaserviroschamados"arquivosestáticos".Arquivos
estáticosfuncionamdeformadiferentenosservidoresemcomparaçãocomnossoprópriocomputador,eprecisamosde
umaferramentacomoo"whitenoise"paraatendê-los.
Vamosdescobrirumpoucomaissobrearquivosestáticosmaistardenotutorial,quandovamoseditaroCSSparaonosso
site.
Porenquantosóprecisamosexecutarumcomandoextrachamado"collectstatic"noservidor.IssodizproDjangoreunir
todososarquivosestáticosqueeleprecisanoservidor.Emsuamaioria,estessãoosarquivosestáticosquefazemosite
doadminbonitonomomento.
20:20~$pythonmanage.pycollectstatic
Youhaverequestedtocollectstaticfilesatthedestination
locationasspecifiedinyoursettings:
/home/edith/my-first-blog/static
Thiswilloverwriteexistingfiles!
Areyousureyouwanttodothis?
Type'yes'tocontinue,or'no'tocancel:yes
Digite"yes"(Sim)evaiembora!Vocênãoadorafazercomputadoresimprimirpáginasepáginasdetexto?Semprefaço
pequenosruídosparaacompanhá-lo.Brp,brpbrp...
Copying'/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.
js'
Copying'/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.
js'
[...]
Copying'/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists
.css'
Copying'/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css'
62staticfilescopiedto'/home/edith/my-first-blog/static'.
CriandoobancodedadosemPythonAnywhere
Aquiestáoutracoisaqueédiferenteentreseucomputadoreoservidor--eleusaumbancodedadosdiferente.Entãoas
contasdeusuárioemensagenspodemserdiferentesnoservidorenoseucomputador.
Entãonósvamosinicializarobancodedadosnoservidortalcomofizemosnoseuprópriocomputador,com migratee
createsuperuser:
49
Implantação!
(mvenv)20:20~$pythonmanage.pymigrate
Operationstoperform:
[...]
Applyingsessions.0001_initial...OK
(mvenv)20:20~$pythonmanage.pycreatesuperuser
Publicaçãodonossoblogcomoumaplicativoweb
AgoranossocódigoestánaPythonAnywhere,nossavirtualenvestápronta,osarquivosestáticosestãorecolhidoseo
bancodedadosestáinicializado,estamosprontosparapublicá-locomoumaplicativodaweb.
CliqueemvoltarparaoPythonAnywheredashboardclicandonoseulogotipoecliquenaguiaWebeváemAddanew
webapp.
Nacaixadediálogo,apósaconfirmaçãodeseunomededomínio,escolhamanualconfiguration(NBnãoaopção
"Django").Emseguida,escolhaPython3.4ecliqueemNextparaconcluiroassistente.
Notacertifique-sevocêescolheuaopção"Manualconfiguration",nãoa"Django".Nóssomosdemaisparaopadrão
deconfiguraçãoDjangodaPythonAnywhere;-)
Definindoovirtualenv
VocêserálevadoparaateladeconfiguraçãodePythonAnywhereparaseuwebappqueéondevocêprecisarádeir
quandoquiserfazeralteraçõesparaoaplicativonoservidor.
Naseção"Virtualenv",cliquenotextovermelhoquediz"Enterthepathtoavirtualenv"edigite: /home/<your-username>/myfirst-blog/myvenv/
Nota:substituaseupróprionomedeusuárioconformeapropriado.Sevocêcometerumerro,PythonAnywhereirá
mostrarumpequenoaviso.
ConfigurandooarquivoWSGI
50
Implantação!
DjangofuncionausandooWSGIprotocol,umpadrãoparaservirsitesusandoPython,queoferecesuportea
PythonAnywhere.AmaneiraqueconfiguramosPythonAnywhereparareconhecernossoblogDjangoéeditandoum
arquivodeconfiguraçãodoWSGI.
Cliquenolink"WSGIconfigurationfile"(naseção"Code"pertodotopodapágina--elevaisernomeadoalgocomo
/var/www/<your-username>_pythonanywhere_com_wsgi.py),evocêserálevadoparaumeditor.
Excluatodooconteúdoatualesubstituacomalgoparecidocomisto:
importos
importsys
path='/home/<your-username>/my-first-blog'#useyourownusernamehere
ifpathnotinsys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE']='mysite.settings'
fromdjango.core.wsgiimportget_wsgi_application
fromwhitenoise.djangoimportDjangoWhiteNoise
application=DjangoWhiteNoise(get_wsgi_application())
Notanãoseesqueçadesubstituiremseupróprionomedeusuárioondediz <your-username>
OqueessearquivofazédizerPythonAnywhereondemoraanossaaplicaçãowebequalonomedoarquivode
configuraçõesDjango.Eletambémdefineaferramentadearquivosestáticos"whitenoise".
AperteSaveeentãovolteparaaguiaWeb.
Játerminamos!AperteobotãograndeverdedeReloadevocêserácapazdeirverosseuaplicativo.Vocêencontraráum
linkparaelenotopodapágina.
Dicasdedebugging
Sevocêvirumerroquandovocêtentavisitaroseusite,oprimeirolugarparaprocuraralgumainformaçãodedebuggingé
noseuerrorlog--vocêencontraráumlinkparaissonaguiawebPythonAnywhere.Versehámensagensdeerrolá.As
maisrecentesestãonaparteinferior.Problemascomunsincluem
esquecerumdospassosquefizemosnoconsole:criandoovirtualenv,ativá-lo,instalandooDjango,collectstatic,
inicializandoobancodedados
cometerumerronocaminhodovirtualenvnaguiaweb--haverágeralmenteumapequenamensagemdeerro
vermelholá,seháumproblema
cometerumerronoarquivodeconfiguraçãoWSGI..--vocêusouocaminhoparaapastadomy-first-blogcertinho?
Otreinadorestáaquiparaajudar!
Vocêestálive!
Apáginapadrãoparaseusitedevedizer"Bem-vindoaoDjango",comoacontecenoseuPClocal.Tenteadicionar
/admin/paraofinaldaURL,evocêserálevadoaositeadmin.Fazerlogincomonomedeusuárioesenha,evocêverá
quevocêpodeadicionarnovasmensagensnoservidor.
Dêemvocêmesmaumenormetapinhanascostas-implantaçõesdeservidorsãoumadaspartesmaisdifíceisdo
desenvolvimentoweb,emuitasvezeslevaaspessoasváriosdiasantesdefazerfuncionar.Masvocêtemseusite
publicado,nainternet,assim!
51
Implantação!
52
Urls
Urls
EstamosprestesaconstruirnossaprimeiraWebpage-umapáginainicialparaoseublog!Masprimeiro,vamosaprender
umpoucomaissobreDjangourls.
OqueéumaURL?
UmaURLésimplesmenteumendereçodaweb,vocêpodeverumaURLtodavezquevocêvisitaqualquersite-évisível
nabarradeendereçosdoseunavegador(Sim! 127.0.0.1:8000éumaURL!Ehttp://djangogirls.orgtambéméumaURL):
CadapáginanaInternetprecisadesuaprópriaURL.Destaformaseuaplicativosabeoquedevemostraraumusuário
queabreumaURL.EmDjango,nósusamosalgochamado URLconf(configuraçãodeURL),queéumconjuntode
padrõesqueDjangovaitentarcoincidircomaURLrecebidaparaencontraravisãocorreta.
ComofuncionamasURLsemDjango?
Vamosabriroarquivo mysite/urls.pyevercomqueeleseparece:
fromdjango.conf.urlsimportinclude,url
fromdjango.contribimportadmin
urlpatterns=[
#Examples:
#url(r'^$','mysite.views.home',name='home'),
#url(r'^blog/',include('blog.urls')),
url(r'^admin/',include(admin.site.urls)),
]
Comovocêpodever,oDjangojácolocoualgumacoisalápranós.
Aslinhasquecomeçamcom #sãocomentários-issosignificaqueessaslinhasnãoserãoexecutadaspeloPython.
Muitoútil,não?
AURLdoadmin,quevocêvisitounocapítuloanteriorjáestáaqui:
url(r'^admin/',include(admin.site.urls)),
IssosignificaqueparacadaURLquecomeçacom admin/oDjangoiráencontrarumcorrespondentemododeexibição.
NestecasonósestamosincluindoummontedeadminURLsparaqueissonãofiquetudoembaladonestepequeno
arquivo..--émaislegívelemaislimpo.
Regex
53
Urls
VocêquersabercomooDjangocoincidecomURLsparaviews?Bem,estaparteécomplicada.oDjangousao regex-expressõesregulares.Regextemmuito(muito!)denormasqueformamumpadrãodepesquisa.Comoregexessãoum
tópicoavançado,nósveremosemdetalhescomoelasfuncionam.
Sevocêaindaquiserentendercomocriamosospadrões,aquiestáumexemplodoprocesso-sóprecisamosum
subconjuntolimitadoderegrasparaexpressaropadrãoqueprocuramos,ouseja:
^paraoiníciodotexto
$paraofinaldotexto
\dparaumdígito
+paraindicarqueoitemanteriordeveserrepetidopelomenosumavez
()paracapturarpartedopadrão
Qualqueroutracoisanadefiniçãodeurlserálevadaliteralmente.
Agoraimaginequevocêtemumsitecomoendereçoassim: http://www.mysite.com/post/12345/,onde 12345éonúmero
doseupost.
Escreverviewsseparadasparatodososnúmerosdepostseriamuitochato.Comexpressõesregularespodemoscriarum
padrãoqueirácoincidircomaurleextraironúmeroparanós: ^post/(\d+)/$.Vamosaospoucosveroqueestamos
fazendoaqui:
^post/estádizendoaoDjangoparapegartudoquetenha post/noiníciodaurl(logoapóso ^)
(\d+)significaquehaveráumnúmero(umoumaisdígitos)equequeremosonúmerocapturadoeextraído
/dizparaoDjangoquedeveseguiroutro /
$indicaofinaldaURLsignificandoqueapenassequênciasterminandocomo /irãocorresponderaessepadrão
SuaprimeiraurlDjango!
ÉhoradecriarnossaprimeiraURL!Queremoshttp://127.0.0.1:8000/paraserumapáginainicialdonossoblogeexibir
umalistadeposts.
Tambémqueremosmanteroarquivode mysite/urls.pylimpo,aínósimportaremosurlsdanossaaplicação blogparao
arquivoprincipal mysite/urls.py.
Váemfrente,apagueaslinhascomentadas(aslinhasquecomeçamcom #)eadicioneumalinhaquevaiimportar
blog.urlsparaaurlprincipal( '').
Oseuarquivo mysite/urls.pydeveagoraseparecercomisto:
fromdjango.conf.urlsimportinclude,url
fromdjango.contribimportadmin
urlpatterns=[
url(r'^admin/',include(admin.site.urls)),
url(r'',include('blog.urls')),
]
ODjangoagorairáredirecionartudooqueentraem'http://127.0.0.1:8000/'para blog.urlseprocurarpornovas
instruçõeslá.
AoescreverasexpressõesregularesemPythonésemprefeitocom rnafrentedasequência-issoésóumadicaútil
paraPythonqueaseqüênciapodecontercaracteresespeciaisquenãosãodestinadasparaPythonemsi,masemvez
dissosãopartedaexpressãoregular.
blog.urls
Crieumnovoarquivovazio blog/urls.py.Tudobem!Adicioneestasduasprimeiraslinhas:
54
Urls
fromdjango.conf.urlsimportinclude,url
from.importviews
AquinósestamosapenasimportandométodosdoDjangoetodososnossos viewsdoaplicativo blog(aindanãotemos
nenhuma,masteremosemumminuto!)
DepoisdissonóspodemosadicionarnossoprimeiraURLpadrão:
urlpatterns=[
url(r'^$',views.post_list),
]
Comovocêpodever,estamosagoraatribuindouma viewchamada post_listpara ^$URL.Essaexpressãoregular
corresponderáa ^(umcomeço)seguidopor $(fim)-entãosomenteumaseqüênciavaziairácorresponder.Eissoé
correto,porqueemresolvedoresdeDjangourl,'http://127.0.0.1:8000/'nãoéumapartedaURL.Estepadrãoirámostrar
oDjangoque views.post_listéolugarcertoparair,sealguémentraemseusitenoendereço'http://127.0.0.1:8000/'.
Tudocerto?Abrahttp://127.0.0.1:8000noseunavegadorpraveroresultado.
Nãotemmais"ItWorks!'maisein?Nãosepreocupe,ésóumapáginadeerro,nadaatemer!Elassãonaverdademuito
úteis:
Vocêpodelerquenãohánoattribute'post_list'.Opost_listtelembraalgumacoisa?Istoécomochamamosonosso
view!Issosignificaqueestátudonolugar,sónãocriamosnossaviewainda.Nãosepreocupe,nóschegaremoslá.
SevocêquersabermaissobreDjangoURLconfs,vejaadocumentaçãooficial:
https://docs.djangoproject.com/en/1.8/topics/http/urls/
55
Views-horadecriar!
Views-horadecriar!
Éhoraderesolverobugquecriamosnocapítuloanterior:)
Umaviewécolocadaondenóscolocamosa"lógica"danossaaplicação.Eleirásolicitarinformaçõesapartirdo model
quevocêcriouantesepassá-loparaum templatequevocêvaicriarnopróximocapítulo.Views,nofundo,nãopassam
demétodosescritosemPythonquesãoumpoucomaiscomplicadosdoqueaquiloquefizemosnocapítuloIntrodução
aoPython.
Asviewssãopostasnoarquivo views.py.Nósvamosadicionarnossasviewsnoarquivo blog/views.py.
blog/views.py
OK,vamosabriroarquivoeveroquetemnele:
fromdjango.shortcutsimportrender
#Createyourviewshere.
Nãotemmuitacoisa.Aviewmaisbásicaseparececomisto.
defpost_list(request):
returnrender(request,'blog/post_list.html',{})
Comovocêpodever,nóscriamosummétodo( def)chamado post_listqueaceitao pedidoe retornarummétodo
renderseráprocessado(paramontar)nossomodelo blog/post_list.html.
Salveoarquivo,váparahttp://127.0.0.1:8000/evejaoquetemosagora.
Outroerro!Leiaoqueestáacontecendoagora:
Estaéfácil:TemplateDoesNotExist.Vamoscorrigirestebugecriarummodelonopróximocapítulo!
AprendamaissobreasviewsdoDjangolendoadocumentaçãooficial:
https://docs.djangoproject.com/en/1.8/topics/http/views/
56
IntroduçãoaHTML
IntroduçãoaHTML
Vocêpodeseperguntar:eoqueéumtemplate?
Umtemplateéumarquivoquenóspodemosreutilizarparaapresentardiferentesinformaçõesdeumaformaconsistente.
Porexemplo,vocêpoderiausarumtemplateparateajudaraescreverumacarta,pois,emboracadacartapossuauma
mensagemeumdestinodiferente,todasterãosempreomesmoformato.
OformatodotemplatedoDjangoédescritoemumalinguagemchamadaHTML(esseéomesmHTMLquemencionamos
noprimeirocapítuloComoaInternetfunciona).
OqueéHTML?
HTMLéumsimplescódigoqueéinterpretadopeloseunavegadorweb-comooChrome,oFirefoxouoSafari-para
exibirumapáginadawebparaousuário.
HTMLsignifica"HyperTextMarkupLanguage".HiperTextsignificaqueéumtipodetextoquesuportahiperlinksentre
páginas.Marcaçãonadamaiséquemarcarumdocumentocomcódigosquedizemparaalguém(nessecaso,o
navegadorweb)comoapáginadeveráserinterpretada.CódigoemHTMLéfeitocomtags,cadaumacomeçandocom
<eterminandocom >.Essastagsmarcamoselementos.
Seuprimeirotemplate!
Criarumtemplatesignificacriarumarquivodetemplate.Tudoéumarquivo,certo?Provavelmentevocêjádeveternotado
isso.
Ostemplatessãosalvosnodiretório blog/templates.Logo,crieumdiretóriochamado templatesdentrododiretóriodo
seublog.Emseguida,crieoutrodiretóriochamado blogdentrodadiretóriotemplates:
blog
└───templates
└───blog
(Vocêdeveestarseperguntandoporquenósprecisamosdedoisdiretórioschamados blog-comovocêdescobrirámais
parafrente,essaéumasimpleseútilconvençãoquefacilitaavidaquandoascoisascomeçaremaficarmais
complicadas.)
Eagoranóscriamosoarquivo post_list.html(deixe-oembrancoporagora)dentrododiretório blog/templates/blog.
Vejacomoonossositeestáseparecendoagora:http://127.0.0.1:8000/
Seocorrerumerrode TemplateDoesNotExiststentereiniciaroseuservidor.Entrenalinhadecomando,pareo
servidorpressionandoCtrl+C(ControlseguidodateclaC,juntas)ereinicie-orodando pythonmanage.pyrunserver.
57
IntroduçãoaHTML
Acabaram-seoserros!Parabéns:)Entretanto,nossositenãomostranadaanãoserumapáginaembranco.Issoporque
onossotemplateestávazio.Entãoprecisamosconsertarisso.
Adicioneaseguintelinhadentrodotemplate:
<html>
<p>Hithere!</p>
<p>Itworks!</p>
</html>
Comonossositesepareceagora?Cliqueparadescobrir:http://127.0.0.1:8000/
Funcionou!Bomtrabalho:)
Atagmaisbásica, <html>,estarásemprenocomeçodequalquerpáginadaweb,assimcomo, </html>sempre
estaránofim.Comovocêpodever,todooconteúdodeumwebsiteseencontraentreatagdeinício <html>eentre
atagdefim </html>
<p>éatagquedenominaparágrafos; </p>determinaofimdecadaparágrafo
Head&body
CadapáginaHTMLtambémédivididaemdoiselementos:head(cabeça)ebody(corpo).
headéumelementoquecontéminformaçõessobreodocumentoquenãosãomostradasnatela.
bodyéumelementoquecontémtudooqueéexibidocomopartedeumapáginadeumsite.
Nósusamosatag <head>paradizeraonavegadorsobreasconfiguraçõesdapágina.Porsuavez,atag <body>dizao
navegadoroquehádeverdadenapágina.
Porexemplo,vocêpodeporoelementotítulodeumapáginawebdentrodatag <head>.Veja:
58
IntroduçãoaHTML
<html>
<head>
<title>Ola'sblog</title>
</head>
<body>
<p>Hithere!</p>
<p>Itworks!</p>
</body>
</html>
Salveoarquivoeatualizesuapágina.
Viucomoonavegadorentendeuque"Ola'sblog"éotítulodapágina?Eleinterpretou <title>Ola'sblog</title>e
colocouotextonabarradetítulodoseunavegador(etambémseráusadoparaosfavoritoseoutrascoisasmais).
Provavelmentevocêjádeveternotadoquecadatagdeaberturacasacomumatagdefechamento,comuma /,eque
oselementosestãoaninhados(ex.:vocênãopodefecharumtagemparticularantesquetodasasoutrastagsque
estiveremdentrodelajáestejamfechadas).
Écomocolocarcoisasdentrodecaixas.Vocêtemumagrandecaixa, <html></html>;dentrodelahá <body></body>,
sendoqueestaaindacontémcaixasmenors: <p></p>.
Vocêprecisaseguiressasregrasdefechamentodetags,edeaninhamentodeelementos-sevocênãofizerisso,o
navegadorpoderánãoestaraptoparainterpretarseucódigodemaneiracorretaesuapáginaseráexibidademaneira
incorreta.
Customizeseutemplate
Agoravocêpodesedivertirumpoucotentandocustomizaroseutemplate!Aquiestãoalgumastagsúteisparaisso:
<h1>Umtítulo</h1>-paraotítulomaisimportante
<h2>Umsub-título</h2>paraumtítuloumnívelabaixo
<h3>Umsub-sub-título</h3>...eporaívai,até <h6>
<em>texto</em>enfatizaseutexto
<strong>text</strong>enfatizafortementeseutexto
<br/>pulaparaapróximalinha(vocênãopodecolocarnadadentrodebr)
<ahref="https://djangogirls.org">link</a>criaumlink
<ul><li>primeiroitem</li><li>segundoitem</li></ul>criaumalista,exatamentecomoessa!
<div></div>defineumaseçãodapágina
Aquiestáumexemplodeumtemplatecompleto:
59
IntroduçãoaHTML
<html>
<head>
<title>DjangoGirlsblog</title>
</head>
<body>
<div>
<h1><ahref="">DjangoGirlsBlog</a></h1>
</div>
<div>
<p>published:14.06.2014,12:14</p>
<h2><ahref="">Myfirstpost</a></h2>
<p>Aeneaneuleoquam.Pellentesqueornaresemlaciniaquamvenenatisvestibulum.Donecidelitnonmipo
rtagravidaategetmetus.Fuscedapibus,tellusaccursuscommodo,tortormauriscondimentumnibh,utfermentummass
ajustositametrisus.</p>
</div>
<div>
<p>published:14.06.2014,12:14</p>
<h2><ahref="">Mysecondpost</a></h2>
<p>Aeneaneuleoquam.Pellentesqueornaresemlaciniaquamvenenatisvestibulum.Donecidelitnonmipo
rtagravidaategetmetus.Fuscedapibus,tellusaccursuscommodo,tortormauriscondimentumnibh,utf.</p>
</div>
</body>
</html>
Nóscriamostrêsseções divaqui.
Oprimeiroelemento divpossuiotítulodonossoblog-éumtítuloeumlink
Osoutrosdoiselementos divpossuemnossaspostagenscomadatadepublicação, h2comotítulodapostagem
queéclicáveledois ps(parágrafos)detexto,umparaadataeoutroparaotextodapostagem.
Issonosdáoseguinteefeito:
Yaaay!Mas,atéagora,nossotemplatemostraexatamantesempreamesmainformação-sendoque,anteriormente,
nósfalávamossobretemplatescomoumamaneiraparaexibirinformaçõesdiferentesemummesmoformato.
60
IntroduçãoaHTML
OquenósrealmentequeremosfazeréexibirpostagensreaisqueforamadicionadasnoDjangoadmin-eissoéoque
faremosemseguida.
Maisumacoisa:deploy!
SeriabomvertudoistonaInternet,certo?VamosfazeroutrodeployPythonAnywhere:
Commit,eponhaseucódigonoGitHub
Primeirodetudo,vejamosquaisarquivosforamalteradosdesdeaúltimaimplantação:
$gitstatus
Verifiquesevocêestánodiretório djangogirlsevamosdizerao gitparaincluirtodasasmudançasdentrodeste
diretório:
$gitadd--all.
Nota -A(abreviaçãode"all",tudoeminglês)significaqueo gittambémreconhecerásevocêdeletoualgum
arquivo(porpadrão,ogitapenasreconhecearquivoscriados/modificados).Lembre-setambém(docapítulo3)que
.significaodiretórioatual.
Antesdenósfazermosouploaddetodososaqruivos,chequemosoqueo gitenviará(todososarquivosqueo gitfor
enviardeveráapareceemverde):
$gitstatus
Estamosquaselá!Agoraéhoradedizeraeleparasalvaressamodificaçãoemseuhistórico.Nósdaremosaeleuma
"mensagemdecommit"ondenósdescrevemosasmodificaçõesquefizemos.Vocêpodeescreveroquevocêquiser
agora,masserámaisútilsevocêescreveralgumacoisamaisdescritiva,algoparavocêpoderselembrardascoisasque
vocêfezfuturamente.
$gitcommit-m"ChangedtheHTMLforthesite."
Certifique-sequevocêusouaspasduplasparadelimitaramensagemdocommit.
Quandofizermosisso,nósfazemosupload(envio)dasnossasmudançasparaoPythonAnywhere:
gitpush
BotedeunovocódigonoPythonAnywhereerecarregueoseuaplicativodaweb
AbraapáginadeconsolesdePythonAnywhereeváparaoseuconsoleBash(oucomeçarumnovo).Emseguida,
execute:
$cd~/my-first-blog
$sourcemyvenv/bin/activate
(myvenv)$gitpull
[...]
(myvenv)$pythonmanage.pycollectstatic
[...]
61
IntroduçãoaHTML
Evejaseucódigosendobaixado.Sevocêdesejaverificarsejáchegou,podeirparaaFilestabeverseucódigono
PythonAnywhere.
Finalmente,puleparaaWebtabeaperteReloademseuaplicativoweb.
Suaatualizaçãodeveestarlive!Váemfrenteeatualizeseusitenonavegador.Asalteraçõesdevemservisíveis:)
62
DjangoORM(Querysets)
QuerySetseORMdoDjango
NestecapítulovocêvaiaprendercomoDjangoseconectaaobancodedadosecomoelearmazenadados.Vamosnessa!
OqueéumQuerySet?
UmQuerySet(conjuntodepesquisa),nofundo,éumalistadeobjetosdeumdadomodelo.UmQuerySetpermiteque
vocêleiaosdadosdobanco,filtreeordeneomesmo.
Émaisfácilaprenderporexemplos.Vamostentar?
OShelldoDjango
Abraoterminaledigite:
(myvenv)~/djangogirls$pythonmanage.pyshell
Oresultadodeveser:
(InteractiveConsole)
>>>
AgoravocêestánoconsoleinterativodoDjango.EleécomoopromptdoPythonsóquecomumasmágicasamais:).
VocêpodeusartodososcomandosdoPythonaquitambém,éclaro.
Todososobjetos
Antes,vamostentarmostrartodasasnossaspostagens.Podemosfazerissocomoseguintecomando:
>>>Post.objects.all()
Traceback(mostrecentcalllast):
File"<console>",line1,in<module>
NameError:name'Post'isnotdefined
Oops!Umerroapareceu.ElenosdizquenãoexistealgochamadoPost.Éverdade--nósesquecemosdeimportá-lo
primeiro!
>>>fromblog.modelsimportPost
Issoésimples:importamosomodelo Postdedentrodo blog.models.Vamostentarmostrartodasaspostagens
novamente:
>>>Post.objects.all()
[<Post:myposttitle>,<Post:anotherposttitle>]
Éumalistadospostsquecriamosanteriormente!CriamosessespostsusandoainterfacedeadministraçãodoDjango.No
entanto,agoraqueremoscriarnovasmensagensutilizandoopython,entãocomoéquefazemosisso?
Criandoumobjeto
ÉassimquevocêcriaumobjetoPostnobancodedados:
63
DjangoORM(Querysets)
>>>Post.objects.create(author=me,title='Sampletitle',text='Test')
Masaquitemosumingredientequefaltava: me.Precisamospassarumainstânciade Usermodelocomoautor.Como
fazerisso?
PrimeirovamosimportaromodeloUser:
>>>fromdjango.contrib.auth.modelsimportUser
Quaisusuáriostemosnonossobancodedados?Experimenteisso:
>>>User.objects.all()
[<User:ola>]
Éosuperusuárioquecriamosanteriormente!Vamosobterumainstânciadeusuárioagora:
me=User.objects.get(username='ola')
Comovocêpodever,nósagorausamosum geta Userwitha usernameiguala'ola'.Claro,vocêtemqueadaptara
seunomedeusuário.
Agorafinalmentepodemoscriarnossaprimeirapostagem:
>>>Post.objects.create(author=me,title='Sampletitle',text='Test')
Viva!Querversefuncionou?
>>>Post.objects.all()
[<Post:Sampletitle>]
Adicionemaispostagens
Agora,vocêpodesedivertirumpoucoeadicionarmaispostagensparavercomofunciona.Adicionemais2-3esigapara
apróximaparte.
Filtrarobjetos
UmagrandepartedeQuerySetséahabilidadedefiltrá-los.Digamosquequeremosencontrartodosaspostagensescritas
pelousuárioola.Nósusaremoso filteremvezde allem Post.objects.all().Entreparêntesesindicamosqueas
condiçõesprecisamseratendidasporumpostagemdeblogparaacabaremnossoqueryset.Emnossocasoé author
queéiguala me.AmaneiradeescreverissonoDjangoé: author=me.Agoraonossotrechodecódigoparececomeste:
>>>Post.objects.filter(author=me)
[<Post:Sampletitle>,<Post:Postnumber2>,<Post:My3rdpost!>,<Post:4thtitleofpost>]
Outalveznósqueremosvertodosospostsquecontenhamapalavra'title'nocampode title?
>>>Post.objects.filter(title__contains='title')
[<Post:Sampletitle>,<Post:4thtitleofpost>]
NotaExistemdoiscaracteresdesublinhado( _)entreo titlee contains.DjangoORMusaestasintaxepara
separarnomesdecampo("title")eoperaçõesoufiltros("contains").Sevocêusarapenasumsublinhado,você
obteráumerrocomo"FieldError:Cannotresolvekeywordtitle_contains".
64
DjangoORM(Querysets)
Vocêtambémpodeobterumalistadetodosospostspublicados.Fazemosissofiltrandotodosospostscom
published_datedefinidonopassado:
>>>fromdjango.utilsimporttimezone
>>>Post.objects.filter(published_date__lte=timezone.now())
[]
Infelizmente,nenhumdosnossospostsestãopublicadosainda.Nóspodemosmudarisso!Primeiroobtenhaumainstância
deumpostquequeremospublicar:
>>>post=Post.objects.get(id=1)
Eentãopublicá-locomonossométodode publish!
>>>post.publish()
Agoratenteobteralistadepostspublicadosnovamente(pressioneasetaparacimabotão3vezesetecleEnter):
>>>Post.objects.filter(published_date__lte=timezone.now())
[<Post:Sampletitle>]
Ordenandoobjetos
UmQuerySettambémnospermiteordenaralistadeobjetos.Vamostentarordenaraspostagenspelocampo
created_date:
>>>Post.objects.order_by('created_date')
[<Post:Sampletitle>,<Post:Postnumber2>,<Post:My3rdpost!>,<Post:4thtitleofpost>]
Vocêtambémpodeinverteraordemadicionando -noinício:
>>>Post.objects.order_by('-created_date')
[<Post:4thtitleofpost>,<Post:My3rdpost!>,<Post:Postnumber2>,<Post:Sampletitle>]
Legal!Vocêjáestáprontoparaapróximaparte!Parafecharoterminaldigite:
>>>exit()
$
65
Dadosdinâmicosnostemplates
DjangoQuerysets
Nóstemosdiferentespeçasaqui:omodel Postestádefinidoem models.py,nóstemos post_listno views.pyeo
templateadicionado.Mascomonósfaremosdefatoparafazercomqueasnossaspostagensapareçamnonosso
templateemHTML?Porqueéissoquenósqueremos:pegaralgumconteúdo(modelssalvosnobancodedados)eexibilodeumamaneirabacananonossotemplate,certo?
Eissoéexatamenteoqueasviewsdevemfazer:conectarmodelsetemplates.Nanossaview post_listviewnós
vamosprecisarpegarosmodelsquequeremosexibirepassá-losparaotemplate.Então,basicamente,emumaviewnós
decidimosoque(ummodel)seráexibidonotemplate.
Certo,ecomonósfaremosisso?
Precisamosabrironosso blog/views.py.Atéagoraaview post_listseparececomisso:
fromdjango.shortcutsimportrender
defpost_list(request):
returnrender(request,'blog/post_list.html',{})
Lembraquandofalamossobreainclusãodecódigoescritoemarquivosdiferentes?Agoraéomomentoemquetemosde
incluiromodelquetemosescritoem models.py.Vamosadicionarestalinha from.modelsimportPostcomoeste:
fromdjango.shortcutsimportrender
from.modelsimportPost
Opontodepoisde fromsignificaodiretórioatualouoaplicativoatual.Como views.pye models.pyestãonomesmo
diretóriopodemossimplesmenteusar .eonomedoarquivo(sem .py).Entãonósimportamosonomedomodelo
( Post).
Eoquevemagora?Parapegarospostsreaisdomodel Postnósprecisamosdeumacoisachamada QuerySet.
QuerySet
VocêjádeveestarfamiliarizadocomomodoqueosQuerySetsfuncionam.NósconversamossobreissonocapítuloORM
doDjango(QuerySets).Agoranósestamosinteressadosemumalistadepostsquesãopublicadoseclassificadospor
published_date,certo?NósjáfizemosissonocapítuloQuerySets!
Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
Agoranóscolocamosestepedaçodecódigodentrodoarquivo blog/views.pyadicionando-oàfunção def
post_list(request):
fromdjango.shortcutsimportrender
fromdjango.utilsimporttimezone
from.modelsimportPost
defpost_list(request):
posts=Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
returnrender(request,'blog/post_list.html',{})
NotequecriamosumavariávelparanossooQuerySet: posts.TrateistocomoonomedonossoQuerySet.Deagoraem
diantenóspodemosnosreferiraeleporestenome.
AúltimapartequefaltaépassaroQuerySet postsparaotemplate(veremoscomoexibi-loemumpróximocapítulo).
66
Dadosdinâmicosnostemplates
Nafunção renderjátemosoparâmetro request(tudooquerecebemosdousuárioatravésdaInternet)eumarquivode
template 'blog/post_list.html'.Oúltimoparâmetro,queseparececomisso: {}éumlugaremquepodemos
acrescentaralgumascoisasparaqueotemplateuse.Precisamosnomeá-los(ficaremoscom 'posts'porenquanto:)).
Deveficarassim: {'posts':posts}.Observequeaparteantesde :estáentreaspas ''.
Entãofinalmentenossoarquivo blog/views.pydeveseparecercomisto:
fromdjango.shortcutsimportrender
fromdjango.utilsimporttimezone
from.modelsimportPost
defpost_list(request):
posts=Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
returnrender(request,'blog/post_list.html',{'posts':posts})
Feito!HoradevoltarparaonossotemplateeexibiressaQuerySet!
SequiserlermaissobreQuerySetsnoDjangovocêdevedarumaolhadaaqui:
https://docs.djangoproject.com/en/1.8/ref/models/querysets/
67
Templates
Templates
Horadeexibiralgumdado!Djangonosdátagsdetemplatesembutidasbastanteúteisparaisso.
Oquesãotagsdetemplate?
Comopodever,vocênãopodecolocarcódigoPythonnoHTML,porqueosnavegadoresnãoirãoentender.Elesapenas
conhecemHTML.NóssabemosqueHTMLébastanteestático,enquantoPythonémuitomaisdinâmico.
TagsdetemplateDjangonospermitetransformarobjetosPythonemcódigoHTML,paraquevocêpossaconstruirsites
dinâmicosmaisrápidoemaisfácil.Uhuu!
Modelodelistadepostdeexibição
Nocapituloanterior,nósfornecemosaonossotemplateumalistadepostagenseavariávelposts.Agoravamosexibirem
nossoHTML.
ParaexibirumavariávelnoDjangotemplate,nósusamoscolchetesduploscomonomedavariáveldentro,exemplo:
{{posts}}
Tentarfazerissonoseutemplate blog/templates/blog/post_list.html(substituiaosegundoeoterceiropardetags <div
></div>pelalinha {{posts}}),salveoarquivoeatualizeapáginaparaverosresultados:
Vocêpodever,tudoquetemosé:
[<Post:Mysecondpost>,<Post:Myfirstpost>]
IstosignificaqueoDjangoaentendecomoumalistadeobjetos.Lembre-sedeintroduçãoaoPythoncomopodemos
exibirlistas?Sim,comosloops!EmumtemplateDjango,fazemosissodaseguintemaneira:
{%forpostinposts%}
{{post}}
{%endfor%}
Tentefazerissonoseutemplate.
68
Templates
Funciona!Masnósqueremosqueelessejamexibidoscomoospostsestáticos,comoosquecriamosanteriormenteno
capítulodeIntroduçãoaHTML.NóspodemosmisturarHTMLcomtagsdetemplate.Oconteúdodatag bodyficará
assim:
<div>
<h1><ahref="/">DjangoGirlsBlog</a></h1>
</div>
{%forpostinposts%}
<div>
<p>published:{{post.published_date}}</p>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{%endfor%}
Tudoquevocêpõeentre {%for%}e {%endfor%}serárepetidoparacadaobjetonalista.Atualizesuapágina:
Vocênotouquedessaveznósusamosumanotaçãoumpoucodiferente {{post.title}}ou {{post.text}}?Nós
estamosacessandoosdadosemcadaumdoscamposquedefinimosnomodeldo Post.Alémdisso, |linebreaksbr
estápassandootextodopostporumfiltro,convertendoquebrasdelinhaemparágrafos.
69
Templates
Maisumacoisa
Seriabomverseseusiteaindaestaráfuncionandonainternet,certo?VamostentarimplantaraPythonAnywhere
novamente.Aquiestáumresumodospassos...
Primeiro,envieseucódigoparaoGithub
$gitstatus
$gitadd--all.
$gitstatus
$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."
$gitpush
Emseguida,façaloginemPythonAnywhereeváparaseuBashconsole(oucomeceumnovo)eexecute:
`$cdmy-first-blog$gitpull
Finalmente,puleparaaWebtabeaperteReloademseuaplicativoweb.Suaatualizaçãodeveestarlive!
Parabéns!AgoraváemfrenteetenteadicionarumnovopostemseuDjangoadmin(Lembre-sedeadicionar
published_date!),emseguida,atualizeapáginaparaverseopostapareceporlá.
Funcionacomomágica?Estamosorgulhosos!Afaste-sedoseucomputadorumpouco,vocêganhouumapausa.:)
70
CSS-Deixemaisbonito
CSS-Deixemaisbonito!
Nossoblogaindaparecefeio,certo?Estánahoradedeixarelemelhor!ParaissonósusaremosoCSS.
OqueéCSS?
Doinglês"CascadingStyleSheets",CSSéumalinguagemusadaparadescreveroaspectoeaformataçãodeumwebsite
escritonumalinguagemdemarcação(comoHTML).Imagineelecomosendoumtipode"maquiagem"paranossosite;).
Masnósnãoqueremosiniciardozerodenovo,certo?Nóstentaremos,maisumavez,usaralgoquefoifeitoe
disponibilizadodegraçaporprogramadoresnainternet.Vocêsabe,reinventararodanãoénadadivertido.
VamosusaroBootstrap!
BootstrapéumdosmaisfamososepopularesframeworksdeHTMLeCSSparadesenvolversitesbonitos:
https://getbootstrap.com/
FoiescritoporprogramadoresquetrabalharamnoTwittereagoraédesenvolvidoporvoluntáriosdetodoomundo.
InstalarBootstrap
ParainstalaroBootstrap,vocêprecisaadicionaraoseucabeçalho(natag <head>dentrodoseuarquivo .html)
( blog/templates/blog/post_list.html):
<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
Issonãoadicionanenhumarquivoaoseuprojeto.Ocódigoapenasapontaparaarquivosqueexistemnainternet.Apenas
sigaemfrente,abraseusiteeatualizeapágina.Aquieleestá!
Jáparecendomelhor!
ArquivosestáticosnoDjango
71
CSS-Deixemaisbonito
Finalmentenósteremosumolharmaisatentonessascoisasquechamamosarquivosestáticos.Arquivosestáticossão
todasassuasimagensearquivosCSS--arquivosquenãosãodinâmicos,entãoseuconteúdonãodependedocontexto
darequisiçãoeseráomesmoparatodososusuários.
OndecolocarosarquivosestáticosparaDjango
Comovocêviuquandorodamos collectstaticnoservidor,Djangojásabeondeencontrarosarquivosestáticosparao
built-in"admin"app.Agorasóprecisamosadicionaralgunsarquivosestáticosparanossopróprioapp, blog.
Fazemosissoatravésdacriaçãodeumapastachamada staticdentrodoaplicativodoblog:
djangogirls
├──blog
│├──migrations
│└──static
└──mysite
Djangoencontraráautomaticamentetodasaspastaschamadas"static"dentrodequalquerumadaspastasdosseus
apps,eserácapazdeusarseuconteúdocomoarquivosestáticos.
SeuprimeiroarquivoCSS!
VamoscriarumarquivoCSSagora,paraadicionarseupróprioestiloparasuapáginadaweb.Crieumnovodiretório
chamado cssdentrodeseudiretório static.Emseguida,crieumnovoarquivochamado blog.cssdentrododiretório
css.Pronto?
djangogirls
└───blog
└───static
└───css
└───blog.css
HoradeescreverCSS!Abraoarquivo static/css/blog.cssnoseueditordecódigo.
NãovamosnosaprofundarmuitoemcustomizareaprendersobreCSSaqui,porqueébemfácilevocêpodeaprenderno
seupróprioapósesteworkshop.RecomendamosfortementefazeresteCodeacademyHTML&CSScouseparaaprender
tudooquevocêprecisasabersobrecomotornarseussitesmaisbonitoscomCSS.
Masvamosfazerpelomenosumpouco.Talvezpossamosmudaracordonossocabeçalho?Paraentenderascores,
computadoresusamcódigosespeciais.Elescomeçamcom #esãoseguidospor6letras(A-F)enúmeros(0-9).Você
podeencontrarexemplosdecódigosdecoresaqui:http://www.colorpicker.com/.Vocêpodetambémusarcores
predefinidas,como rede green.
Emseuarquivo static/css/blog.cssvocêdeveadicionaroseguintecódigo:
h1a{
color:#FCA205;
}
h1aéumseletordeCSS.Issosignificaquenósestamosaplicandonossosestilosparaqualquerelemento adentrode
umelemento h1(i.e.quandotivermosnocódigoalgocomo: <h1><ahref="">link</a></h1>).Nestecasonósestamos
dizendoparamudaracorpara #FCA205,queélaranja.Claro,vocêpodecolocaracorquevocêquiseraqui!
EmumarquivoCSSpodemosdeterminarestilosparaelementosnoarquivoHTML.Oselementossãoidentificadospelo
nomedoelemento(ouseja, a, h1, body),oatributode classouoatributo id.Classeeidsãonomesquevocê
mesmodáaoelemento.Classesdefinemgruposdeelementos,eidsapontamparaelementosespecíficos.Porexemplo,a
72
CSS-Deixemaisbonito
seguintetagpodeseridentificadaporCSSusandoatagdenome a,aclasse link_externoouaidentificaçãode
link_para_a_pagina_wiki:
<ahref="https://en.wikipedia.org/wiki/Django"class="external_link"id="link_to_wiki_page">
LeiasobreSeletoresCSSemw3schools.
Então,precisamostambémcontaronossotemplateHTMLquenósadicionamosCSS.Abraoarquivo
blog/templates/blog/post_list.htmleadicioneessalinhanoiníciodomesmo:
{%loadstaticfiles%}
Estamosapenascarregandoarquivosestáticosaqui:).Depois,entreo <head> e/</head>,depoisdoslinksparaos
arquivosdeCSSdoBootstrap(onavegadorlêosarquivosnaordemqueelessãodados,entãoocódigoemnosso
arquivopodesubstituirocódigoemarquivosdeinicialização),adicioneestalinha:
<linkrel="stylesheet"href="{%static'css/blog.css'%}">
SódissemosquenossomodeloondeseencontranossoarquivoCSS.
Agora,seuarquivodeveficarassim:
{%loadstaticfiles%}
<html>
<head>
<title>DjangoGirlsblog</title>
<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<linkrel="stylesheet"href="{%static'css/blog.css'%}">
</head>
<body>
<div>
<h1><ahref="/">DjangoGirlsBlog</a></h1>
</div>
{%forpostinposts%}
<div>
<p>published:{{post.published_date}}</p>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{%endfor%}
</body>
</html>
OK,salveoarquivoeatualizeosite!
73
CSS-Deixemaisbonito
Bomtrabalho!Talvezagentetambémqueiradarumpoucodearaonossositeeaumentaramargemdoladoesquerdo?
Vamostentar!
body{
padding-left:15px;
}
AdicioneistoaoseuarquivoCSS,salveevejacomoelefunciona!
Talvezagentepossacustomizarafontenonossocabeçalho?Colenaseção <head>doarquivo
blog/templates/blog/post_list.htmloseguinte:
<linkhref="https://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext"rel="stylesheet"type="text/css">
EssalinhairáimportarumafontechamadaLobsterdoGoogleFonts(https://www.google.com/fonts).
Agoraadicionealinha font-family:'Lobster';noCSSdoarquivo static/css/blog.cssdentrodoblocodedeclaração
h1a(ocódigoentreaschaves {e })eatualizeapágina:
74
CSS-Deixemaisbonito
h1a{
color:#FCA205;
font-family:'Lobster';
}
Incrível!
Comomencionadoacima,CSSusaoconceitodeclasses,quebasicamentepermitequevocênomeiepartedocódigo
HTMLeapliqueestilosapenasàestaparte,semafetarasoutras.Ésuperútilsevocêtiverduasdivs,maselesestão
fazendoalgomuitodiferente(comooseucabeçalhoeseupost),entãovocênãoquerqueelesfiquemparecidos.
VáemfrenteeonomeiealgumaspartesdocódigoHTML.Adicioneumaclassechamadade page-headerparao div
quecontémocabeçalho,assim:
<divclass="page-header">
<h1><ahref="/">DjangoGirlsBlog</a></h1>
</div>
Eagora,adicioneumaclasse postemsua divquecontémumpostdeblog.
<divclass="post">
<p>published:{{post.published_date}}</p>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
Agoraadicionaremosblocosdedeclaraçãodeseletoresdiferentes.Seletorescomeçandocom .sereferemàsclasses.
ExistemmuitostutoriaiseexplicaçõessobreCSSnaWebparaajudarvocêaentenderocódigoaseguir.Porenquanto,
bastacopiarecolá-loemseuarquivo mysite/static/css/blog.css:
75
CSS-Deixemaisbonito
.page-header{
background-color:#ff9400;
margin-top:0;
padding:20px20px20px40px;
}
.page-headerh1,.page-headerh1a,.page-headerh1a:visited,.page-headerh1a:active{
color:#ffffff;
font-size:36pt;
text-decoration:none;
}
.content{
margin-left:40px;
}
h1,h2,h3,h4{
font-family:'Lobster',cursive;
}
.date{
float:right;
color:#828282;
}
.save{
float:right;
}
.post-formtextarea,.post-forminput{
width:100%;
}
.top-menu,.top-menu:hover,.top-menu:visited{
color:#ffffff;
float:right;
font-size:26pt;
margin-right:20px;
}
.post{
margin-bottom:70px;
}
.posth1a,.posth1a:visited{
color:#000000;
}
EntãoenvolvaocódigoHTMLqueexibeasmensagenscomdeclaraçõesdeclasses.Substituaisto:
{%forpostinposts%}
<divclass="post">
<p>published:{{post.published_date}}</p>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{%endfor%}
noarquivo blog/templates/blog/post_list.htmlporisto:
76
CSS-Deixemaisbonito
<divclass="contentcontainer">
<divclass="row">
<divclass="col-md-8">
{%forpostinposts%}
<divclass="post">
<divclass="date">
{{post.published_date}}
</div>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{%endfor%}
</div>
</div>
</div>
Salveessesarquivoseatualizeseusite.
Uhuu!Ficouincrível,né?Ocódigoquenósacabamosdecolarnãoétãodifícildeentenderevocêdevesercapazde
entenderamaiorparteapenaslendo.
NãotenhamedodemexerumpoucocomesseCSSetentarmudaralgumascoisas.Sevocêquebraralgumacoisa,não
sepreocupe,vocêsemprepodedesfazê-lo!
Dequalquerforma,recomendamosquefaçaessecursoon-lineCodeacademyHTML&CSSCoursecomodeverdecasa
pós-workshopparaaprendertudooquevocêprecisasabersobrecomotornarseussitesmaisbonitoscomCSS.
Prontoparaopróximocapítulo?!:)
77
Estendendoostemplates
Estendendoostemplates
OutracoisaboaqueoDjangotempravocêéotemplateextending.Oqueissosignifica?Issosignificaquevocêpode
usarasmesmaspartesdoseuHTMLemdiferentespáginasdoseusite.
Dessaformavocênãoprecisaficarserepetindoemcadaarquivoquandoquiserusaramesmainformação/layout.Ese
vocêquisermudaralgumacoisanãoprecisafazerissoemtodotemplate,sóumavez!
Criartemplatebase
Umtemplatebaseéotemplatemaisbásicoquevocêestenderáemcadapáginadoseusite.
Vamoscriarumarquivo base.htmlnapasta blog/templates/blog/:
blog
└───templates
└───blog
base.html
post_list.html
Abra-oecopietudoqueestánoarquivo post_list.htmlpara base.html,dessejeito:
{%loadstaticfiles%}
<html>
<head>
<title>DjangoGirlsblog</title>
<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<linkhref='//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext'rel='stylesheet'type='text/css'
>
<linkrel="stylesheet"href="{%static'css/blog.css'%}">
</head>
<body>
<divclass="page-header">
<h1><ahref="/">DjangoGirlsBlog</a></h1>
</div>
<divclass="contentcontainer">
<divclass="row">
<divclass="col-md-8">
{%forpostinposts%}
<divclass="post">
<divclass="date">
{{post.published_date}}
</div>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{%endfor%}
</div>
</div>
</div>
</body>
</html>
Entãoem base.html,substituatodoseu <body>(tudoentre <body>e </body>)comisso:
78
Estendendoostemplates
<body>
<divclass="page-header">
<h1><ahref="/">DjangoGirlsBlog</a></h1>
</div>
<divclass="contentcontainer">
<divclass="row">
<divclass="col-md-8">
{%blockcontent%}
{%endblock%}
</div>
</div>
</div>
</body>
Basicamentenóssubstituimostudoentre {%forpostinposts%}{%endfor%}por:
{%blockcontent%}
{%endblock%}
Oqueissosignifica?Vocêacaboudecriarum block(bloco),queéumatagdetemplatequetepermiteinserirHTML
nesteblocoemoutrostemplatesqueestendem base.html.Nósvamostemostrarcomofazerissojájá.
Salveeabraoarquivo blog/templates/blog/post_list.htmlnovamente.Apagueexatamentetudoquenãoestiverdentro
datagbodyeapaguetambém <divclass="page-header"></div>,deformaqueoarquivofiquedaseguintemaneira:
{%forpostinposts%}
<divclass="post">
<divclass="date">
{{post.published_date}}
</div>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{%endfor%}
Agoraadicioneestalinhaaoiníciodoarquivo:
{%extends'blog/base.html'%}
Issosignificaque,agora,nósestamosestendendootemplate base.htmlem post_list.html.Umaúltimacoisa:colocar
tudo(excetopelalinhaqueacabamosdeadicionar)entre {%blockcontent%}e {%endblockcontent%}.Comoaseguir:
{%extends'blog/base.html'%}
{%blockcontent%}
{%forpostinposts%}
<divclass="post">
<divclass="date">
{{post.published_date}}
</div>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{%endfor%}
{%endblockcontent%}
Éisso!Vejaseoseusiteaindaestáfuncionandodireito:)
Seocorrerumerrode TemplateDoesNotExists,quedizquenãoexistenenhumarquivochamado blog/base.htmle
sevocêtivero runserverexecutandonoterminal,tentainterrompê-lo(precionandoCtrl+C-obotãoControlmaiso
botãoCjuntos)ereinicieelerodandoocomando pythonmanage.pyrunserver.
79
Estendendoostemplates
80
Ampliesuaaplicação
Ampliesuaaplicação
Jáconcluímostodosospassosnecessáriosparaacriaçãodonossosite:sabemoscomocriarummodelo,umaurl,uma
vieweumtemplate.Tambémsabemoscomomelhoraraaparênciadonossowebsite.
Horadepraticar!
Aprimeiracoisaqueprecisamosnonossoblogé,obviamente,umapáginaparamostrarumapostagem,certo?
Játemosummodelode Post,entãonãoprecisamosadicionarnadaao models.py.
Criarumlinknotemplate
Vamoscomeçarcomaadiçãodeumlinkdentrodoarquivo blog/templates/blog/post_list.html.Nestemomentoeledeve
separecercom:
{%extends'blog/base.html'%}
{%blockcontent%}
{%forpostinposts%}
<divclass="post">
<divclass="date">
{{post.published_date}}
</div>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{%endfor%}
{%endblockcontent%}
Queremosterumlinkparaumapáginadedetalhenotítulodopost.Vamostransformar <h1><href="">{{post.title
}}</a></h1>emumlink:
<h1><ahref="{%url'blog.views.post_detail'pk=post.pk%}">{{post.title}}</a></h1>
Tempoparaexplicaromisterioso {%url'blog.views.post_detail'pk=post.pk%}.Comovocêpodesuspeitar,anotação
de {%%}significaqueestamosusandoastagsdetemplatedoDjango.Destavezvamosusarumaquevaicriaruma
URLparanós!
blog.views.post_detailéumcaminhoparaum post_detailVistaquequeremoscriar.Presteatenção: blogéonome
dasuaaplicação(odiretório blog), viewsvemdonomedoarquivo views.pye,aúltimaparte- post_detail-éo
nomedaview.
Agoraquandoformospara:http://127.0.0.1:8000/teremosumerro(comoesperado,jáquenãotemosumaURLouuma
viewpara post_detail).Vaiseparecercomisso:
81
Ampliesuaaplicação
VamoscriaraURLem urls.pyparaanossa post_detailview!
URL:http://127.0.0.1:8000/post/1/
QueremoscriarumaURLparaguiaroDjangoparaaviewchamada post_detail,queirámostrarumpostcompletodo
blog.Adicionealinha url(r'^post/(?P<pk>[0-9]+)/$',views.post_detail),aoarquivo blog/urls.py.Deveficarassim:
fromdjango.conf.urlsimporturl
from.importviews
urlpatterns=[
url(r'^$',views.post_list),
url(r'^post/(?P<pk>[0-9]+)/$',views.post_detail),
]
Pareceassustador,masnãosepreocupe-vamosexplicareleparavocê:-começacom ^denovo..."oinício"- post/
significaapenasqueapósocomeço,daURLdeveterapalavraposte/.Atéaqui,tudobem.- (?P<pk>[0-9]+)-essa
parteémaiscomplicada.IssosignificaqueoDjangovailevartudoquevocêcolocaraquietransferirparaumaviewcomo
umavariávelchamada pk. [0-9]tambémnosdizquesópodeserumnúmero,nãoumaletra(tudoentre0e9). +
significaqueprecisaexistirumoumaisdígitos.Entãoalgocomo http://127.0.0.1:8000/post//nãoéválido,mas
http://127.0.0.1:8000/post/1234567890/éperfeitamenteok!- /-entãoprecisamosde/outravez- $-"ofim"!
Issosignificaquesevocêdigitar http://127.0.0.1:8000/post/5/emseunavegador,Djangovaientenderquevocêestá
procurandoumaviewchamada post_detailetransferirainformaçãodeque pkéiguala 5paraaquelaview.
pkéumaabreviaçãopara primarykey(chaveprimária).EssenomegeralmenteéusadonosprojetosfeitosemDjango.
Masvocêpodedaronomequequiseràsvariáveis(lembre-se:minúsculoe _aoinvésdeespaçosembranco!).Por
exemploemvezde (?P<pk>[0-9]+)podemosterumavariável post_id,entãoestaparteficariacomo: (?P<post_id>[09]+).
Razoável!Vamosatualizarapágina:http://127.0.0.1:8000/Boom!Aindaoutroerro!Comoesperado!
82
Ampliesuaaplicação
Vocêselembraqualéopróximopasso?Claro:adicionandoumaview!
post_detailview
Destavezanossaviewrecebeumparâmetroextra pk.Nossaviewprecisapegá-la,certo?Entãovamosdefinirnossa
funçãocomo defpost_detail(request,pk):.Observequeprecisamosusarexatamenteomesmonomeque
especificamosemurls( pk).Omitiressavariáveléerradoeresultaráemumerro!
Agoraqueremosreceberapenasumpostdoblog.Paraissopodemosusarquerysetscomoeste:
Post.objects.get(pk=pk)
Masestecódigotemumproblema.Senãohouvernenhum Postcoma chaveprimária( pk)fornecidateremosumerro
horroroso!
Nãoqueremosisso!Mas,claro,oDjangovemcomalgoquevailidarcomissoparanós: get_object_or_404.Casonão
hajanenhum Postcomodado pkexibiráumapáginamuitomaisagradável(chamada PageNotFound404-página
nãoencontrada).
83
Ampliesuaaplicação
Aboanotíciaéquevocêrealmentepodecriarsuaprópriapáginade Pagenotfoundetorná-lotãobonitaquantovocê
quiser.Masissonãoésuperimportanteagora,entãonósvamosignorá-la.
Ok,horadeadicionarumaviewaonossoarquivo views.py!
Devemosabrir blog/views.pyeadicionaroseguintecódigo:
fromdjango.shortcutsimportrender,get_object_or_404
Pertodeoutraslinhas from.Enofinaldoarquivo,adicionaremosanossaview:
defpost_detail(request,pk):
post=get_object_or_404(Post,pk=pk)
returnrender(request,'blog/post_detail.html',{'post':post})
Sim.Estánahoradeatualizarapágina:http://127.0.0.1:8000/
84
Ampliesuaaplicação
Funcionou!Masoqueacontecequandovocêclicaemumlinknotítulodopostdoblog?
Ahnão!Outroerro!Masnósjásabemoscomolidarcomisso,né?Precisamosadicionarumtemplate!
Vamoscriarumarquivoem blog/templates/blogchamado post_detail.html.
Seráalgoparecidocomisto:
85
Ampliesuaaplicação
{%extends'blog/base.html'%}
{%blockcontent%}
<divclass="post">
{%ifpost.published_date%}
<divclass="date">
{{post.published_date}}
</div>
{%endif%}
<h1>{{post.title}}</h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{%endblock%}
Maisumavezestamosestendendo base.html.Noblocode contentqueremosexibiropublished_date(datade
publicação)dopost(sehouver),títuloetexto.Masdevemosdiscutiralgumascoisasimportantes,certo?
{%if...%}...{%endif%}éumatagdetemplatequepodemosusarquandoqueremosverificaralgo(Lembre-se if
...else...docapítulointroduçãoaoPython?).Nestecenário,queremosverificarse published_datedeumpostnão
estávazia.
Ok,podemosatualizarnossapáginaeverse Pagenotfoundjásefoi.
Yay!Funciona!
Maisumacoisa:horadeimplantar!
SeriabomverseseusiteaindaestarátrabalhandoemPythonAnywhere,certo?Vamostentarfazerdeploynovamente.
$gitstatus
$gitadd--all.
$gitstatus
$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."
$gitpush
86
Ampliesuaaplicação
Então,emumconsolePythonAnywhereBash:
$cdmy-first-blog
$gitpull
Finalmente,puleparaaWebtabeaperteReload.
Edeveserisso!Parabéns:)
87
Formulários
Formulários
Porúltimoqueremosumaformalegaldeadicionareeditaraspostagensdonossoblog.A ferramentadeadministraçãodo
Djangoélegal,maselaéumpoucodifícildecustomizarededeixarmaisbonita.Seusarmos formuláriosteremos
controleabsolutosobrenossainterface-podemosfazerqualquercoisaqueimaginarmos!
UmacoisalegaldoDjangoéquenóspodemostantocriarumformuláriodozerocomopodemoscriarum ModelFormque
salvaoresultadodoformulárioparaumdeterminadomodelo.
Issoéexatamenteoquenósqueremosfazer:criaremosumformulárioparaonossomodelo Post.
AssimcomotodaparteimportantedoDjango,formstemseupróprioarquivo: forms.py.
Precisamoscriarumarquivocomestenomedentrodapasta blog.
blog
└──forms.py
Ok,vamosabri-loeescreverneleoseguinte:
fromdjangoimportforms
from.modelsimportPost
classPostForm(forms.ModelForm):
classMeta:
model=Post
fields=('title','text',)
PrimeiroprecisamosimportaromódulodeformuláriosdoDjango( fromdjangoimportforms)e,obviamente,nosso
modelo Post( from.modelsimportPost).
PostForm,comovocêjádevesuspeitar,éonomedonossoformulário.PrecisamosdizeraoDjangoqueesteformulárioé
um ModelForm(assimoDjangopodefazeramágicapragente)-o forms.ModelForméoresponsávelporisso.
Segundo,nóstemosaclasse MetaondedizemosaoDjangoqualmodelodeveriaserusadoparacriaresteformulário
( model=Post).
Finalmente,nóspodemosdizerqual(is)campo(s)deveriamentraremnossoformulário.Nessecenárionósqueremos
apenaso titlee textparaserexposto- authordeveriaserapessoaqueestálogadanosistema(nessecaso,você!)
e created_datedeveriasersetadoautomaticamentequandonóscriamosumpost(nocódigo),correto?
Eéissoaí!Tudooqueprecisamosfazeragoraéusaroformulárioemumaviewemostrá-loemumtemplate.
Então,maisumavez,nósiremoscriar:umlinkparaapágina,umaURL,umavieweumtemplate.
Linkparaapáginacomoformulário
Éhoradeabrir blog/templates/blog/base.html.Nósiremosadicionarumlinkem divnomeado page-header:
<ahref="{%url'blog.views.post_new'%}"class="top-menu"><spanclass="glyphiconglyphicon-plus"></span></a>
Notequenósqueremoschamarnossanovavisão post_new.
Depoisdeadicionaralinha,seuhtmldeveseparecercomisso:
88
Formulários
{%loadstaticfiles%}
<html>
<head>
<title>DjangoGirlsblog</title>
<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<linkhref='//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext'rel='stylesheet'type='text/css'
>
<linkrel="stylesheet"href="{%static'css/blog.css'%}">
</head>
<body>
<divclass="page-header">
<ahref="{%url'blog.views.post_new'%}"class="top-menu"><spanclass="glyphiconglyphicon-plus"></span>
</a>
<h1><ahref="/">DjangoGirlsBlog</a></h1>
</div>
<divclass="contentcontainer">
<divclass="row">
<divclass="col-md-8">
{%blockcontent%}
{%endblock%}
</div>
</div>
</div>
</body>
</html>
Depoisdesalvarerecarregarapágina http://127.0.0.1:8000vocêverá,obviamente,umerrofamiliar NoReverseMatch
certo?
URL
Vamosabriroarquivo blog/urls.pyeescrever:
url(r'^post/new/$',views.post_new,name='post_new'),
Ocódigofinaldeveseparecercomisso:
fromdjango.conf.urlsimporturl
from.importviews
urlpatterns=[
url(r'^$',views.post_list),
url(r'^post/(?P<pk>[0-9]+)/$',views.post_detail),
url(r'^post/new/$',views.post_new,name='post_new'),
]
Apósrecarregarosite,nósveremosum AttributeError,desdequenósnãotemosavisão post_newimplementada.
Vamosadicioná-laagora.
post_newview
Horadeabriroarquivo blog/views.pyeadicionaraslinhasseguintescomorestodaslinhas from:
from.formsimportPostForm
enossaview:
89
Formulários
defpost_new(request):
form=PostForm()
returnrender(request,'blog/post_edit.html',{'form':form})
Paracriarumnovoformulario Post,nósdevemoschamar PostForm()epassá-loparaotemplate.Nósiremosvoltar
paraestaview,masporagoravamoscriarrapidamenteumtemplateparaoformulário.
Template(modelos)
Precisamoscriarumarquivo post_edit.htmlnapasta blog/templates/blog.Prafazeroformuláriofuncionarprecisamos
demuitascoisas:
Temosqueexibiroformulário.Podemosfazerissosimplesmentecomum``.
AlinhaacimaprecisaestardentrodeumatagHTMLform: <formmethod="POST">...</form>
Precisamosdeumbotão Salvar.FazemosissocomumbotãoHTML: <buttontype="submit">Save</button>
Efinalmente,depoisdeabriratag <form...>precisamosadicionarum {%csrf_token%}.Issoémuitoimportante,
poiséissoquefazonossoformulárioficarseguro!ODJangovaireclamarsevocêesquecerdeadicionarissoe
simplesmentesalvaroformulário:
Beleza,entãovamosvercomoficouoHTML post_edit.html:
{%extends'blog/base.html'%}
{%blockcontent%}
<h1>Newpost</h1>
<formmethod="POST"class="post-form">{%csrf_token%}
{{form.as_p}}
<buttontype="submit"class="savebtnbtn-default">Guardar</button>
</form>
{%endblock%}
Horadeatualizar!Há!Seuformulárioapareceu!
90
Formulários
Mas,espereumminuto!Quandovocêdigitaalgumacoisanoscampos titlee textetentasalvaroqueacontece?
Nada!Estamosnovamentenamesmapáginaenossotextosumiu...Enenhumpostfoiadicionado.Entãooquedeu
errado?
Arespostaé:nada.Precisamostrabalharumpoucomaisnanossaview.
Salvandooformulário
Abra blog/views.pymaisumavez.Atualmentetudoquetemosnavisão post_newé:
defpost_new(request):
form=PostForm()
returnrender(request,'blog/post_edit.html',{'form':form})
Quandonósenviamosoformulário,somostrazidosdevoltaparaamesmavisão,masdestaveztemosmaisalgunsdados
no request,maisespecificamenteem request.POST(onomenãotemnadacom"post"deblog,temavercomofatode
queestamos"postando"dados).VocêselembraquenoarquivoHTMLnossadefiniçãode <form>temavariável
method="POST"?Todososcamposvindosdo"form"estarãodisponíveisagoraem request.POST.Vocênãodeveria
renomear POSTparanadadiferentedisso(oúnicooutrovalorválidopara methodé GET,masnósnãotemostempo
paraexplicarqualéadiferença).
Entãonanossaviewnóstemosduassituaçõesseparadasparalidar.Aprimeiraéquantoacessamosapáginapela
primeiravezequeremosumformulárioembranco.Easegunda,équandonóstemosquevoltarparaaviewcomtodosos
dadosdoformulárioquenósdigitamos.Dessemodo,precisamosadicionarumacondição(usaremos ifparaisso).
91
Formulários
ifrequest.method=="POST":
[...]
else:
form=PostForm()
Estánahoradepreencherospontos [...].Se methodé POSTentãonósqueremosconstruiro PostFormcomos
dadosqueveemdoformulário,certo?Nósiremosfazerassim:
form=PostForm(request.POST)
Fácil!Próximacoisaéverificarseoformulárioestácorreto(todososcamposrequeridossãodefinidosevaloresincorretos
nãoserãosalvos).Fazemosissocom form.is_valid().
Verificamosseoformulárioéválidoeseestivertudocerto,podemossalvá-lo!
ifform.is_valid():
post=form.save(commit=False)
post.author=request.user
post.published_date=timezone.now()
post.save()
Basicamente,temosduascoisasaqui:Salvamosoformuláriocom form.saveeadicionadosumautor(desdequenãohaja
ocampo authorem PostForm,eestecampoéobrigatório!). commit=Falsesignificaquenãoqueremossalvaromodelo
Postainda-queremosadicionarautorprimeiro.Namaioriadasvezesvocêiráusar form.save(),sem commit=False,
masnestecaso,precisamosfazerisso. post.save()irápreservarasalterações(adicionandoautor)eécriadoumnovo
postnoblog!
Finalmente,nãoseriafantásticosenóspudéssemosimediatamenteiràpáginade post_detailparaorecém-criadoblog
post,certo?Parafazerissonósprecisaremosdemaisumaimportação:
fromdjango.shortcutsimportredirect
Adicione-ologonoiníciodoseuarquivo.Eagorapodemosdizer:váparaapágina post_detailparaumrecém-criado
post.
returnredirect('blog.views.post_detail',pk=post.pk)
blog.views.post_detailéonomedaviewquequeremosir.Lembre-sequeessaviewexigeumavariável pk?Para
passarissonas viewsusamos pk=post.pk,ondepostéorecém-criadoblogpost.
Ok,nósfalamosmuito,masprovavelmentequeremosveroquetodaaviewirápareceragora,certo?
defpost_new(request):
ifrequest.method=="POST":
form=PostForm(request.POST)
ifform.is_valid():
post=form.save(commit=False)
post.author=request.user
post.published_date=timezone.now()
post.save()
returnredirect('blog.views.post_detail',pk=post.pk)
else:
form=PostForm()
returnrender(request,'blog/post_edit.html',{'form':form})
Vamosversefunciona.Váparaopáginahttp://127.0.0.1:8000/post/new/,adicioneum titleeo text,salve...evoilà!O
novoblogpostéadicionadoenóssomosredirecionadosparaapáginade post_detail!
92
Formulários
Vocêprovavelmentenotouquenósnãoestamosdefinindoadatadepublicaçãoemtudo.Vamosintroduzirumbotãode
publicaçãoemDjangoGirlsTutorial:Extensões.
Issoéincrível!
Validaçãodeformulários
Agora,nóslhemostraremoscomoosfórmulariossãolegais.Opostdoblogprecisateroscampos titlee text.Em
nossomodelo Postnãodissemos(emoposiçãoa published_date)queessescamposnãosãonecessários,então
Django,porpadrão,espera-osaserdefinido.
Tentesalvaroformuláriosem titlee text.Adivinheoquevaiacontecer!
Djangoestátomandocontadevalidarsetodososcamposdenossoformulárioestãocorretos.Nãoéincrível?
ComorecentementeusamosainterfacedeadministraçãodoDjangoosistemaentendequeestamoslogados.
Existemalgumassituaçõesquepoderiamlevarasermosdeslogadosdosistema(fecharonavegador,reiniciar
bancodedadosetc.).Sevocêperceberqueerrosestãoaparecendoaocriarumpostquereferenciaumusuário
quenãoestálogado,váparaapáginaadminhttp://127.0.0.1:8000eloguenovamente.Issovairesolveroproblema
temporariamente.Háumajustepermanenteesperandoporvocêemliçãodecasa:adicionarsegurançanoseu
site!,capítuloapósotutorialprincipal.
93
Formulários
Editandooformulário
Agorasabemoscomoadicionarumnovoformulário.Masesequisermoseditarumjáexistente?Émuitosemelhanteao
quefizemos.Vamoscriaralgumascoisasimportantesrapidamente(sevocênãoentenderalgumacoisa-vocêdeve
perguntaraseuprofessorouvejaoscapítulosanteriores,jácobrimostodasessasetapasanteriormente).
Abra blog/templates/blog/post_detail.htmleadicionealinha:
<aclass="btnbtn-default"href="{%url'post_edit'pk=post.pk%}"><spanclass="glyphiconglyphicon-pencil"></span></a
>
Agoraomodeloestaráparecidocom:
{%extends'blog/base.html'%}
{%blockcontent%}
<divclass="date">
{%ifpost.published_date%}
{{post.published_date}}
{%endif%}
<aclass="btnbtn-default"href="{%url'post_edit'pk=post.pk%}"><spanclass="glyphiconglyphicon-pencil"></span
></a>
</div>
<h1>{{post.title}}</h1>
<p>{{post.text|linebreaksbr}}</p>
{%endblock%}
Em blog/urls.pyadicionamosestalinha:
url(r'^post/(?P<pk>[0-9]+)/edit/$',views.post_edit,name='post_edit'),
Nósreutilizaremosomodelo blog/templates/blog/post_edit.html,entãoaúltimacoisaquefaltaéumaview.
Vamosabrir blog/views.pyeadicionarnofinaldoarquivo:
defpost_edit(request,pk):
post=get_object_or_404(Post,pk=pk)
ifrequest.method=="POST":
form=PostForm(request.POST,instance=post)
ifform.is_valid():
post=form.save(commit=False)
post.author=request.user
post.published_date=timezone.now()
post.save()
returnredirect('blog.views.post_detail',pk=post.pk)
else:
form=PostForm(instance=post)
returnrender(request,'blog/post_edit.html',{'form':form})
94
Formulários
Issoéquaseexatamenteigualanossaviewde post_new,certo?Masnãototalmente.Primeiracoisa:passamosum
parâmetroextradaurl pk.Emseguida:pegamosomodelo Postquequeremoseditarcom get_object_or_404(Post,
pk=pk)eentão,quandocriamosumformuláriopassamosestepostcomouma instância,tantoquandosalvamoso
formulário:
form=PostForm(request.POST,instance=post)
comoquandonósapenasabrimosumformuláriocomestepostparaeditar:
form=PostForm(instance=post)
Ok,vamostestarsefunciona!Vamosparaapágina post_detail.Devehaverumbotãoeditarnocantosuperiordireito:
Quandovocêclicarnelevocêveráoformuláriocomanossapostagem:
95
Formulários
Sinta-selivreparamudarotítuloouotextoesalvarasmudanças!
Parabéns!Suaaplicaçãoestáficandocadavezmaiscompleta!
SevocêprecisardemaisinformaçõessobreformuláriosdoDjangovocêdeveleradocumentação:
https://docs.djangoproject.com/en/1.8/topics/forms/
Maisumacoisa:horadeimplantar!
VamosversetudoissofuncionanaPythonAnywhere.Tempoparaoutrodeploy!
Primeiro,commitoseunovocódigoecoloquenoGithub
$gitstatus
$gitadd--all.
$gitstatus
$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."
$gitpush
Então,emumconsolePythonAnywhereBash:
$cdmy-first-blog
$gitpull
Finalmente,puleparaaWebtabeaperteReload.
Edeveserisso!Parabéns:)
96
Formulários
97
Domínio
Domínio
PythonAnywheretedeuumdomíniogratuito,mastalvezvocênãoqueirater".pythonanywhere.com"nofinaldaURLdo
seublog.Talvezvocêqueiraseublogapenas"www.infinite-kitten-pictures.org"ou"www.3d-printed-steam-engineparts.com"ou"www.antique-buttons.com"ou"www.mutant-unicornz.net",ousejaoquevaiser.
Aquivamosfalarumpoucosobreondeobterumdomínioecomoligá-loaseuaplicativodawebemPythonAnywhere.No
entanto,vocêdevesaberqueamaioriadosdomínioscustamdinheiroePythonAnyweretambémcobraumataxamensal
parausarseupróprionomededomínio--nãoémuitodinheiro,nototal,masissoprovavelmenteéalgoquevocêsóquer
fazersevocêestárealmentecomprometido!
Onderegistrarumdomínio?
Umdomínionormalcustamaisoumenos15dólaresporano.Existemdomíniosmaiscarosemaisbaratosdependendo
doprovedor.Existemumasériedeempresasdasquaisvocêpodecomprarumdomínio:umasimplespesquisanogoogle
podelistarumasériedelas.
OnossofavoritoéoIwantmyname(euqueromeunome).Elesanunciamseuserviçocomo"gestãodedomínioindolor",
eele,realmente,éindolor.
Vocêtambémpodeobterdomíniosgratuitamente.dot.tkéumlugarparapegarum,masvocêdeveestarcientedeque
domíniosgrátisàsvezesparecemmuitobaratos--seseusitevaiserparaumprofissionaldenegócios,vocêdevepensar
empagarporumdomínio"correto"queterminaem .com.
ComoapontarseudomínionoPythonAnywhere
Sevocêpassouporiwantmyname.com,cliqueem domíniosnomenueescolhaseudomíniorecém-adquirido.Em
seguida,localizeecliquenolink manageDNSrecords:
Agoravocêprecisalocalizaresteformulário:
Epreenchercomosseguintesdetalhes:-Hostname:www-tipo:CNAME-valor:seudomíniodePythonAnywhere(por
exemplodjangogirls.pythonanywhere.com)-TTL:60
CliquenobotãoAdicionaresalveasmudançasnapartedebaixo.
NotaSevocêusouumprovedordedomíniodiferente,oUIexataparaencontraroseuDNS/configuraçõesde
CNAMEserádiferente,masseuobjetivoéomesmo:paraconfigurarumCNAMEqueapontaseunovodomíniono
yourusername.pythonanywhere.com.
98
Domínio
Podelevaralgunsminutosparaoseudomíniocomeçaratrabalhar,entãosejapaciente!
Configureodomínioatravésdeumwebappna
PythonAnywhere.
VocêtambémprecisadizerPythonAnywherequevocêdesejausaroseudomíniopersonalizado.
VáparaapáginaPythonAnywherecontaseupgradesuaconta.Aopçãomaisbarata(umplanode"Hacker")ébompara
começar,vocêpodesempreatualizá-lomaistardequandovocêficarsuperfamosoetivermilhõesdeacessos.
Emseguida,vánaWebtabeanotealgumascoisas:
Copieocaminhoparaseuvirtualenvecoloqueemumlugarseguro
Cliqueparaseuarquivodeconfiguraçãodowsgi,copieoconteúdoecoleemumlugarseguro.
Emseguida,excluaseuantigowebapp.Nãosepreocupe,issonãovaiexcluirnadadoseucódigo,eleapenasiráse
desligardodomínioyourusername.pythonanywhere.com.Emseguida,crieumnovoaplicativowebesigaestespassos:
Digiteseunomededomínionovo
Escolha"manualconfiguration"
EscolhaPython3.4
Eéisso!
Quandovocêtivervoltadoparaawebtab.
Colarocaminhovirtualenvquevocêsalvouantes
Clicarnoarquivodeconfiguraçãowsgiecolaroconteúdodoseuarquivodeconfiguraçãoantigo
Cliqueemreloadwebappevocêdeveencontrarseusitelivenonovodomínio!
Sevocêtiverqualquerproblema,cliquenolink"Enviarfeedback"nositePythonAnywhere,eumdosseusadministradores
amigáveisvaiestarláparaajudá-lo.
99
Oquevemdepois?
Oquevemdepois?
Parabéns!Vocêédemais.Estamosorgulhosos!<3
Oquefazeragora?
Façaumapausaerelaxe.Vocêacaboudefazeralgorealmentegrande.
Depoisdisso:
SigaDjangogirlsnoFacebookouTwitterparaficaratualizada
Vocêpoderecomendaroutrasfontes?
Sim!Primeiro,váemfrenteetentenossooutrolivro,chamadoDjangoGirlsTutorial:Extensions.
Depoisvocêpodetentarasfonteslistadasabaixo.Todaselassãorecomendadas!
Django'sofficialtutorial
NewCodertutorials
CodeAcademyPythoncourse
CodeAcademyHTML&CSScourse
DjangoCarrotstutorial
LearnPythonTheHardWaybook
GettingStartedWithDjangovideolessons
TwoScoopsofDjango:BestPracticesforDjangobook
100
Download