0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
TabeladeconteúdosIntrodução
Comofuncionaainternet?
Introduçãoàlinhadecomando
InstalaçãodoPython
EditordeCódigo
IntroduçãoaoPython
OqueéDjango?
InstalaçãodoDjango
Criandoumprojeto
ModelosdoDjango
Administração
Implantação!
Urls
Views-horadecriar!
IntroduçãoaHTML
DjangoORM(Querysets)
Dadosdinâmicosnostemplates
Templates
CSS-Deixemaisbonito
Estendendoostemplates
Ampliesuaaplicação
Formulários
Domínio
Oquevemdepois?
DjangoGirlsTutorial
2
TutorialDjangoGirls
EstetrabalhoélicenciadosobalicençaCreativeCommonsAttribution-ShareAlike4.0.Paraverumacópiadestalicença,visitehttp://creativecommons.org/licenses/by-sa/4.0/
TranslationThistutorialhasbeentranslatedfromEnglishtoPortuguesebyagroupofawesomevolunteers.SpecialthanksforhelpgoesouttoWillieLawrence,VivianMacedo,CleitonLima,danieltex,LeandroSilvaAraujo,AdailtondoNascimento,PabloPalacios,PauloAlem,EricHideki,JoaoLuizLorencetti,clemente.jnr,LeonardoAlvesdosSantos,joepreludian,GabrielaCavalcantedaSilve,RafaelBiagionideFazio,FabioC.BarrionuevodaLuz,ffabiorj,LucasMagnum,1pedro,AdjamiltonJunior,LeandroBarbosa,KleberCPinheiro,KatyannaMoura,AnnandaSousa,FlavioBarros,MarcelRibeiroDantas,AdamVictorNazarethBrandizzi,BernardoFontes,AntonioLuis,RaonyGuimaresCorreodoCarmoLisboaCardenas,CamillaAchuttiandCarlaSuarez.Wow!<3<3
IntroduçãoVocêjásentiucomoseomundofossecadavezmaissobretecnologiaequedealgumaformavocêtenhaficadopratrás?Vocêjáimaginoucomoseriacriarumwebsitemasnuncatevemotivaçãosuficienteparacomeçar?Vocêjápensouqueomundodosoftwareécomplicadodemaisatéparatentarfazeralgumacoisasozinho?
Bem,nóstemosboasnotíciasparavocê!Programaçãonãoétãodifícilquantopareceenósqueremostemostraroquãodivertidopodeser.
Estetutorialnãoirátetransformarmagicamenteemumprogramador.Sevocêquerserbomnissoprecisademesesouatémesmoanosdetreinoeprática.Masnósqueremostemostrarqueaprogramaçãooucriaçãodewebsitesnãoétãocomplicadaquantoparece.Nóstentaremosexplicarosdiferentespedaçostãobemquantopudermos,talquevocênãosesintaintimidadopelatecnologia.
Nósesperamosconseguirfazervocêamaratecnologiatantoquantonósamamos!
Oquevocêiráaprenderduranteotutorial?
DjangoGirlsTutorial
3Introdução
Quandovocêtiverterminadootutorialvocêteráumaaplicaçãowebsimplesefuncional:seupróprioblog.Nósvamosmostrarcomocolocá-loonline,paraqueoutrosvejamseutrabalho!
Eleseparecerá(maisoumenos)comisso:
Sevocêseguirotutorialporcontaprópriaenãotiverumtreinadorparaajudaremcasodequalquerproblema,nóstemosumchatparavocê: 1.Nóspedimosaosnossostreinadoreseparticipantesanterioresparaacessaremládetemposemtemposeajudaremoutroscomotutorial!Nãotenhamedodefazersuaperguntalá!
OK,vamospelocomeço...
SobreotutorialecontribuiçõesEstetutorialémantidoporDjangoGirls.Sevocêencontrarquaisquererrosouquiseratualizarotutorial,porfavorsigaasorientaçõesdecontribuição.
DjangoGirlsTutorial
4Introdução
Gostariadenosajudaratraduzirotutorialparaoutrosidiomas?nomomento,astraduçõesestãosendomantidasnaplataformacrowdin.comem:
https://crowdin.com/project/django-girls-tutorial
Seoseuidiomanãoestálistadonocrowdin,porfavoropenanewissueinformandooidiomaparaquepossamosadicioná-lo.
DjangoGirlsTutorial
5Introdução
ComofuncionaainternetEstecapítuloéinspiradonapalestra"ComoaInternetfunciona"deJessicaMcKellar(http://web.mit.edu/jesstess/www/).
ApostamosquevocêusaaInternettodososdias.Masvocêsaberealmenteoqueacontecequandovocêdigitaumendereçocomohttp://djangogirls.orgemseunavegadorepressiona'Enter'?
Aprimeiracoisaquevocêprecisaentenderéqueumsiteésóummontedearquivossalvosemumdiscorígido.Assimcomoseusfilmes,músicasoufotos.Noentanto,háumapartequeéexclusivaparasites:essaparteincluicódigosdecomputadorchamadoHTML.
Sevocênãoestiverfamiliarizadacomaprogramação,podeserdifícilcompreenderoHTMLnocomeço,masseusnavegadoresdaweb(comooChrome,Safari,Firefox,etc)amamele.NavegadoresdaWebsãoprojetadosparaentenderessecódigo,seguirsuasinstruçõeseapresentartodosessesarquivosdequeseusiteéfeitoexatamentedojeitoquevocêquerqueelessejamapresentados.
Igualàtodososarquivos,osarquivosHTMLprecisamserarmazenadosnumdiscorígido.Prainternetnósusamospoderososcomputadoresespeciaischamadosservidores.Elesnãotêmumatela,omouseouoteclado,porquesuafinalidadeprincipaléparaarmazenardadoseservi-los.Éporissoqueelessãochamadosdeservidores..--porqueelesservemavocê,dados.
OK,masvocêquersabercomoquêainternetseparece,certo?
Fizemosumdesenhopravocê!Veja:
DjangoGirlsTutorial
6Comofuncionaainternet?
Quebagunçané?Naverdadeéumarededemáquinasconectadas(osservidoresmencionadosacima).Centenasdemilharesdemáquinas!Muitos,muitosquilômetrosdecabosemtodoomundo!Paraverquãocomplicadaainternetévocêpodevisitarumsite(http://submarinecablemap.com/)quemostraummapacomoscabossubmarinos.Aquiestáumscreenshotdosite:
DjangoGirlsTutorial
7Comofuncionaainternet?
Fascinante,não?Mas,obviamente,nãoépossívelterumfioconectadoatodamáquinaligadanainternet.Logo,parachegaremumamáquina(porexemploaquelaondehttp://djangogirls.orgestásalva)nósprecisamospassarumarequisiçãopormuitasmáquinasdiferentes.
Separececomisso:
Imaginequequandovocêdigitahttp://djangogirls.orgvocêenviaumacartaquediz:"QueridoDjangoGirls,eudesejoverositedjangogirls.org.Envieelepramim,porfavor!"
Suacartavaiparaaagênciadoscorreiosmaispróximadevocê.Depoisvaiparaoutraqueéumpoucomaispertodoseudestinatário,depoisparaoutraeoutraatéquesejaentregueaoseudestino.Oúnicodiferencialéquesevocêenviarcartas(pacotesdedados)comfreqüênciaparaomesmolugar,cadacartapodepassarpordiferentesagênciasdecorreios(roteadores),dependendodecomoelassãodistribuídasemcadaagência.
DjangoGirlsTutorial
8Comofuncionaainternet?
Sim,ésimplesassim.Vocêenviamensagenseesperaalgumaresposta.Claro,aoinvésdepapelecanetavocêusabytesdedados,masaideiaéamesma!
Aoinvésdeendereçoscomonomedarua,cidade,códigopostalenomedopaís,nósusamosendereçosIP.PrimeiroseucomputadorperguntapeloDNS(DomainNameSystem-SistemadeNomedeDomínio)paratraduzirdjangogirls.orgparaumendereçoIP.Ofuncionamentodelesepareceumpoucocomasantigaslistastelefônicasondevocêpodeolharparaonomedapessoaquequerentraremcontatoeacharoseunúmerodetelefoneeendereço.
Quandovocêenviaumacarta,elaprecisatercertascaracterísticasparaserentreguecorretamente:umendereço,selo,etc.Vocêtambémusaumalinguagemqueoreceptadorcompreende,certo?Omesmoacontececompacotesdedadosquevocêenviaparaverumsite:vocêusaumprotocolochamadoHTTP(HypertextTransferProtocol-ProtocolodeTransferênciadeHipertexto).
Então,basicamente,quandovocêtemumsitevocêprecisaterumservidor(máquina)ondeeleficahospedado.Oservidorestáàesperadequaisquerrequisiçõesrecebidas(cartasquesolicitamaoservidoroenviodoseusite)eeleenviadevoltaseusite(emoutracarta).
ComoesteéumtutorialdeDjangovocêvaiperguntaroqueoDjangofaz.Quandoenviaumarespostanemsemprevocêquerenviaramesmacoisaparatodomundo.Émuitomelhorsesuascartassãopersonalizadas,especialmenteparaapessoaqueacaboude
DjangoGirlsTutorial
9Comofuncionaainternet?
escreverparavocê,certo?ODjangoajudavocêacriaressaspersonalizadaseinteressantescartas:).
Chegadefalar,éhoradecriar!
DjangoGirlsTutorial
10Comofuncionaainternet?
IntroduçãoàlinhadecomandoÉemocionante,não?!Vocêvaiescreversuaprimeiralinhadecódigoempoucosminutos:)
Deixe-nosapresentá-loaoseuprimeironovoamigo:alinhadecomando!
Asetapasaseguirmostrarãoavocêcomousarajanelapretaquetodososhackersusam.Podeparecerumpoucoassustadornocomeço,masrealmenteéapenasumpromptesperandoporcomandosdevocê.
Qualéalinhadecomando?Ajanela,quenormalmenteéchamadadelinhadecomandoouinterfacedelinhadecomando,éumaplicativobaseadoemtextoparavisualização,manipulaçãoemanuseiodearquivosemseucomputador(comoporexemplo,oWindowsExplorerouoFindernoMac,masseminterfacegráfica).Outrosnomesparaalinhadecomandosão:cmd,CLI,prompt,consoleouterminal.
AbraainterfacedelinhadecomandoParacomeçaralgunsexperimentos,precisamosabriranossainterfacedelinhadecomandoprimeiro.
Windows
VáemIniciar→TodososProgramas→Acessórios→Promptdecomando.
MacOSX
Applications→Utilities→Terminal.
Linux
ProvavelmentevocêvaiacharemApplications→Accessories→Terminal,masissodependedoseusistemaoperacional.QualquercoisaésóprocurarnoGoogle:)
Prompt
DjangoGirlsTutorial
11Introduçãoàlinhadecomando
Agoravocêdeveverumajanelabrancaoupretaqueestáàesperadeseuscomandos.
SevocêestiveremMacounumLinux,vocêprovavelmenteveráum``$,comoeste:
$
NoWindows,éumsinalde>,comoeste:
>
Cadacomandoseráantecedidoporestesinaleumespaço,masvocênãoprecisadigitá-lo.Seucomputadorfaráissoporvocê:)
Apenasumapequenanota:noseucaso,talvezháalgocomoC:\Users\ola>ouOlas-MacBookAir:~ola$antesdosinaldopromptistoestará100%correto.Nestetutorialnósapenassimplificaremoseleparaomínimo.
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
DjangoGirlsTutorial
12Introduçãoàlinhadecomando
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çanapastaHome.
Nota:'pwd'significa'printworkingdirectory'.
Listandoarquivosepastas
Entãooquetemnele?Serialegaldescobrir.Vamosver:
$ls
Applications
Desktop
Downloads
Music
...
Windows:
>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
...
DjangoGirlsTutorial
13Introduçãoàlinhadecomando
Entraremoutrapasta
TalvezagentequeiraentrarnanossapastaDesktop?
$cdDesktop
Windows:
>cdDesktop
Vejaserealmenteentramosnapasta:
$pwd
/Users/olasitarska/Desktop
Windows:
>cd
C:\Users\olasitarska\Desktop
Aquiestá!
Dicadeprofissional:sevocêdigitarcdDeapertarateclatabnoseuteclado,alinhadecomandoirápreencherautomaticamenteorestodonomeparaquevocêpossanavegarrapidamente.Sehouvermaisdeumapastaquecomececom"D",aperteateclatabduasvezesparaobterumalistadeopções.
Criandoumapasta
QuetalcriarumdiretórioDjangoGirlsnasuaáreadetrabalho?Vocêpodefazerassim:
$mkdirdjangogirls
Windows:
>mkdirdjangogirls
DjangoGirlsTutorial
14Introduçãoàlinhadecomando
Estecomandovaicriarumapastacomonomedjangogirlsnonossodesktop.Vocêpodeverificarseeleestálá,sódeolharnasuaáreadetrabalhoouexecutandoumcomandols/dir!Experimente:)
Dicadeprofissional:Sevocênãoquiserdigitaromesmocomandováriasvezes,tentepressionarsetaparacimaesetaparabaixonotecladoparapercorrercomandosusadosrecentemente.
Exercite-se!
Umpequenodesafioparavocê:nasuamaisnovapastacriadadjangogirlscrieumaoutrapastachamadateste.Useoscomandoscdemkdir.
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:
DjangoGirlsTutorial
15Introduçãoàlinhadecomando
>cd..
Fazendocdpara..nósmudaremosdodiretórioatualparaodiretóriopai(quesignificaodiretórioquecontémodiretórioatual).
Vejaondevocêestá:
$pwd
/Users/olasitarska/Desktop
Windows:
>cd
C:\Users\olasitarska\Desktop
Agoraéhoradeexcluirodiretóriodjangogirls.
Atenção:Aexclusãodearquivosusandodel,rmdirourméirrecuperável,significandoArquivosexcluídosvãoemboraparasempre!Então,tenhacuidadocomestecomando.
$rm-rdjangogirls
Windows:
>rmdir/Sdjangogirls
djangogirls,Temcerteza<S/N>?S
Pronto!Paratercertezaqueapastafoiexcluída,vamoschecar:
$ls
Windows:
>dir
Saindo
Porenquantoéisso!Agoravocêfecharalinhadecomandocomsegurança.Vamosfazerdojeitohacker,certo?:)
DjangoGirlsTutorial
16Introduçãoàlinhadecomando
$exit
Windows:
>exit
Legal,né?:)
SumárioAquivaiumalistadealgunscomandosúteis:
Comando(Windows)
Comando(MacOS/Linux) Descrição Exemplo
exit exit Fechaajanela exit
cd cd Mudaapasta cdtest
dir ls Listaaspastaseosarquivos dir
copy cp Copiaumarquivo copyc:\test\test.txtc:\windows\test.txt
move mv Moveumarquivo movec:\test\test.txtc:\windows\test.txt
mkdir mkdir Criaumapasta mkdirtestdirectory
del rm Deletaumapastae/ouarquivo delc:\test\test.txt
Estessãoapenasalgunsdospoucoscomandosquevocêpodeexecutaremsualinhadecomando,masvocênãovaiusarmaisnadadoqueistohoje.
Sevocêestivercurioso,ss64.comcontémumareferênciacompletadecomandosparatodosossistemasoperacionais.
Pronto?VamosmergulharnoPython!
DjangoGirlsTutorial
17Introduçãoàlinhadecomando
VamoscomeçarcomPythonFinalmentechegamosaqui!
Masprimeiro,vamosfalarumpoucosobreoqueoPythoné.Pythonéumalinguagemdeprogramaçãomuitopopularquepodeserusadaparacriarsites,jogos,softwarescientíficos,gráficosemuito,muitomais.
OPythonéorigináriodadécadade1980eseuprincipalobjetivoéserlegívelporsereshumanos(nãoapenasmáquinas!),porissoeleparecemuitomaissimplesdoqueoutraslinguagensdeprogramação.Issofazelemaisfácildeaprender,masnãoseengane,Pythontambémémuitopoderoso!
InstalaçãodoPythonEstesubcapítuloébaseadoemumtutorialcriadoporGeekGirlsCarrots(http://django.carrots.pl/)
DjangoéescritoemPython.NóprecisamosdeleparafazerqualquercoisaemDjango.Vamoscomeçarcomsuainstalação!NósqueremosquevocêinstaleoPython3.4,entãosevocêtemqualquerversãoanterior,vocêvaiprecisaratualizá-la.
Windows
VocêpodebaixaroPythonparaWindowsnowebsitehttps://www.python.org/downloads/release/python-343/.Depoisdefazerodownloaddoarquivo*.msi,vocêprecisaexecutá-lo(dandoumduplo-cliquenele)eseguirasinstruções.Éimportantelembrarocaminho(apasta)ondevocêinstalouoPython.Elaseráútildepois!
Cuidadocomumacoisa:nasegundateladoassistentedeinstalação,marcado"Customize",certifique-sevocêrolarparabaixoeescolhaaopção"Adicionarpython.exeparaocaminho",comoem
DjangoGirlsTutorial
18InstalaçãodoPython
Linux
ÉmuitoprovávelquevocêjátenhaoPythoninstaladoeconfigurado.Paratercertezaseeleestáinstalado(equalasuaversão),abraumterminaledigiteoseguintecomando:
$python3--version
Python3.4.2
SevocênãotemoPythoninstaladoouquerumaversãodiferente,vocêpodeinstalá-lodaseguintemaneira:
Ubuntu
Digiteoseguintecomandonoterminal:
sudoapt-getinstallpython3.4
Fedora
Useoseguintecomandonoterminal:
DjangoGirlsTutorial
19InstalaçãodoPython
sudoyuminstallpython3.4
OSX
Vocêprecisaacessarositehttps://www.python.org/downloads/release/python-342/ebaixaroinstaladordoPython:
downloaddoinstaladorMacOSX64-bit/32-bitDMG,Dêumduplo-cliqueparaabri-lo,Dêumduplo-cliquenoPython.mpkgparaexecutaroinstalador.
VerifiqueseainstalaçãofoibemsucedidaabrindooTerminaledigitandoocomandopython3:
$python3--version
Python3.4.2
Sevocêtiverqualquerdúvidaousealgumacoisadeuerradoevocênãosabeoquefazer-porfavorpergunteaoseuinstrutor!Àsvezes,ascoisasnãoestãoindobemeémelhorpedirajudaaalguémcommaisexperiência.
DjangoGirlsTutorial
20InstalaçãodoPython
EditordeCódigoVocêestáprestesaescreversuaprimeiralinhadecódigo,entãoéhoradebaixarumeditordecódigo!
Existemmuitoseditoresdiferenteseemgrandeparteseresumeapreferênciapessoal.AmaioriadosprogramadoresPythonusaascomplexas,masextremamentepoderosasIDEs(IntegratedDevelopmentEnvironments,ouemportuguês,AmbientededesenvolvimentoIntegrado),taiscomoPyCharm.Parauminiciante,entretanto,estasIDE'ssãomenosconvenientes;nossasrecomendaçõessãobemmaissimples,porém,igualmentepoderosas.
Nossassugestõesestãoabaixo,massinta-selivreparaperguntaraoseucoachquaissãoassuaspreferências-assimvaisermaisfácilobteraajudadeles.
GeditGeditéumeditoropen-source,gratuito,disponívelparatodosossistemasoperacionais.
Baixeaqui
SublimeText2SublimeText2éumeditormuitopopularcomumperíododeavaliaçãogratuita.Éfácildeinstalareusar,eestádisponívelparatodosossistemasoperacionais.
Baixeaqui
AtomAtoméumnovoeditordecódigocriadopeloGitHub.Eleégratuito,open-source,fácildeinstalarefácildeusar.EstádisponívelparaWindows,OSXeLinux.
Baixeaqui
Porqueestamosinstalandoumeditordecódigo?
DjangoGirlsTutorial
21EditordeCódigo
VocêdeveestarseperguntandoporqueestamosinstalandoessesoftwareeditordecódigoespecialaoinvésdeusaralgocomoWordouBlocodeNotas.
Primeiroéquecódigoprecisasertextosemformatação,eoproblemacomprogramascomoWordeTexteditéqueelesnaverdadenãoproduzemtextosemformatação,elesfazem"richtext"(comfonteseformatação),usandoformatospersonalizadoscomoRTF.
Asegundarazãoéqueeditoresdecódigosãoespecializadosemeditarcódigo,entãoelespodemoferecerrecursosúteis,comorealcedecódigocomcoresdeacordocomoseusignificado,ouautomaticamentefecharcitaçõesparavocê.
Nósvamosverissoemaçãodepois.Embrevevocêteráseueditordecódigocomoumadassuasferramentasfavoritas.:)
DjangoGirlsTutorial
22EditordeCódigo
IntroduçãoaoPythonPartedestecapítuloébaseadonosTutoriaisdeGeekGirlsCarrots(http://django.carrots.pl/).
Vamosescreverumpoucodecódigo!
InterpretadorPythonParacomeçarabrincarcomPythonnósprecisamosabrirumalinhadecomandonoseucomputador.Vocêjásabedevercomofazerisso--vocêaprendeuissonocapítuloIntroduçãoàLinhadeComando.</p>Assimqueestiverpronto,sigaasinstruçõesabaixo.
NósqueremosabriroPythonnumterminal,entãodigitepython3etecleEnter.
$python3
Python3.4.2(...)
Type"copyright","credits"or"license"formoreinformation.
>>>
SeuprimeirocomandoPython!DepoisdeexecutarocomandoPython,opromptmudoupara>>>.Paranós,issosignificaqueporenquantosóutilizaremoscomandosnalinguagemPython.Vocênãoprecisadigitar>>>-OPythonfaráissoporvocê.
SevocêdesejasairdoconsoledoPython,apenasdigiteexit()ouuseoatalhoCtrl+ZnoWindowseCtrl+DnoMac/Linux.Entãovocênãovaivermaiso>>>.
MasagoranãoqueremossairdalinhadecomandodoPython.Queremosaprendermaissobreele.Vamos,então,fazeralgomuitosimples.Porexemplo,tentedigitaralgumaoperaçãomatemática,como2+3eaperteEnter.
>>>2+3
5
Incrível!Vêcomoarespostasimplesmenteaparece?OPythonconhecematemática!Vocêpodetentaroutroscomandoscomo:-4*5-5-1-40/2
Divirta-secomissoporumtempoedepoisvolteaqui:).
DjangoGirlsTutorial
23IntroduçãoaoPython
Comovocêpodever,oPythonéumaótimacalculadora.Sevocêestáseperguntandooquemaisvocêpodefazer...
StringsQuetaloseunome?Digiteseuprimeironomeentreaspas,dessejeito:
>>>"Ola"
'Ola'
Vocêacaboudecriarsuaprimeirastring!Stringéumsequênciadecaracteresquepodemserprocessadapelocomputador.Astringsempreprecisainiciareterminarcomomesmocaractere.Estepodeseraspasduplas(')ousimples(")-elasdizemaoPythonqueoqueestádentrodelaséumastring.
Stringspodemserjuntadas.Tenteisto:
>>>"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:
DjangoGirlsTutorial
24IntroduçãoaoPython
>>>"Ola".upper()
'OLA'
Vocêacaboudeusarafunçãouppernasuastring!Umafunção(comoupper())éumconjuntodeinstruçõesqueoPythonrealizaemumdeterminadoobjeto("Ola"),semprequevocêchamarporele.
Sevocêquersaberonúmerodeletrasdoseunome,existeumafunçãoparaissotambém!
>>>len("Ola")
3
Seperguntandoporquealgumasvezesvocêchamafunçõescomum.nofimdeumastring(como"Ola".upper())ealgumasvezesvocêprimeirochamaafunçãocolocandoastringnosparênteses?Bem,emalgunscasos,funçõespertencemaobjetos,comoupper(),quesópodeserutilizadaemstrings.Nessecaso,nóschamamosafunçãodemétodo.Outrasvezes,funçõesnãopertencemanadaespecíficoepodemserusadasemdiferentestiposdeobjetos,assimcomolen().Éporissoquenósestamosfornecendo"Ola"comoumparâmetroparaafunçãolen.
Sumário
OK,chegadestrings.Atéagoravocêaprendeusobre:
oprompt-digitarcomandos(códigos)nointerpretadorPythonresultaemrespostasemPythonnúmerosestrings-noPython,númerossãousadosparamatemáticaestringsparaobjetosdetextooperadores-como+e*,combinamvaloresparaproduzirumnovovalorfunções-comoupper()elen(),executamaçõesnosobjetos.
Issoéobásicosobretodasaslinguagensdeprogramaçãoquevocêaprende.Prontoparaalgomaisdifícil?Apostamosquesim!
ErrosVamostentaralgonovo.Podemosobterotamanhodeumnúmerodamesmaformaquepodemosencontrarotamanhodonossonome?Digitelen(304023)epressioneEnter:
DjangoGirlsTutorial
25Introduçã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êmumcomprimento,certo?
>>>len(str(304023))
6
Funcionou!Usamosafunçãostrdentrodafunçãolen.str()convertetudoparastrings.
AfunçãostrconverteascoisasemstringsAfunçãointconverteascoisasemnúmerosinteiros
Importante:podemosconverternúmerosemtexto,masnósnãopodemos,necessariamente,convertertextoemnúmeros-oqueint('hello')querdizer?
VariáveisUmconceitoimportantenaprogramaçãoéoconceitodevariáveis.Umavariávelnãoénadamaisdoqueumnomeparaalgumacoisa,detalformaquevocêpossausá-lamaistarde.Osprogramadoresusamessasvariáveisparaguardardados,parafazerseuscódigosmaislegíveiseparanãoterqueselembrarsempreoquealgumascoisassignificam.
Digamosquequeremoscriarumanovavariávelchamadanome:
>>>name="Ola"
Vê?Éfácil!Ésófazer:nomeigualaOla.
Comovocêpercebeu,seuprogramanãoretornounadacomofezanteriormente.Entãocomosabemosqueavariávelrealmenteexiste?SimplesmentedigitenomeetecleEnter:
>>>name
'Ola'
Yippee!Suaprimeiravariável:)!Vocêsemprepodemudaroseuvalor:
DjangoGirlsTutorial
26IntroduçãoaoPython
>>>name="Sonja"
>>>name
'Sonja'
Vocêpodeusá-latambémemfunções:
>>>len(name)
5
Incrívelnão?Claro,variáveispodemserqualquercoisa,entãopodemsernúmerostambém!Tenteisso:
>>>a=4
>>>b=6
>>>a*b
24
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áesteerrosevocêtentarusarumavariávelquenãofoidefinidaainda.Sevocêencontraresseerrodepois,vejasenoseucódigosevocênãodigitouonomedeumavariávelerrado.
Brinquecomissoporumtempoevejaoquevocêconseguefazer!
AfunçãoprintTenteisso:
>>>name='Maria'
>>>name
'Maria'
>>>print(name)
Maria
DjangoGirlsTutorial
27IntroduçãoaoPython
Quandovocêapenasdigitaname,ointerpretadorPythonrespondecomarepresentaçãocomostringdavariável'name',quesãoasletrasM-a-r-i-a,entreaspassimples.Quandovocêdizprint(name),Pythonvai"imprimir"oconteúdodavariávelnatela,semasaspas,oqueémaispuro.
Comoveremosmaistarde,print()tambéméútilquandoqueremosimprimiralgodentrodefunções,ouquandoqueremosimprimiralgoemváriaslinhas.
ListasAlémdestringseinteiros,oPythontemtodosostiposdiferentesdeobjetos.Vamosapresentarumchamadolista.Listassãoexatamenteoquevocêachaqueelassão:elassãoobjetosquesãolistasdeoutrosobjetos:)
Váemfrenteecrieumalista:
>>>[]
[]
Sim,estaéumalistavazia.Nãoémuito,nãoé?Vamoscriarumalistadosnúmerosdaloteria.Comonãoqueremosficarrepetindoocódigotodootempovamoscriarumavariávelparaela:
>>>lottery=[3,42,12,19,30,59]
Tudocerto,nóstemosumalista!Oquepodemosfazercomisso?Vamosverquantosnúmerosdeloteriaexistemnestalista.Vocêtemideiadequalfunçãodeveusarparaisso?Vocêjásabedisso!
>>>len(lottery)
6
Sim!len()podetedaronúmerodeobjetosquefazempartedeumalista.Umamãonaroda,não?Vamosorganizarissoagora:
>>>lottery.sort()
Issonãoretornanada,apenastrocaaordememqueosnúmerosaparecemnalista.Vamosimprimirissooutravezeveroqueacontece:
DjangoGirlsTutorial
28IntroduçãoaoPython
>>>print(lottery)
[3,12,19,30,42,59]
Comovocêpodever,osnúmerosnanossalistaestãoordenadosdomenorparaomaior.Parabéns!
Talvezagentequeirainverteressaordem?Vamosfazerisso!
>>>lottery.reverse()
>>>print(lottery)
[59,42,30,19,12,3]
Molezané?Sevocêquiseradicionaralgumacoisaàsualista,vocêpodefazeristodigitandooseguintecomando:
>>>lottery.append(199)
>>>print(lottery)
[59,42,30,19,12,3,199]
Sevocêquisermostrarapenasoprimeironúmerovocêpodeusarindices.Umíndiceéumnúmeroquedizondeumitemdalistaestá.Oscomputadoresgostamdeiniciaracontagempor0,entãooprimeiroobjetotemíndice0,opróximotemíndice1eporaívai.Tenteisso:
>>>print(lottery[0])
59
>>>print(lottery[1])
42
Comovocêpodever,vocêpodeacessardiferentesobjetosnasualistausandoonomedalistaeoíndicedoobjetodentrodoscolchetes.
Pordiversãoextra,tentealgunsoutrosíndices:6,7,1000,-1,-6ou-1000.Vejasevocêconseguepreveroresultadoantesdetentarocomando.Osresultadosfazemsentido?
VocêpodeencontrarumalistadetodososmétodosdisponíveisnestecapítulonadocumentaçãodoPython:https://docs.python.org/3/tutorial/datastructures.html
DicionáriosUmdicionárioésemelhanteaumalista,masvocêpodeacessarvaloresatravésdeumachaveaoinvésdeumíndice.Umachavepodeserqualquerstringounúmero.Asintaxeparadefinirumdicionáriovazioé:
DjangoGirlsTutorial
29IntroduçãoaoPython
>>>{}
{}
Issomostraquevocêacaboudecriarumdicionáriovazio.Hurra!
Agora,tenteescreveroseguintecomando(tentesubstituircomassuasprópriasinformaçõestambém):
>>>participant={'name':'Ola','country':'Poland','favorite_numbers':[7,42,92]}
Comessecomando,vocêacaboudecriarumavariávelchamadaparticipantcomtrêsparesdechave-valor:
Achavenomeapontaparaovalor'Ola'(umobjetostring),paisapontapara'Polonia'(outrastring),enumeros_favoritosapontampara[7,42,92](umalistcomtrêsnúmerosnela).
Vocêpodechecaroconteúdodechavesindividuaiscomasintaxe:
>>>print(participant['name'])
Ola
Veja,ésimilaraumalista.Masvocênãoprecisalembraroíndice-apenasonome.
OqueacontecesepedirmosaoPythonovalordeumachavequenãoexiste?Vocêconsegueadivinhar?Vamostentaredescobrir!
>>>participant['age']
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
KeyError:'age'
Olha,outroerro!EsseéumKeyError.Pythonébastanteprestativoetedizqueachave'age'nãoexistenonessedicionário.
Quandousarumdicionarioouumalista?Bem,umbompontopararefletir.Penseemumasoluçãoantesdeolhararespostanapróximalinha.
Vocêprecisadeumasequênciaordenadadeitens?Useumalist.Vocêprecisaassociarvalorescomchaves,assimvocêpodeprocurá-loseficientemente(pelachave)maistarde?Useumdictionary.
DjangoGirlsTutorial
30IntroduçãoaoPython
Dicionários,comolistas,sãomutáveis,ouseja,quepodemsermudadosdepoisquesãocriados.Vocêpodeadicionarnovosparesdechave/valorparaodicionárioapóssuacriação,como:
>>>participant['favorite_language']='Python'
Comoaslists,usarométodolen()emdicionáriosretornaonúmerodepareschave-valornodicionario.Váemfrenteedigiteocomando:
>>>len(participant)
4
Esperoqueagorafaçasentidoatéagora.:)Prontaparamaisdiversãocomdicionários?Pulenapróximalinhaparacoisasincríveis.
Vocêpodeusarocomandodelparadeletarumitemnodicionario.Digamos,sevocêquerexcluiraentradacorrespondenteachave'favorite_numbers',bastadigitaroseguintecomando:
>>>delparticipant['favorite_numbers']
>>>participant
{'country':'Poland','favorite_language':'Python','name':'Ola'}
Comovocêpodevernoretorno,oparchave-valorcorrespondenteàchave'favorite_numbers'foiexcluído.
Alémdissovocêpodemudarovalorassociadocomumachavejácriadanodicionário.Digite:
>>>participant['country']='Germany'
>>>participant
{'country':'Germany','favorite_language':'Python','name':'Ola'}
Comovocêpodever,ovalordachave'country'foialteradode'Poland'para'Germany'.:)Emocionante?Hurra!Vocêacaboudeaprenderoutracoisaincrível.
Sumário
Incrível!Agoravocêsabemuitosobreprogramação.Nestaúltimapartevocêaprendeusobre:
erros-agoravocêsabecomolereentendererrosqueaparecemseoPythonnão
DjangoGirlsTutorial
31IntroduçãoaoPython
entenderumcomandoquevocêdeuvariáveis-nomesparaobjetosquepermitemvocêprogramarfacilmenteedeixarseucódigomaislegívellistas-listasdeobjetosarmazenadosemumaordemespecíficadicionários-objetosarmazenadoscomopareschave-valor
Empolgado(a)paraopróximopasso?:)
ComparecoisasGrandepartedaprogramaçãoconsisteemcompararcoisas.Oqueémaisfácildecomparar?Números,éclaro.Vamosvercomoissofunciona:
>>>5>2
True
>>>3<1
False
>>>5>2*2
True
>>>1==1
True
>>>5!=2
True
DemosaoPythonalgunsnúmerosparacomparar.Comovocêpodever,Pythonpodecompararnãosónúmerosmastambémresultadosdemétodos.Legal,hein?
Vocêestáseperguntandoporquecolocamosdoissinaisdeigual==ladoaladoparacompararseosnúmerossãoiguais?Nósusamosumúnico=paraatribuirvaloresavariáveis.Vocêsempre,sempreprecisacolocardois==sequiserverificarseascoisassã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émaiorqueyx<ysignifica:xémenorquey
DjangoGirlsTutorial
32IntroduçãoaoPython
x<=ysignifica:xémenorouigualayx>=ysignifica:xémaiorouigualay
Fantástico!Quermais?Tenteisto:
>>>6>2and2<3
True
>>>3>2and2<1
False
>>>3>2or2<1
True
VocêpodedaraoPythonquantosnúmerosparacompararquantovocêquiser,eelevaitedarumaresposta!Espertinho,certo?
and-sevocêusarooperadorand,ambasascomparaçõesterãoqueserverdadeirasparaquetodoocomandosejaverdadeiroor-sevocêusarooperadoror,apenasumadascomparaçõesprecisaserverdadeiraparaqueocomandotodosejaverdadeiro
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</0)>.Emvezdisso,elemostrouumTypeErrorenosdissequeosdoistiposnãopodemsercomparadosjuntos.</p>
BooleanoAcidentalmente,vocêaprendeusobreumnovotipodeobjetoemPython.Échamadodebooleano--eprovavelmenteotipomaisfácilqueexiste.
Existemapenasdoisobjetosbooleanos:-True(verdadeiro)-False(falso)
MasparaoPythonentenderisso,vocêprecisasempreescreverTrue(primeiraletramaiúscula,comorestodasletrasemminúsculo).true,TRUE,tRUEnãovaifuncionar--sóTrueécorreto.(OmesmoseaplicaaoFalse,claro.)
Booleanospodemservariáveistambém!Veja:
DjangoGirlsTutorial
33IntroduçãoaoPython
>>>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!Atéagoranósescrevemostodonossocódigoemuminterpretadorpython,quenoslimitaaumalinhadecódigoemummomento.Programasnormaissãosalvosemarquivoseexecutadospelonossointerpretadordelinguagemdeprogramaçãooucompilador.AtéagorajácorremosnossosprogramasdeumalinhadecadaveznointerpretadorPython.Nósvamosprecisardemaisdeumalinhadecódigoparaaspróximastarefas,entãoprecisaremosrapidamente:
SaídadointerpretadorPythonAbraseueditordecódigodesuaescolhaSalvaralgumcódigoemumnovoarquivodepythonExecutá-lo!
ParasairdointerpretadorPythonqueestamosusando,simplesmentedigiteo~exit()~função:
>>>exit()
$
Issovaicolocá-lonopromptdecomando.
DjangoGirlsTutorial
34IntroduçãoaoPython
Anteriormente,nósescolhemosumeditordecódigodaseçãodoeditordecódigo.Nósprecisamosabriroeditoragoraeescreveralgumcódigoemumnovoarquivo:</p>
print('Hello,Djangogirls!')
NotaVocêdeveobservarqueumadascoisasmaislegaissobreeditoresdecódigo:cores!NoconsoledoPython,tudoeradamesmacor,masagoravocêdeveverqueafunçãodeImprimiréumacordiferentedasequênciadecaracteresnoseuinterior.Issoéchamadode"realcedesintaxe",eéumaajudamuitoútilquandoestáprogramando.Percebaacordascoisasevocêvaiobterumadicaparaquandovocêesquecerdefecharumaseqüênciadecaracteres,oufazerumerrodedigitaçãoemumnomedepalavra-chave(comodefemumafunção,queveremosabaixo).Estaéumadasrazõespelasquaisquenósusamosumeditordecódigo:)
Obviamente,vocêéumdesenvolvedorpythonbastanteexperienteagora,entãosinta-selivreparaescreverumcódigoquevocêaprendeuhoje.
Agoratemosdesalvaroarquivoedêumnomedescritivo.Vamoschamaroarquivopython_intro.pyesalve-oemseudesktop.Podemosnomearoarquivotudooquequisermos,oimportanteaquiétercertezaqueoarquivoterminanopy,istodiznossocomputador,queéumarquivoexecutáveldepythonePythonpodeexecutá-lo.
Comoarquivosalvo,éhoradeexecutá-lo!Usandoashabilidadesquevocêaprendeunaseçãodelinhadecomando,useoterminalaltereosdiretóriosparaodesktop.
EmumMac,ocomandoseráparecidocomisto:
cd/Users/<your_name>/Desktop
NoLinux,seráassim(apalavra"Desktop"podesertraduzidoparaseuidioma):
cd/home/<your_name>/Desktop
Enowindows,vaiserassim:
cdC:\Users\<your_name>\Desktop
Sevocêficarpreso,sópedirajuda.
e,emseguida,usaroPythonparaexecutarocódigonoarquivoassim:
DjangoGirlsTutorial
35IntroduçãoaoPython
$python3python_intro.py
Hello,Djangogirls!
Tudobem!Vocêacaboudeseuprimeiroprogramaempythonquefoisalvoemumarquivo.Mesintoótimo?
Vocêpodeagorapassarparaumaferramentaessencialnaprogramação:
if...elif...elseMuitascoisasnocódigosópodemserexecutadassedeterminadascondiçõesforematendidas.ÉporissoqueoPythontemalgumacoisachamadadeclaraçãoif.
Substituaocódigonoarquivopython_intro.pyparaisto:
if3>2:
Sesalvouesteeelefoiexecutado,nósveríamosumerrocomoeste:
$python3python_intro.py
File"python_intro.py",line2
^
SyntaxError:unexpectedEOFwhileparsing
Pythonesperaquefornecemosmaisinstruçõesqueserãosupostamenteexecutadascasoacondição3>2venhaaserverdadeira(ouTruenessecaso).VamostentarfazeroPythonimprimir"Itworks!".Altereoseucódigonoseuarquivopython_intro.pyparaisto:
if3>2:
print('Itworks!')
Observecomopodemosterrecuadoapróximalinhadecódigopor4espaços?PrecisamosfazerissoparaquePythonsabequecódigoaserexecutadoseocódigoresultaemtrue.Vocêpodefazerumespaço,masquasetodososprogramadoresPythonfazemcom4paratornarascoisasumolharpuro.Umúnicotabtambémvaicontarcomo4espaços.
Salvá-loeexecutenovamente:
$python3python_intro.py
Itworks!
DjangoGirlsTutorial
36IntroduçãoaoPython
Esenão?
Nosexemplosanteriores,ocódigofoiexecutadosomentequandoascondiçõeseramverdade.MasoPythontambémteminstruçõeselifeelse:
if5>2:
print('5isindeedgreaterthan2')
else:
print('5isnotgreaterthan2')
Quandoforexecutadoiráimprimir:
$python3python_intro.py
5emaiorque2
Se2forumnúmeromaiordoque5,entãoosegundocomandoseráexecutado.Fácil,né?Vamosvercomofuncionaoelif:
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>,>=,==,<=,<eoand,orBooleano-umtipodeobjetoquesótemumdosdoisvalores:TrueouFalseSalvandoarquivos-armazenamentodecódigoemarquivosassimvocêpodeexecutarprogramasmaiores.if...elif...else-instruçõesquepermitemquevocêexecuteocódigosomentese
DjangoGirlsTutorial
37IntroduçãoaoPython
determinadascondiçõesforematendidas.Éhoradaúltimapartedestecapítulo!
Suasprópriasfunções!Selembradefunçõescomolen()quevocêpodeexecutarnoPython?Bem,boasnotícias,agoravocêvaiaprenderaescreversuasprópriasfunções!
UmafunçãoéumsequênciadeinstruçõesqueoPythondeveexecutar.CadafunçãoemPythoncomeçacomapalavra-chavedef,seguidodeumnomeparaafunçãoeopcionalmenteumalistadeparâmetros.Vamoscomeçarcomumafunçãosimples.Substituaocódigonopython_intro.pycomoseguinte:
defhi():
print('Hithere!')
print('Howareyou?')
hi()
Ok,nossaprimeirafunçãoestápronta!
Vocêpodeseperguntarporqueescrevemosonomedafunçãonaparteinferiordoarquivo.IstoéporquePythonlêoarquivoeexecuta-lodecimaparabaixo.Então,parausaranossafunção,temosre-escrevê-lonaparteinferior.
Vamosexecuta-loagoraeveroqueacontece:
$python3python_intro.py
Hithere!
Howareyou?
Issofoifácil!Vamosconstruirnossaprimeirafunçãocomparâmetros.Usaremosoexemploanterior-umafunçãoquediz'hi'paraquemoexecuta-comumname:
defhi(name):
Comovocêpodever,agorademosumparâmetrochamadonameparanossafunção:
DjangoGirlsTutorial
38IntroduçãoaoPython
defhi(name):
ifname=='Ola':
print('HiOla!')
elifname=='Sonja':
print('HiSonja!')
else:
print('Hianonymous!')
hi()
Comovocêpodever,nósprecisamoscolocardoisespaçosantesdafunçãoprint,porqueifprecisasaberoquedeveacontecerquandoacondiçã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çãohi()(aquelaquedeclaramos)temumargumentoobrigatório(chamadoname)equenósesquecemosdepassá-loaochamarafunção.Vamoscorrigi-lonaparteinferiordoarquivo:
hi("Ola")
eexecutenovamente:
$python3python_intro.py
HiOla!
Esemudarmosonome?
hi("Sonja")
eexecutá-lo:
$python3python_intro.py
HiSonja!
DjangoGirlsTutorial
39IntroduçãoaoPython
Agora,oqueachaquevaiacontecersevocêescreveroutronomelá?(NãoOlaouSonja)Experimentá-loeversevocêestácerto.Eledeveimprimiristo:
Hianonymous!
Istoéincrível,não?Dessamaneiravocênãoprecisaserepetir(DRY-don'trepeatyourself)cadavezqueformudaronomedapessoaqueafunçãopretendecumprimentar.Eéexatamenteporissoqueprecisamosdefunções-vocênuncaquerrepetirseucódigo!
Vamosfazeralgomaisinteligente..--existemmaisquedoisnomes,eescreverumacondiçãoparacadaumseriadifícil,certo?
defhi(name):
print('Hi'+name+'!')
hi("Rachel")
Vamoschamarocódigoagora:
$python3python_intro.py
HiRachel!
Parabéns!Vocêacaboudeaprenderacriarfunções:)!
LaçosJáéaúltimaparte.Foirápido,não?:)
Comomencionamos,osprogramadoressãopreguiçosos,nãogostamderepetirasmesmascoisas.Programaçãofalasobrecomoautomatizarascoisas,entãonãoqueremoscumprimentarcadapessoapeloseunomemanualmente,certo?Éaíondeoslaçosvemacalhar.
Aindaselembradaslistas?Vamosfazerumalistadegarotas:
girls=['Rachel','Monica','Phoebe','Ola','You']
Queremoscumprimentartodaselaspelosseusnomes.Temosafunçãohiparafazerisso,entãovamosusá-laemumloop:
fornameingirls:
DjangoGirlsTutorial
40IntroduçãoaoPython
O~for~declaraçãosecomportadamesmaformaparao~if~declaração,có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çãoforcomespaçoserárepetidoparacadaelementodalistagirls.
Vocêtambémpodeusaroforemnúmerosusandoafunçãorange:
foriinrange(1,6):
print(i)
Queiriaimprimir:
1
2
3
4
5
rangeéumafunçãoquecriaumalistadenúmerosqueseseguemumapósooutro(essesnúmerossãodadosporvocêcomoparâmetros).
DjangoGirlsTutorial
41IntroduçãoaoPython
NotequeosegundodessesdoisnúmerosnãoestáincluídonalistaqueoPythonmostrou(emrange(1,6),contade1a5,maso6nãoéincluído).
SumárioÉisso.Vocêétotalmentedemais!Nãoétãofácil,entãovocêdevesesentirorgulhosodesimesmo.Estamosdefinitivamenteorgulhososdevocêporterchegadoatéaqui!
Talvezvocêqueirabrevementefazeralgomais-espreguiçar,andarumpouco,descansarosolhos-antesdeirparaopróximocapítulo.:)
DjangoGirlsTutorial
42IntroduçãoaoPython
OqueéDjango?Djangoéumframeworkgratuitoedecódigoabertoparaacriaçãodeaplicaçõesweb,escritoemPython.Éumframeworkweb,ouseja,éumconjuntodecomponentesqueajudaadesenvolversitesdeformamaisrápidaemaisfácil.
Veja,quandovocêestáconstruindoumsite,vocêsempreprecisaumconjuntosimilardecomponentes:umamaneiradelidarcomaautenticaçãodousuário(inscrever-se,realizarlogin,realizarlogout),paineldegerenciamentoparaoseusite,formulários,uploaddearquivos,etc.
Felizmenteparavocê,hámuitotempo,outraspessoasnotaramvariassemelhançasnosproblemasenfrentadospelosdesenvolvedoreswebquandoestãocriandoumnovosite,entãoelesuniram-seecriaramosframeworks(Djangoéumdeles)quelhedãocomponentesprontos,quevocêpodeusar.
Frameworksexistemparasalvá-lodeterquereinventararodaeajudamaaliviarasobrecargaquandovocêestáconstruindoumnovosite.
Porquevocêprecisadeumframework?ParaentenderoqueDjangoénaverdade,precisamosolharmaisdepertoosservidores.Aprimeiracoisaéqueoservidorprecisasaberquevocêquerparaservi-loumapáginadaWeb.
Imagineumacaixadecorreio(porta)queémonitoradaporcartasrecebidas(requisição).Issoéfeitoporumservidorweb.Oservidorweblêacartaeenviaumarespostacomumapáginaweb.Mas,quandovocêquerenviaralgumacoisavocêprecisaterumconteúdo.EoDjangoéaquiloquevailheajudaracriaresseconteúdo.
Oqueacontecequandoalguémsolicitaumsitedoseuservidor?QuandochegaumarequisiçãoparaoservidorwebelaépassadaparaoDjangoquetentadescobrirdoqueelasetrata.Primeiroelepegaumendereçowebetentadescobriroquefazer.EssaparteéfeitapelourlresolverdoDjango.(NotequeoendereçodeumsitesechamaURL-UniformResourceLocator,emportuguêsLocalizadordeRecursosUniforme,dessaformaonomeurlresolver,ouresolvedordeurls,fazsentido).Issonãoémuito
DjangoGirlsTutorial
43OqueéDjango?
inteligente-levaàumalistadepadrõesetentacorresponderaURL.ODjangoverificapadrõesdecimaparabaixoesealgoécorrespondido,passaasolicitaçãoparaafunçãoassociada(queéchamadaview).
Imagineumcarteirocomumacarta.Elaestáandandopelaruaeverificacadanúmerodecasacomaqueestánacarta.Seelecorresponder,elacolocaacartalá.Éassimquefuncionaourlresolver!
Todasascoisasinteressantessãofeitasdentrodaview:podemosdarumaolhadanobancodedadosparaprocuraralgumasinformações.Talvezousuárioqueiramudaralgonosdados?Comoumacartadizendo:"Porfavormudeadescriçãodomeuemprego."-aviewchecasevocêtempermissãoparafazerissoeentãoatualizaadescriçãodoempregopravocê,enviandoemseguidaumamensagem:"Feito!".EntãoaviewgeraumarespostaeoDjangopodeenviá-laparaonavegadordocliente.
Claro,adescriçãoacimaémuitosimplificada,masvocênãoprecisasaberdetalhestécnicosainda.Terumaideiageraljáésuficiente.
Entãoemvezdemergulharemmuitosdetalhes,nóssimplesmentevamoscomeçarcriandoalgocomoDjangoeaprenderemostodaaspartesimportantesaolongodocaminho!
DjangoGirlsTutorial
44OqueéDjango?
InstalaçãodoDjangoPartedestecapítuloébaseadonostutoriaisdoGeekGirlsCarrots(http://django.carrots.pl/).
Partedestecapítuloébaseadonodjango-marcadortutoriallicenciadosobreCreativeCommonsAttribution-ShareAlike4.0InternationalLicense.Otutorialdodjango-marcadoréprotegidopordireitosautoraisporMarkusZapke-Gründemannetal.
AmbientevirtualAntesdeinstalarmosoDjango,nósiremosinstalarumaferramentaextremamenteútilqueiráajudaramanterseuambientededesenvolvimentoarrumadoemseucomputador.Épossívelignorarestepasso,maséaltamenterecomendadonãocomeçarcomamelhorconfiguração,evitandoproblemasadiante!
Então,vamoscriarumambientevirtual(tambémchamadoumvirtualenv).IssoisolarásuaconfiguraçãoPython/Djangoemumabaseporprojeto,significaquequaisquermudançasquefizeremumwebsitenãoafetaráquaisqueroutrasaplicaçõesqueestiverdesenvolvendoaparte.Arrumado,certo?
Tudooquevocêprecisafazeréencontrarumdiretórionoqualvocêdesejacriarovirtualenv;SeudiretórioHome,porexemplo.NoWindowspodeparecercomoC:\Usuário\Nome(ondeNomeéonomedoseulogin).
Paraestetutorialusaremosumnovodiretóriodjangogirlsdoseudiretóriohome:
mkdirdjangogirls
cddjangogirls
Nósvamosfazerumvirtualenvchamadomeuenv.Oformatogeraldessecomandoé:
python3-mvenvmyvenv
Windows
Paracriarumnovovirtualenv,vocêprecisaabriroconsole(Nósfalamossobreissoalgunscapítulosatrás,lembra-se?)eexecutarC:\Python34\python-mvenvmyvenv.Seráalgoparecidocomisto:
DjangoGirlsTutorial
45InstalaçãodoDjango
C:\Usuário\Nome\djangogirls>C:\Python34\python-mvenvmyvenv
ondeC:\Python34\pythonéodiretórioemquevocêpreviamenteinstalouPythonemyvenvéonomedasuavirtualenv.Vocêpodeusarqualqueroutronome,massempreuseminúsculasesemespaços,acentosoucaracteresespeciais.Tambéméumaboaideiamanteronomecurto-vocêiráreferenciarmuitoaele!
LinuxeOSX
CriarumvirtualenvtantonoLinuxcomoOSXésimplescomoexecutarpython3-mvenvmyvenv.Seráalgoparecidocomisto:
~/djangogirls$python3-mvenvmyvenv
myvenvéonomedasuavirtualenv.Vocêpodeusarqualqueroutronome,maspermaneçaemcaixabaixa(minúsculas)enãouseespaçosentreosnomes.Tambéméumaboaideiamanteronomecurto-vocêiráreferenciarmuitoaele!
NOTA:IniciaroambientevirtualnoUbuntu14.04assimretornaráoseguinteerro:
Error:Command'['/home/eddie/Slask/tmp/venv/bin/python3','-Im','ensurepip','--upgrade','--default-pip']'returnednon-zeroexitstatus1
Paracontornaresseproblema,useocomandovirtualenv.
~/djangogirls$sudoapt-getinstallpython-virtualenv
~/djangogirls$virtualenv--python=python3.4myvenv
TrabalhandocomovirtualenvOcomandoacimacriaráumdiretóriochamadomyvenv(ousejaonomequevocêescolheu)quecontémonossoambientevirtual(basicamenteumconjuntodediretóriosearquivos).Tudooquequeremosporenquantoéiniciá-loexecutando:
C:\Usuário\Nome\djangogirls>myvenv\Scripts\activate
noWindows,ou:
~/djangogirls$sourcemyvenv/bin/activate
DjangoGirlsTutorial
46InstalaçãodoDjango
noOSXenoLinux.
Lembre-sedesubstituirmyvenvcomseunomeescolhidodovirtualenv!
NOTE:àsvezessource(fonte)podenãoestardisponível.Nessescasos,tentefazerissoemvezdisso:
~/djangogirls$.myvenv/bin/activate
Vocêvaisaberquetemumvirtualenvfuncionandoquandoveropromptnoseuconsoleseparecercom:
(myvenv)C:\Usuário\Nome\djangogirls>
ou:
(myvenv)~/djangogirls$
Percebaqueoprefixo(myvenv)aparece!
Aotrabalhardentrodeumambientevirtual,pythoniráautomaticamentesereferiraversãocorretaparaquepossautilizarpythonemvezdepython3.
Ok,nóstemostodasasdependênciasimportantesnolugar.FinalmentepodemosinstalaroDjango!
InstalandooDjangoAgoraquevocêtemasuavirtualenviniciado,vocêpodeinstalarDjangousandopip.Noconsole,executepipinstalldjango==1.8.5(Percebaqueusamosumduplosinaldeigual:==).
(myvenv)~$pipinstalldjango==1.8.5
Downloading/unpackingdjango==1.8.5
Installingcollectedpackages:django
Successfullyinstalleddjango
Cleaningup...
noWindows
DjangoGirlsTutorial
47InstalaçãodoDjango
SevocêreceberumerroaochamaropipnaplataformaWindowsporfavor,verifiqueseocaminhodoprojetocontémespaços,acentosoucaracteresespeciais(exemplo,C:\Users\UserName\djangogirls).Sesimporfavormovaparaoutrolugarsemespaços,acentosoucaracteresespeciais(sugestãoé:C:\djangogirls).Apósamudança,porfavortentenovamenteocomandoacima.
NoLinux
SevocêreceberumerroaochamarpipnoUbuntu12.04porfavorexecutepython-mpipinstall-U--force-reinstallpipparacorrigirainstalaçãodopipnovirtualenv.
Éisso!Agoravocêestá(finalmente)prontoparacriarumaaplicaçãoDjango!
DjangoGirlsTutorial
48InstalaçãodoDjango
SeuprimeiroprojetoDjango!PartedestecapítuloébaseadonostutoriaisdoGeekGirlsCarrots(http://django.carrots.pl/).
Partedestecapítuloébaseadonodjango-marcadortutoriallicenciadosobreCreativeCommonsAttribution-ShareAlike4.0InternationalLicense.Otutorialdodjango-marcadoréprotegidopordireitosautoraisporMarkusZapke-Gründemannetal.
Nósvamoscriarumblogsimples!
Oprimeiropassoparacriá-loécomeçarumnovoprojetodeDjango.Basicamente,istosignificaquevamosexecutaralgunsscriptsfornecidospeloDjangoqueirácriaroesqueletodeumprojetoDjangoparanós:umbandodediretóriosearquivosqueusaremosmaistarde.
OsnomesdealgunsarquivosediretóriossãomuitoimportantesparaoDjango.Nãorenomeieosarquivosqueestamosprestesacriar.Moverparaumlugardiferentetambémnãoéumaboaidéia.Djangoprecisamanterumadeterminadaestruturaparasercapazdeencontrarcoisasimportantes.
Lembre-sequetudonovirtualenv.Sevocênãovêumprefixo(myvenv)emseuconsole,vocêprecisaativarovirtualenv.NósexplicamoscomofazerissonocapítuloinstalaçãodoDjangonapartetrabalhandocomvirtualenv.Vocêpodefazerissodigitandooseguintecomando:myvenv\Scripts\activatenoWindowsoumyvenv/bin/activatenoMacOS/Linux.
NotaVerifiquequevocêincluiuoponto(.)nofinaldocomando,éimportanteporquedizoscriptparainstalaroDjangoemseudiretó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órioestruturaqueseparececomisso:
DjangoGirlsTutorial
49Criandoumprojeto
djangogirls
├───manage.py
└───mysite
settings.py
urls.py
wsgi.py
__init__.py
manage.pyéumscriptqueajudacomagestãodosite.Comissoseremoscapazesdeiniciarumservidordewebnonossocomputadorseminstalarnada,entreoutrascoisas.
Oarquivosettings.pycontémaconfiguraçãodoseusite.
Lembraquandofalamossobreumcarteiroverificandoondeentregarumacarta?arquivourls.pycontémumalistadospadrõesusadosporurlresolver.
Vamosignorarosoutrosarquivosporagora-nósnãovamosmudá-los.Aúnicacoisaalembrarénãoexcluí-losporacidente!
ConfigurandoVamosfazeralgumasalteraçõesnomysite/settings.py.Abraoarquivousandooeditordecódigoquevocêinstalouanteriormente.
Seriabomterahoracorretanonossosite.Váparaa<wikipediatimezoneslistecopieseufusohorário.(porexemplo.Europa/Berlim)
Emsettings.py,localizealinhaquecontémTIME_ZONEemodifiqueparaescolherseuprópriofusohorário:
TIME_ZONE='Europe/Berlin'
Modifique"Europa/Berlim",conformeocaso
Nóstambémprecisaramosadicionarumcaminhoparaarquivosestáticos(nósvamosdescobrirtudosobrearquivosestáticoseCSSmaistardenotutorial).DesçaatéofinaldoarquivoelogoabaixodaentradaSTATIC_URL,adicioneumnovoumchamadoSTATIC_ROOT:
STATIC_URL='/static/'
STATIC_ROOT=os.path.join(BASE_DIR,'static')
DjangoGirlsTutorial
50Criandoumprojeto
InstalaçãodeumbancodedadosHáummontedesoftwaredebancodedadosdiferentequepodearmazenardadosparaoseusite.Nósvamosusaropadrão,sqlite3.
Istojáestáconfiguradonestapartedoseuarquivomysite/settings.py:
DATABASES={
'default':{
'ENGINE':'django.db.backends.sqlite3',
'NAME':os.path.join(BASE_DIR,'db.sqlite3'),
}
}
Paracriarumbancodedadosparaonossoblog,vamosfazeroseguintenoconsole.Digite:pythonmanage.pymigrate(precisamosestarnodiretórioquecontémoarquivomanage.pydjangogirls).Seissodercerto,vocêdeveveralgocomoisto:
(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émoarquivomanage.py(odiretóriodjangogirls).Noconsole,nóspodemosiniciaroservidorwebexecutandoopythonmanage.pyrunserver:
(myvenv)~/djangogirls$pythonmanage.pyrunserver
Agoratudoquevocêprecisafazeréverificarseseusiteestásendoexecutado-abraseunavegador(Firefox,Chrome,Safari,InternetExplorerouoquevocêusa)edigiteoendereço:
http://127.0.0.1:8000/
Oservidorwebvaiassumirseupromptdecomandoatévocêpará-lo:paradigitarmaiscomandosouabrirumanovajaneladoterminal(enãoseesqueçadeativarseuvirtualenvneletambém),oupararoservidordeweb,alternandodevoltaparaajanelanaqualestá
DjangoGirlsTutorial
51Criandoumprojeto
executandoepressionandoCTRL+C-botõesdecontroleeCjuntos(noWindows,vocêpodeterquepressionarCtrl+Break).
Parabéns!Vocêcriouseuprimeirositeeoexecutouusandoumservidordeweb!Nãoéimpressionante?
Prontoparaopróximopasso?Estánahoradecriaralgumconteúdo!
DjangoGirlsTutorial
52Criandoumprojeto
ModelosdoDjangoAgoraoquenósqueremoscriaréalgoquearmazenetodosospostsnonossoblog.Masparafazerissoprecisamosaprenderumpoucomaissobrecoisaschamadasobjetos.
ObjetosExisteumconceitonaprogramaçãochamadoProgramaçãoOrientadaàObjetos(POO).Aideiaéqueaoinvésdeescrevertudocomoumachatasequênciadeinstruçõesdeprogramaçãopodemosmodelarascoisasedefinircomoelasinteragemumascomasoutras.
Entãooqueéumobjeto?Éumacoleçãodepropriedadeseações.Istopodeparecerestranho,masvamoslhedarumexemplo.
SequeremosmodelarumgatonóscriaremosumobjetoGatoquepossuialgumaspropriedades,porexemplocor,idade,humor(bom,mau,sonolento;)),dono(queéumobjetodaclassePessoaou,casosejaumgatoderua,essapropriedadeévazia).
EentãooGatotemalgumasações:ronronar,arranharoucomer(noqualvamosdaraogatoalgumaComidaDeGato,quepoderiaserumobjetoseparadocompropriedades,comosabor).
Gato
--------
cor
idade
humor
dono
ronronar()
arranhar()
comer(comida_de_gato)
ComidaDeGato
--------
sabor
Então,basicamente,aideiaédescrevercoisasreaisnocódigocompropriedades(chamadasdepropriedadesdoobjeto)eações(chamadasdemétodos).
DjangoGirlsTutorial
53ModelosdoDjango
Comonósiremosmodelaraspostagensdoblogentão?Queremosconstruirumblog,certo?
Precisamosresponderàpergunta:oqueéumapostagemdeblog?Quepropriedadesdeveter?
Bem,comcertezanossoblogprecisadealgumapostagemcomoseuconteúdoeumtítulo,certo?Tambémseriabomsaberquemaescreveu-entãoprecisamosdeumautor.Finalmente,queremossaberquandoapostagemfoicriadaepublicada.
Post
--------
title
text
author
created_date
published_date
Quetipodecoisapodeserfeitacomumapostagem?Serialegalteralgummétodoquepubliqueapostagem,nãoémesmo?
Entãoprecisamosdeummétodochamadopublicar.
Comojásabemosoquequeremosalcançar,podemoscomeçaramodelagememDjango!
ModelodoDjangoSabendooqueumobjetoé,nóscriaremosummodelonoDjangoparaapostagemdoblog.
UmmodelonoDjangoéumtipoespecialdeobjeto-eleésalvoemumbancodedados.Umbancodedadoséumacoleçãodedados.Obancodedadoséumlocalemquevocêvaisalvardadossobreusuários,suaspostagens,etc.UsaremosumbancodedadoschamadoSQLiteparaarmazenarasnossasinformações.EsteéoadaptadordebancodedadospadrãoDjango--elevaiserosuficienteparanósnestemomento.
Vocêpodepensaremummodelodebancodedadoscomoumaplanilhacomcolunas(campos)elinhas(dados).
Criandoumaaplicação
Paramantertudoarrumadovamoscriarumaplicativoseparadodentrodonossoprojeto.Émuitobomtertudoorganizadodesdeoinício.Paracriarumaplicativoprecisamosexecutaroseguintecomandonoconsole(apartirdodiretóriodjangogirlsondeestáoarquivomanage.py):
DjangoGirlsTutorial
54ModelosdoDjango
(myvenv)~/djangogirls$pythonmanage.pystartappblog
Vocêvainotarqueumnovodiretórioblogécriadoequeeleagoracontémumnúmerodearquivos.Nossosdiretóriosearquivosnonossoprojetodevemseparecercomeste:
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.Fazemosissonoarquivomysite/settings.py.PrecisamosencontraroINSTALLED_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
Noarquivoblog/models.pydefinimostodososobjetoschamadosModelos-esteéumlugaremquevamosdefinirnossapostagemdoblog.
Vamosabrirblog/models.py,removatudodeleeescrevaocódigocomoeste:
DjangoGirlsTutorial
55ModelosdoDjango
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(_)emcadaladodostr.AquelescaracteressãousadosfreqüentementeemPythoneàsvezesoschamamosde"dunder"(abreviaçãode"double-underscore"ou"duplosublinhado").
Éassustador,não?Masnãosepreocupe,vamosexplicaroqueestaslinhassignificam!
Todasaslinhascomeçandocomfromouimportsãolinhasqueadicionamalgunspedaçosdeoutrosarquivos.Entãoaoinvésdecopiarecolarasmesmascoisasemcadaarquivo,podemosincluiralgumaspartescomfrom...import....
classPost(models.Model):-estalinhadefineonossomodelo(éumobjeto).
classéumapalavra-chaveespecialqueindicaqueestamosdefinindoumobjeto.Postéonomedonossomodelo,podemoslhedarumnomediferente(maséprecisoevitarosespaçosembrancoecaracteresespeciais).Semprecomeceumnomedeclassecomumaletramaiúscula.models.ModelsignificaqueoPostéummodelodeDjango,entãooDjangosabeelequedevesersalvonobancodedados.
Agorapodemosdefiniraspropriedadesquediscutimos:titulo,texto,data_criacao,data_publicacaoeautor.Paraissoprecisamosdefinirumtipodecampo(éumtexto?Éumnúmero?Umadata?Umarelaçãocomoutroobjeto,porexemplo,umusuário?).
models.CharField-assimécomovocêdefineumtextocomumnúmerolimitadodecaracteres.models.TextField-esteéparatextoslongossemumlimite.Seráidealparaumconteúdodepostdeblog,certo?models.DateTimeField-esteéumadataehora.
DjangoGirlsTutorial
56ModelosdoDjango
models.ForeignKey-esteéumlinkparaoutromodelo.Nósnãovamosexplicarcadapedaçodecódigoaqui,poisissolevariamuitotempo.VocêdeveolharadocumentaçãodoDJangosevocêquisersabermaissobrecamposdoModelecomodefinircoisasalémdestasdescritasacima(https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types).
Quetaldefpublish(self):?Éexatamenteonossométododepublishquefalávamosantes.def,significaquesetratadeumfunção/método.publishéonomedométodo.Vocêpodealterar,sequiser.Aregraéqueusamosletrasminúsculasesublinhadosemvezdeespaçosembranco(ouseja,sevocêquerterummétodoquecalculaopreçomédio,vocêpoderiachamá-localculate_average_price).
Métodosmuitasvezesreturnalgo.Háumexemplodeque,nométodo__str__.Nessecenário,quandochamamos__str__()teremosumtexto(string),comumtítulodoPost.
Sealgoaindanãoestáclarosobremodelos,sinta-selivreparapediroseutreinador!Sabemosqueémuitocomplicado,especialmentequandovocêaprenderoquesãoobjetosefunçõesaomesmotempo.Masesperoqueelesepareceumpoucomenosmágicaparavocêagora!
Criandotabelasparanossosmodelosnobancodedados
Oúltimopassoéadicionarnossonovomodeloparanossobancodedados.PrimeirotemosquefazeroDjangosaberquenóstemosalgumasmudançasemnossomodelo(sócriamosisso),digitepythonmanage.pymakemigrationsblog.Seráalgoparecidocomisto:
(myvenv)~/djangogirls$pythonmanage.pymakemigrationsblog
Migrationsfor'blog':
0001_initial.py:
-CreatemodelPost
Djangopreparaumarquivodemigraçãoquetemosdeaplicaragoraparanossobancodedados,tipopythonmanage.pymigrateblog,asaídadeveser:
(myvenv)~/djangogirls$pythonmanage.pymigrateblog
Operationstoperform:
Applyallmigrations:blog
Runningmigrations:
Applyingblog.0001_initial...OK
Viva!NossomodelodePostestáagoraemnossobancodedados,seriaumprazervê-lo,certo?SaltarparaopróximocapítuloparaveroaspectodoseuPost!
DjangoGirlsTutorial
57ModelosdoDjango
AdministraçãoParaadicionar,editareremoverpostagensquenóscriamosusaremosoDjangoadmin.
Vamosabriroarquivoblog/admin.pyesubstituirseuconteúdopor:
fromdjango.contribimportadmin
from.modelsimportPost
admin.site.register(Post)
Comovocêpodever,nósimportamos(incluímos)omodeloPostdefinidonocapítuloanterior.Paratornarnossomodelovisívelnapáginadeadministração,nósprecisamosregistrá-locom:admin.site.register(Post).
OK,horadeolharparaonossomodelodePost.Lembre-sedeexecutarpythonmanage.pyrunservernoconsoleparaexecutaroservidorweb.Váparaonavegadoredigiteoendereçohttp://127.0.0.1:8000/admin/Vocêveráumapáginadeloginassim:
Parafazerloginvocêprecisacriarumsuperuser-umusuárioquepossuicontrolesobretudodosite.Volteparaoterminaledigitepythonmanage.pycreatesuperuser,pressioneenteredigiteseunomedeusuário(caixabaixa,semespaço),endereçodee-maile
DjangoGirlsTutorial
58Administração
passwordquandoelesforemrequisitados.Nãosepreocupequevocênãopodeverasenhaquevocê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êdevevisualizaropaineldecontroledoDjangoadmin.
Váparaaspostagenseexperimenteumpoucocomelas.Adicionecincoouseispostagens.Nãosepreocupecomoconteúdo-vocêpodecopiarecolaralgumtextodestetutorialparaoconteúdoparaeconomizartempo:).
Certifique-sequepelomenosduasoutrêspostagens(masnãotodas)têmadatadepublicaçãodefinida.Issoseráútildepois.
DjangoGirlsTutorial
59Administração
SevocêquisersabermaissobreoDjangoadmin,vocêdeveconferiradocumentaçãodoDjango:https://docs.djangoproject.com/en/1.8/ref/contrib/admin/
Esteéprovavelmenteumbommomentoparatomarumcafé(ouchocolate)oualgoparacomerparareporaasenergias.VocêcriouseuprimeiromodelodeDjango-vocêmereceumpoucodedescanso!
DjangoGirlsTutorial
60Administração
Implantação!NotaOcapítuloseguintepodeseràsvezesumpoucodifícildepassar.Persistaetermine-o;Implantaçãoéumaparteimportantedoprocessodedesenvolvimentodewebsite.Estecapítuloestálocalizadonomeiodotutorialparaqueseututorpossalheajudarcomoprocessoligeiramentecomplexodecolocarseusiteonline.Istosignificaquevocêaindapodeterminarotutorialporcontaprópriasevocêcontinuaremoutromomento.
Atéagoranossositesóestavadisponívelnoseucomputador,agoravocêvaiaprendercomopublicarelenainternet!AimplantaçãoéoprocessodepublicaçãodoseuaplicativonaInternetdetalformaqueaspessoaspossam,finalmente,verseuaplicativo:).
Comovocêaprendeu,umwebsiteprecisaestarlocalizadonumservidor.Existemmuitosprovedores,masiremosutilizaroquetemumprocessodedeployrelativamentesimples:PythonAnywhere.PythonAnywhereégratuitoparaaplicaçõespequenasquenãopossuemmuitosvisitantes,entãoserásuficienteparavocêporenquanto.
OoutroserviçoexternoqueusaremoséGitHub,queéumserviçodehospedagemdecódigo.Existemoutros,masquasetodososprogramadorespossuemumacontanoGitHubatualmenteeagoravocêtambém!
UsaremosoGitHubcomoumtrampolimparatransportarnossocódigoparaoPythinAnywhere.
GitGité"sistemadecontroledeversão"usadopormuitosprogramadores-umsoftwarequecontrolamudançasnosarquivosaolongodotempoparaquevocêpossarecuperarversõesespecíficasdepois.Umpoucocomo"controlarmudanças"noMicrosoftWord,masmuitomaispoderoso.
InstalandooGit
Windows
DjangoGirlsTutorial
61Implantação!
VocêpodebaixarGitemgit-scm.com.Vocêpodeapertar"nextnextnext"emtodosospassosexcetoum;noquintopassochamado"AdjustingyourPATHenvironment",escolha"RunGitandassociatedUnixtoolsfromtheWindowscommand-line"(aopçãodebaixo).Alémdisso,opadrãoestáótimo.CheckoutestiloWindows,commitUnix-stylelinhasdeconfirmaçãoestábom.
MacOS
BaixarGitgit-scm.comesigaasinstruções.
Linux
Seelejánãoestiverinstalado,Gitdeveestardisponívelatravésdeseugerenciadordepacotes,entãotente:
sudoapt-getinstallgit
#or
sudoyuminstallgit
ComeçandonossorepositórionoGitGitcontrolaasalteraçõesparaumdeterminadoconjuntodearquivosnoquechamamosderepositóriodecódigo(ou"repo").Vamoscomeçarumparanossoprojeto.Abraoconsoleeexecuteessescomandos,nodiretóriodjangogirls:
Nota:Verifiqueoseudiretóriodetrabalhoatualcomumpwd(OSX/Linux)ouocomandocd(Windows)antesdeinicializarorepositório.Vocêdeveestarnapastadjangogirls.
$gitinit
InitializedemptyGitrepositoryin~/djangogirls/.git/
$gitconfiguser.name"YourName"
Inicializarorepositóriogitéalgoquesóprecisamosfazerumavezporprojeto(evocênãoteráquere-introduzironomedeusuárioee-mailnuncamais)
Gitirácontrolarasalteraçõesparatodososarquivosepastasnestediretório,masexistemalgunsarquivosquequeremosignorar.Fazemosissoatravésdacriaçãodeumarquivochamado.gitignorenodiretóriobase.Abraseueditorecrieumnovoarquivocomoseguinteconteúdo:
DjangoGirlsTutorial
62Implantação!
*.pyc
__pycache__
myvenv
db.sqlite3
.DS_Store
Esalvecomo.gitignorenapastadenívelsuperior"djangogirls".
Nota:Opontonoiníciodonomedoarquivoéimportante!Sevocêestátendoalgumadificuldadeemcriá-la(MacsnãogostamdecriararquivosquecomeçamcomumpontoatravésdoFinder,porexemplo),useorecurso"SaveAs"noseueditorquesemprefunciona.
Éumaboaidéiaparausarumcomandodegitstatusantesdegittaddousemprequevocênãotivercertezadequeseráfeito,paraevitarsurpresas(porexemplo,serãoadicionadosarquivoserradosoucommitados).Ocomandogitstatusretornainformaçõessobretodososarquivoscontrolado/modificado/encenado,statusderamoemuitomais.Ooutputdevesersemelhantea:
$gitstatus
Onbranchmaster
Initialcommit
Untrackedfiles:
(use"gitadd<file>..."toincludeinwhatwillbecommitted)
.gitignore
blog/
manage.py
mysite/
nothingaddedtocommitbutuntrackedfilespresent(use"gitadd"totrack)
Efinalmentenóssalvamosnossasalterações,Váparaoseuconsoleeexecuteestescomandos:
$gitadd-A.
$gitcommit-m"MyDjangoGirlsapp,firstcommit"
[...]
13fileschanged,200insertions(+)
createmode100644.gitignore
[...]
createmode100644mysite/wsgi.py
DjangoGirlsTutorial
63Implantação!
EmpurrandoonossocódigoparaGitHubVáparaGitHub.comecadastreumanovaegratuitacontadeusuário.Emseguida,crieumnovorepositório,edêonome"my-first-blog".Deixeo"initialisewithaREADME"desmarcado,deixeaopção.gitignoreembranco(jáfizemosissomanualmente)ealicençacomoNone.
NotaOnomemy-first-blogéimportante--vocêpoderiaescolheroutracoisa,masvamosusá-lomuitasvezesnasinstruçõesabaixoevocêteriaquesubstituí-locadavez.Éprovavelmentemaisfácilficarcomonomemy-first-blog.
Natelaseguinte,vocêserámostradaacloneURLdoseurepo.Escolhaaversão"HTTPS",copie,evamoscolá-lonoterminalembreve:
DjangoGirlsTutorial
64Implantação!
AgoraprecisamosligarorepositórioGitnoseucomputadorcomonoGitHub.
$gitremoteaddoriginhttps://github.com/<your-github-username>/my-first-blog.git
$gitpush-uoriginmaster
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,oDjangoGirlsTutorialemuitosoutrosgrandesprojetosdesoftwaredefonteabertatambémhospedamseucódigonoGitHub:)
CriaçãodenossoblogemPythonAnywhereEmseguida,éhoradeseinscreverparaumacontagratuitade"Beginner"naPythonAnywhere.
DjangoGirlsTutorial
65Implantação!
www.pythonanywhere.comNota:aoescolherseunomedeutilizadoraqui,tenhaemmentequeaURLdoseublogteráoformulárioyourusername.pythonanywhere.com,entãoescolhaseunicknameouonomedoqueéoblog.
PullingourcodedownonPythonAnywhereQuandovocêseinscreveparaPythonAnywhere,vocêélevadoaoseupaineldecontroleoupágina"Consoles".Escolhaaopçãoiniciaroconsole"Bash"--queéaversãoPythonAnywheredeumconsole,comoaquelanoseuPC
Nota:PythonAnywhereébaseadoemLinux,assimsevocêestivernoWindowsoconsolevaiparecerumpoucodiferentedoqueestánoseucomputador.
VamospuxarnossocódigodeGitHubemPythonAnywhereatravésdacriaçãodeum"clone"dorepo.DigiteoseguinteparaoconsolenaPythonAnywhere:
$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:
DjangoGirlsTutorial
66Implantaçã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".Arquivosestáticosfuncionamdeformadiferentenosservidoresemcomparaçãocomnossoprópriocomputador,eprecisamosdeumaferramentacomoo"whitenoise"paraatendê-los.
Vamosdescobrirumpoucomaissobrearquivosestáticosmaistardenotutorial,quandovamoseditaroCSSparaonossosite.
Porenauntosóprecisamosexecutarumcomandoextrachamado"collectstatic"noservidor.IssodizproDjangoreunirtodososarquivosestáticosqueeleprecisanoservidor.Emsuamaioria,estessãoosarquivosestáticosquefazemositedoadminbonitonomomento.
20:20~$pythonmanage.pycollectstatic
Youhaverequestedtocollectstaticfilesatthedestination
locationasspecifiedinyoursettings:
/home/edith/my-first-blog/static
Thiswilloverwriteexistingfiles!
Areyousureyouwanttodothis?
Type'yes'tocontinue,or'no'tocancel:yes
Digite"Sim"evaiembora!Vocênãoadorafazercomputadoresimprimirpáginasepáginasdetexto?Semprefaçopequenosruídosparaacompanhá-lo.Brp,brpbrp...
DjangoGirlsTutorial
67Implantação!
opying'/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ãoascontasdeusuárioemensagenspodemserdiferentesnoservidorenoseucomputador.
Entãonósvamosinicializarobancodedadosnoservidortalcomofizemosnoseuprópriocomputador,commigrateecreatesuperuser:
(mvenv)20:20~$pythonmanage.pymigrate
Operationstoperform:
[...]
Applyingsessions.0001_initial...OK
(mvenv)20:20~$pythonmanage.pycreatesuperuser
PublicaçãodonossoblogcomoumaplicativowebAgoranossocódigoestánaPythonAnywhere,nossavirtualenvestápronta,osarquivosestáticosestãorecolhidoseobancodedadosestáinicializado,estamosprontosparapublicá-locomoumaplicativodaweb.
CliqueemvoltarparaoPythonAnywheredashboardclicandonoseulogotipoecliquenaguiaWebeváemAddanewwebapp.
Nacaixadediálogo,apósaconfirmaçãodeseunomededomínio,escolhamanualconfiguration(NBnãoaopção"Django").Emseguida,escolhaPython3.4ecliqueemNextparaconcluiroassistente.
Notacertifique-sevocêescolheuaopção"Manualconfiguration",nãoa"Django".NóssomosdemaisparaopadrãodeconfiguraçãoDjangodaPythonAnywhere;-)
Definindoovirtualenv
DjangoGirlsTutorial
68Implantação!
VocêserálevadoparaateladeconfiguraçãodePythonAnywhereparaseuwebappqueéondevocêprecisarádeirquandoquiserfazeralteraçõesparaoaplicativonoservidor.
Naseção"Virtualenv",cliquenotextovermelhoquediz"Enterthepathtoavirtualenv"edigite:/home//my-first-blog/myvenv/
Nota:substituaseupróprionomedeusuárioconformeapropriado.Sevocêcometerumerro,PythonAnywhereirámostrarumpequenoaviso.
ConfigurandooarquivoWSGI
DjangofuncionausandooWSGIprotocol,umpadrãoparaservirsitesusandoPython,queoferecesuporteaPythonAnywhere.AmaneiraqueconfiguramosPythonAnywhereparareconhecernossoblogDjangoéeditandoumarquivodeconfiguraçãodoWSGI.
Cliquenolink"AWSGIconfigurationfile"(naseção"Code"pertodotopodapágina--elevaisernomeadoalgocomo/var/www/<your-username>_pythonanywhere_com_wsgi.py),evocêserálevadoparaumeditor.
Excluatodooconteúdoatualesubstituacomalgoparecidocomisto:
DjangoGirlsTutorial
69Implantação!
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çãowebequalonomedoarquivodeconfiguraçõesDjango.Eletambémdefineaferramentadearquivosestáticos"whitenoise".
AperteSaveeentãovolteparaaguiaWeb.
Játerminamos!AperteobotãograndeverdedeReloadevocêserácapazdeirverosseuaplicativo.Vocêencontraráumlinkparaelenotopodapágina.
DicasdedebuggingSevocêvirumerroquandovocêtentavisitaroseusite,oprimeirolugarparaprocuraralgumainformaçãodedebuggingénoseuerrorlog--vocêencontraráumlinkparaissonaguiawebPythonAnywhere.Versehámensagensdeerrolá.Asmaisrecentesestãonaparteinferior.Problemascomunsincluem
esquecerumdospassosquefizemosnoconsole:criandoovirtualenv,ativá-lo,instalandooDjango,collectstatic,inicializandoobancodedadoscometerumerronocaminhodovirtualenvnaguiaweb--haverágeralmenteumapequenamensagemdeerrovermelholá,seháumproblemacometerumerronoarquivodeconfiguraçãoWSGI..--vocêusouocaminhoparaapastadomy-first-blogcertinho?
Otreinadorestáaquiparaajudar!
Vocêestálive!
DjangoGirlsTutorial
70Implantação!
Apáginapadrãoparaseusitedevedizer"Bem-vindoaoDjango",comoacontecenoseuPClocal.Tenteadicionar/admin/paraofinaldaURL,evocêserálevadoaositeadmin.Fazerlogincomonomedeusuárioesenha,evocêveráquevocêpodeadicionarnovasmensagensnoservidor.
Dëemvocêmesmaumenormetapinhanascostas-implantaçõesdeservidorsãoumadaspartesmaisdifíceisdodesenvolvimentoweb,emuitasvezeslevaaspessoasváriosdiasantesdefazerfuncionar.Masvocêtemseusitepublicado,nainternet,assim!
DjangoGirlsTutorial
71Implantação!
UrlsEstamosprestesaconstruirnossaprimeiraWebpage-umapáginainicialparaoseublog!Masprimeiro,vamosaprenderumpoucomaissobreDjangourls.
OqueéumaURL?UmaURLésimplesmenteumendereçodaweb,vocêpodeverumaURLtodavezquevocêvisitaqualquersite-évisívelnabarradeendereçosdoseunavegador(Sim!127.0.0.1:8000éumaURL!Ehttp://djangogirls.comtambéméumaURL):
CadapáginanaInternetprecisadesuaprópriaURL.DestaformaseuaplicativosabeoquedevemostraraumusuárioqueabreumaURL.EmDjango,nósusamosalgochamadoURLconf(configuraçãodeURL),queéumconjuntodepadrõesqueDjangovaitentarcoincidircomaURLrecebidaparaencontraravisãocorreta.
ComofuncionamasURLsemDjango?Vamosabriroarquivomysite/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.
DjangoGirlsTutorial
72Urls
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çacomadmin/oDjangoiráencontrarumcorrespondentemododeexibição.NestecasonósestamosincluindoummontedeadminURLsparaqueissonãofiquetudoembaladonestepequenoarquivo..--émaislegívelemaislimpo.
RegexVocêquersabercomooDjangocoincidecomURLsparaviews?Bem,estaparteécomplicada.oDjangousaoregex--expressõesregulares.Regextemmuito(muito!)denormasqueformamumpadrãodepesquisa.Comoregexessãoumtópicoavançado,nósveremosemdetalhescomoelasfuncionam.
Sevocêaindaquiserentendercomocriamosospadrões,aquiestáumexemplodoprocesso-sóprecisamosumsubconjuntolimitadoderegrasparaexpressaropadrãoqueprocuramos,ouseja:
^paraoiníciodotexto
$paraofinaldotexto
\dparaumdígito
+paraindicarqueoitemanteriordeveserrepetidopelomenosumavez
()paracapturarpartedopadrão
Qualqueroutracoisanadefiniçãodeurlserálevadaliteralmente.
Agoraimaginequevocêtemumsitecomoendereçoassim:http://www.mysite.com/post/12345/,onde12345éonúmerodoseupost.
Escreverviewsseparadasparatodososnúmerosdepostseriamuitochato.Comexpressõesregularespodemoscriarumpadrãoqueirácoincidircomaurleextraironúmeroparanós: post/(\d+)/$.Vamosaospoucosveroqueestamosfazendoaqui:
^post/estádizendoaoDjangoparapegartudoquetenhapost/noiníciodaurl(logoapóso )(\d+)significaquehaveráumnúmero(umoumaisdígitos)equequeremosonúmerocapturadoeextraído/dizparaoDjangoquedeveseguiroutro/
DjangoGirlsTutorial
73Urls
$indicaofinaldaURLsignificandoqueapenassequênciasterminandocomo/irãocorresponderaessepadrão
SuaprimeiraurlDjango!ÉhoradecriarnossaprimeiraURL!Queremoshttp://127.0.0.1:8000/paraserumapáginainicialdonossoblogeexibirumalistadeposts.
Tambémqueremosmanteroarquivodemysite/urls.pylimpo,aínósimportaremosurlsdanossaaplicaçãoblogparaoarquivoprincipalmysite/urls.py.
Váemfrente,apagueaslinhascomentadas(aslinhasquecomeçamcom#)eadicioneumalinhaquevaiimportarblog.urlsparaaurlprincipal('').
Oseuarquivomysite/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/'parablog.urlseprocurarpornovasinstruçõeslá.
AoescreverasexpressõesregularesemPythonésemprefeitocomrnafrentedasequência-issoésóumadicaútilparaPythonqueaseqüênciapodecontercaracteresespeciaisquenãosãodestinadasparaPythonemsi,masemvezdissosãopartedaexpressãoregular.
blog.urlsCrieumnovoarquivovazioblog/urls.py.Tudobem!Adicioneestasduasprimeiraslinhas:
fromdjango.conf.urlsimportinclude,url
from.importviews
AquinósestamosapenasimportandométodosdoDjangoetodososnossosviewsdoaplicativoblog(aindanãotemosnenhuma,masteremosemumminuto!)
DepoisdissonóspodemosadicionarnossoprimeiraURLpadrão:
DjangoGirlsTutorial
74Urls
urlpatterns=[
url(r'^$',views.post_list),
]
Comovocêpodever,estamosagoraatribuindoumaviewchamadapost_listpara $
URL.Essaexpressãoregularcorresponderáa (umcomeço)seguidopor$(fim)-entãosomenteumaseqüênciavaziairácorresponder.Eissoécorreto,porqueemresolvedoresdeDjangourl,'http://127.0.0.1:8000/'nãoéumapartedaURL.EstepadrãoirámostraroDjangoqueviews.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écomochamamosonossoview!Issosignificaqueestátudonolugar,sónãocriamosnossaviewainda.Nãosepreocupe,nóschegaremoslá.
SevocêquersabermaissobreDjangoURLconfs,vejaadocumentaçãooficial:https://docs.djangoproject.com/en/1.8/topics/http/urls/
DjangoGirlsTutorial
75Urls
Views-horadecriar!Éhoraderesolverobugquecriamosnocapítuloanterior:)
Umaviewécolocadaondenóscolocamosa"lógica"danossaaplicação.Eleirásolicitarinformaçõesapartirdomodelquevocêcriouantesepassá-loparaumtemplatequevocêvaicriarnopróximocapítulo.Views,nofundo,nãopassamdemétodosescritosemPythonquesãoumpoucomaiscomplicadosdoqueaquiloquefizemosnocapítuloIntroduçãoaoPython.
Asviewssãopostasnoarquivoviews.py.Nósvamosadicionarnossasviewsnoarquivoblog/views.py.
blog/views.pyOK,vamosabriroarquivoeveroquetemnele:
fromdjango.shortcutsimportrender
#Createyourviewshere.
Nãotemmuitacoisa.Aviewmaisbásicaseparececomisto.
defpost_list(request):
returnrender(request,'blog/post_list.html',{})
Comovocêpodever,nóscriamosummétodo(def)chamadopost_listqueaceitaopedidoeretornarummétodorenderseráprocessado(paramontar)nossomodeloblog/post_list.html.
Salveoarquivo,váparahttp://127.0.0.1:8000/evejaoquetemosagora.
Outroerro!Leiaoqueestáacontecendoagora:
DjangoGirlsTutorial
76Views-horadecriar!
Estaéfácil:TemplateDoesNotExist.Vamoscorrigirestebugecriarummodelonopróximocapítulo!
AprendamaissobreasviewsdoDjangolendoadocumentaçãooficial:https://docs.djangoproject.com/en/1.8/topics/http/views/
DjangoGirlsTutorial
77Views-horadecriar!
IntroduçãoaHTMLVocêpodeseperguntar:eoqueéumtemplate?
Umtemplateéumarquivoquenóspodemosreutilizarparaapresentardiferentesinformaçõesdeumaformaconsistente.Porexemplo,vocêpoderiausarumtemplateparateajudaraescreverumacarta,pois,emboracadacartapossuaumamensagemeumdestinodiferente,todasterãosempreomesmoformato.
OformatodotemplatedoDjangoédescritoemumalinguagemchamadaHTML(esseéomesmHTMLquemencionamosnoprimeirocapítuloComoaInternetfunciona).
OqueéHTML?HTMLéumsimplescódigoqueéinterpretadopeloseunavegadorweb-comooChrome,oFirefoxouoSafari-paraexibirumapáginadawebparaousuário.
HTMLsignifica"HyperTextMarkupLanguage".HiperTextsignificaqueéumtipodetextoquesuportahiperlinksentrepáginas.Marcaçãonadamaiséquemarcarumdocumentocomcódigosquedizemparaalguém(nessecaso,onavegadorweb)comoapáginadeveráserinterpretada.CódigoemHTMLéfeitocomtags,cadaumacomeçandocom<eterminandocom>.Essastagsmarcamoselementos.
Seuprimeirotemplate!Criarumtemplatesignificacriarumarquivodetemplate.Tudoéumarquivo,certo?Provavelmentevocêjádeveternotadoisso.
Ostemplatessãosalvosnodiretórioblog/templates.Logo,crieumdiretóriochamadotemplatesdentrododiretóriodoseublog.Emseguida,crieoutrodiretóriochamadoblogdentrodadiretóriotemplates:
blog
└───templates
└───blog
(Vocêdeveestarseperguntandoporquenósprecisamosdedoisdiretórioschamadosblog-comovocêdescobrirámaisparafrente,essaéumasimpleseútilconvençãoquefacilitaavidaquandoascoisascomeçaremaficarmaiscomplicadas.)
DjangoGirlsTutorial
78IntroduçãoaHTML
Eagoranóscriamosoarquivopost_list.html(deixe-oembrancoporagora)dentrododiretórioblog/templates/blog.
Vejacomoonossositeestáseparecendoagora:http://127.0.0.1:8000/
SeocorrerumerrodeTemplateDoesNotExiststentereiniciaroseuservidor.Entrenalinhadecomando,pareoservidorpressionandoCtrl+C(ControlseguidodateclaC,juntas)ereinicie-orodandopythonmanage.pyrunserver.
Acabaram-seoserros!Parabéns:)Entretanto,nossositenãomostranadaanãoserumapáginaembranco.Issoporqueonossotemplateestá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>sempreestaránofim.Comovocêpodever,todooconteúdode
DjangoGirlsTutorial
79IntroduçãoaHTML
umwebsiteseencontraentreatagdeinício<html>eentreatagdefim</html><p>éatagquedenominaparágrafos;</p>determinaofimdecadaparágrafo
Head&bodyCadapá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>dizaonavegadoroquehádeverdadenapágina.
Porexemplo,vocêpodeporoelementotítulodeumapáginawebdentrodatag<head>.Veja:
<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>ecolocouotextonabarradetítulodoseunavegador(etambémseráusadoparaosfavoritoseoutrascoisasmais).
DjangoGirlsTutorial
80IntroduçãoaHTML
Provavelmentevocêjádeveternotadoquecadatagdeaberturacasacomumatagdefechamento,comuma/,equeoselementosestãoaninhados(ex.:vocênãopodefecharumtagemparticularantesquetodasasoutrastagsqueestiveremdentrodelajáestejamfechadas).
Écomocolocarcoisasdentrodecaixas.Vocêtemumagrandecaixa,<html></html>;dentrodelahá<body></body>,sendoqueestaaindacontémcaixasmenors:<p></p>.
Vocêprecisaseguiressasregrasdefechamentodetags,edeaninhamentodeelementos-sevocênãofizerisso,onavegadorpoderánãoestaraptoparainterpretarseucódigodemaneiracorretaesuapáginaseráexibidademaneiraincorreta.
CustomizeseutemplateAgoravocê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="http://djangogirls.org">link</a>criaumlink<ul><li>primeiroitem</li><li>segundoitem</li></ul>criaumalista,exatamentecomoessa!<div></div>defineumaseçãodapágina
Aquiestáumexemplodeumtemplatecompleto:
DjangoGirlsTutorial
81Introduçã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.Donecidelitnonmiportagravidaategetmetus.Fuscedapibus,tellusaccursuscommodo,tortormauriscondimentumnibh,utfermentummassajustositametrisus.
</div>
<div>
<p>published:14.06.2014,12:14</p>
<h2><ahref="">Mysecondpost</a></h2>
<p>Aeneaneuleoquam.Pellentesqueornaresemlaciniaquamvenenatisvestibulum.Donecidelitnonmiportagravidaategetmetus.Fuscedapibus,tellusaccursuscommodo,tortormauriscondimentumnibh,utf.
</div>
</body>
</html>
Nóscriamostrêsseçõesdivaqui.
Oprimeiroelementodivpossuiotítulodonossoblog-éumtítuloeumlinkOsoutrosdoiselementosdivpossuemnossaspostagenscomadatadepublicação,h2comotítulodapostagemqueéclicáveledoisps(parágrafos)detexto,umparaadataeoutroparaotextodapostagem.
Issonosdáoseguinteefeito:
DjangoGirlsTutorial
82IntroduçãoaHTML
Yaaay!Mas,atéagora,nossotemplatemostraexatamantesempreamesmainformação-sendoque,anteriormente,nósfalávamossobretemplatescomoumamaneiraparaexibirinformaçõesdiferentesemummesmoformato.
OquenósrealmentequeremosfazeréexibirpostagensreaisqueforamadicionadasnoDjangoadmin-eissoéoquefaremosemseguida.
Maisumacoisa:deploy!SeriabomvertudoistonaInternet,certo?VamosfazeroutrodeployPythonAnywhere:
Commit,eponhaseucódigonoGitHub
Primeirodetudo,vejamosquaisarquivosforamalteradosdesdeaúltimaimplantação:
$gitstatus
Verifiquesevocêestánodiretóriodjangogirlsevamosdizeraogitparaincluirtodasasmudançasdentrodestediretório:
$gitadd-A.
DjangoGirlsTutorial
83IntroduçãoaHTML
Nota-A(abreviaçãode"all",tudoeminglês)significaqueogittambémreconhecerásevocêdeletoualgumarquivo(porpadrão,ogitapenasreconhecearquivoscriados/modificados).Lembre-setambém(docapítulo3)que.significaodiretórioatual.
Antesdenósfazermosouploaddetodososaqruivos,chequemosoqueogitenviará(todososarquivosqueogitforenviardeveráapareceemverde):
$gitstatus
Estamosquaselá!Agoraéhoradedizeraeleparasalvaressamodificaçãoemseuhistórico.Nósdaremosaeleuma"mensagemdecommit"ondenósdescrevemosasmodificaçõesquefizemos.Vocêpodeescreveroquevocêquiseragora,masserámaisútilsevocêescreveralgumacoisamaisdescritiva,algoparavocêpoderselembrardascoisasquevocê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
[...]
Evejaseucódigosendobaixado.Sevocêdesejaverificarsejáchegou,podeirparaaFilestabeverseucódigonoPythonAnywhere.
Finalmente,puleparaaWebtabeaperteReloademseuaplicativoweb.
DjangoGirlsTutorial
84IntroduçãoaHTML
Suaatualizaçãodeveestarlive!Váemfrenteeatualizeseusitenonavegador.Asalteraçõesdevemservisíveis:)
DjangoGirlsTutorial
85IntroduçãoaHTML
QuerySetseORMdoDjangoNestecapítulovocêvaiaprendercomoDjangoseconectaaobancodedadosecomoelearmazenadados.Vamosnessa!
OqueéumQuerySet?UmQuerySet(conjuntodepesquisa),nofundo,éumalistadeobjetosdeumdadomodelo.UmQuerySetpermitequevocêleiaosdadosdobanco,filtreeordeneomesmo.
Émaisfácilaprenderporexemplos.Vamostentar?
OShelldoDjangoAbraoterminaledigite:
(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
DjangoGirlsTutorial
86DjangoORM(Querysets)
Oops!Umerroapareceu.ElenosdizquenãoexistealgochamadoPost.Éverdade--nósesquecemosdeimportá-loprimeiro!
>>>fromblog.modelsimportPost
Issoésimples:importamosomodeloPostdedentrodoblog.models.Vamostentarmostrartodasaspostagensnovamente:
>>>Post.objects.all()
[<Post:myposttitle>,<Post:anotherposttitle>]
Éumalistadospostsquecriamosanteriormente!CriamosessespostsusandoainterfacedeadministraçãodoDjango.Noentanto,agoraqueremoscriarnovasmensagensutilizandoopython,entãocomoéquefazemosisso?
Criandoumobjeto
ÉassimquevocêcriaumobjetoPostnobancodedados:
>>>Post.objects.create(author=me,title='Sampletitle',text='Test')
Masaquitemosumingredientequefaltava:me.PrecisamospassarumainstânciadeUsermodelocomoautor.Comofazerisso?
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ósagorausamosumgetaUserwithausernameiguala'ola'.Claro,vocêtemqueadaptaraseunomedeusuário.
Agorafinalmentepodemoscriarnossaprimeirapostagem:
DjangoGirlsTutorial
87DjangoORM(Querysets)
>>>Post.objects.create(author=me,title='Sampletitle',text='Test')
Viva!Querversefuncionou?
>>>Post.objects.all()
[<Post:Sampletitle>]
Adicionemaispostagens
Agora,vocêpodesedivertirumpoucoeadicionarmaispostagensparavercomofunciona.Adicionemais2-3esigaparaapróximaparte.
Filtrarobjetos
UmagrandepartedeQuerySetséahabilidadedefiltrá-los.Digamosquequeremosencontrartodosaspostagensescritaspelousuárioola.NósusaremosofilteremvezdeallemPost.objects.all().Entreparêntesesindicamosqueascondiçõesprecisamseratendidasporumpostagemdeblogparaacabaremnossoqueryset.Emnossocasoéauthorqueéigualame.AmaneiradeescreverissonoDjangoé:author=me.Agoraonossotrechodecódigoparececomeste:
>>>Post.objects.filter(author=me)
[<Post:Sampletitle>,<Post:Postnumber2>,<Post:My3rdpost!>,<Post:4thtitleofpost>]
Outalveznósqueremosvertodosospostsquecontenhamapalavra'title'nocampodetitle?
>>>Post.objects.filter(title__contains='title')
[<Post:Sampletitle>,<Post:4thtitleofpost>]
NotaExistemdoiscaracteresdesublinhado(_)entreotitleecontains.DjangoORMusaestasintaxeparasepararnomesdecampo("title")eoperaçõesoufiltros("contains").Sevocêusarapenasumsublinhado,vocêobteráumerrocomo"FieldError:Cannotresolvekeywordtitle_contains".
Vocêtambémpodeobterumalistadetodosospostspublicados.Fazemosissofiltrandotodosospostscompublished_datedefinidonopassado:
fromdjango.utilsimporttimezonePost.objects.filter(published_date__lte=timezone.now())[]
DjangoGirlsTutorial
88DjangoORM(Querysets)
Infelizmente,nenhumdosnossospostsestãopublicadosainda.Nóspodemosmudarisso!Primeiroobtenhaumainstânciadeumpostquequeremospublicar:
>>>post=Post.objects.get(id=1)
Eentãopublicá-locomonossométododepublish!
>>>post.publish()
Agoratenteobteralistadepostspublicadosnovamente(pressioneasetaparacimabotão3vezesetecleEnter):
>>>Post.objects.filter(published_date__lte=timezone.now())
[<Post:Sampletitle>]
Ordenandoobjetos
UmQuerySettambémnospermiteordenaralistadeobjetos.Vamostentarordenaraspostagenspelocampocreated_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()
$
DjangoGirlsTutorial
89DjangoORM(Querysets)
DjangoQuerysetsNóstemosdiferentespeçasaqui:omodelPostestádefinidoemmodels.py,nóstemospost_listnoviews.pyeotemplateadicionado.MascomonósfaremosdefatoparafazercomqueasnossaspostagensapareçamnonossotemplateemHTML?Porqueéissoquenósqueremos:pegaralgumconteúdo(modelssalvosnobancodedados)eexibi-lodeumamaneirabacananonossotemplate,certo?
Eissoéexatamenteoqueasviewsdevemfazer:conectarmodelsetemplates.Nanossaviewpost_listviewnósvamosprecisarpegarosmodelsquequeremosexibirepassá-losparaotemplate.Então,basicamente,emumaviewnósdecidimosoque(ummodel)seráexibidonotemplate.
Certo,ecomonósfaremosisso?
Precisamosabrironossoblog/views.py.Atéagoraaviewpost_listseparececomisso:
fromdjango.shortcutsimportrender
defpost_list(request):
returnrender(request,'blog/post_list.html',{})
Lembraquandofalamossobreainclusãodecódigoescritoemarquivosdiferentes?Agoraéomomentoemquetemosdeincluiromodelquetemosescritoemmodels.py.Vamosadicionarestalinhafrom.modelsimportPostcomoeste:
fromdjango.shortcutsimportrender
from.modelsimportPost
Opontodepoisdefromsignificaodiretórioatualouoaplicativoatual.Comoviews.pyemodels.pyestãonomesmodiretóriopodemossimplesmenteusar.eonomedoarquivo(sem.py).Entãonósimportamosonomedomodelo(Post).
Eoquevemagora?ParapegarospostsreaisdomodelPostnósprecisamosdeumacoisachamadaQuerySet.
QuerySet
DjangoGirlsTutorial
90Dadosdinâmicosnostemplates
VocêjádeveestarfamiliarizadocomomodoqueosQuerySetsfuncionam.NósconversamossobreissonocapítuloORMdoDjango(QuerySets).</p>Agoranósestamosinteressadosemumalistadepostsquesãopublicadoseclassificadosporpublished_date,certo?NósjáfizemosissonocapítuloQuerySets!
Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
Agoranóscolocamosestepedaçodecódigodentrodoarquivoblog/views.pyadicionando-oàfunçãodefpost_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.Deagoraemdiantenóspodemosnosreferiraeleporestenome.
AúltimapartequefaltaépassaroQuerySetpostsparaotemplate(veremoscomoexibi-loemumpróximocapítulo).
Nafunçãorenderjátemosoparâmetrorequest(tudooquerecebemosdousuárioatravésdaInternet)eumarquivodetemplate'blog/post_list.html'.Oúltimoparâmetro,queseparececomisso:{}éumlugaremquepodemosacrescentaralgumascoisasparaqueotemplateuse.Precisamosnomeá-los(ficaremoscom'posts'porenquanto:)).Deveficarassim:{'posts':posts}.Observequeaparteantesde:estáentreaspas''.
Entãofinalmentenossoarquivoblog/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!
DjangoGirlsTutorial
91Dadosdinâmicosnostemplates
SequiserlermaissobreQuerySetsnoDjangovocêdevedarumaolhadaaqui:https://docs.djangoproject.com/en/1.8/ref/models/querysets/
DjangoGirlsTutorial
92Dadosdinâmicosnostemplates
TemplatesHoradeexibiralgumdado!Djangonosdátagsdetemplatesembutidasbastanteúteisparaisso.
Oquesãotagsdetemplate?Comopodever,vocênãopodecolocarcódigoPythonnoHTML,porqueosnavegadoresnãoirãoentender.ElesapenasconhecemHTML.NóssabemosqueHTMLébastanteestático,enquantoPythonémuitomaisdinâmico.
TagsdetemplateDjangonospermitetransformarobjetosPythonemcódigoHTML,paraquevocêpossaconstruirsitesdinâmicosmaisrápidoemaisfácil.Uhuu!
ModelodelistadepostdeexibiçãoNocapituloanterior,nósfornecemosaonossotemplateumalistadepostagenseavariávelposts.AgoravamosexibiremnossoHTML.
ParaexibirumavariávelnoDjangotemplate,nósusamoscolchetesduploscomonomedavariáveldentro,exemplo:
{{posts}}
Tentarfazerissonoseutemplateblog/templates/blog/post_list.html(substituiaosegundoeoterceiropardetags<div></div>pelalinha{{posts}}),salveoarquivoeatualizeapáginaparaverosresultados:
Vocêpodever,tudoquetemosé:
DjangoGirlsTutorial
93Templates
[<Post:Mysecondpost>,<Post:Myfirstpost>]
IstosignificaqueoDjangoaentendecomoumalistadeobjetos.Lembre-sedeintroduçãoaoPythoncomopodemosexibirlistas?Sim,comosloops!EmumtemplateDjango,fazemosissodaseguintemaneira:
{%forpostinposts%}
{{post}}
{%endfor%}
Tentefazerissonoseutemplate.
Funciona!Masnósqueremosqueelessejamexibidoscomoospostsestáticos,comoosquecriamosanteriormentenocapítulodeIntroduçãoaHTML.NóspodemosmisturarHTMLcomtagsdetemplate.Oconteúdodatagbodyficará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|linebreaks}}</p>
</div>
{%endfor%}
Tudoquevocêpõeenrte{%for%}e{%endfor%}serárepetidoparacadaobjetonalista.Atualizesuapágina:
DjangoGirlsTutorial
94Templates
Vocênotouquedessaveznósusamosumanotaçãoumpoucodiferente{{post.title}}ou{{post.text}}?NósestamosacessandoosdadosemcadaumdoscamposquedefinimosnomodeldoPost.Alémdisso,|linebreaksestápassandootextodopostporumfiltro,convertendoquebrasdelinhaemparágrafos.
MaisumacoisaSeriabomverseseusiteaindaestaráfuncionandonainternet,certo?VamostentarimplantaraPythonAnywherenovamente.Aquiestáumresumodospassos...
Primeiro,envieseucódigoparaoGithub
$gitstatus
$gitadd-A.
$gitstatus
$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."
$gitpush
Emseguida,façaloginemPythonAnywhereeváparaseuBashconsole(oucomeceumnovo)eexecute:
$cdmy-first-blog$gitpull
DjangoGirlsTutorial
95Templates
Finalmente,puleparaaWebtabeaperteReloademseuaplicativoweb.Suaatualizaçãodeveestarlive!
Parabéns!AgoraváemfrenteetenteadicionarumnovopostemseuDjangoadmin(Lembre-sedeadicionarpublished_date!),emseguida,atualizeapáginaparaverseopostapareceporlá.
Funcionacomomágica?Estamosorgulhosos!Afaste-sedoseucomputadorumpouco,vocêganhouumapausa.:)
DjangoGirlsTutorial
96Templates
CSS-Deixemaisbonito!Nossoblogaindaparecefeio,certo?Estánahoradedeixarelemelhor!ParaissonósusaremosoCSS.
OqueéCSS?Doinglês"CascadingStyleSheets",CSSéumalinguagemusadaparadescreveroaspectoeaformataçãodeumwebsiteescritonumalinguagemdemarcação(comoHTML).Imagineelecomosendoumtipode"maquiagem"paranossosite;).
Masnósnãoqueremosiniciardozerodenovo,certo?Nóstentaremos,maisumavez,usaralgoquefoifeitoedisponibilizadodegraçaporprogramadoresnainternet.Vocêsabe,reinventararodanãoénadadivertido.
VamosusaroBootstrap!BootstrapéumdosmaisfamososepopularesframeworksdeHTMLeCSSparadesenvolversitesbonitos:http://getbootstrap.com/
FoiescritoporprogramadoresquetrabalharamnoTwittereagoraédesenvolvidoporvoluntáriosdetodoomundo.
InstalarBootstrapParainstalaroBootstrap,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.Apenassigaemfrente,abraseusiteeatualizeapágina.Aquieleestá!
DjangoGirlsTutorial
97CSS-Deixemaisbonito
Jáparecendomelhor!
ArquivosestáticosnoDjangoFinalmentenósteremosumolharmaisatentonessascoisasquechamamosarquivosestáticos.ArquivosestáticossãotodasassuasimagensearquivosCSS--arquivosquenãosãodinâmicos,entãoseuconteúdonãodependedocontextodarequisiçãoeseráomesmoparatodososusuários.
OndecolocarosarquivosestáticosparaDjango
Comovocêviuquandorodamoscollectstaticnoservidor,Djangojásabeondeencontrarosarquivosestáticosparaobuilt-in"admin"app.Agorasóprecisamosadicionaralgunsarquivosestáticosparanossopróprioapp,blog.
Fazemosissoatravésdacriaçãodeumapastachamadastaticdentrodoaplicativodoblog:
djangogirls
├──blog
│├──migrations
│└──static
└──mysite
Djangoencontraráautomaticamentetodasaspastaschamadas"static"dentrodequalquerumadaspastasdosseusapps,eserácapazdeusarseuconteúdocomoarquivosestáticos.
DjangoGirlsTutorial
98CSS-Deixemaisbonito
SeuprimeiroarquivoCSS!VamoscriarumarquivoCSSagora,paraadicionarseupróprioestiloparasuapáginadaweb.Crieumnovodiretóriochamadocssdentrodeseudiretóriostatic.Emseguida,crieumnovoarquivochamadoblog.cssdentrododiretóriocss.Pronto?
djangogirls
└───blog
└───static
└───css
└───blog.css
HoradeescreverCSS!Abraoarquivostatic/css/blog.cssnoseueditordecódigo.
NãovamosnosaprofundarmuitoemcustomizareaprendersobreCSSaqui,porqueébemfácilevocêpodeaprendernoseupróprioapósesteworkshop.RecomendamosfortementefazeresteCodeacademyHTML&CSScouseparaaprendertudooquevocê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émusarcorespredefinidas,comoredegreen.
Emseuarquivostatic/css/blog.cssvocêdeveadicionaroseguintecódigo:
h1a{
color:#FCA205;
}
h1aéumseletordeCSS.Issosignificaquenósestamosaplicandonossosestilosparaqualquerelementoadentrodeumelementoh1(i.e.quandotivermosnocódigoalgocomo:<h1><ahref="">link</a></h1>).Nestecasonósestamosdizendoparamudaracorpara#FCA205,queélaranja.Claro,vocêpodecolocaracorquevocêquiseraqui!
EmumarquivoCSSpodemosdeterminarestilosparaelementosnoarquivoHTML.Oselementossãoidentificadospelonomedoelemento(ouseja,a,h1,body),oatributodeclassouoatributoid.Classeeidsãonomesquevocêmesmodáaoelemento.Classesdefinemgruposdeelementos,eidsapontamparaelementosespecíficos.Porexemplo,aseguintetagpodeseridentificadaporCSSusandoatagdenomea,aclasselink_externoouaidentificaçãodelink_para_a_pagina_wiki:
DjangoGirlsTutorial
99CSS-Deixemaisbonito
<ahref="http://en.wikipedia.org/wiki/Django"class="external_link"id="link_to_wiki_page"
LeiasobreSeletoresCSSemw3schools.
Então,precisamostambémcontaronossotemplateHTMLquenósadicionamosCSS.Abraoarquivoblog/templates/blog/post_list.htmleadicioneessalinhanoiníciodomesmo:
{%loadstaticfiles%}
Estamosapenascarregandoarquivosestáticosaqui:).Depois,entreo<head>e/</head>,depoisdoslinksparaosarquivosdeCSSdoBootstrap(onavegadorlêosarquivosnaordemqueelessãodados,entãoocódigoemnossoarquivopodesubstituirocó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|linebreaks}}</p>
</div>
{%endfor%}
</body>
</html>
OK,salveoarquivoeatualizeosite!
DjangoGirlsTutorial
100CSS-Deixemaisbonito
Bomtrabalho!Talvezagentetambémqueiradarumpoucodearaonossositeeaumentaramargemdoladoesquerdo?Vamostentar!
body{
padding-left:15px;
}
AdicioneistoaoseuarquivoCSS,salveevejacomoelefunciona!
Talvezagentepossacustomizarafontenonossocabeçalho?Colenaseção<head>doarquivoblog/templates/blog/post_list.htmloseguinte:
<linkhref="http://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext"rel="stylesheet"
DjangoGirlsTutorial
101CSS-Deixemaisbonito
EssalinhairáimportarumafontechamadaLobsterdoGoogleFonts(https://www.google.com/fonts).
Agoraadicionealinhafont-family:'Lobster';noCSSdoarquivostatic/css/blog.cssdentrodoblocodedeclaraçãoh1a(ocódigoentreaschaves{e})eatualizeapágina:
h1a{
color:#FCA205;
font-family:'Lobster';
}
Incrível!
Comomencionadoacima,CSSusaoconceitodeclasses,quebasicamentepermitequevocênomeiepartedocódigoHTMLeapliqueestilosapenasàestaparte,semafetarasoutras.Ésuperútilsevocêtiverduasdivs,maselesestãofazendoalgomuitodiferente(comooseucabeçalhoeseupost),entãovocênãoquerqueelesfiquemparecidos.
VáemfrenteeonomeiealgumaspartesdocódigoHTML.Adicioneumaclassechamadadepage-headerparaodivquecontémocabeçalho,assim:
<divclass="page-header">
<h1><ahref="/">DjangoGirlsBlog</a></h1>
</div>
Eagora,adicioneumaclassepostemsuadivquecontémumpostdeblog.
DjangoGirlsTutorial
102CSS-Deixemaisbonito
<divclass="post">
<p>published:{{post.published_date}}</p>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaks}}</p>
</div>
Agoraadicionaremosblocosdedeclaraçãodeseletoresdiferentes.Seletorescomeçandocom.sereferemàsclasses.ExistemmuitostutoriaiseexplicaçõessobreCSSnaWebparaajudarvocêaentenderocódigoaseguir.Porenquanto,bastacopiarecolá-loemseuarquivomysite/static/css/blog.css:
DjangoGirlsTutorial
103CSS-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:
DjangoGirlsTutorial
104CSS-Deixemaisbonito
{%forpostinposts%}
<divclass="post">
<p>published:{{post.published_date}}</p>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaks}}</p>
</div>
{%endfor%}
noarquivoblog/templates/blog/post_list.htmlporisto:
<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|linebreaks}}</p>
</div>
{%endfor%}
</div>
</div>
</div>
Salveessesarquivoseatualizeseusite.
Uhuu!Ficouincrível,né?Ocódigoquenósacabamosdecolarnãoétãodifícildeentenderevocêdevesercapazdeentenderamaiorparteapenaslendo.
NãotenhamedodemexerumpoucocomesseCSSetentarmudaralgumascoisas.Sevocêquebraralgumacoisa,nãosepreocupe,vocêsemprepodedesfazê-lo!
DjangoGirlsTutorial
105CSS-Deixemaisbonito
Dequalquerforma,recomendamosquefaçaessecursoon-lineCodeacademyHTML&CSSCoursecomodeverdecasapós-workshopparaaprendertudooquevocêprecisasabersobrecomotornarseussitesmaisbonitoscomCSS.
Prontoparaopróximocapítulo?!:)
DjangoGirlsTutorial
106CSS-Deixemaisbonito
EstendendoostemplatesOutracoisaboaqueoDjangotempravocêéotemplateextending.Oqueissosignifica?IssosignificaquevocêpodeusarasmesmaspartesdoseuHTMLemdiferentespáginasdoseusite.
Dessaformavocênãoprecisaficarserepetindoemcadaarquivoquandoquiserusaramesmainformação/layout.Esevocêquisermudaralgumacoisanãoprecisafazerissoemtodotemplate,sóumavez!
CriartemplatebaseUmtemplatebaseéotemplatemaisbásicoquevocêestenderáemcadapáginadoseusite.
Vamoscriarumarquivobase.htmlnapastablog/templates/blog/:
blog
└───templates
└───blog
base.html
post_list.html
Abra-oecopietudoqueestánoarquivopost_list.htmlparabase.html,dessejeito:
DjangoGirlsTutorial
107Estendendoostemplates
{%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
<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|linebreaks}}</p>
</div>
{%endfor%}
</div>
</div>
</div>
</body>
</html>
Entãoembase.html,substituatodoseu<body>(tudoentre<body>e</body>)comisso:
<body>
<divclass="page-header">
<h1><ahref="/">DjangoGirlsBlog</a></h1>
</div>
<divclass="contentcontainer">
<divclass="row">
<divclass="col-md-8">
{%blockcontent%}
{%endblock%}
</div>
</div>
</div>
</body>
DjangoGirlsTutorial
108Estendendoostemplates
Basicamentenóssubstituimostudoentre{%forpostinposts%}{%endfor%}por:
{%blockcontent%}
{%endblock%}
Oqueissosignifica?Vocêacaboudecriarumblock(bloco),queéumatagdetemplatequetepermiteinserirHTMLnesteblocoemoutrostemplatesqueestendembase.html.Nósvamostemostrarcomofazerissojájá.
Salveeabraoarquivoblog/templates/blog/post_list.htmlnovamente.Apagueexatamentetudoquenãoestiverdentrodatagbodyeapaguetambém<divclass="page-header"></div>,deformaqueoarquivofiquedaseguintemaneira:
{%forpostinposts%}
<divclass="post">
<divclass="date">
{{post.published_date}}
</div>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaks}}</p>
</div>
{%endfor%}
Agoraadicioneestalinhaaoiníciodoarquivo:
{%extends'blog/base.html'%}
Issosignificaque,agora,nósestamosestendendootemplatebase.htmlempost_list.html.Umaúltimacoisa:colocartudo(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|linebreaks}}</p>
</div>
{%endfor%}
{%endblockcontent%}
DjangoGirlsTutorial
109Estendendoostemplates
Éisso!Vejaseoseusiteaindaestáfuncionandodireito:)
SeocorrerumerrodeTemplateDoesNotExists,quedizquenãoexistenenhumarquivochamadoblog/base.htmlesevocêtiverorunserverexecutandonoterminal,tentainterrompê-lo(precionandoCtrl+C-obotãoControlmaisobotãoCjuntos)ereinicieelerodandoocomandopythonmanage.pyrunserver.
DjangoGirlsTutorial
110Estendendoostemplates
AmpliesuaaplicaçãoJáconcluímostodosospassosnecessáriosparaacriaçãodonossosite:sabemoscomocriarummodelo,umaurl,umavieweumtemplate.Tambémsabemoscomomelhoraraaparênciadonossowebsite.
Horadepraticar!
Aprimeiraqueprecisamosnonossoblogé,obviamente,umapáginaparamostrarumapostagem,certo?
JátemosummodelodePost,entãonãoprecisamosadicionarnadaaomodels.py.
CriarumlinknotemplateVamoscomeçarcomaadiçãodeumlinkdentrodoarquivoblog/templates/blog/post_list.html.Nestemomentoeledeveseparecercom:
{%extends'blog/base.html'%}
{%blockcontent%}
{%forpostinposts%}
<divclass="post">
<divclass="date">
{{post.published_date}}
</div>
<h1><ahref="">{{post.title}}</a></h1>
<p>{{post.text|linebreaks}}</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çãode{%%}significaqueestamosusandoastagsdetemplatedoDjango.DestavezvamosusarumaquevaicriarumaURLparanós!
DjangoGirlsTutorial
111Ampliesuaaplicação
blog.views.post_detailéumcaminhoparaumpost_detailVistaquequeremoscriar.Presteatenção:blogéonomedasuaaplicação(odiretórioblog),viewsvemdonomedoarquivoviews.pye,aúltimaparte-post_detail-éonomedaview.
Agoraquandoformospara:http://127.0.0.1:8000/teremosumerro(comoesperado,jáquenãotemosumaURLouumaviewparapost_detail).Vaiseparecercomisso:
VamoscriaraURLemurls.pyparaanossapost_detailview!
URL:http://127.0.0.1:8000/post/1/
QueremoscriarumaURLparaguiaroDjangoparaaviewchamadapost_detail,queirámostrarumpostcompletodoblog.Adicionealinhaurl(r'^post/(?P<pk>[0-9]+)/$',views.post_detail),aoarquivoblog/urls.py.Deveficarassim:
fromdjango.conf.urlsimportinclude,url
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]+)-essaparteémaiscomplicada.IssosignificaqueoDjangovailevartudoquevocêcolocaraquietransferirparaumaviewcomoumavariávelchamadapk.[0-9]tambémnosdizquesópodeserumnúmero,nãoumaletra(tudoentre0e9).+significaqueprecisaexistirumoumaisdígitos.Entãoalgocomohttp://127.0.0.1:8000/post//nãoéválido,mashttp://127.0.0.1:8000/post/1234567890/éperfeitamenteok!-/-entãoprecisamosde/outravez-$-"ofim"!
DjangoGirlsTutorial
112Ampliesuaaplicação
Issosignificaquesevocêdigitarhttp://127.0.0.1:8000/post/5/emseunavegador,Djangovaientenderquevocêestáprocurandoumaviewchamadapost_detailetransferirainformaçãodequepkéiguala5paraaquelaview.
pkéumaabreviaçãoparaprimarykey(chaveprimária).EssenomegeralmenteéusadonosprojetosfeitosemDjango.Masvocêpodedaronomequequiseràsvariáveis(lembre-se:minúsculoe_aoinvésdeespaçosembranco!).Porexemploemvezde(?P<pk>[0-9]+)podemosterumavariávelpost_id,entãoestaparteficariacomo:(?P<post_id>[0-9]+).
Razoável!Vamosatualizarapágina:http://127.0.0.1:8000/Boom!Aindaoutroerro!Comoesperado!
Vocêselembraqualéopróximopasso?Claro:adicionandoumaview!
post_detailviewDestavezanossaviewrecebeumparâmetroextrapk.Nossaviewprecisapegá-la,certo?Entãovamosdefinirnossafunçãocomodefpost_detail(request,pk):.Observequeprecisamosusarexatamenteomesmonomequeespecificamosemurls(pk).Omitiressavariáveléerradoeresultaráemumerro!
Agoraqueremosreceberapenasumpostdoblog.Paraissopodemosusarquerysetscomoeste:
Post.objects.get(pk=pk)
Masestecódigotemumproblema.SenãohouvernenhumPostcomachaveprimária(pk)fornecidateremosumerrohorroroso!
DjangoGirlsTutorial
113Ampliesuaaplicação
Nãoqueremosisso!Mas,claro,oDjangovemcomalgoquevailidarcomissoparanós:get_object_or_404.CasonãohajanenhumPostcomodadopkexibiráumapáginamuitomaisagradável(chamadaPageNotFound404-páginanãoencontrada).
AboanotíciaéquevocêrealmentepodecriarsuaprópriapáginadePagenotfoundetorná-lotãobonitaquantovocêquiser.Masissonãoésuperimportanteagora,entãonósvamosignorá-la.
Ok,horadeadicionarumaviewaonossoarquivoviews.py!
Devemosabrirblog/views.pyeadicionaroseguintecódigo:
fromdjango.shortcutsimportrender,get_object_or_404
Pertodeoutraslinhasfrom.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/
DjangoGirlsTutorial
114Ampliesuaaplicação
Funcionou!Masoqueacontecequandovocêclicaemumlinknotítulodopostdoblog?
Ahnão!Outroerro!Masnósjásabemoscomolidarcomisso,né?Precisamosadicionarumtemplate!
Vamoscriarumarquivoemblog/templates/blogchamadopost_detail.html.
Seráalgoparecidocomisto:
DjangoGirlsTutorial
115Ampliesuaaplicaçã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|linebreaks}}</p>
</div>
{%endblock%}
Maisumavezestamosestendendobase.html.Noblocodecontentqueremosexibiropublished_date(datadepublicação)dopost(sehouver),títuloetexto.Masdevemosdiscutiralgumascoisasimportantes,certo?
{%if...%}...{%endif%}éumatagdetemplatequepodemosusarquandoqueremosverificaralgo(Lembre-seif...else...docapítulointroduçãoaoPython?).Nestecenário,queremosverificarsepublished_datedeumpostnãoestávazia.
Ok,podemosatualizarnossapáginaeversePagenotfoundjásefoi.
Yay!Funciona!
DjangoGirlsTutorial
116Ampliesuaaplicação
Maisumacoisa:horadeimplantar!SeriabomverseseusiteaindaestarátrabalhandoemPythonAnywhere,certo?Vamostentarfazerdeploynovamente.
$gitstatus
$gitadd-A.
$gitstatus
$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."
$gitpush
Então,emumconsolePythonAnywhereBash:
$cdmy-first-blog
$gitpull
Finalmente,puleparaaWebtabeaperteReload.Edeveserisso!Parabéns:)
DjangoGirlsTutorial
117Ampliesuaaplicação
FormuláriosPorúltimoqueremosumaformalegaldeadicionareeditaraspostagensdonossoblog.AferramentadeadministraçãodoDjangoélegal,maselaéumpoucodifícildecustomizarededeixarmaisbonita.Seusarmosformuláriosteremoscontroleabsolutosobrenossainterface-podemosfazerqualquercoisaqueimaginarmos!
UmacoisalegaldoDjangoéquenóspodemostantocriarumformuláriodozerocomopodemoscriarumModelFormquesalvaoresultadodoformulárioparaumdeterminadomodelo.
Issoéexatamenteoquenósqueremosfazer:criaremosumformulárioparaonossomodeloPost.
AssimcomotodaparteimportantedoDjango,formstemseupróprioarquivo:forms.py.
Precisamoscriarumarquivocomestenomedentrodapastablog.
blog
└──forms.py
Ok,vamosabri-loeescreverneleoseguinte:
fromdjangoimportforms
from.modelsimportPost
classPostForm(forms.ModelForm):
classMeta:
model=Post
fields=('title','text',)
PrimeiroprecisamosimportaromódulodeformuláriosdoDjango(fromdjangoimportforms)e,obviamente,nossomodeloPost(from.modelsimportPost).
PostForm,comovocêjádevesuspeitar,éonomedonossoformulário.PrecisamosdizeraoDjangoqueesteformulárioéumModelForm(assimoDjangopodefazeramágicapragente)-oforms.ModelForméoresponsávelporisso.
Segundo,nóstemosaclasseMetaondedizemosaoDjangoqualmodelodeveriaserusadoparacriaresteformulário(model=Post).
DjangoGirlsTutorial
118Formulários
Finalmente,nóspodemosdizerqual(is)campo(s)deveriamentraremnossoformulário.Nessecenárionósqueremosapenasotitleetextparaserexposto-authordeveriaserapessoaqueestálogadanosistema(nessecaso,você!)ecreated_datedeveriasersetadoautomaticamentequandonóscriamosumpost(nocódigo),correto?
Eéissoaí!Tudooqueprecisamosfazeragoraéusaroformulárioemumaviewemostrá-loemumtemplate.
Então,maisumavez,nósiremoscriar:umlinkparaapágina,umaURL,umavieweumtemplate.
LinkparaapáginacomoformulárioÉhoradeabrirblog/templates/blog/base.html.Nósiremosadicionarumlinkemdivnomeadopage-header:
<ahref="{%url'blog.views.post_new'%}"class="top-menu"><spanclass="glyphiconglyphicon-plus"
Notequenósqueremoschamarnossanovavisãopost_new.
Depoisdeadicionaralinha,seuhtmldeveseparecercomisso:
DjangoGirlsTutorial
119Formulá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
<linkrel="stylesheet"href="{%static'css/blog.css'%}">
</head>
<body>
<divclass="page-header">
<ahref="{%url'blog.views.post_new'%}"class="top-menu"><spanclass="glyphiconglyphicon-plus"
<h1><ahref="/">DjangoGirlsBlog</a></h1>
</div>
<divclass="contentcontainer">
<divclass="row">
<divclass="col-md-8">
{%blockcontent%}
{%endblock%}
</div>
</div>
</div>
</body>
</html>
Depoisdesalvarerecarregarapáginahttp://127.0.0.1:8000vocêverá,obviamente,umerrofamiliarNoReverseMatchcerto?
URLVamosabriroarquivoblog/urls.pyeescrever:
url(r'^post/new/$',views.post_new,name='post_new'),
Ocódigofinaldeveseparecercomisso:
fromdjango.conf.urlsimportinclude,url
from.mportviews
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'),
]
DjangoGirlsTutorial
120Formulários
Apósrecarregarosite,nósveremosumAttributeError,desdequenósnãotemosavisãopost_newimplementada.Vamosadicioná-laagora.
post_newviewHoradeabriroarquivoblog/views.pyeadicionaraslinhasseguintescomorestodaslinhasfrom:
from.formsimportPostForm
enossaview:
defpost_new(request):
form=PostForm()
returnrender(request,'blog/post_edit.html',{'form':form})
ParacriarumnovoformularioPost,nósdevemoschamarPostForm()epassá-loparaotemplate.Nósiremosvoltarparaestaview,masporagoravamoscriarrapidamenteumtemplateparaoformulário.
Template(modelos)Precisamoscriarumarquivopost_edit.htmlnapastablog/templates/blog.Prafazeroformuláriofuncionarprecisamosdemuitascoisas:
Temosqueexibiroformulário.Podemosfazerissosimplesmentecomum``.AlinhaacimaprecisaestardentrodeumatagHTMLform:<formmethod="POST">...</form>
PrecisamosdeumbotãoSalvar.FazemosissocomumbotãoHTML:<buttontype="submit">Save</button>
Efinalmente,depoisdeabriratag<form...>precisamosadicionarum{%csrf_token%}.Issoémuitoimportante,poiséissoquefazonossoformulárioficarseguro!ODJangovaireclamarsevocêesquecerdeadicionarissoesimplesmentesalvaroformulário:
DjangoGirlsTutorial
121Formulários
Beleza,entãovamosvercomoficouoHTMLpost_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!
DjangoGirlsTutorial
122Formulários
Mas,espereumminuto!Quandovocêdigitaalgumacoisanoscampostitleetextetentasalvaroqueacontece?
Nada!Estamosnovamentenamesmapáginaenossotextosumiu...Enenhumpostfoiadicionado.Entãooquedeuerrado?
Arespostaé:nada.Precisamostrabalharumpoucomaisnanossaview.
SalvandooformulárioAbrablog/views.pymaisumavez.Atualmentetudoquetemosnavisãopost_newé:
defpost_new(request):
form=PostForm()
returnrender(request,'blog/post_edit.html',{'form':form})
Quandonósenviamosoformulário,somostrazidosdevoltaparaamesmavisão,masdestaveztemosmaisalgunsdadosnorequest,maisespecificamenteemrequest.POST(onomenãotemnadacom"post"deblog,temavercomofatodequeestamos"postando"dados).VocêselembraquenoarquivoHTMLnossadefiniçãode<form>tema
DjangoGirlsTutorial
123Formulários
variávelmethod="POST"?Todososcamposvindosdo"form"estarãodisponíveisagoraemrequest.POST.VocênãodeveriarenomearPOSTparanadadiferentedisso(oúnicooutrovalorválidoparamethodéGET,masnósnãotemostempoparaexplicarqualéadiferença).
Entãonanossaviewnóstemosduassituaçõesseparadasparalidar.Aprimeiraéquantoacessamosapáginapelaprimeiravezequeremosumformulárioembranco.Easegunda,équandonóstemosquevoltarparaaviewcomtodososdadosdoformulárioquenósdigitamos.Dessemodo,precisamosadicionarumacondição(usaremosifparaisso).
ifrequest.method=="POST":
[...]
else:
form=PostForm()
Estánahoradepreencherospontos[...].SemethodéPOSTentãonósqueremosconstruiroPostFormcomosdadosqueveemdoformulário,certo?Nósiremosfazerassim:
form=PostForm(request.POST)
Fácil!Próximacoisaéverificarseoformulárioestácorreto(todososcamposrequeridossãodefinidosevaloresincorretosnãoserãosalvos).Fazemosissocomform.is_valid().
Verificamosseoformulárioéválidoeseestivertudocerto,podemossalvá-lo!
ifform.is_valid():
post=form.save(commit=False)
post.author=request.user
post.save()
Basicamente,temosduascoisasaqui:Salvamosoformuláriocomform.saveeadicionadosumautor(desdequenãohajaocampoauthoremPostForm,eestecampoéobrigatório!).commit=FalsesignificaquenãoqueremossalvaromodeloPostainda-queremosadicionarautorprimeiro.Namaioriadasvezesvocêiráusarform.save(),semcommit=False,masnestecaso,precisamosfazerisso.post.save()irápreservarasalterações(adicionandoautor)eécriadoumnovopostnoblog!
Finalmente,nãoseriafantásticosenóspudéssemosimediatamenteiràpáginadepost_detailparaorecém-criadoblogpost,certo?Parafazerissonósprecisaremosdemaisumaimportação:
DjangoGirlsTutorial
124Formulários
fromdjango.shortcutsimportredirect
Adicione-ologonoiníciodoseuarquivo.Eagorapodemosdizer:váparaapáginapost_detailparaumrecém-criadopost.
returnredirect('blog.views.post_detail',pk=post.pk)
blog.views.post_detailéonomedaviewquequeremosir.Lembre-sequeessaviewexigeumavariávelpk?Parapassarissonasviewsusamospk=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.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/novo/,adicioneumtitleeotext,salve...evoilà!Onovoblogpostéadicionadoenóssomosredirecionadosparaapáginadepost_detail!
Vocêprovavelmentenotouquenósnãoestamosdefinindoadatadepublicaçãoemtudo.VamosintroduzirumbotãodepublicaçãoemDjangoGirlsTutorial:Extensões.
Issoéincrível!
ValidaçãodeformuláriosAgora,nóslhemostraremoscomoosfórmulariossãolegais.Opostdoblogprecisateroscampostitleetext.EmnossomodeloPostnãodissemos(emoposiçãoapublished_date)queessescamposnãosãonecessários,entãoDjango,porpadrão,espera-osaserdefinido.
Tentesalvaroformuláriosemtitleetext.Adivinheoquevaiacontecer!
DjangoGirlsTutorial
125Formulários
Djangoestátomandocontadevalidarsetodososcamposdenossoformulárioestãocorretos.Nãoéincrível?
ComorecentementeusamosainterfacedeadministraçãodoDjangoosistemaentendequeestamoslogados.Existemalgumassituaçõesquepoderiamlevarasermosdeslogadosdosistema(fecharonavegador,reiniciarbancodedadosetc.).Sevocêperceberqueerrosestãoaparecendoaocriarumpostquereferenciaumusuárioquenãoestálogado,váparaapáginaadminhttp://127.0.0.1:8000eloguenovamente.Issovairesolveroproblematemporariamente.Háumajustepermanenteesperandoporvocêemliçãodecasa:adicionarsegurançanoseusite!,capítuloapósotutorialprincipal.
DjangoGirlsTutorial
126Formulários
EditandooformulárioAgorasabemoscomoadicionarumnovoformulário.Masesequisermoseditarumjáexistente?Émuitosemelhanteaoquefizemos.Vamoscriaralgumascoisasimportantesrapidamente(sevocênãoentenderalgumacoisa-vocêdeveperguntaraseuprofessorouvejaoscapítulosanteriores,jácobrimostodasessasetapasanteriormente).
Abrablog/templates/blog/post_detail.htmleadicionealinha:
<aclass="btnbtn-default"href="{%url'post_edit'pk=post.pk%}"><spanclass="glyphiconglyphicon-pencil"
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"
</div>
<h1>{{post.title}}</h1>
<p>{{post.text|linebreaks}}</p>
{%endblock%}
Emblog/urls.pyadicionamosestalinha:
url(r'^post/(?P<pk>[0-9]+)/edit/$',views.post_edit,name='post_edit'),
Nósreutilizaremosomodeloblog/templates/blog/post_edit.html,entãoaúltimacoisaquefaltaéumaview.
Vamosabrirblog/views.pyeadicionarnofinaldoarquivo:
DjangoGirlsTutorial
127Formulários
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.save()
returnredirect('blog.views.post_detail',pk=post.pk)
else:
form=PostForm(instance=post)
returnrender(request,'blog/post_edit.html',{'form':form})
Issoéquaseexatamenteigualanossaviewdepost_new,certo?Masnãototalmente.Primeiracoisa:passamosumparâmetroextradaurlpk.Emseguida:pegamosomodeloPostquequeremoseditarcomget_object_or_404(Post,pk=pk)eentão,quandocriamosumformuláriopassamosestepostcomoumainstância,tantoquandosalvamosoformulário:
form=PostForm(request.POST,instance=post)
comoquandonósapenasabrimosumformuláriocomestepostparaeditar:
form=PostForm(instance=post)
Ok,vamostestarsefunciona!Vamosparaapáginapost_detail.Devehaverumbotãoeditarnocantosuperiordireito:
DjangoGirlsTutorial
128Formulários
Quandovocêclicarnelevocêveráoformuláriocomanossapostagem:
Sinta-selivreparamudarotítuloouotextoesalvarasmudanças!
Parabéns!Suaaplicaçãoestáficandocadavezmaiscompleta!
DjangoGirlsTutorial
129Formulários
SevocêprecisardemaisinformaçõessobreformuláriosdoDjangovocêdeveleradocumentação:https://docs.djangoproject.com/en/1.8/topics/forms/
Maisumacoisa:horadeimplantar!VamosversetudoissofuncionanaPythonAnywhere.Tempoparaoutrodeploy!
Primeiro,commitoseunovocódigoecoloquenoGithub
$gitstatus
$gitadd-A.
$gitstatus
$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."
$gitpush
Então,emumconsolePythonAnywhereBash:
$cdmy-first-blog
$gitpull
Finalmente,puleparaaWebtabeaperteReload.Edeveserisso!Parabéns:)
DjangoGirlsTutorial
130Formulários
DomínioPythonAnywheretedeuumdomíniogratuito,mastalvezvocênãoqueirater".pythonanywhere.com"nofinaldaURLdoseublog.Talvezvocêqueiraseublogapenas"www.infinite-kitten-pictures.org"ou"www.3d-printed-steam-engine-parts.com"ou"www.antique-buttons.com"ou"www.mutant-unicornz.net",ousejaoquevaiser.
Aquivamosfalarumpoucosobreondeobterumdomínioecomoligá-loaseuaplicativodawebemPythonAnywhere.Noentanto,vocêdevesaberqueamaioriadosdomínioscustamdinheiroePythonAnyweretambémcobraumataxamensalparausarseupróprionomededomínio--nãoémuitodinheiro,nototal,masissoprovavelmenteéalgoquevocêsóquerfazersevocêestárealmentecomprometido!
Onderegistrarumdomínio?Umdomínionormalcustamaisoumenos15dólaresporano.Existemdomíniosmaiscarosemaisbaratosdependendodoprovedor.Existemumasériedeempresasdasquaisvocêpodecomprarumdomínio:umasimplespesquisanogooglepodelistarumasériedelas.
OnossofavoritoéoIwantmyname(euqueromeunome).Elesanunciamseuserviçocomo"gestãodedomínioindolor",eele,realmente,éindolor.
Vocêtambémpodeobterdomíniosgratuitamente.dot.tkéumlugarparapegarum,masvocêdeveestarcientedequedomíniosgrátisàsvezesparecemmuitobaratos--seseusitevaiserparaumprofissionaldenegócios,vocêdevepensarempagarporumdomínio"correto"queterminaem.com.
ComoapontarseudomínionoPythonAnywhereSevocêpassouporiwantmyname.com,cliqueemdomíniosnomenueescolhaseudomíniorecém-adquirido.Emseguida,localizeecliquenolinkmanageDNSrecords:
Agoravocêprecisalocalizaresteformulário:
DjangoGirlsTutorial
131Domínio
Epreenchercomosseguintesdetalhes:-Hostname:www-tipo:CNAME-valor:seudomíniodePythonAnywhere(porexemplodjangogirls.pythonanywhere.com)-TTL:60
CliquenobotãoAdicionaresalveasmudançasnapartedebaixo.
NotaSevocêusouumprovedordedomíniodiferente,oUIexataparaencontraroseuDNS/configuraçõesdeCNAMEserádiferente,masseuobjetivoéomesmo:paraconfigurarumCNAMEqueapontaseunovodomínionoyourusername.pythonanywhere.com.
Podelevaralgunsminutosparaoseudomíniocomeçaratrabalhar,entãosejapaciente!
ConfigureodomínioatravésdeumwebappnaPythonAnywhere.VocêtambémprecisadizerPythonAnywherequevocêdesejausaroseudomíniopersonalizado.
VáparaapáginaPythonAnywherecontaseupgradesuaconta.Aopçãomaisbarata(umplanode"Hacker")ébomparacomeçar,vocêpodesempreatualizá-lomaistardequandovocêficarsuperfamosoetivermilhõesdeacessos.
Emseguida,vánaWebtabeanotealgumascoisas:
CopieocaminhoparaseuvirtualenvecoloqueemumlugarseguroCliqueparaseuarquivodeconfiguraçãodowsgi,copieoconteúdoecoleemumlugarseguro.
Emseguida,excluaseuantigowebapp.Nãosepreocupe,issonãovaiexcluirnadadoseucódigo,eleapenasirásedesligardodomínioyourusername.pythonanywhere.com.Emseguida,crieumnovoaplicativowebesigaestespassos:
DigiteseunomededomínionovoEscolha"manualconfiguration"EscolhaPython3.4Eéisso!
DjangoGirlsTutorial
132Domínio
Quandovocêtivervoltadoparaawebtab.
ColarocaminhovirtualenvquevocêsalvouantesClicarnoarquivodeconfiguraçãowsgiecolaroconteúdodoseuarquivodeconfiguraçãoantigo
Cliqueemreloadwebappevocêdeveencontrarseusitelivenonovodomínio!
Sevocêtiverqualquerproblema,cliquenolink"Enviarfeedback"nositePythonAnywhere,eumdosseusadministradoresamigáveisvaiestarláparaajudá-lo.
DjangoGirlsTutorial
133Domínio
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'sofficialtutorialNewCodertutorialsCodeAcademyPythoncourseCodeAcademyHTML&CSScourseDjangoCarrotstutorialLearnPythonTheHardWaybookGettingStartedWithDjangovideolessonsTwoScoopsofDjango:BestPracticesforDjangobook
DjangoGirlsTutorial
134Oquevemdepois?