tutorial de django girls

132

Upload: trannguyet

Post on 07-Jan-2017

259 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: Tutorial de Django Girls
Page 2: Tutorial de Django Girls

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

TabladecontenidoIntroducción

¿CómofuncionaInternet?

Introducciónalalíneadecomandos

InstalacióndePython

Editordecódigo

IntroducciónaPython

¿QuéesDjango?

InstalacióndeDjango

ComenzarunproyectoenDjango

ModelosenDjango

AdministradordeDjango

¡Desplegar!

Djangourls

VistasdeDjango-¡Eshoradecrear!

IntroducciónaHTML

ORMdeDjango(Querysets)

Datosdinámicosenplantillas

PlantillasdeDjango

CSS-Hazlobonito

Extenderplantillas

Amplíatuaplicación

FormulariosenDjango

Dominio

¿Quésigue?

DjangoGirlsTutorial

2

Page 3: Tutorial de Django Girls

TutorialdeDjangoGirls

EstetrabajoestábajolalicenciainternacionalCreativeCommonsAttribution-ShareAlike4.0.Paraverunacopiadeestalicencia,visitaelsiguienteenlacehttp://creativecommons.org/licenses/by-sa/4.0/

TranslationThistutorialhasbeentranslatedfromEnglishintoSpanishbyawonderfulgroupofvolunteers.SpecialthanksgoestoVictoriaMartinezdelaCruz,KevinMorales,JoshuaAranda,SilviaFrias,Leticia,AndreaGonzalez,AdrianManjarres,RodrigoCaicedo,MariaChavez,MarceloNicolasManso,RosaDurante,Moises,IsraelMartinezVargas,JuanCarlos_,N0890Dy,IvanYivoff,KhaterineCastellano,ErickNavarro,cyncyncyn,ZeroSoul13,ErickAguayo,ErnestoRico-Schmidt,MiguelLozano,osueboy,dynarroandGeraldinaGarciaAlvarez.

Introducción¿Algunavezhassentidoqueelmundoestácadavezmáscercanoalatecnologíaydeciertomodotehasquedadoatrás?¿Algunaveztehaspreguntadocómocrearunsitiowebperonuncahastenidolasuficientemotivaciónparaempezar?¿Haspensadoalgunavezqueelmundodelsoftwareesdemasiadocomplicadoparaticomoparaintentarhaceralgoportucuenta?

Bueno,¡tenemosbuenasnoticiasparati!Programarnoestandifícilcomoaparentayqueremosmostrartecuándivertidopuedellegaraser.

Estetutorialnoteconvertiráenprogramadormágicamente.Siquieresserbuenaenesto,necesitarásmesesoinclusosañosdeaprendizajeypráctica.Peroqueremosmostrartequeprogramarocrearsitioswebnoestancomplicadocomoparece.Intentaremosexplicarpequeñasparteslomejorquepodamos,deformaquenotesientasintimidadaporlatecnología.

¡Esperamospoderhacerteamarlatecnologíatantocomonosotraslohacemos!

¿Quéaprenderásconestetutorial?

DjangoGirlsTutorial

3Introducción

Page 4: Tutorial de Django Girls

Cuandotermineseltutorial,tendrásunaaplicaciónwebsimpleyfuncional:tupropioblog.Temostraremoscomopublicarlaonline,¡asíotrospodránvertutrabajo!

Tendrá(másomenos)éstaapariencia:

Siestássiguiendoestetutorialportucuentaynotienesanadiequeteayudeencasodesurgiralgúnproblema,tenemosunchatparati: .¡Hemospedidoanuestrostutoresyparticipantesanterioresqueesténahídevezencuandoparaayudaraotrosconeltutorial!¡Notemasdejartuspreguntasallí!

Bien,empecemosporelprincipio...

SobrenosotrosycómocontribuirEstetutoriallomantieneDjangoGirls.Siencuentrasalgúnerroroquieresactualizareltutorial,porfavorsiguelaguíadecómocontribuir.

DjangoGirlsTutorial

4Introducción

Page 5: Tutorial de Django Girls

¿Tegustaríaayudarnosatraducireltutorialaotrosidiomas?Actualmente,lastraduccionessellevanacabosobrelaplataformacrowdin.comen:

https://crowdin.com/project/django-girls-tutorial

Situidiomanoestalistadoencrowdin,porfavorabreunnuevoproblemainformandoelidiomaasípodemosagregarlo.

DjangoGirlsTutorial

5Introducción

Page 6: Tutorial de Django Girls

¿CómofuncionaInternet?Estecapituloestáinspiradoporlacharla"HowtheInternetworks"deJessicaMcKellar(http://web.mit.edu/jesstess/www/).

ApostamosqueutilizasInternettodoslosdías.Pero,¿sabesloquepasacuandoescribesunadireccióncomohttp://djangogirls.orgentunavegadorypresionas'Enter'?

Loprimeroquetienesqueentenderesqueunsitiowebessólounmontóndearchivosguardadosenundiscoduro.Aligualquetuspelículas,músicaofotos.Sinembargo,lossitioswebposeenunapeculiaridad:ellosincluyenuncódigodecomputadorasllamadoHTML.

Sinoestásfamiliarizadaconlaprogramación,puedeserdifícildecaptarHTMLalprincipio,perotusnavegadoresweb(comoChrome,Safari,Firefox,etc.)loaman.Losnavegadoreswebestándiseñadosparaentenderestecódigo,seguirsusinstruccionesymostrartodosesosarchivosdeloscualestusitiowebestáhechodelamaneraexactacomotuquieresquesemuestren.

Comocualquierotroarchivo,tenemosqueguardarlosarchivosHTMLenalgúnlugardeundiscoduro.ParaInternet,usamosunascomputadorasespecialesypoderosasllamadasservidores.Ellasnotienenunapantalla,mouseoteclado,debidoaquesupropósitoesalmacenardatosyservirlos.Poresarazónsonllamadosservidores--porqueellossirvenlosdatos.

Ok,quizástepreguntescómoluceInternet,¿cierto?

¡Tehemoshechounaimagen!Lucealgoasí:

DjangoGirlsTutorial

6¿CómofuncionaInternet?

Page 7: Tutorial de Django Girls

Pareceunlío,¿no?Enrealidadesunareddemáquinasconectadas(losmencionadosservidores).¡Cientosdemilesdemáquinas!¡Muchos,muchoskilómetrosdecablesalrededordelmundo!PuedesvisitarelsitiowebSubmarineCableMap(http://submarinecablemap.com/)dondesemuestranlasconexionesdecablessubmarinosalrededordelmundoyverlocomplicadaqueeslared.Aquíhayunacapturadepantalladelapáginaweb:

DjangoGirlsTutorial

7¿CómofuncionaInternet?

Page 8: Tutorial de Django Girls

Esfascinante,¿no?Pero,obviamente,noesposibleteneruncableentrecadamáquinaconectadaaInternet.Asíque,parallegaraunamáquina(porejemplolaquealojaahttp://djangogirls.org)tenemosquepasarunasolicitudatravésdemuchasmáquinasdiferentes.

Separeceaesto:

DjangoGirlsTutorial

8¿CómofuncionaInternet?

Page 9: Tutorial de Django Girls

Imaginaquecuandoescribeshttp://djangogirls.org,estasenviandounacartaquedice:"QueridosDjangoGirls,megustaríaversusitiowebdjangogrils.org.Porfavor,envíenmelo!"

Tucartavahacialaoficinadecorreomáscercana.Luegovaaotraunpocomáscercanadesudestinatario,luegoaotrayaotrahastaqueesentregadaensudestino.Loúnicacosadiferenteesquesituenvíascartas(paquetesdedatos)confrecuenciaalmismolugar,cadacartapuedepasarporoficinasdecorreos(routers)totalmentediferentes,dependiendodecómosedistribuyenencadaoficina.

DjangoGirlsTutorial

9¿CómofuncionaInternet?

Page 10: Tutorial de Django Girls

Sí,estansimplecomoeso.Enviarmensajesyesperaralgunarespuesta.Porsupuesto,envezdepapelylapicerausasbytesdedatos,¡perolaideaeslamisma!

Enlugardedireccionesconelnombredelacalle,ciudad,códigopostalynombredelpaís,utilizamosdireccionesIP.TucomputadorapideprimeroelDNS(DomainNameSystem-enespañolSistemadeNombresdeDominio)paratraducirdjangogirls.orgaunadirecciónIP.Funcionacomolosviejosdirectoriostelefónicosdondepuedesbuscarelnombredelapersonaquesedeseascontactaryestenosmuestrasunúmerodeteléfonoydirección.

Cuandoenvíasunacarta,éstanecesitatenerciertascaracterísticasparaserentregadacorrectamente:unadirección,sello,etc.Tambiénutilizasunlenguajequeelreceptorpuedaentender,¿cierto?Lomismosucedeconlospaquetesdedatosqueenvíasparaverunsitioweb:utilizasunprotocolollamadoHTTP(HypertextTransferProtocol-enespañolProtocolodeTransferenciadeHipertexto).

Asíque,básicamente,cuandotienesunsitiowebnecesitastenerunservidor(lamáquina)dondevive.Elservidorestáesperandocualquiersolicitudentrante(cartasquepidenalservidorqueenvíetusitioweb)yésterespondeenviandotusitioweb(enotracarta).

PuestoqueesteesuntutorialdeDjango,segurotepreguntarásquéesloquehaceDjango.Bueno,cuandoenvíasunarespuesta,nosiemprequieresenviarlomismoatodoelmundo.Esmuchomejorsituscartassonpersonalizadas,especialmenteparalapersonaqueacabadeescribir,¿cierto?Djangonosayudaconlacreacióndeestascartaspersonalizadas:).

DjangoGirlsTutorial

10¿CómofuncionaInternet?

Page 11: Tutorial de Django Girls

Bastadecharlas,¡pongamosmanosalaobra!

DjangoGirlsTutorial

11¿CómofuncionaInternet?

Page 12: Tutorial de Django Girls

IntroducciónalainterfazdelíneadecomandosEsemocionante,¿verdad?Vasaescribirtuprimeralíneadecódigoenpocosminutos:)

Permítenospresentarteatuprimernuevoamigo:¡lalíneadecomandos!

Lossiguientespasostemostraráncómousaraquellaventananegraquetodosloshackersusan.Puedeparecerunpocoaterradoralprincipioperoessolounmensajeenpantallaqueesperaaqueledesórdenes.

¿Quéeslalíneadecomandos?Laventana,quegeneralmenteesllamadalíneadecomandosointerfazdelíneadecomandos,esunaaplicaciónbasadaentextoparaver,manejarymanipulararchivosentucomputadora(comoporejemploelExploradordeWindowsoFinderenMac,perosinlainterfazgráfica).Otrosnombresparalalíneadecomandosson:cmd,CLI,símbolodelsistema,consolaoterminal.

AbrirlainterfazdelíneadecomandosLoprimeroquedebemoshacerparaempezaraexperimentarconnuestrainterfazdelineadecomandosesabrirla.

Windows

IralmenúInicio→Todoslosprogramas→Accesorios→CommandPrompt

MacOSX

Aplicaciones→Servicios→Terminal

Linux

EstáprobablementeenAplicaciones→Accesorios→Terminal,peroesodependedetudistribución.Sinoloencuentras,Googlealo:)

DjangoGirlsTutorial

12Introducciónalalíneadecomandos

Page 13: Tutorial de Django Girls

PromptAhoradeberíasverunaventanablancaonegraqueestáesperandotusórdenes.

SiestásenMacoLinux,probablementeverás$,así:

$

EnWindows,esunsignoasí>,comoeste:

>

Cadacomandoseráprecedidoporestesignoyunespacio,peronotienesqueescribirlo.Tucomputadoraloharáporti:)

Sólounapequeñanota:entucaso,talvezhayalgocomoC:\Users\ola>oOlas-MacBook-Air:~ola$antesdelpromptyesoes100%correcto.Enestetutoriallosimplificaremoslomásposible.

Tuprimercomando(¡YAY!)Vamosaempezarconalgosimple.Escribeestecomando:

$whoami

o

>whoami

YluegooprimelateclaEnter.Esteeselresultado:

$whoamiolasitarska

Comopuedesver,lacomputadorasólotepresentótunombredeusuario.Bien,¿eh?:)

Tratadeescribircadacomando,nocopiesypegues.¡Teacordarásmásdeestamanera!

Básicos

DjangoGirlsTutorial

13Introducciónalalíneadecomandos

Page 14: Tutorial de Django Girls

Cadasistemaoperativotieneunconjuntodiferentedecomandosparalalíneadecomandos,asíqueasegúratedeseguirlasinstruccionesparatusistemaoperativo.Vamosaintentarlo,¿deacuerdo?

Directorioactual

Seríabuenosaberdóndeestamosahora,¿cierto?Vamosaver.EscribeestecomandoyoprimeEnter:

$pwd

/Users/olasitarska

SiestásenWindows:

>cd

C:\Users\olasitarska

Probablementeverásalgosimilarentumáquina.Unavezqueabreslalíneadecomandosgeneralmenteempiezaseneldirectoriohomedetuusuario.

Nota:'pwd'significa'printworkingdirectory'-enespañol,'mostrardirectoriodetrabajo'.

Listadearchivosydirectorios

¿Quéhayaquí?Seríabuenosaber.Veamos:

$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

14Introducciónalalíneadecomandos

Page 15: Tutorial de Django Girls

Cambiaeldirectorioactual

¿Quizáspodemosiranuestroescritorio?

$cdDesktop

Windows:

>cdDesktop

Compruebasirealmentehacambiado:

$pwd

/Users/olasitarska/Desktop

Windows:

>cd

C:\Users\olasitarska\Desktop

¡Aquíestá!

Protip:siescribescdDyluegooprimestabenelteclado,lalíneadecomandosautomáticamentecompletaráelrestodelnombreparaquepuedasnavegarmásrápido.Sihaymásdeunacarpetaqueempiececon"D",presionaelbotóntabdosvecesparaobtenerunalistadeopciones.

Creardirectorio

¿QuétalsicreamosundirectoriodeDjangoGirlsentuescritorio?Puedeshacerlodeestamanera:

$mkdirdjangogirls

Windows:

>mkdirdjangogirls

DjangoGirlsTutorial

15Introducciónalalíneadecomandos

Page 16: Tutorial de Django Girls

Estepequeñocomandocrearáunacarpetaconelnombredjangogirlsentuescritorio.¡Puedescomprobarsiestáallíbuscandoentuescritoriooejecutandoelcomandols/dir!Inténtalo:)

Protip:Sinoquieresescribirunayotravezlosmismoscomandos,pruebaoprimiendolaflechaarribayflechaabajodetutecladoparaverrecientescomandosutilizados.

¡Ejercicios!

Unpequeñoretoparati:eneldirectorioreciéncreadodjangogirlscreaundirectoriollamadotest.Utilizaloscomandoscdymkdir.

Solución:

$cddjangogirls

$mkdirtest

$ls

Windows:

>cddjangogirls

>mkdirtest

>dir

08/05/201419:28<DIR>test

¡Felicitaciones!:)

Limpiar

Noqueremosdejarundesorden,asíquevamosaeliminartodoloquehicimoshastaestemomento.

Enprimerlugar,tenemosquevolveralescritorio:

$cd..

Windows:

DjangoGirlsTutorial

16Introducciónalalíneadecomandos

Page 17: Tutorial de Django Girls

>cd..

cd..cambiaráeldirectorioactualaldirectoriopadre(quesignificaeldirectorioquecontieneeldirectorioactual).

Revisadóndeestás:

$pwd

/Users/olasitarska/Desktop

Windows:

>cd

C:\Users\olasitarska\Desktop

Ahoraeshoradeeliminareldirectoriodjangogirls.

Atención:Eliminararchivosutilizandodel,rmdirormhacequenopuedanrecuperarse,loquesignificaquelosarchivosborradosdesapareceránparasiempreDebessermuycuidadosaconestecomando.

$rm-rdjangogirls

Windows:

>rmdir/sdjangogirls

djangogirls,¿Estásseguro<Y/N>?Y

Hecho!Asegurémonosqueenverdadfueronborrados,vamosaver:

$ls

Windows:

>dir

Salida

¡Estoestodoporahora!Ahorapuedescerrarlalíneadecomandossinproblemas.Vamosahacerloalestilohacker,¿bien?:)

DjangoGirlsTutorial

17Introducciónalalíneadecomandos

Page 18: Tutorial de Django Girls

$exit

Windows:

>exit

Genial,¿no?:)

ÍndiceAquíhayunalistadealgunoscomandosútiles:

Comando(Windows)

Comando(MacOS/Linux) Descripción Ejemplo

exit exit Cierralaventana exit

cd cd Cambiaeldirectorio cdtest

dir ls Listadirectorios/archivos dir

copy cp Copiadearchivos copyc:\test\test.txtc:\windows\test.txt

move mv Muevearchivos movec:\test\test.txtc:\windows\test.txt

mkdir mkdir Creaunnuevodirectorio mkdirtestdirectory

del rm Eliminaarchivos/directorios delc:\test\test.txt

Estossonsoloalgunosdeloscomandosquepuedesejecutarenlalíneadecomandos.Novasausarnadamásqueesosporahora.

Sitienescuriosidad,ss64.comcontieneunareferenciacompletadecomandosparatodoslossistemasoperativos.

¿Lista?¡VamosasumergirnosenPython!

DjangoGirlsTutorial

18Introducciónalalíneadecomandos

Page 19: Tutorial de Django Girls

VamosaempezarconPython¡Porfinestamosaquí!

Peroprimero,déjenosdecirtequéesPython.Pythonesunlenguajedeprogramaciónmuypopularquepuedeutilizarseparalacreacióndesitiosweb,juegos,softwareacadémico,gráficosymucho,muchomás.

Pythonseoriginóenladécadade1980ysuobjetivoprincipalesserlegibleporlossereshumanos(¡nosóloparalasmáquinas!),poresoparecemuchomássimplequeotroslenguajesdeprogramación.Estohacequeseamásfácildeaprender,peronotepreocupes,¡Pythonestambiénmuypoderoso!

InstalacióndePythonEstesubcapítulosebasaenuntutorialdeGeekGirlsCarrots(http://django.carrots.pl/)

DjangoestáescritoenPython.NecesitamosPythonparacualquiercosaenDjango.¡Vamosaempezarconlainstalación!QueremosqueinstalesPython3.4,asíquesitienesalgunaversiónanterior,deberásactualizarla.

Windows

PuedesdescargarPythonparaWindowsdesdeelsitiowebhttps://www.python.org/downloads/release/python-343/.Despuésdedescargarelarchivo*.msi,debesejecutarlo(hazdobleclickenelarchivo)ysiguelasinstrucciones.Esimportanterecordarlaruta(eldirectorio)dondesehainstaladoPython.¡Seránecesariomásadelante!

Algoparatenerencuenta:enlasegundapantalladelasistentedeinstalación,llamada"Customize",asegúratedeirhaciaabajoyelegirlaopción"Addpython.exetothePath",comoen

DjangoGirlsTutorial

19InstalacióndePython

Page 20: Tutorial de Django Girls

Linux

EsmuyposiblequeyatengasPythoninstalado.Paraverificarqueyalotienesinstalado(yquéversiónes),abreunaconsolaytipeaelsiguientecomando:

$python3--version

Python3.4.2

SinotienesPythoninstaladoosiquieresunaversióndiferente,puedesinstalarlocomosigue:

Ubuntu

Tipeaestecomandoentuconsola:

sudoapt-getinstallpython3.4

Fedora

Usaestecomandoentuconsola:

DjangoGirlsTutorial

20InstalacióndePython

Page 21: Tutorial de Django Girls

sudoyuminstallpython3.4

OSX

Debesiralsitiowebhttps://www.python.org/downloads/release/python-342/ydescargarelinstaladordePython:

descargaelarchivoDMGMacOSX64-bit/32-bitinstaller,hazdobleclickparaabrirlo,dobleclickenPython.mpkgparaejecutaralinstalador.

VerificaquelainstalaciónfueexitosaabriendolaTerminalyejecutandoelcomandopython3:

$python3--version

Python3.4.2

Sitienesalgunadudaosialgosaliómalynosabescómoresolverlo-¡pideayudaatututor!Algunasveceslascosasnosalentanfácilmenteyesmejorpedirayudaaalguienconmásexperiencia.

DjangoGirlsTutorial

21InstalacióndePython

Page 22: Tutorial de Django Girls

EditordecódigoEstásapuntodeescribirtuprimeralíneadecódigo,asíque¡eshoradedescargaruneditordecódigo!

Haymuchoseditoresdiferentes,cuálusardependemuchodelapreferenciapersonal.LamayoríadeprogramadoresdePythonusanIDEs(EntornosdeDesarrolloIntegrados)complejosperomuypoderosos,comoPyCharm.Sinembargo,comoprincipiante,esoesprobablementemenosconveniente;nuestrasrecomendacionessonigualdepoderosasperomuchomassimples.

Nuestrassugerenciasestánlistadasabajo,perosiéntetelibredepreguntarleatututorcuálessonsuspreferencias-asíserámásfácilobtenersuayuda.

GeditGeditesuneditordecódigoabierto,gratis,disponibleparatodoslossistemasoperativos.

Descárgaloaquí

SublimeText2SublimeTextesuneditormuypopularconunperiododepruebagratis.Esfácildeinstalaryestádisponibleparatodoslossistemasoperativos.

Descárgaloaquí

AtomAtomesuneditordecódigomuynuevocreadoporGitHub.Esgratis,decódigoabierto,fácildeinstalaryfácildeusar.EstádisponibleparaWindows,OSXyLinux.

Descárgaloaquí

¿Porquéestamosinstalandouneditordecódigo?

DjangoGirlsTutorial

22Editordecódigo

Page 23: Tutorial de Django Girls

Puedesestarpreguntándoteporquéestamosinstalandouneditorespecial,enlugardeusaruneditorconvencionalcomoWordoNotepad.

Enprimerlugar,elcódigotienequesertextoplanoyelproblemadelasaplicacionescomoWordoTexteditesqueenrealidadnoproducentextoplano.Loquegeneranestextoenriquecido(contipografíasyformato),usandoformatospropioscomortf.

Lasegundarazónesqueloseditoresdecódigosonherramientasespecializadasy,comotales,tienencaracterísticasmuyútiles,comoresaltarlasintáxisdelcódigocondiferentescoloresdeacuerdoasusignificadoocerrarcomillasportiautomáticamente.

Veremostodoestoenacciónmásadelante.Enbreveempezarásapensarentufieleditordecódigocomounadetusherramientasfavoritas:)

DjangoGirlsTutorial

23Editordecódigo

Page 24: Tutorial de Django Girls

IntroducciónaPythonPartedeestecapítulosebasaentutorialesporGeekGirlsCarrots(http://django.carrots.pl/).

¡Vamosaescribiralgodecódigo!

PythonpromptParaempezarajugarconPython,tenemosqueabrirunalíneadecomandosennuestracomputadora.Yasabescómohacerlo,loaprendisteenelcapítulodeIntroducciónalalíneadecomandos.

Unavezqueestéslisto,siguelassiguientesinstrucciones.

QueremosabrirunaconsoladePython,asíqueescribepython3ypulsaEnter.

$python3

Python3.4.2(...)

Type"copyright","credits"or"license"formoreinformation.

>>>

TuprimercomandoenPython!DespuésdeejecutarelcomandodePython,elcursorcambiaa>>>.ParanosotrosestosignificaqueporahorasólopodemosutilizarcomandosenellenguajePython.Notienesqueescribirel>>>-Pythonloharáporti.

SideseassalirdelaconsoladePythonencualquiermomento,simplementeescribeexit()ousaelatajoCtrl+ZparaWindowsyCtrl+DparaMac/Linux.Luegonoverásmás>>>.

PeroahoranoqueremossalirdelaconsoladePython.Queremosaprendermássobreella.Vamosaempezarconalgomuysimple.Porejemplo,tratadeescribiralgodematemáticas,como2+3ypulsaEnter.

>>>2+3

5

DjangoGirlsTutorial

24IntroducciónaPython

Page 25: Tutorial de Django Girls

¡Bien!¿Vescomosaliólarespuesta?¡Pythonsabematemáticas!Podríasintentarotroscomandoscomo:-4*5-5-1-40/2

Diviérteteconestoporunmomentoyluegovuelveaquí:).

Comopuedesver,Pythonesunagrancalculadora.Siteestáspreguntandoquémáspuedehacer...

Strings¿Ytunombre?Escribatunombredepilaenfrasescomoésta:

>>>"Ola"

'Ola'

¡Hascreadotuprimerstring!Esunasecuenciadecaracteresquepuedeserprocesadaporunacomputadora.Elstring(oenespañol,cadena)debecomenzaryterminarconelmismocarácter.Estopuedesercomillassimples(')odobles(")-ellasledicenaPythonqueloqueestadentroesunacadena.

Lascadenaspuedenserconcatenadas.Pruebaesto:

>>>"Hola"+"Ola"

'HolaOla'

Tambiénpuedesmultiplicarlascadenasconunnúmero:

>>>"Ola"*3

'OlaOlaOla'

Sinecesitasponerunapóstrofedentrodetucadena,tienesdosmanerasdehacerlo.

Usandocomillasdobles:

>>>"Runnin'downthehill"

"Runnin'downthehill"

oescapandoelapóstrofeconunabarrainvertida(``):

>>>'Runnin\'downthehill'

"Runnin'downthehill"

DjangoGirlsTutorial

25IntroducciónaPython

Page 26: Tutorial de Django Girls

Bien,¿eh?Paravertunombreenletrasmayúsculas,simplementeescribe:

>>>"Ola".upper()

'OLA'

¡Usastelafunciónupperentucadena!Unafunción(comoupper())esunconjuntodeinstruccionesquePythontienequerealizarsobreunobjetodeterminado("Ola")unavezquesellama.

Siquisierassaberelnúmerodeletrasquecontienetunombre,tambiénexisteunafunciónparaesto.

>>>len("Ola")

3

Tepreguntarásporquéavecessellamaalasfuncionesconun.alfinaldeunacadena(como"Ola".upper())yavecessellamaaunafunciónycolocaslacadenaentreparéntesis.Bueno,enalgunoscasoslasfuncionespertenecenaobjetos,comoupper(),quesólopuedeserutilizadosobrecadenas(upper()esunafuncióndelosobjetosstring).Enestecaso,llamamosmétodoaestafunción.Otraveces,lasfuncionesnopertenecenaningúnobjetoespecíficoypuedenserusadosendiferentesobjetos,comolen().Estaeslarazóndeporquéestamospasando"Ola"comounparámetroalafunciónlen.

Resumen

Ok,suficientesobrelascadenas.Hastaahorahasaprendidosobre:

laterminal-teclearcomandos(código)dentrodelaterminaldePythonresultaenrespuestasdePythonnúmerosystrings-enPythonlosnúmerossonusadosparamatemáticasystringsparaobjetosdetextooperadores-como+y*,combinavaloresparaproducirunonuevofunciones-comoupper()ylen(),realizanopcionessobrelosobjetos.

Estossonlosconocimientosbásicosquepuedesaprenderdecualquierlenguajedeprogramación.¿Listaparaalgounpocomásdifícil?¡Apostamosqueloestás!

Errores

DjangoGirlsTutorial

26IntroducciónaPython

Page 27: Tutorial de Django Girls

Intentemosconalgonuevo.¿Podríamosobtenerlalongituddeunnúmerodelamismamaneraqueobtuvimoslalongituddenuestronombre?Teclealen(304023)ypresionaEnter:

>>>len(304023)

Traceback(mostrecentcalllast):

File"<stdin>",line1,in<module>

TypeError:objectoftype'int'hasnolen()

¡Obtuvimosnuestroprimererror!Dicequelosobjetosdetipo"int"(númerosenteros)notienenningunalongitud.¿Quépodemoshacerahora?Quizáspodemosescribirelnumerocomounstring.Losstringstienenlongitud,¿cierto?

>>>len(str(304023))

6

¡Funcionó!Utilizamoslafunciónstrdentrodelafunciónlen.str()conviertetodoastrings.

LafunciónstrconviertecosasenstringsLafunciónintconviertecosasenintegers

Importante:podemosconvertirnúmerosentexto,peronopodemosnecesariamenteconvertirtextoennúmeros-¿quéseríaint('hello')?

VariablesUnconceptoimportanteenprogramaciónsonlasvariables.Unavariablenoesmásqueunnombreparaalgunacosaparaquepuedasusarlamástarde.Losprogramadoresusanestasvariablesparaalmacenardatos,hacersucódigomáslegibleyasínotenerqueseguirrecordandoquehacecadacosa.

Supongamosquequeremoscrearunanuevavariablellamadaname:

>>>name="Ola"

¿Ves?¡Esfácil!Essimplemente:nameequivaleaOla.

Comotehasdadocuenta,elprogramanoregresaalgocomolohaciaantes.Entonces,¿Cómosabemosquelavariableexisterealmente?SimplementeintroducenameypulsaEnter:

DjangoGirlsTutorial

27IntroducciónaPython

Page 28: Tutorial de Django Girls

>>>name

'Ola'

¡Súper!Tuprimervariable:).Siemprepodráscambiaraloqueserefiere:

>>>name="Sonja"

>>>name

'Sonja'

Puedesusarladentrodefuncionestambién:

>>>len(name)

5

Increíble,¿verdad?Porsupuesto,lasvariablespuedensercualquiercosa,¡tambiénnúmeros!Pruebaesto:

>>>a=4

>>>b=6

>>>a*b

24

Pero¿quépasasiusamoselnombreequivocado?¿Puedesadivinarquépasaría?¡Vamosaprobar!

>>>city="Tokyo"

>>>ctiy

Traceback(mostrecentcalllast):

File"<stdin>",line1,in<module>

NameError:name'ctiy'isnotdefined

¡Unerror!Comopuedesver,PythontienediferentestiposdeerroresyestesellamaNameError.Pythontedaráesteerrorsiintentasutilizarunavariablequenohasidodefinidaaún.Simásadelanteteencuentrasconesteerror,verificatucódigoparaversinohasescritomalunavariable.

Juegaconestoporunratoymiraquepuedeshacer!

LafunciónprintIntentaesto:

DjangoGirlsTutorial

28IntroducciónaPython

Page 29: Tutorial de Django Girls

>>>name='Maria'

>>>name

'Maria'

>>>print(name)

Maria

Cuandosóloescribesname,elintérpretedePythonrespondeconlarepresentacióndelstringdelavariable'name',quesonlasletrasM-a-r-i-a,rodeadasdecomillassimples''.Cuandodicesprint(name),Pythonvaa"imprimir"elcontenidodelavariablealapantalla,sinlascomillas,queesmejor.

Comoveremosdespués,print()tambiénesútilcuandoqueremosimprimircosasdesdeadentrodelasfunciones,obiencuandoqueremosimprimircosasenmúltipleslíneas.

ListasAdemásdestringeintegers,Pythontienetodaclasedediferentestiposdeobjetos.Ahoravamosaintroducirunollamadolist.Laslistassonexactamenteloquepiensasqueson:sonobjetosquesonlistasdeotrosobjetos:)

Anímateycreaunalista:

>>>[]

[]

Sí,estalistaestávacía.Noesmuyútil,¿verdad?Vamosacrearunalistadenúmerosdelotería.Noqueremosrepetirtodoeltiempo,asíquelospondremosenunavariabletambién:

>>>lottery=[3,42,12,19,30,59]

Muybien,¡tenemosunalista!¿Quépodemoshacerconella?Vamosavercuántosnúmerosdeloteríahayenlalista.¿Tienesalgunaideadequéfuncióndeberíasusarparaeso?¡Yasabesesto!

>>>len(lottery)

6

¡Sí!len()puededarteelnúmerodeobjetosenunalista.Útil,¿verdad?Talvezlaordenemosahora:

DjangoGirlsTutorial

29IntroducciónaPython

Page 30: Tutorial de Django Girls

>>>lottery.sort()

Estonodevuelvenada,sólocambióelordenenquelosnúmerosaparecenenlalista.Vamosaimprimirlalistaotravezyverquepasó:

>>>print(lottery)

[3,12,19,30,42,59]

Comopuedesver,losnúmerosentulistaahoraestánordenadosdemenoramayor.¡Felicidades!

¿Tegustaríainvertireseorden?¡Vamosahacerlo!

>>>lottery.reverse()

>>>print(lottery)

[59,42,30,19,12,3]

Fácil,¿no?Siquieresañadiralgoatulista,puedeshacerloescribiendoestecomando:

>>>lottery.append(199)

>>>print(lottery)

[59,42,30,19,12,3,199]

Sideseasmostrarsóloelprimernúmero,puedeshacerlomedianteelusodeindexes(enespañol,índices).Uníndiceeselnúmeroquetedicedóndeenunalistaapareceunítem.Lacomputadorainicialacuentaen0,asíqueelprimerobjetoentulistaestáenelíndice0,elsiguientees1,yasísucesivamente.Intentaesto:

>>>print(lottery[0])

59

>>>print(lottery[1])

42

Comopuedesver,puedesaccederadiferentesobjetosentulistautilizandoelnombredelalistayelíndicedelobjetodentrodecorchetes.

Paradiversiónadicional,pruebaalgunosotrosíndices:6,7,1000,-1,-6ó-1000.Aversisepuedespredecirelresultadoantesdeintentarelcomando.¿Tienensentidolosresultados?

PuedesencontrarunalistadetodoslosmétodosdisponiblesparalistasenestecapítulodeladocumentacióndePython:https://docs.python.org/3/tutorial/datastructures.html

DjangoGirlsTutorial

30IntroducciónaPython

Page 31: Tutorial de Django Girls

DiccionariosUndiccionarioessimilaraunalista,peroaccedesavaloresusandounaclaveenvezdeuníndice.Unaclavepuedesercualquiercadenaonúmero.Lasintaxisparadefinirundiccionariovacíoes:

>>>{}

{}

Estodemuestraqueacabasdecrearundiccionariovacío.¡Hurra!

Ahora,trataescribiendoelsiguientecomando(intentareemplazandoconpropiainformación):

>>>participant={'name':'Ola','country':'Poland','favorite_numbers':[7,42,92]}

Conestecomando,acabasdecrearunavariableparticipantcontresparesclave-valor:

Laclavenameapuntaalvalor'Ola'(unobjetostring),countryapuntaa'Poland'(otrostring),yfavorite_numbersapuntaa[7,42,92](unalistcontresnúmerosenella).

Puedesverificarelcontenidodeclavesindividualesconestasintaxis:

>>>print(participant['name'])

Ola

Loves,essimilaraunalista.Perononecesitasrecordarelíndice-sóloelnombre.

¿QuépasasilepedimosaPythonelvalordeunaclavequenoexiste?¿Puedesadivinar?¡Pruébaloyverás!

>>>participant['age']

Traceback(mostrecentcalllast):

File"<stdin>",line1,in<module>

KeyError:'age'

¡Mira,otroerror!EsteesunKeyError.Pythonteayudaytedicequelallave'age'noexisteenestediccionario.

¿Cuándoutilizarundiccionarioounalista?Bueno,esoesunbuenpuntoparareflexionar.Sólotenunasoluciónenmenteantesdemirarlarespuestaenlasiguientelínea.

DjangoGirlsTutorial

31IntroducciónaPython

Page 32: Tutorial de Django Girls

¿Sólonecesitasunasecuenciaordenadadeelementos?Usaunalista.¿Necesitasasociarvaloresconclaves,asípuedesbuscarloseficientemente(usandolasclaves)másadelante?Utilizaundiccionario.

Losdiccionarios,comolaslistas,sonmutables,loquesignificaquepuedensercambiadosdespuésdesercreados.Puedesagregarnuevosparesclave/valoreneldiccionariodespuésdequehasidocreado,porejemplo:

>>>participant['favorite_language']='Python'

Comoenlaslistas,elmétodolen()enlosdiccionarios,devuelveelnúmerodeparesclave-valoreneldiccionario.Adelante,escribeelcomando:

>>>len(participant)

4

Esperotengasentidohastaahora.:)¿Listaparamásdiversiónconlosdiccionarios?Saltaalasiguientelíneaparaalgunascosassorprendentes.

Puedesutilizarelcomandodelparaborrarunelementoeneldiccionario.Porejemplo,sideseaseliminarlaentradacorrespondientealaclave'favorite_numbers',sólotienesqueescribirelsiguientecomando:

>>>delparticipant['favorite_numbers']

>>>participant

{'country':'Poland','favorite_language':'Python','name':'Ola'}

Comopuedesverenlasalida,elpardeclave-valorcorrespondientealaclave'favorite_numbers'hasidoeliminado.

Ademásdeesto,tambiénpuedescambiarunvalorasociadoaunaclaveyacreadaeneldiccionario.Teclea:

>>>participant['country']='Germany'

>>>participant

{'country':'Germany','favorite_language':'Python','name':'Ola'}

Comopuedesver,elvalordelaclave'country'hasidomodificadode'Poland'a'Germany'.:)¿Emocionante?¡Hurra!Hasaprendidootracosaasombrosa.

Resumen

DjangoGirlsTutorial

32IntroducciónaPython

Page 33: Tutorial de Django Girls

¡Genial!Sabesmuchosobreprogramaciónahora.Enestaúltimaparteaprendistesobre:

errors-ahorasabescómoleeryentenderloserroresqueaparecensiPythonnoentiendeuncomandoquelehasdadovariables-nombresparalosobjetosquetepermitencodificarmásfácilmenteyhacerelcódigomáslegiblelists-listasdeobjetosalmacenadosenunordendeterminadodictionaries-objetosalmacenadoscomoparesclave-valor

¿Emocionadaporlasiguienteparte?:)

ComparacosasUnagranpartedelaprogramaciónincluyecompararcosas.¿Quéeslomásfácilparacomparar?Números,porsupuesto.Vamosavercómofunciona:

>>>5>2

True

>>>3<1

False

>>>5>2*2

True

>>>1==1

True

>>>5!=2

True

LedimosaPythonalgunosnúmerosparacomparar.Comopuedesver,Pythonnosólopuedecompararnúmeros,sinoquetambiénpuedecompararresultadosdemétodo.Bien,¿eh?

¿Tepreguntasporquépusimosdossignosigual==alladodelotroparacompararsilosnúmerossoniguales?Utilizamosunsolo=paraasignarvaloresalasvariables.Siempre,siempreesnecesarioponerdos==Sideseascomprobarquelascosassonigualesentresí.Tambiénpodemosafirmarquelascosasnosonigualesaotras.Paraeso,utilizamoselsímbolo!=,comomostramosenelejemploanterior.

DadostareasmásaPython:

>>>6>=12/2

True

>>>3<=2

False

DjangoGirlsTutorial

33IntroducciónaPython

Page 34: Tutorial de Django Girls

>y<sonfáciles,pero¿quéessignifica>=y<=?Seleenasí:

x>ysignifica:xesmayorqueyx<ysignifica:xesmenorqueyx<=ysignifica:xesmenoroigualqueyx>=ysignifica:xesmayoroigualquey

¡Genial!¿Quiereshacerunomas?Intentaesto:

>>>6>2and2<3

True

>>>3>2and2<1

False

>>>3>2or2<1

True

PuedesdarleaPythontodoslosnúmerosparacompararquequieras,ysiempretedaráunarespuesta.Muyinteligente,¿verdad?

and-siutilizaseloperadorand,ambascomparacionesdebenserTrueparaqueelresultadodetodoelcomandoseaTrueor-siutilizaseloperadoror,sólounadelascomparacionestienequeserTrueparaqueelresultadodetodoelcomandoseaTrue

¿Hasoídolaexpresión"compararmanzanasconnaranjas"?VamosaprobarelequivalenteenPython:

>>>1>'django'

Traceback(mostrecentcalllast):

File"<stdin>",line1,in<module>

TypeError:unorderabletypes:int()>str()

Aquíverásquealigualqueenlaexpresión,Pythonnoescapazdecompararunnúmero(int)yunstring(str).Encambio,muestraunTypeErrorynosdicequelosdostiposnosepuedencomparados.

BooleanPorcierto,acabasdeaprenderacercadeunnuevotipodeobjetoenPython.SellamaunBoolean--yesprobablementeeltipomássimplequeexiste.

HaysólodosobjetosBoolean:-True-False

DjangoGirlsTutorial

34IntroducciónaPython

Page 35: Tutorial de Django Girls

PeroparaquePythonentiendaesto,esnecesarioquesiempreloescribascomoTrue(primeraletramayúscula,conelrestodelaletrasminúsculas).true,TRUE,tRUEnofuncionarán--sóloTrueescorrecto.(LomismoaplicaaFalsetambién,porsupuesto.)

Losvaloresbooleanospuedenservariables,también.Veelsiguienteejemplo:

>>>a=True

>>>a

True

Tambiénpuedeshacerlodeestamanera:

>>>a=2>5

>>>a

False

Practicaydiviérteteconlosbooleanosejecutandolossiguientescomandos:

TrueandTrue

FalseandTrue

Trueor1==1

1!=2

¡Felicidades!Losbooleanossonunadelasfuncionesmásgenialesenprogramaciónyacabasdeaprendercómousarlos.

¡Guárdalo!HastaahorahemosestadoescribiendonuestrocódigoPythonenelintérprete,locualnoslimitaaunalíneadecódigoalavez.Normalmentelosprogramassonguardadosenarchivosysonejecutadosporelintérpreteocompiladordenuestrolenguajedeprogramación.Hastaahora,hemosestadocorriendonuestrosprogramasdeaunalíneaporvezenelintérpretedePython.Necesitaremosmásdeunalíneadecódigoparalassiguientestareas,entoncesnecesitaremoshacerrápidamenteloquesigue:

SalirdelintérpretedePythonAbrireleditordetextodenuestraelecciónGuardaralgodecódigoenunnuevoarchivodePython¡Ejecutarlo!

ParasalirdelintérpretedePythonquehemosestadousando,simplementeescribelafunciónexit():

DjangoGirlsTutorial

35IntroducciónaPython

Page 36: Tutorial de Django Girls

>>>exit()

$

Estotellevarádevueltaalalíneadecomandos.

Anteriormente,elegimosuneditordecódigoenlaseccióndeEditordecódigo.Tendremosqueabrireleditorahorayescribiralgodecódigoenunarchivonuevo:

print('Hello,Djangogirls!')

NotaDeberíasnotarunadelascosasmásgenialesdeloseditoresdecódigo:¡loscolores!EnlaconsoladePython,todoeradelmismocolor,peroahorapuedesverquelafunciónprintesdeuncolordiferentedelstringqueestáadentrodeella.Esosedenomina"resaltadodesintaxis",yesunagranayudacuandoestásprogramando.Prestaatenciónaloscolores,yobtendrásunapistacuandoteolvidesdecerrarunstringocometesunerroralescribirunapalabraclave(comoeldefenunafunción,queveremosabajo).Estaesunadelasrazonesporlascualesusaruneditordecódigo:)

Obviamente,ahoraeresunadesarrolladoraPythonmuyexperimentada,asíquesiéntetelibredeescribiralgodelcódigoquehasaprendidohoy.

Ahoratenemosqueguardarelarchivoyasignarleunnombredescriptivo.Vamosallamaralarchivopython_intro.pyyguardarloentuescritorio.Podemosnombrarelarchivodecualquiermaneraquequeramos,loimportanteaquíesasegurarsequeelarchivofinalicecon.py,estoleindicaanuestracomputadoraqueesteesunarchivoejecutabledePythonyquePythonpuedecorrerlo.

Conelarchivoguardado,¡eshoradeejecutarlo!Utilizandolashabilidadesquehasaprendidoenlaseccióndelíneadecomandos,utilizalaterminalparacambiarlosdirectorioseiralescritorio.

EnunaMac,elcomandoseveráalgocomoesto:

cd/Users/<your_name>/Desktop

EnLinux,vaaserasí(lapalabra"Desktop"puedeestartraducidaatuidioma):

cd/home/<your_name>/Desktop

YenWindows,seráasí:

DjangoGirlsTutorial

36IntroducciónaPython

Page 37: Tutorial de Django Girls

cdC:\Users\<your_name>\Desktop

Sitequedasatascada,sólopideayuda.

yluegousaPythonparaejecutarelcódigoenelarchivocomosigue:

$python3python_intro.py

Hello,Djangogirls!

¡Muybien!EjecutastetuprimerprogramadePythondesdeunarchivo.¿Nosesienteincreíble?

Ahorapuedesmoverteaunaherramientaesencialenlaprogramación:

If...elif...elseUnmontóndecosasenelcódigosólosonejecutadascuandosecumplenlascondicionesdadas.PoresoPythontienealgollamadosentenciasif.

Reemplazaelcódigoentuarchivopython_intro.pyporesto:

if3>2:

Siloguardáramosyloejecutáramos,veríamosunerrorcomoeste:

$python3python_intro.py

File"python_intro.py",line2

^

SyntaxError:unexpectedEOFwhileparsing

Pythonesperaqueledemosmásinstruccionesquesesuponeseránejecutadassilacondición3>2resultaserverdadera(oTrueenestecaso).IntentemoshacerquePythonimprima"Itworks!".Cambiatucódigoenelarchivopython_intro.pyparaqueseveacomoesto:

if3>2:

print('Itworks!')

¿Observascómohemosindentadolasiguientelíneadecódigocon4espacios?TenemosquehacerestoparaquePythonsepaquécódigoejecutarsilacomparaciónresultaverdadera.Puedesponerunespacio,perocasitodoslosprogramadoresPythonhacen4

DjangoGirlsTutorial

37IntroducciónaPython

Page 38: Tutorial de Django Girls

espaciosparahacerqueelcódigoseamáslegible.Unsolotabtambiéncontarácomo4espacios.

Guárdaloyejecútalodenuevo:

$python3python_intro.py

Itworks!

¿Quépasasilacondiciónnoesverdadera?

Enejemplosanteriores,elcódigofueejecutadosólocuandolascondicioneseranciertas.PeroPythontambiéntienedeclaracioneselifyelse:

if5>2:

print('5isindeedgreaterthan2')

else:

print('5isnotgreaterthan2')

Alejecutarestoseimprimirá:

$python3python_intro.py

5isindeedgreaterthan2

Si2fueraunnúmeromayorque5,entonceselsegundocomandoseríaejecutado.Fácil,¿verdad?Vamosavercómofuncionaelif:

name='Sonja'

ifname=='Ola':

print('HeyOla!')

elifname=='Sonja':

print('HeySonja!')

else:

print('Heyanonymous!')

yalejecutarlo:

$python3python_intro.py

HeySonja!

¿Vesloquepasóahí?

Resumen

DjangoGirlsTutorial

38IntroducciónaPython

Page 39: Tutorial de Django Girls

Enlosúltimostresejerciciosaprendisteacercade:

Compararcosas-enPythonpuedescompararcosashaciendousode>,>=,==,<=,<ydelosoperatoresandyorBoolean-untipodeobjetoquesólopuedetenerunodedosvalores:TrueoFalseGuardararchivos-cómoalmacenarcódigoenarchivosasípuedesejecutarprogramasmásgrandesif...elif...else-sentenciasquetepermitenejecutarcódigosólocuandosecumplenciertascondiciones

¡Eshoradeleerlaúltimapartedeestecapítulo!

¡Tuspropiasfunciones!¿Recuerdaslasfuncionescomolen()quepuedesejecutarenPython?Bien,buenasnoticias,¡ahoraaprenderáscómoescribirtuspropiasfunciones!

UnafunciónesunasecuenciadeinstruccionesquePythondebeejecutar.CadafunciónenPythoncomienzaconlapalabraclavedef,seleasignaunnombreypuedeteneralgunosparámetros.Vamosaempezarconalgofácil.Reemplazaelcódigoenpython_intro.pyconlosiguiente:

defhi():

print('Hithere!')

print('Howareyou?')

hi()

Bien,¡nuestraprimerafunciónestálista!

Tepreguntarásporquéhemosescritoelnombredelafunciónenlaparteinferiordelarchivo.EstoesporquePythonleeelarchivoyloejecutadesdearribahaciaabajo.Asíqueparapoderutilizarnuestrafunción,tenemosquereescribirsunombreenlaparteinferior.

Ejecutemosestoyveamosquésucede:

$python3python_intro.py

Hithere!

Howareyou?

¡Esofuefácil!Vamosaconstruirnuestraprimerafunciónconparámetros.Utilizaremoselejemploanterior-unafunciónquedice'Hi'alapersonaqueejecutaelprograma-conunnombre:

DjangoGirlsTutorial

39IntroducciónaPython

Page 40: Tutorial de Django Girls

defhi(name):

Comopuedesver,ahoradimosanuestrafunciónunparámetroquellamamosname:

defhi(name):

ifname=='Ola':

print('HiOla!')

elifname=='Sonja':

print('HiSonja!')

else:

print('Hianonymous!')

hi()

Comopuedesnotar,tuvimosqueponerdosindentacionesantesdelafunciónprintporqueifnecesitasaberloquedeberíaocurrircuandosecumplelacondición.Vamosavercómofunciona:

$python3python_intro.py

Traceback(mostrecentcalllast):

File"python_intro.py",line10,in<module>

hi()

TypeError:hi()missing1requiredpositionalargument:'name'

Oops,unerror.Porsuerte,Pythonnosdaunmensajedeerrorbastanteútil.Nosdicequelafunciónhi()(laquedefinimos)tieneunargumentorequerido(llamadoname)yquesenosolvidópasarloalllamaralafunción.Vamosaarreglarloenlaparteinferiordelarchivo:

hi("Ola")

yloejecutamosotravez:

$python3python_intro.py

HiOla!

¿Ysicambiamoselnombre?

hi("Sonja")

ylocorremos:

DjangoGirlsTutorial

40IntroducciónaPython

Page 41: Tutorial de Django Girls

$python3python_intro.py

HiSonja!

Ahora,¿quécreesquepasarásiescribesotronombreallí?(NoOlaoSonja).Pruébaloyverássitienesrazón.Estodeberíaimprimir:

Hianonymous!

Estoesincreíble,¿verdad?Deestaformanotienesquerepetirtodocadavezquedeseascambiarelnombredelapersonaalaquelafuncióndeberíasaludar.Yesoesexactamenteporquénecesitamosfunciones-¡paranorepetirtucódigo!

Vamosahaceralgomásinteligente-haymásdedosnombres,yescribirunacondiciónparacadaunoseríadifícil,¿no?

defhi(name):

print('Hi'+name+'!')

hi("Rachel")

Ahoravamosallamaralcódigo:

$python3python_intro.py

HiRachel!

¡Felicidades!Acabasdeaprendercómoescribirfunciones:)

BuclesEstayaeslaúltimaparte.¿Esofuerápido,verdad?:)

Comohemosmencionado,losprogramadoressonperezosos,nolesgustarepetircosas.Laprogramaciónintentaautomatizarlascosas,asíquenoqueremossaludaracadapersonaporsunombremanualmente,¿verdad?Esahídondelosbuclessevuelvenmuyútiles.

¿Todavíarecuerdaslaslistas?Hagamosunalistadelaschicas:

girls=['Rachel','Monica','Phoebe','Ola','You']

Queremossaludaratodasellasporsunombre.Tenemoslafunciónhiquehaceeso,asíquevamosausarlaenunbucle:

DjangoGirlsTutorial

41IntroducciónaPython

Page 42: Tutorial de Django Girls

fornameingirls:

Lasentenciaforsecomportademanerasimilaralasentenciaif,elcódigoquesiguecontinuacióndebeestarindentadousandocuatroespacios.

Aquíestáelcódigocompletoqueestaráenelarchivo:

defhi(name):

print('Hi'+name+'!')

girls=['Rachel','Monica','Phoebe','Ola','You']

fornameingirls:

hi(name)

print('Nextgirl')

ycuandoloejecutamos:

$python3python_intro.py

HiRachel!

Nextgirl

HiMonica!

Nextgirl

HiPhoebe!

Nextgirl

HiOla!

Nextgirl

HiYou!

Nextgirl

Comopuedesver,todoloqueponesconunaindentacióndentrodeunasentenciaforserárepetidoparacadaelementodelalistagirls.

Tambiénpuedesusarelforennúmerosusandolafunciónrange:

foriinrange(1,6):

print(i)

Loqueimprimirá:

1

2

3

4

5

DjangoGirlsTutorial

42IntroducciónaPython

Page 43: Tutorial de Django Girls

rangeesunafunciónquecreaunalistadenúmerosenserie(estosnúmerossonproporcionadosporticomoparámetros).

TenencuentaqueelsegundodeestosdosnúmerosnoseráincluidoenlalistaqueretornaráPython(esdecir,range(1,6)cuentadesde1a5,peronoincluyeelnúmero6).

ResumenEsoestodo.¡Eresgenial!Estonofuetanfácilrealmente,asíquedeberíassentirteorgullosadetimisma.¡Estamosmuyorgullososdequehayasllegadohastaaquí!

Talvezquierashaceralgodistintoporunmomento-estirarte,caminarunpoco,descansartusojos-antesdepasaralsiguientecapítulo.:)

DjangoGirlsTutorial

43IntroducciónaPython

Page 44: Tutorial de Django Girls

¿QuéesDjango?Django(gdh/ˈdʒæŋɡoʊ/jang-goh)esunframeworkparaaplicacioneswebgratuitoyopensource,escritoenPython.EsunWEBframework-unconjuntodecomponentesqueteayudanadesarrollarsitioswebmásfácilyrápidamente.

Verás,cuandoestásconstruyendounsitioweb,frecuentementenecesitasunconjuntodecomponentessimilares:unamanerademanejarlaautenticacióndeusuarios(registrarse,iniciarsesión,cerrarsesión),unpaneldeadministraciónparatusitioweb,formularios,unaformadesubirarchivos,etc.

Porsuerteparati,hacetiempovariaspersonasnotaronquelosdesarrolladoreswebenfrentanproblemassimilarescuandoconstruyenunsitionuevo,poresojuntaroncabezasycrearonframeworks(Djangoesunodeellos)queteofrecencomponenteslistosparausarse.

Losframeworksexistenparaahorrartetenerquereinventarlaruedayayudarteaaliviarlacargacuandoconstruyesunsitio.

¿Porquénecesitasunframework?ParaentenderparaqueesDjango,necesitamosmirarmasdecercaalosservidores.Loprimeroesqueelservidornecesitasaberquequieresquetesirvaunapáginaweb.

Imaginaunbuzón(puerto)elcualesmonitoreadoporcartasentrantes(peticiones).Estoesrealizadoporunservidorweb.Elservidorwebleelacarta,yenvíaunarespuestaconunapáginaweb.Perocuandoquieresenviaralgo,tienesqueteneralgúncontenido.YDjangoesalgoqueteayudaacrearelcontenido.

¿Quésucedecuandoalguiensolicitaunapáginawebdetuservidor?CuandollegaunapeticiónaunservidorwebespasadoaDjangoqueintentaaveriguarloquerealmenteessolicitado.Tomaprimerounadireccióndepáginawebytratadeaveriguarquéhacer.EstaparteesrealizadaporurlresolverdeDjango(tengaencuentaqueladireccióndeunsitiowebesllamadaURL-UniformResourceLocator-asíqueelnombre

DjangoGirlsTutorial

44¿QuéesDjango?

Page 45: Tutorial de Django Girls

urlresolvertienesentido).Estenoesmuyinteligente-tomaunalistadepatronesytratadeigualarlaURL.DjangocompruebalospatronesdearribahaciaabajoysialgosecoincideentoncesDjangolepasalasolicitudalafunciónasociada(quesellamavista).

Imaginaauncarterollevandounacarta.Ellaestácaminandoporlacalleycompruebacadanúmerodecasaconelqueestáenlacarta.Sicoincide,elladejalacartaallí.Asíescomofuncionaelurlresolver!

Enlafuncióndevistasehacentodaslascosasinteresantes:podemosmiraraunabasededatosparabuscaralgunainformación.¿Talvezelusuariopidiócambiaralgoenlosdatos?Comounacartadiciendo"Porfavorcambialadescripcióndemitrabajo."Lavistapuedecomprobarsitenespermitidohacereso,entoncesactualizarladescripcióndeltrabajoparaustedydevolverleunmensaje:"¡hecho!".EntonceslavistageneraunarespuestayDjangopuedeenviarlaalnavegadordelusuario.

Porsupuesto,ladescripciónanteriorsesimplificaunpoco,perononecesitassabertodaslascosastécnicasaun.Tenerunaideageneralessuficiente.

Asíqueenlugardemeternosdemasiadoenlosdetalles,simplementecomenzaremoscreandoalgoconDjangoyaprenderemostodaslaspiezasimportantesenelcamino!

DjangoGirlsTutorial

45¿QuéesDjango?

Page 46: Tutorial de Django Girls

InstalacióndeDjangoPartedeestecapituloestabasadoenlostutorialesdeGeekGirlsCarrots(http://django.carrots.pl/).

Partedeestecapítulosebasaeneldjango-marcadortutorialbajolicenciadeCreativeCommonsAttribution-ShareAlike4.0internacional.Eltutorialdedjango-marcadortienederechosdeautordeMarkusZapke-Gündemannetal.

EntornovirtualAntesdeinstalarDjango,instalaremosunaherramientaextremadamenteútilqueayudaráamantenertuentornodedesarrolloordenadoensucomputadora.Esposibleomitirestepaso,peroesmuyrecomendablenohacerlo-¡comenzarconlamejorconfiguraciónposibleayudaraaevitarmuchosproblemasenelfuturo!

Asíque,vamosacrearunentornovirtual(tambiénllamadounvirtualenv).AislarálaconfiguraciónPython/Djangoenbasedecadaproyecto,loquesignificaquecualquiercambioquerealiceenunsitiowebnoafectaráaotrosquetambiénestésdesarrollando.Genial,¿no?

Todoloquenecesitashaceresencontrarundirectorioenelquedeseescrearelvirtualenv;tudirectoriohome,porejemplo.EnWindowspuedeversecomoC:\Users\Name(dondenombreeselnombredetuusuario).

Paraestetutorialusaremosunnuevodirectoriodjangogirlsentudirectoriohome:

mkdirdjangogirls

cddjangogirls

Haremosunvirtualenvllamadomyvenv.Elcomandogeneralestaráenelformato:

python3-mvenvmyvenv

Windows

Paracrearunnuevovirtualenv,debesabrirlaconsola(teloindicamosunoscuantoscapítulosantes,¿recuerdas?)yejecutaC:\Python34\python-mvenvmyvenv.Severáasí:

DjangoGirlsTutorial

46InstalacióndeDjango

Page 47: Tutorial de Django Girls

C:\Users\Name\djangogirls>C:\Python34\python-mvenvmyvenv

endondeC:\Python34\pythoneseldirectorioenelqueinstalastePythonpreviamenteymyvenveselnombredetuvirtualenv.Puedesutilizarcualquierotronombre,peroasegúratedeusarminúsculasynodejarespacios,acentosocaracteresespeciales.Tambiénesunabuenaideamantenerelnombrecorto.¡Vasareferirteaélmucho!

LinuxyOSX

CrearunvirtualenvenLinuxyOSXestansimplecomoejecutarpython3-mvenvmyvenv.Severáasí:

~/djangogirls$python3-mvenvmyvenv

myvenveselnombredetuvirtualenv.Puedesusarcualquierotronombre,peromanténelusodeminúsculasynoincluyasespacios.Tambiénesunabuenaideamantenerelnombrecorto.¡Vasareferirteaélmucho!

Nota:Actualmente,iniciarelentornovirtualenUbuntu14.04deestamaneraproduceelsiguienteerror:

Error:Command'['/home/eddie/Slask/tmp/venv/bin/python3','-Im','ensurepip','--upgrade','--default-pip']'returnednon-zeroexitstatus1

Paraevitaresto,utilizadirectamenteelcomandovirtualenv.

~/djangogirls$sudoapt-getinstallpython-virtualenv

~/djangogirls$virtualenv--python=python3.4myvenv

TrabajarconvirtualenvEstecomandoanteriorcrearáundirectoriollamadomyvenv(ocualquiernombrequehayasescogido)quecontienenuestroentornovirtual(básicamenteunmontóndearchivosycarpetas).Todoloquequeremoshacerahoraesiniciarloejecutando:

C:\Users\Name\djangogirls>myvenv\Scripts\activate

enWindows,o:

DjangoGirlsTutorial

47InstalacióndeDjango

Page 48: Tutorial de Django Girls

~/djangogirls$sourcemyvenv/bin/activate

enOSXyLinux.

¡Recuerdareemplazarmyvenvcontunombredevirtualenvquehayaselegido!

Nota:aveceslafuentepodríanoestardisponible.Enesoscasostratadehacerloesto:

~/djangogirls$.myvenv/bin/activate

Sabrásquetienesvirtualenviniciadocuandoveasquepareceestemensajeenlaconsola:

(myvenv)C:\Users\Name\djangogirls>

o:

(myvenv)~/djangogirls$

¡Notaqueelprefijo(myvenv)aparece!

Cuandotrabajesenunentornovirtual,pythonautomáticamentesereferiráalaversióncorrecta,demodoquepuedesutilizarpythonenvezdepython3.

Tenemostodaslasdependenciasimportantesensulugar.¡FinalmentepodemosinstalarDjango!

InstalarDjangoAhoraquetienestuvirtualenviniciado,puedesinstalarDjangousandopip.Enlaconsola,ejecutapipinstalldjango==1.8(fíjatequeutilizamosundoblesignoigual:==).

(myvenv)~$pipinstalldjango==1.8

Downloading/unpackingdjango==1.8

Installingcollectedpackages:django

Successfullyinstalleddjango

Cleaningup...

EnWindows

DjangoGirlsTutorial

48InstalacióndeDjango

Page 49: Tutorial de Django Girls

SiobtienesunerroralejecutarpipenWindowscompruebasilarutadetuproyectocontieneespacios,acentosocaracteresespeciales(porejemplo,C:\Users\UserName\djangogirls).Silotiene,porfavorconsideramoverlaaotrolugarsinespacios,acentosocaracteresespeciales(sugerencia:C:\djangogirls).Despuésdehacerloejecutanuevamenteelcomandoanterior.

enLinux

SiobtienesunerroralcorrerpipenUbuntu12.04ejecutapython-mpipinstall-U-force-resintallpipparaarreglarlainstalacióndepipenelvirtualenv.

Esoestodo!Ahoraestáslisto(porfin)paracrearunaaplicaciónDjango!

DjangoGirlsTutorial

49InstalacióndeDjango

Page 50: Tutorial de Django Girls

¡TuprimerproyectoenDjango!PartedeestecapituloestabasadoenlostutorialesdeGeekGirlsCarrots(http://django.carrots.pl/).

Partedeestecapítulosebasaeneldjango-marcadortutorialbajolicenciadeCreativeCommonsAttribution-ShareAlike4.0internacional.Eltutorialdedjango-marcadortienederechosdeautordeMarkusZapke-Gündemannetal.

Vamosacrearunsimpleblog!

ElprimerpasoparacrearloesparainiciarunnuevoproyectoenDjango.Básicamente,estosignificaquepodráscorreralgunosscriptsproporcionadosporDjangoquecrearánelesqueletodeunproyectoparanosotros:unmontóndedirectoriosyarchivosquevamosautilizarmásadelante.

LosnombresdealgunosarchivosydirectoriossonmuyimportantesparaDjango.Nodeberíasrenombrarlosarchivosqueestamosapuntodecrear.Moverlosaunlugardiferentetampocoesunabuenaidea.Djangotienequemantenerunaciertaestructuraparasercapazdeencontrarcosasimportantes.

Recuerdacorrertodoenelvirtualenv.Sinovesunprefijo(myvenv)entuconsolanecesitasactivartuvirtualenv.ExplicamoscómohaceresoenelcapítulodeInstalacióndeDjangoenlasecciónTrabajandoconvirtualenv.Puedeshacerloescribiendoelsiguientecomando:myvenv\Scripts\activateenWindowsomyvenv/bin/activateenMacOS/Linux.

NotaControladosvecesqueincluisteelpunto(.)alfinaldelcomando,esimportanteporqueledicealscriptqueinstaleDjangoeneldirectorioactual.

Enlaconsoladebesejecutar(recuerdanoescribir(myvenv)~/djangogirls$,¿ok?):

(myvenv)~/djangogirls$django-adminstartprojectmysite.

EnWindows:

(myvenv)C:\Users\Name\djangogirls>django-admin.pystartprojectmysite.

django-admin.pyesunscriptquecrearálosarchivosydirectoriosparati.Ahoradeberíastenerunaestructuradedirectoriosparecidaaesto:

DjangoGirlsTutorial

50ComenzarunproyectoenDjango

Page 51: Tutorial de Django Girls

djangogirls

├───manage.py

└───mysite

settings.py

urls.py

wsgi.py

__init__.py

manage.pyesunscriptqueayudaconlaadministracióndelsitio.Conellopodremosiniciarunservidorwebennuestroordenadorsinnecesidaddeinstalarnadamás,entreotrascosas.

Elarchivosettings.pycontienelaconfiguracióndetusitioweb.

¿Recuerdascuandohablamosdeuncarteroquedebíacomprobardondeentregarunacarta?Elarchivourls.pycontieneunalistadelospatronesutilizadosporurlresolver.

Ignoremoslosotrosarchivosporahora-noloscambiaremos.¡Loúnicoquedebesrecordaresnoborrarlosporaccidente!

CambiandolaconfiguraciónVamosahaceralgunoscambiosenmysite/settings.py.Abreelarchivousandoeleditordecódigoquehasinstaladoanteriormente.

Seríabuenotenerelhorariocorrectoennuestrositioweb.VealalistadehusoshorariosdeWikipediaycopiatuzonahoraria(TZ).(porejemplo,Europe/Berlin)

Ensettings.py,encuentralalíneaquecontieneTIME_ZONEymodifícalaparaelegirtupropiazonahoraria:

TIME_ZONE='Europe/Berlin'

Modificando"Europe/Berlin"comocorresponda

Tambiénnecesitaremosagregarunarutaparalosarchivosestáticos(aprenderemostodosobrelosarchivosestáticosyCSSmástardeenestetutorial).Vehaciaabajohastaelfinaldelarchivo,yjustopordebajodelaentradaSTATIC_URL,agregaunanuevallamadaSTATIC_ROOT:

STATIC_URL='/static/'

STATIC_ROOT=os.path.join(BASE_DIR,'static')

DjangoGirlsTutorial

51ComenzarunproyectoenDjango

Page 52: Tutorial de Django Girls

ConfigurarunabasededatosHayunagranvariedaddeopcionesdebasesdedatosparaalmacenarlosdatosdetusitio.Utilizaremoselquevienepordefecto,sqlite3.

Estoyaestáconfiguradoenestapartedetuarchivomysite/settings.py:

DATABASES={

'default':{

'ENGINE':'django.db.backends.sqlite3',

'NAME':os.path.join(BASE_DIR,'db.sqlite3'),

}

}

Paracrearunabasededatosparanuestroblog,ejecutemoslosiguienteenlaconsola:pythonmanage.pymigrate(necesitamosestareneldirectoriodedjangogirlsquecontieneelarchivomanage.py).Siesovabien,deberíasveralgoasí:

(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

¡Ylisto!¡Eshoradeiniciarelservidorwebyversinuestrositiowebestáfuncionando!

Debesestareneldirectorioquecontieneelarchivomanage.py(enlacarpetadjangogirls).Enlaconsola,podemosiniciarelservidorwebejecutandopythonmanage.pyrunserver:

(myvenv)~/djangogirls$pythonmanage.pyrunserver

Ahoratodoloquedebeshacerescontrolarquetusitioestécorriendo-abretunavegador(Firefox,Chrome,Safari,InternetExploreroelqueutilices)eingresaladirección:

http://127.0.0.1:8000/

Elservidorwebseapropiarádetuconsolahastaqueloterminesmanualmente:paratipearmáscomandosoabresunanuevaterminal(ynoteolvidesdeactivartuvirtualenvallítambién),ofrenaelservidorwebyendoalaconsolaenlaqueestácorriendoypresionando

DjangoGirlsTutorial

52ComenzarunproyectoenDjango

Page 53: Tutorial de Django Girls

Ctrl+C-lasteclasControlyCjuntas(enWindows,deberáspresionarCtrl+Break).

¡Felicitaciones!¡Hascreadotuprimersitiowebylohasejecutadousandounservidorweb!¿Noesgenial?

¿Listaparaelpróximopaso?¡Esmomentodecrearalgodecontenido!

DjangoGirlsTutorial

53ComenzarunproyectoenDjango

Page 54: Tutorial de Django Girls

ModelosenDjangoLoquequeremoscrearahoraesalgoquevaaalmacenartodoslospostsennuestroblog.Peroparapoderhacerlotenemosquehablarunpocodeacercadealgollamadoobjetos.

ObjetosHayunconceptoenelmundodelaprogramaciónllamadoprogramaciónorientadaaobjetos.Laideaesqueenlugardeescribirtodocomounaaburridasecuenciadeinstruccionesdeprogramaciónpodemosmodelarcosasydefinircómointeractúanconlasdemás.

Entonces¿Quéesunobjeto?Esunconjuntodepropiedadesyacciones.Suenararo,perotedaremosunejemplo.

SiqueremosunmodelarungatocrearemosunobjetoGatoquetienealgunaspropiedades,comosonporejemplocolor,edad,estadodeánimo(esdecir,bueno,malo,sueño;)),dueño(queesunobjetoPersonao,talvez,enelcasodequeelgatoseacallejero,estapropiedadestarávacía).

YluegoelGatotienealgunasacciones:ronronear,rasguñaroalimentarse(enlacualdaremosalgatoalgunosComidaDeGato,quepodríaserunobjetoindependienteconpropiedades,comoporejemplo,sabor).

Gato

---------

color

edad

humor

dueño

ronronear()

rasguñar()

alimentarse(comida_de_gato)

ComidaDeGato

----------

sabor

Básicamentesetratadedescribircosasrealesenelcódigoconpropiedades(llamadaspropiedadesdelobjeto)ylasacciones(llamadasmétodos).

Yahora,¿cómomodelamoslospostsenelblog?Queremosconstruirunblog,¿no?

DjangoGirlsTutorial

54ModelosenDjango

Page 55: Tutorial de Django Girls

Tenemosprimeroqueresponderalgunaspreguntas:¿Quéesunpostdeunblog?¿Quécaracterísticasdebetener?

Bueno,seguroquenuestrospostsnecesitanuntextoconsucontenidoyuntítulo,¿cierto?Tambiénseríabuenosaberquiénloescribió,asíquenecesitamosunautor.Porúltimo,queremossabercuándoelpostfuecreadoypublicado.

Post

--------

title

text

author

created_date

published_date

¿Quétipodecosaspodríahacerseconunaentradadelblog?Seríabuenoteneralgúnmétodoquepubliquelaentrada,¿no?

Asíquevamosanecesitarelmétodopublicar.

Puestoqueyasabemosloquequeremoslograr,¡podemosempezaramoderlarloenDjango!

ModeloenDjangoSabiendoquéesunobjeto,podemoscrearunmodeloenDjangoparanuestrospostsenelblog.

UnmodeloenDjangoesuntipoespecialdeobjetoqueseguardaenlabasededatos.Unabasededatosesunacoleccióndedatos.Allíesellugarenelcualalmacenaráslainformaciónsobreusuarios,postsdelblog,etc.UtilizaremosunabasededatosSQLiteparaalmacenarnuestrosdatos.EsteeseladaptadordebasededatospredeterminadaenDjango--serásuficienteparanosotrosporahora.

Piensaenelmodeloenlabasededatoscomounahojadecálculoconcolumnas(campos)yfilas(datos).

Creandounaaplicación

Paramantenertodoenorden,crearemosunaaplicaciónseparadadentrodenuestroproyecto.Esmuybuenotenertodoorganizadodesdeelprincipio.Paracrearunaaplicación,necesitamosejecutarelsiguientecomandoenlaconsola(dentrodelacarpetadedjangogirlsdondeestáelarchivomanage.py):

DjangoGirlsTutorial

55ModelosenDjango

Page 56: Tutorial de Django Girls

(myvenv)~/djangogirls$pythonmanage.pystartappblog

Vasnotarquesecreaunnuevodirectoriollamadoblogycontieneunaseriedearchivos.Nuestrosdirectoriosyarchivosennuestroproyectodeberíanparecerseaesto:

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

DespuésdecrearunaaplicacióntambiénnecesitamosdecirleaDjangoquedebeutilizarla.Lohacemosenelarchivomysite/settings.py.TenemosqueencontrarINSTALLED_APPSyañadirunalíneaquecontiene'blog',justoporencimade).Elproductofinaldebeteneresteaspecto:

INSTALLED_APPS=(

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'blog',

)

CreandoelModeloPost

Enelarchivoblog/models.pydefinimostodoslosobjetosllamadosModels-esteesunlugarenelcualdefiniremosnuestromodelopost.

Vamosabrirblog/models.py,quitamostodoyescribimosuncódigocomoeste:

DjangoGirlsTutorial

56ModelosenDjango

Page 57: Tutorial de Django Girls

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

Vuelveaverificarqueusastedosguionesbajos(_)encadaladodelstr.EstosseutilizanconfrecuenciaenPythonyavecestambiénlosllamamos"dunder"(diminutivoeninglésde"double-underscore").

Daunpocodemiedo,¿verdad?Peronotepreocupes,¡vamosaexplicarquésignificanestaslíneas!

Todaslaslíneasquecomienzanconfromoimportsonlíneasparaañadiralgodeotrosarchivos.Asíqueenvezdecopiarypegarlasmismascosasencadaarchivo,podemosincluiralgunaspartesconfrom...import....

classPost(models.Model):-estalíneadefinenuestromodelo(esunobjeto).

classesunapalabraclavequeindicaqueestamosdefiniendounobjeto.Posteselnombredenuestromodelo.Podemosdarleunnombrediferente(perodebemosevitarespaciosenblancoycaracteresespeciales).Unaclasesiemprecomienzaconsuprimeraletraenmayúscula.models.ModelsignificaquePostesunmodelodeDjango,asíDjangosabequedebeguardarloenlabasededatos.

Ahoradefinimoslaspropiedadesquehablábamos:title,text,created_date,published_dateyauthor.Parahaceresotenemosquedefiniruntipodecampo(¿estexto?¿unnúmero?¿unafecha?¿unarelaciónconotroobjeto-esdecir,unusuario?).

models.CharField-estoescomodefinesuntextoconunnúmerolimitadodecaracteres.models.TextField-estoesparatextoslargossinunlímite.Seráidealparael

DjangoGirlsTutorial

57ModelosenDjango

Page 58: Tutorial de Django Girls

contenidodeunpost,¿verdad?models.DateTimeField-estoesfechayhora.modelos.ForeignKey-esteesunvínculoconotromodelo.

Novamosaexplicarcadapedacitodecódigo,yaquenostomaríademasiadotiempo.DebesecharunvistazoaladocumentacióndeDjangosiquieressabermássobreloscamposdelosModelosycómodefinircosasdiferentesalasdescritasanteriormente(https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types).

¿Yquésobredefpublish(self):?Esexactamentenuestrométodopublishquemencionamosanteriormente.defsignificaquesetratadeunafunciónométodo.publisheselnombredelmétodo.Puedescambiarlo,siquieres.Lareglaesqueusamosminúsculasyguionesbajosenlugardeespacios(esdecir,siquierestenerunmétodoquecalculeelpreciomedio,estepodríallamarsecalculate_average_price).

Losmétodosmuyamenudodevuelvenalgo.Hayunejemplodeestoenelmétodo__str__.Enesteescenario,cuandollamamosa__str__()obtendremosuntexto(string)conuntítulodePost.

Sialgotodavíanoestáclarosobremodelos,¡nodudesenpreguntaratututor!Sabemosqueesmuycomplicado,sobretodocuandoestásentendiendoquéfuncionesyobjetossonmientrassiguesestedocumento.Consuerte,¡todotieneunpocomássentidoparatiahora!

Creartablasparalosmodelosentubasededatos

Elúltimopasoesañadirnuestronuevomodeloanuestrabasededatos.PrimerotenemosquehacerqueDjangosepaquetenemosalgunoscambiosennuestromodelo(acabamosdecrearlo),escribepythonmanage.pymakemigrationsblog.Severáasí:

(myvenv)~/djangogirls$pythonmanage.pymakemigrationsblog

Migrationsfor'blog':

0001_initial.py:

-CreatemodelPost

Djangoprepararáunarchivodemigraciónquetenemosqueaplicarahoraanuestrabasededatosescribiendopythonmanage.pymigrateblog.Elresultadodebeser:

(myvenv)~/djangogirls$pythonmanage.pymigrateblog

Operationstoperform:

Applyallmigrations:blog

Runningmigrations:

Applyingblog.0001_initial...OK

DjangoGirlsTutorial

58ModelosenDjango

Page 59: Tutorial de Django Girls

¡Hurra!NuestromodelodePostestáahoraennuestrabasededatos.Seríabuenoverlo,¿no?¡DirígetealsiguientecapítuloparavercómolucetuPost!

DjangoGirlsTutorial

59ModelosenDjango

Page 60: Tutorial de Django Girls

AdministradordeDjangoParaagregar,editaryborrarlospostsquehemosmodelado,utilizaremoseladministradordeDjango.

Vamosaabrirelarchivoblog/admin.pyyreemplazarsucontenidoconesto:

fromdjango.contribimportadmin

from.modelsimportPost

admin.site.register(Post)

Comopuedesver,importamos(incluimos)elmodeloPostdefinidoenelcapítuloanterior.Parahacernuestromodelovisibleenlapáginadeladministrador,tenemosqueregistrarelmodeloconadmin.site.register(Post).

Ok,eshoradevertumodeloPost.Recuerdaejecutarpythonmanage.pyrunserverenlaconsolaparacorrerelservidorweb.Vealnavegadorytipealadirecciónhttp://127.0.0.1:8000/admin/.Verásunapáginadeingresocomolaquesigue:

Parapoderingresardeberáscrearunsuperusuario-unusuarioquetienecontrolsobretodoloquehayenelsitio.Vuelvehaciaatrásatulíneadecomandosytipeapythonmanage.pycreatesuperuser,presionaenterytipeatunombredeusuario(enminúsculas,sinespacios),direccióndeemailycontraseñacuandoseanrequeridos.Notepreocupesquenopuedes

DjangoGirlsTutorial

60AdministradordeDjango

Page 61: Tutorial de Django Girls

vertucontraseñamientraslatipeas-asíescomodebeser.Simplementetipéalaypresiona'Enter'paracontinuar.Lasalidadeestecomandodeberíaverseasí(nombredeusuarioyemaildeberíanserlostuyos):

(myvenv)~/djangogirls$pythonmanage.pycreatesuperuser

Username:admin

Emailaddress:[email protected]

Password:

Password(again):

Superusercreatedsuccessfully.

Vuelveatunavegadoreingresaconlascredencialesdesuperusuarioqueelegiste,ahoradeberíaspoderverelpaneldeadministracióndeDjango.

VeaPostsyexperimentaunpococonesto.Agregacincooseispostsdelblog.Notepreocupesporelcontenido-puedessimplementecopiarypegartextodeestetutorialenelcontenidodetuspostsparaahorrartiempo:).

Asegúratedequeporlomenosdosotresposts(peronotodas)tienenlafechadepublicación.Seráútilluego.

DjangoGirlsTutorial

61AdministradordeDjango

Page 62: Tutorial de Django Girls

SiquieressabermássobreeladministradordeDjango,puedesvisitarladocumentacióndeDjango:https://docs.djangoproject.com/en/1.8/ref/contrib/admin/

Esteprobablementeseaunbuenmomentoparatomaruncafé(oté)oalgoparacomeryre-energizarte.CreastetuprimermodelodeDjango-¡merecesunpequeñorecreo!

DjangoGirlsTutorial

62AdministradordeDjango

Page 63: Tutorial de Django Girls

¡Despliega!Nota:Elsiguientecapítulopuedeseravecesunpocodifícildesuperar.Sepersistenteyacábalo.Eldespliegueesunaparteimportantedelprocesoeneldesarrolloweb.Estecapítuloestásituadoenelmediodeltutorialparaquetututorpuedaayudarteaponertusitiowebenlínea,loquepuedeserunprocesoalgomáscomplicado.Estosignificaquepodrásacabareltutorialportucuentasiseteacabaeltiempo.

Hastaahoratusitiowebestabadisponiblesóloentuordenador,¡ahoraaprenderáscómodesplegarlo!EldespliegueeselprocesodepublicartuaplicaciónenInternetparaquelagentepuedaaccederyvertuaplicación:).

Comoyahasaprendido,unsitiowebtienequeestarenunservidor.Haymuchosproveedores,perousaremosunoquetieneunprocesodedesplieguerelativamentesimple:PythonAnywhere.PythonAnywhereesgratisparapequeñasaplicacionesquenotienendemasiadosvisitantes,definitivamentesuficienteparaestecaso.

ElotroservicioexternoquevamosautilizaresGitHub,unserviciodealojamientodecódigo.Hayotrasopcionesporahí,perohoyendíacasitodoslosprogramadorestienenunacuentadeGitHub,¡yahoratútambiénlavasatener!

UsaremosGitHubcomopasointermedioparatransportarnuestrocódigodesdeyhastaPythonAnywhere.

GitGitesun"sistemadecontroldeversiones"usadopormuchosprogramadores-esunsistemaqueregistraloscambiosenlosarchivosatravésdeltiempodeformatalquepuedasaccederaversionesespecíficascuandolodesees.Esmuysimilaralaopciónde"registrarcambios"enMicrosoftWord,peromuchomáspoderoso.

InstalarGit

Windows

PuedesdescargarGitdegit-scm.com.Puedeshacerclicen"Next"paratodoslospasosexceptoenuno;enelquintopasotitulado"AdjustingyourPATHenvironment",elije"RunGitandassociatedUnixtoolsfromtheWindowscommand-line"(laúltimaopción).Apartede

DjangoGirlsTutorial

63¡Desplegar!

Page 64: Tutorial de Django Girls

eso,losvalorespordefectofuncionaránbien."CheckoutWindows-style,commitUnix-stylelineendings"tambiénestábien.

MacOS

DescargaGitdegit-scm.comysiguelasinstrucciones.

Linux

Sinolotienesyainstalado,gitdeberíaestardisponibleatravésdeladministradordepaquetes,pruebacon:

sudoapt-getinstallgit

#o

sudoyuminstallgit

IniciarnuestrorepositorioGitGitrastrealoscambiosrealizadosaungrupodeterminadodeficherosenloquellamamosunrepositoriodecódigo(o"repo"paraabreviar).Iniciemosunoparanuestroproyecto.Abrelaconsolayejecutalossiguientescomandoseneldirectoriodedjangogirls:

Nota:Compruebaeldirectoriodetrabajoactualconelcomandopwd(OSX/Linux)ocd(Windows)antesdeinicializarelrepositorio.Deberíasestarenlacarpetadjangogirls.

$gitinit

InitializedemptyGitrepositoryin~/djangogirls/.git/

$gitconfiguser.name"Tunombre"

$gitconfiguser.emailtú@ejemplo.com

Inicializarelrepositoriogitesalgoquesólonecesitamoshacerunavezporproyecto(ynotendrásquevolveraponertuusuarioycorreoelectróniconuncamás)

Gitllevaráunregistrodeloscambiosrealizadosentodoslosficherosycarpetasenestedirectorio,perohayalgunosficherosquequeremosqueignore.Estolohacemoscreandounficherollamado.gitignoreeneldirectoriobase.Abretueditorycreaunnuevoficheroconelsiguientecontenido:

DjangoGirlsTutorial

64¡Desplegar!

Page 65: Tutorial de Django Girls

*.pyc

__pycache__

myvenv

db.sqlite3

.DS_Store

Yguárdalocomo.gitignoreenlaprimeracarpeta"djangogirls".

Nota:¡Elpuntoalprincipiodelnombredelficheroesimportante!Sitienesdificultadesparacrearlo(alosMacnolesgustaquecreesficherosqueempiezanporpuntodesdeFinder,porejemplo),usalaopción"Guardarcomo"entueditor,esonofalla.

Esbuenaideautilizarelcomandogitstatusantesdegitaddocuandonoestésseguradeloquevaahacer,paraevitarcualquiersorpresa(porejemplo,añadirohacercommitdeficherosnodeseados).Elcomandogitstatusdevuelveinformaciónsobrelosficherossinseguimiento(untracked),modificados,preparados(staged),elestadodelaramaymuchomás.Lasalidadeberíasersimilara:

$gitstatus

Onbranchmaster

Initialcommit

Untrackedfiles:

(use"gitadd<file>..."toincludeinwhatwillbecommitted)

.gitignore

blog/

manage.py

mysite/

nothingaddedtocommitbutuntrackedfilespresent(use"gitadd"totrack)

Yfinalmenteguardamosnuestroscambios.Vealaconsolayejecutaestoscomandos:

$gitadd-A.

$gitcommit-m"MiappDjangoGirls,primercommit"

[...]

13fileschanged,200insertions(+)

createmode100644.gitignore

[...]

createmode100644mysite/wsgi.py

EnviarnuestrocódigoaGitHub

DjangoGirlsTutorial

65¡Desplegar!

Page 66: Tutorial de Django Girls

VisitaGitHub.comyregistraunanuevacuentadeusuariogratuita.Luego,creaunnuevorepositorioconelnombre"my-first-blog".Dejadesmarcadalaopción"InitialisewithaREADME",dejalaopción.gitignoreenblanco(lohemoshechoamano)ydejalalicenciacomo"None".

NotaElnombremy-first-blogesimportante.Podríaselegirotracosa,perovaaaparecermuchasvecesenlasinstruccionesquesiguenytendríasquesustituirlocadavez.Probablementeseamássencilloquedarteconelnombremy-first-blog.

EnlapróximapantallaveráslaURLparaclonarturepositorio.Eligelaversión"HTTPS",cópialayenunmomentolapegaremosenlaconsola:

DjangoGirlsTutorial

66¡Desplegar!

Page 67: Tutorial de Django Girls

AhoratenemosqueconectarelrepositorioGitdetuordenadorconelqueestáenGitHub.

$gitremoteaddoriginhttps://github.com/<your-github-username>/my-first-blog.git

$gitpush-uoriginmaster

EscribetunombredeusuarioycontraseñadeGitHubydeberíasveralgoasí:

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.

TucódigoestáahoraenGitHub.¡Veymíralo!Verásqueestáenbuenacompañía;Django,elTutorialdeDjangoGirlsymuchosotrosgrandesproyectosdecódigoabiertotambiénalojansucódigoenGitHub:)

ConfigurarnuestroblogenPythonAnywhereEshoraderegistrarunacuentagratuitadetipo"Beginner"enPythonAnywhere.

www.pythonanywhere.com

Nota:CuandoelijastunombredeusuariotenencuentaquelaURLdetublogtendrálaformanombredeusuario.pythonanywhere.com,asíqueobienelijetupropioapodoobienunnombrequedescribasobrequétratatublog.

BajarnuestrocódigoenPythonAnywhereCuandotehayasregistradoenPythonAnywhereserásredirigidaatupaneldecontrolopágina"Consoles".Elijelaopciónparainiciarunaconsola"Bash",queeslaversiónPythonAnywheredeunaconsola,comolaquetienesentuPC

Nota:PythonAnywhereestábasadoenLinux,porloquesiestásenWindowslaconsolaseráunpocodistintaalaquetienesentuordenador.

DjangoGirlsTutorial

67¡Desplegar!

Page 68: Tutorial de Django Girls

DescarguemosnuestrocódigodesdeGitHubaPythonAnywheremediantelacreacióndeun"clon"delrepositorio.EscribelosiguienteenlaconsoladePythonAnywhere:

$gitclonehttps://github.com/<tu-usuario-github>/my-first-blog.git

EstovaadescargarunacopiadetucódigoenPythonAnywhere.Compruébaloescribiendo:

$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

CrearunvirtualenvenPythonAnywhere

Talycomohicisteentupropioordenador,puedescrearunvirtualenvenPythonAnywhere.EnlaconsolaBash,escribe:

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.8whitenoise-1.0.6

Recopilarficherosestáticos

DjangoGirlsTutorial

68¡Desplegar!

Page 69: Tutorial de Django Girls

¿Teestabaspreguntandoquéesesode"whitenoise"?Esunaherramientaparaservirlosllamados"ficherosestáticos".Losficherosestáticosfuncionandedistintaformaenlosservidoresencomparaciónconcómolohacenennuestropropioordenadorynecesitamosunaherramientacomo"whitenoise"paraservirlos.

Aprenderemosunpocomássobrelosficherosestáticosmásadelante,cuandoeditemoselCSSdenuestrositio.

Porahorasólonecesitamosejecutarenelservidoruncomandoadicionalllamado"collectstatic".LediceaDjangoquerecopiletodoslosficherosestáticosquenecesitaenelservidor.Porelmomento,principalmentesonlosficherosestáticosquehacenqueelpaneldeadministraciónestébonito.

20:20~$pythonmanage.pycollectstatic

Youhaverequestedtocollectstaticfilesatthedestination

locationasspecifiedinyoursettings:

/home/edith/my-first-blog/static

Thiswilloverwriteexistingfiles!

Areyousureyouwanttodothis?

Type'yes'tocontinue,or'no'tocancel:yes

Escribe"yes",¡yahíva!¿Noteencantahacerquelascomputadorasimprimanpáginasypáginasdetextoimposibledeentender?Siemprehagoruiditosparaacompañarlo.Brp,brpbrp...

Copying'/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js'

Copying'/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js'

[...]

Copying'/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css'

Copying'/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css'

62staticfilescopiedto'/home/edith/my-first-blog/static'.

CrearlabasededatosenPythonAnywhere

Aquíhayotracosaqueesdiferenteentretuordenadoryelservidor:ésteutilizaunabasededatosdiferente.Porlotanto,lascuentasdeusuarioylasentradaspuedenserdiferentesenelservidoryentuordenador.

Asíqueinicializamoslabasededatosenelservidorigualquelohicimosennuestroordenador,conmigrateycreatesuperuser:

DjangoGirlsTutorial

69¡Desplegar!

Page 70: Tutorial de Django Girls

(mvenv)20:20~$pythonmanage.pymigrate

Operationstoperform:

[...]

Applyingsessions.0001_initial...OK

(mvenv)20:20~$pythonmanage.pycreatesuperuser

PublicarnuestroblogcomounaaplicaciónwebAhoraquenuestrocódigoestáenPythonAnywhere,elvirtualenvestálisto,losficherosestáticoshansidorecopiladosylabasededatosestáinicializada,estamoslistasparapublicarlacomounaaplicaciónweb.

HazclicenellogodePythonAnywhereparavolveralpanelprincipal,hazclicenlapestañaWebypinchaenAddanewwebapp.

Enlaventanadediálogo,despuésdeconfirmarelnombrededominio,elijemanualconfiguration(configuraciónmanual)(NBlaopción"Django"no).Luego,elijePython3.4yhazclicen"Next"paraterminarconelasistente.

Notaasegúratedeelegirlaopciónde"Manualconfiguration",nolade"Django".SomosdemasiadobuenasparalaconfiguraciónpordefectodeDjangodePythonAnywhere;-)

Configurarelvirtualenv

SerásredirigidaalapantalladeconfiguracióndePythonAnywhereparatuaplicaciónweb,alaquedeberásaccedercadavezquequierashacercambiosenlaaplicacióndelservidor.

DjangoGirlsTutorial

70¡Desplegar!

Page 71: Tutorial de Django Girls

Enlasección"Virtualenv",hazcliceneltextorojoquedice"Enterthepathtoavirtualenv"(Introducelarutaaunvirtualenv)yescribe:/home/<-tu-usuario->/my-first-blog/myvenv/

Nota:sustituyetupropionombredeusuariocomocorresponda.Sicometesunerror,PythonAnywheretemostraráunapequeñaadvertencia.

ConfigurarelficheroWSGI

Djangofuncionautilizandoel"protocoloWSGI",unestándarparaservirsitioswebusandoPython,quePythonAnywheresoporta.LaformadeconfigurarPythonAnywhereparaquereconozcanuestroblogDjangoeseditarunficherodeconfiguraciónWSGI.

Hazclicenelenlace"WSGIconfigurationfile"(enlasección"Code"enlapartedearribadelapágina;sellamaráalgoparecidoa/var/www/<tu-usuario>_pythonanywhere_com_wsgi.py)yteredirigiráaleditor.

Eliminatodoelcontenidoactualyreemplázaloconalgocomoesto:

DjangoGirlsTutorial

71¡Desplegar!

Page 72: Tutorial de Django Girls

importos

importsys

path='/home/<tu-usuario>/my-first-blog'#aquíutilizatupropiousuario

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())

Notanoolvidessustituirtupropionombredeusuariodondedice<tu-usuario>

EsteficheroseencargadedecirleaPythonAnywheredóndevivenuestraaplicaciónwebycómosellamaelficherodeconfiguracióndeDjango.Tambiénconfiguralaherramientaparaficherosestáticos"whitenoise".

DaleaSaveyvuelvealapestañaWeb.

¡Todolisto!DalealbotónverdegrandequediceReloadypodrásvertuaplicación.Verásunenlaceaellaenlapartedearribadelapágina.

ConsejosdedepuraciónSiapareceunerrorcuandointentasvisitartusitio,elprimerlugarquedeberásrevisarparaobtenerinformacióndedepuracióneselerrorlog;encontrarásunenlaceaélenlapestañaWebdePythonAnywhere.Miraaversihayalgúnmensajedeerrorahí.Losmásrecientesestánalfinal.Losproblemasmáscomunesincluyen

olvidaralgunodelospasosquehicimosenlaconsola:crearelvirtualenv,activarlo,instalarDjangoenél,ejecutarcollectstatic,inicializarlabasededatoscometerunerrorenlarutadelvirtualenvenlapestañaWeb;suelehaberunmensajitodeerrordecolorrojo,sihayalgúnproblemacometerunerrorenelficherodeconfiguraciónWSGI;¿haspuestobienlarutaalacarpetamy-first-blog?

¡Tututorestáahíparaayudar!

¡Estásenvivo!

DjangoGirlsTutorial

72¡Desplegar!

Page 73: Tutorial de Django Girls

Lapáginapordefectodetusitiodeberíadecir"WelcometoDjango",igualqueentuPClocal.Intentaañadir/admin/alfinaldelaURLyteredirigiráalpaneldeadministración.Ingresacontunombredeusuarioycontraseñayverásquepuedesañadirnuevasentradasenelservidor.

DateunaGRANpalmadaenlaespalda;losdesplieguesenelservidorsonunadelaspartesmáscomplejasdeldesarrollowebymuchasvecesalagentelecuestavariosdíastenerlofuncionando.Perotútienestusitioenvivo,enInternetdeverdad,¡asícomosuena!

DjangoGirlsTutorial

73¡Desplegar!

Page 74: Tutorial de Django Girls

DjangourlsVamosaconstruirnuestraprimerapáginaweb--¡unapáginadeinicioparatublog!Peroprimero,vamosaaprenderunpocosobreDjangourls.

¿QuéesunaURL?UnaURLessimplementeunadirecciónweb,puedesverunaURLcadavezquevisitascualquiersitioweb-esvisibleenlabarradedireccionesdetunavegador(¡Sí!127.0.0.1:8000esunaURL.Yhttp://djangogirls.comestambiénunaURL):

CadapáginaenInternetnecesitasupropiaURL.DeestamaneratuaplicaciónsabeloquedebemostraraunusuarioqueabreunaURL.EnDjangoseusaalgollamadoURLconf(configuracióndeURL),unconjuntodepatronesqueDjangointentaráhacercoincidirconladirecciónURLrecibidaparaencontrarlavistacorrecta.

¿CómofuncionanlasURLsenDjango?Vamosaabrirelarchivomysite/urls.pyyvercómoes:

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)),

]

Comopuedesver,Djangoyapusoalgoaquíparanosotros.

DjangoGirlsTutorial

74Djangourls

Page 75: Tutorial de Django Girls

Laslíneasquecomienzancon#soncomentarios-significaqueesaslíneasnoseránejecutadasporPython.Muyútil,¿verdad?

YaestáaquílaURLdeadmin,quevisitasteenelcapítuloanterior:

url(r'^admin/',include(admin.site.urls)),

EstosignificaqueparacadaURLqueempiezaconadmin/Djangoencontrarásucorrespondienteview.EnestecasoestamosincluyendoenunasolalíneamuchasURLsdeadmin,asínoestátodocomprimidoenestepequeñoarchivo-esmáslimpioylegible.

Regex¿TepreguntascómoDjangocoincidelasdireccionesURLconlasvistas?Bueno,estaparteesdifícil.Djangoutilizaregex--expresionesregulares.Regextienemuchas(¡unmontón!)denormasqueformanunpatróndebúsqueda.Dadoquelasexpresionesregularessonuntemaavanzado,noentraremosendetallessobresufuncionamiento.

Siteinteresaentendercómocreamosesospatrones,aquíhayunejemplodelproceso-solamentenecesitaremosunsubconjuntodereglaslimitadoparaexpresarelpatrónqueestamosbuscando:

^denotaelprincipiodeltexto

$denotaelfinaldeltexto

\drepresentaundígito

+indicaqueelítemanteriordeberíaserrepetido<strong>porlomenos</strong>unavez

()paraencerrarunapartedelpatrón

CualquierotracosaenladefinicióndelURLserátomadaliteralmente.

Ahoraimaginaquetienesunsitiowebconunadireccióncomoesta:http://www.mysite.com/post/12345/,donde12345eselnúmerodepost.

Escribirvistasseparadasparatodoslosnúmerosdepostseríarealmentemolesto.ConlasexpresionesregularespodemoscrearunpatrónquecoincidirálaURLyextraeráelnúmeroparanosotras: ̂ post/(\d+)/$.Analicemosestaexpresiónparteporparteparaentenderquéesloqueestamoshaciendoaquí:

^post/leestádiciendoaDjangoquetomecualquiercosaquetengapost/alprincipiodelURL(justoantesde ̂ )(\d+)significaquehabráunnúmero(deunoomásdígitos)yquequeremosqueesenúmeroseacapturadoyextraído

DjangoGirlsTutorial

75Djangourls

Page 76: Tutorial de Django Girls

/lediceaDjangoqueotrocaracter/deberíaveniracontinuación$indicaelfinaldelURL,loquesignificaquesólocadenasfinalizandocon/coincidiránconestepatrón

¡TuprimerURLdeDjango!¡EshoradecrearnuestroprimerURL!Queremosque'http://127.0.0.1:8000/'sealapáginadeiniciodenuestroblogyquemuestreunalistadeposts.

Tambiénqueremosmantenerelarchivomysite/urls.pylimpio,asíqueimportaremosURLsdenuestroblogalarchivomysite/urls.pyprincipal.

Eliminalaslíneascomentadas(líneascomenzandocon#)yagregaunalíneaqueimportaráblog.urlsenelurlprincipal('').

Tuarchivomysite/urls.pydeberíaversecomoeste:

fromdjango.conf.urlsimportinclude,url

fromdjango.contribimportadmin

urlpatterns=[

url(r'^admin/',include(admin.site.urls)),

url(r'',include('blog.urls')),

]

Djangoahoraredirigirátodoloquevayahacia'http://127.0.0.1:8000/'ablog.urlsybuscarámásinstruccionesallí.

CuandoescribesexpresionesregularesenPythonacostúmbrateaponerralprincipiodelacadena-estoessolamenteunapistaparaquePythonentiendaquelacadenacontenerácaracteresespecialesquenosonparaserinterpretadosporPythonsinoquesonpartedelaexpresiónregular.

blog.urlsCreaunnuevoarchivovacíoblog/urls.py.¡Muybien!Agregaestasprimerasdoslíneas:

fromdjango.conf.urlsimportinclude,url

from.importviews

AquísoloestamosimportandolosmétodosdeDjangoytodasnuestrasviewsdelblog(todavíanotenemosninguna,peroloharemosenunminuto)

DjangoGirlsTutorial

76Djangourls

Page 77: Tutorial de Django Girls

Luegodeesto,podemosagregarnuestroprimerpatrónURL:

urlpatterns=[

url(r'^$',views.post_list),

]

Comopuedesver,ahoraestamosasignandounaviewllamadapost_listalURL ̂ $.Estaexpresiónregularcoincidirácon ̂ (uninicio)seguidode$(unfinal)-porlotanto,sólounacadenavacíacoincidirá.Yestoescorrecto,yaqueenlosURLresolversdeDjango'http://127.0.0.1:8000/'noespartedelURL.EstepatrónmostraráaDjangoqueviews.post_listesellugarcorrectoalqueirsialguieningresaatusitiowebconladirección'http://127.0.0.1:8000/'.

¿Todobien?Abrehttp://127.0.0.1:8000/entunavegadorparaverelresultado.

Nohaymásun"Itworks",¿verdad?Notepreocupes,essolamenteunapáginadeerror,¡nadaquenosasuste!Dehecho,sonbastanteútiles:

Puedesleerquenohayningúnatributo'post_list'.¿post_listterecuerdaalgo?¡Asíescomollamamosanuestravista!Estosignificaquetodoestáensulugar,sóloquenocreamosnuestraviewtodavía.Notepreocupes,yallegaremosaeso.

SiquieressabermássobreDjangoURLconfs,miraladocumentaciónoficial:https://docs.djangoproject.com/en/1.8/topics/http/urls/

DjangoGirlsTutorial

77Djangourls

Page 78: Tutorial de Django Girls

VistasdeDjango-¡Eshoradecrear!Eshoradedeshacersedelerrorquehemoscreadoenelcapítuloanterior:)

UnaViewesunlugardondeponemosla"lógica"denuestraaplicación.Sesolicitaráinformacióndelmodelquecreasteanteriormenteysepasaráaunaviewquecrearásenelpróximocapítulo.LasvistassonsólométodosdePythonquesonunpocomáscomplicadosqueloquehicimosenelcapítulodeIntroducciónaPython.

LasVistassecolocanenelarchivoviews.py.Agregaremosnuestrasviewsalarchivoblog/views.py.

blog/views.pyBien,vamosabrirestearchivoyverloquecontiene:

fromdjango.shortcutsimportrender

#Createyourviewshere.

Nodemasiadascosasaquítodavía.Laviewmássimplepuedesercomoesto:

defpost_list(request):

returnrender(request,'blog/post_list.html',{})

Comopuedesver,hemoscreadounmétodo(def)llamadopost_listquetomaunrequestyhaceunreturndeunmétodorenderquerenderizará(construirá)nuestraplantillablog/post_list.html.

Guardaelarchivo,dirígeteahttp://127.0.0.1:8000/yveamosloquetenemosahora.

¡Otroerror!Leamosloqueestápasandoahora:

DjangoGirlsTutorial

78VistasdeDjango-¡Eshoradecrear!

Page 79: Tutorial de Django Girls

Esteesunofácil:TemplateDoesNotExist.¡Vamosaarreglaresteerrorcreandounaplantillaenelsiguientecapítulo!

AprendemásacercadelasviewsdeDjangoleyendoladocumentaciónoficial:https://docs.djangoproject.com/en/1.8/topics/http/views/

DjangoGirlsTutorial

79VistasdeDjango-¡Eshoradecrear!

Page 80: Tutorial de Django Girls

IntroducciónaHTMLTeestaráspreguntando,¿quéesunaplantilla?

Unaplantillaesunarchivoquepodemosreutilizarparapresentarinformacióndiferentedeformaconsistente-porejemplo,sepodríautilizarunaplantillaparaayudarteaescribirunacarta,porqueaunquecadacartapuedecontenerunmensajedistintoydirigirseaunapersonadiferente,compartiránelmismoformato.

ElformatodeunaplantilladeDjangosedescribeenunlenguajellamadoHTML(queeselcódigoHTMLquemencionamosenelprimercapítuloCómofuncionaInternet).

¿QuéesHTML?HTMLesunsimplecódigoqueesinterpretadoportunavegadorweb-comoChrome,FirefoxoSafari-paramostrarunapáginawebalusuario.

HTMLsignificaHyperTextMarkupLanguage-enespañol,LenguajedeMarcasdeHyperTexto.HyperTextsignificaqueesuntipodetextoquesoportahipervínculosentrepáginas.Markupsignificaquehemostomadoundocumentoylohemosmarcadoconcódigoparadecirleaalgo(enestecaso,unnavegador)cómointerpretarlapágina.ElcódigoHTMLestáconstruidoconetiquetas,cadaunacomenzandocon<yterminandocon>.Estasetiquetasdemarcadosonelementos.

¡Tuprimeraplantilla!Crearunaplantillasignificacrearunarchivodeplantilla.Todoesunarchivo,¿verdad?Probablementehayasnotadoestoya.

Lasplantillasseguardaneneldirectoriodeblog/templates/blog.Asíqueprimerocreaundirectoriollamadotemplatesdentrodetudirectorioblog.Luegocreaotrodirectoriollamadoblogdentrodetudirectoriodetemplates:

blog

└───templates

└───blog

DjangoGirlsTutorial

80IntroducciónaHTML

Page 81: Tutorial de Django Girls

(Talveztepreguntesporquénecesitamosdosdirectoriosllamadosblog-comodescubrirásmásadelante,estoessimplementeunaútilconvencióndenomenclaturaquehacelavidamásfácilcuandolascosasempiezanacomplicarsemás.)

Yahoracreaunarchivopost_list.html(déjaloenblancoporahora)dentrodelacarpetablog/templates/blog.

Miracómosevesusitiowebahora:http://127.0.0.1:8000/

SitodavíatienesunerrorTemplateDoesNotExists,intentareiniciarelservidor.Vealalíneadecomandos,deténelservidorpulsandoCtrl+C(teclasControlyCjuntas)ycomienzadenuevomediantelaejecucióndelcomandopythonmanage.pyrunserver.

¡Ningúnerrormás!Felicidades:)Sinembargo,porahora,tusitiowebnoestápublicandonadaexceptounapáginaenblanco,porquelaplantillatambiénestávacía.Tenemosquearreglarlo.

Añadelosiguienteatuarchivodeplantilla:

<html>

<p>Hithere!</p>

<p>Itworks!</p>

</html>

¿Cómoluceahoratusitioweb?Hazclickparaver:http://127.0.0.1:8000/

¡Funcionó!Buentrabajo:)

Laetiquetamásbásica,<html>,essiempreelprincipiodecualquierpáginaweby</html>essiempreelfinal.Comopuedesver,todoelcontenidodelapáginawebvadesdeelprincipiodelaetiqueta<html>yhastalaetiquetadecierre</html><p>esunaetiquetaparaloselementosdepárrafo;</p>cierracadapárrafo

Cabeza&cuerpoCadapáginaHTMLtambiénsedivideendoselementos:headybody.

headesunelementoquecontieneinformaciónsobreeldocumentoquenosemuestraenlapantalla.

bodyesunelementoquecontienetodoloquesemuestracomopartedelapáginaweb.

DjangoGirlsTutorial

81IntroducciónaHTML

Page 82: Tutorial de Django Girls

Usamos<head>paradecirleelnavegadoracercadelaconfiguracióndelapáginay<body>paradecirloquerealmenteestáenlapágina.

Porejemplo,puedesponerleuntítuloalapáginawebdentrodela<head>,así:

<html>

<head>

<title>Ola'sblog</title>

</head>

<body>

<p>Hithere!</p>

<p>Itworks!</p>

</body>

</html>

Guardaelarchivoyactualizatupágina.

¿Observascómoelnavegadorhacomprendidoque"Ola'sblog"eseltítulodetupágina?Hainterpretado<title>Ola'sblog</title>ycolocóeltextoenlabarradetítulodetunavegador(tambiénseutilizaráparamarcadoresyasísucesivamente).

Probablementetambiénhayasnotadoquecadaetiquetadeaperturacoincideconunaetiquetadecierre,conun/,yqueloselementossonanidados(esdecir,nopuedescerrarunaetiquetaparticularhastaquetodoslosqueestabanensuinteriorsehayancerradotambién).

Escomoponercosasencajas.Tienesunacajagrande,<html></html>;ensuinteriorhay<body></body>,yquecontienelascajasaúnmáspequeñas:<p></p>.

Tienesqueseguirestasreglasdeetiquetasdecierreydeanidacióndeelementos-sinolohaces,elnavegadorpuedenosercapazdeinterpretarloscorrectamenteytupáginasemostraráincorrectamente.

Personalizatuplantilla¡Ahorapuedesdivertirteunpocoytratardepersonalizartuplantilla!Aquíhayalgunasetiquetasútilesparaeso:

<h1>Untítulo</h1>-paratutítulomásimportante<h2>Unsubtítulo</h2>-paraeltítulodelsiguientenivel<h3>Unsubsubtítulo</h3>-...yasíhasta<h6><em>texto</em>-poneencursivatutexto<strong>texto</strong>-poneennegritatutexto

DjangoGirlsTutorial

82IntroducciónaHTML

Page 83: Tutorial de Django Girls

<br/>-unsaltodelínea(nopuedescolocarnadadentrodebr)<ahref="http://djangogirls.org">link</a>-creaunvínculo<ul><li>primerelemento</li><li>segundoelemento</li></ul>-creaunalista,¡igualqueesta!<div></div>-defineunaseccióndelapágina

Aquíhayunejemplodeunaplantillacompleta:

<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>

Aquíhemoscreadotresseccionesdiv.

Elprimerelementodivcontieneeltítulodenuestroblog-esunencabezadoyunenlaceOtrosdoselementosdivcontienennuestrospostsconlafechadepublicación,h2conuntítuloqueesclickeableydosp(párrafo)detexto,unoparalafechayunoparanuestropost.

Nosdaesteefecto:

¡Yaaay!Perohastaelmomento,nuestraplantillasólomuestraexactamentelamismainformación-considerandoqueanteshablábamosdeplantillascomopermitiéndonosmostrarinformacióndiferenteenelmismoformato.

DjangoGirlsTutorial

83IntroducciónaHTML

Page 84: Tutorial de Django Girls

LoquequeremosrealmenteesmostrarpostsrealesañadidosennuestrapáginadeadministracióndeDjango-yahíesadondevamosacontinuación.

Unacosamás:¡despliega!SeríabuenovertodoestodisponibleenInternet,¿no?HagamosotrodespliegueenPythonAnywhere:

HazuncommitysubetucódigoaGitHub

Enprimerlugar,veamosquéarchivoshancambiadodesdequehicimoseldespliegueporúltimavez:

$gitstatus

Asegúratedequeestáseneldirectoriodjangogirlsyvamosadecirleagitqueincluyatodosloscambiosdentrodeestedirectorio:

$gitadd-A.

Nota-A(abreviaturade"all")significaquegittambiénreconocerásihaseliminadoarchivos(pordefecto,sóloreconocearchivosnuevos/modificados).Tambiénrecuerda(delcapítulo3)que.significaeldirectorioactual.

Antesdequesubamostodoslosarchivos,vamosaverquéesloquegitsubirá(todoslosarchivosquegitcargarádeberíanaparecerenverde):

$gitstatus

Yacasiestamos,ahoraestiempodedecirlequeguardeestecambioensuhistorial.Vamosadarleun"mensajedecommit"dondedescribimosloquehemoscambiado.Puedesescribircualquiercosaquetegustaríaenestaetapa,peroesútilescribiralgodescriptivoparaquepuedesrecordarloquehashechoenelfuturo.

$gitcommit-m"CambieelHTMLparalapágina."

NotaAsegúratedeusarcomillasdoblesalrededordelmensajedecommit.

Unavezquehicimosesto,subimos(push)nuestroscambiosaPythonAnywhere:

DjangoGirlsTutorial

84IntroducciónaHTML

Page 85: Tutorial de Django Girls

gitpush

DescargatunuevocódigoaPythonAnywhereyactualizatuaplicaciónweb

AbrelapáginadeconsolasdePythonAnywhereyveatuconsolaBash(ocomienzaunanueva).Luego,ejecuta:

$cd~/my-first-blog$gitpull[...]

Ymiracómotucódigosedescarga.Siquierescomprobarqueyahaterminado,puedesiralapestañaFilesyvertucódigoenPythonAnywhere.

Finalmente,dirígetealapestañaWebyseleccionaReloadentuaplicaciónweb.

¡Tuactualizacióndeberíaestarenlínea!Actualizatusitiowebenelnavegador.Ahoradeberíaspodervertuscambios:)

DjangoGirlsTutorial

85IntroducciónaHTML

Page 86: Tutorial de Django Girls

ORMdeDjangoyQuerySetsEnestecapítuloaprenderáscómoDjangoseconectaalabasededatosyalmacenalosdatosenella.¡Vamosasumergirnos!

¿QuéesunQuerySet?UnQuerySetes,enesencia,unalistadeobjetosdeunmodelodeterminado.UnQuerySettepermiteleerlosdatosdebasededatos,filtrarlosyordenarlos.

Esmásfácildeaprenderconejemplos.Vamosaintentarlo,¿deacuerdo?

DjangoshellAbrelaconsolayescribeestecomando:

(myvenv)~/djangogirls$pythonmanage.pyshell

Elresultadodeberíaser:

(InteractiveConsole)

>>>

AhoraestásenlaconsolainteractivadeDjango.EscomolaconsoladePython,peroconuntoquedemagiaDjango:).PuedesutilizartodosloscomandosPythonaquítambién,porsupuesto.

Vertodoslosobjetos

Vamosamostrartodosnuestrospostsprimero.Puedeshacerloconelsiguientecomando:

>>>Post.objects.all()

Traceback(mostrecentcalllast):

File"<console>",line1,in<module>

NameError:name'Post'isnotdefined

¡Uy!Aparecióunerror.NosdicequenohayningúnobjetoPost.Estoescorrecto,¡nosolvidamosdeimportarloprimero!

DjangoGirlsTutorial

86ORMdeDjango(Querysets)

Page 87: Tutorial de Django Girls

>>>fromblog.modelsimportPost

Estoessimple:importamoselmodeloPostdeblog.models.Vamosaintentarmostrartodoslospostsnuevamente:

>>>Post.objects.all()

[<Post:myposttitle>,<Post:anotherposttitle>]

Estaesunalistadelaspostscreadasanteriormente.HemoscreadoestospostsusandolainterfazdeladministradordeDjango.Sinembargo,ahoraqueremoscrearnuevospostsusandoPython,¿cómolohacemos?

Crearobjetos

EstaeslaformadecrearunnuevoobjetoPostenlabasededatos:

>>>Post.objects.create(author=me,title='Sampletitle',text='Test')

Perohayuningredientefaltante:me.NecesitamospasarunainstanciadelmodeloUsercomoautor.¿Cómohacemoseso?

PrimeroimportemoselmodeloUser:

>>>fromdjango.contrib.auth.modelsimportUser

¿Quéusuariostenemosennuestrabasededatos?Veamos:

>>>User.objects.all()

[<User:ola>]

Esteeselsuperusuarioquecreamosanteriormente,Vamosaobtenerunainstanciadeeseusuarioahora:

me=User.objects.get(username='ola')

Comopuedesver,hicimosungetdeunUserconelusernamequeseaiguala'ola'.¡Genial!Acuérdatedeponertunombredeusuarioparaobtenertuusuario.

Ahorafinalmentepodemoscrearnuestroprimerpost:

DjangoGirlsTutorial

87ORMdeDjango(Querysets)

Page 88: Tutorial de Django Girls

>>>Post.objects.create(author=me,title='Sampletitle',text='Test')

¡Hurra!¿Quieresprobarsifuncionó?

>>>Post.objects.all()

[<Post:Sampletitle>]

Agregamásposts

Ahorapuedesdivertirteunpocoyañadirmáspostsparavercómofunciona.Añade2ó3másyavanzaalasiguienteparte.

Filtrarobjetos

UnaparteimportantedelosQuerySetseslahabilidadparafiltrarlos.DigamosquequeremosencontrartodoslospostscuyoautoreselUserola.UsaremosfilterenvezdeallenPost.objects.all().Enlosparéntesisestableceremosquécondiciónoconducionesdebencumplirseporunpostdelblogparaterminarennuestroqueryset.Ennuestrocasoseríaauthoresigualame.LaformadeescribirloenDjangoes:author=me.Ahoranuestrobloquedecódigosevecomoesto:

>>>Post.objects.filter(author=me)

[<Post:Sampletitle>,<Post:Postnumber2>,<Post:My3rdpost!>,<Post:4thtitleofpost>]

¿Otalvezquerramosvertodoslospostsquecontenganlapalabra'title'enelcampotitle?

>>>Post.objects.filter(title__contains='title')

[<Post:Sampletitle>,<Post:4thtitleofpost>]

NotaHaydosguionesbajos(_)entretitleycontains.DjangoORMutilizaestasintaxisparasepararlosnombresdeloscampos("title")yoperacionesofiltros("contains").Sisóloutilizasunguiónbajo,obtendrásunerrorcomo"FieldError:Cannotresolvekeywordtitle_contains".

Tambiénpuedesobtenerunalistadetodoslospostspublicados.Lohacemosfiltrandolospostsquetienenelcampopublished_dateenelpasado:

fromdjango.utilsimporttimezonePost.objects.filter(published_date__lte=timezone.now())[]

DjangoGirlsTutorial

88ORMdeDjango(Querysets)

Page 89: Tutorial de Django Girls

Desafortunadamente,ningunodenuestrospostshansidopublicadostodavía.¡Vamosacambiaresto!Primeroobténunainstanciadeunpostquequerramospublicar:

>>>post=Post.objects.get(id=1)

¡Luegoutilizaelmétodopublishparapublicarlo!

>>>post.publish()

Ahoraintentaobtenerlalistadepostspublicadosnuevamente(presionalateclaconlaflechahaciaarriba3vecesypresionaEnter):

>>>Post.objects.filter(published_date__lte=timezone.now())

[<Post:Sampletitle>]

Ordenandoobjetos

LosQuerySetstambiéntepermitenordenarlalistadeobjetos.Intentemosordenarlosporelcampocreated_date:

>>>Post.objects.order_by('created_date')

[<Post:Sampletitle>,<Post:Postnumber2>,<Post:My3rdpost!>,<Post:4thtitleofpost>]

Tambiénpodemosinvertirelordenamientoagregando-alprincipio:

>>>Post.objects.order_by('-created_date')

[<Post:4thtitleofpost>,<Post:My3rdpost!>,<Post:Postnumber2>,<Post:Sampletitle>]

¡Genial!¡Ahoraestáslistaparalasiguienteparte!Paracerrarlaconsola,tipea:

>>>exit()

$

DjangoGirlsTutorial

89ORMdeDjango(Querysets)

Page 90: Tutorial de Django Girls

QuerysetsdeDjangoTenemosdiferentespiezasensulugar:elmodeloPostestádefinidoenmodels.py,tenemosapost_listenviews.pyylaplantillaagregada.¿PerocómoharemosrealmenteparaquenuestrospostsaparezcanennuestraplantillaHTML?Porqueesoesloquequeremoshacer:tomaralgúncontenido(modelosguardadosenlabasededatos)ymostrarloadecuadamenteennuestraplantilla,¿no?

Estoesexactamenteloquelasviewssesuponequehacen:conectarmodelosconplantillas.Ennuestraviewpost_listnecesitaremostomarlosmodelosquedeseamosmostrarypasarlosaunaplantilla.Asíquebásicamenteenunaviewdecidimosqué(modelo)semostraráenunaplantilla.

Muybien,ahora¿cómolohacemos?

Necesitamosabrirnuestroarchivoblog/views.py.Hastaahoralaviewpost_listseveasí:

fromdjango.shortcutsimportrender

defpost_list(request):

returnrender(request,'blog/post_list.html',{})

¿Recuerdascuandohablamosdeincluircódigoendiferentesarchivos?Ahoratenemosqueincluirelmodeloquedefinimosenelarchivomodels.py.Agregaremoslalíneafrom.modelsimportPostdelasiguienteforma:

fromdjango.shortcutsimportrender

from.modelsimportPost

Elpuntodespuésdefromindicaeldirectorioactualolaaplicaciónactual.Comoviews.pyymodels.pyestánenelmismodirectorio,simplementeusamos.yelnombredelarchivo(sin.py).Ahoraimportamoselnombredelmodelo(Post).

¿Peroahoraquésigue?ParatomarpublicacionesrealesdelmodeloPost,necesitamosalgollamadoQuerySet(conjuntodeconsultas).

QuerySet

DjangoGirlsTutorial

90Datosdinámicosenplantillas

Page 91: Tutorial de Django Girls

YadebesestarfamiliarizadaconlaformaenquefuncionanlosQuerySets.HablamosdeellosenelcapítuloDjangoORM(QuerySets).

Entoncesahoranosinteresaobtenerunalistadeentradasdelblogquehansidopublicadasyordenadasporpublished_date(fechadepublicación),¿no?¡YahicimosesoenelcapítuloQuerySets!

Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')

Ahorapondremosestebloquedecódigoenelarchivoblog/views.py,agregándoloalafuncióndefpost_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',{})

ObservaquecreamosunavariableennuestroQuerySet:posts.TómalacomoelnombredenuestroQuerySet.DeaquíenadelantevamosareferirnosalQuerySetconesenombre.

LaúltimaparteespasarelQuerySetpostsalaplantilla(veremoscómomostrarlaenelsiguientecapítulo).

Enlafunciónrenderyatenemoselparámetrorequest(todoloquerecibimosdelusuarioviaInternet)yelarchivo'blog/post_list.html'comoplantilla.Elúltimoparámetro,queseveasí:{}esuncampoenelquepodemosagregaralgunascosasparaquelaplantillalasuse.Necesitamosnombrarlos(losseguiremosllamando'posts'porahora:)).Sedeberíaverasí:{'posts':posts}.Observaquelapartequevaantesde:estáentrecomillas''.

Finalmentenuestroarchivoblog/views.pydeberíaverseasí:

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})

DjangoGirlsTutorial

91Datosdinámicosenplantillas

Page 92: Tutorial de Django Girls

¡Terminamos!AhoraregresemosanuestraplantillaymostremosesteQuerySet.

SiquieresleerunpocomásacercadeQuerySetsenDjango,puedesdarleunvistazoa:https://docs.djangoproject.com/en/1.8/ref/models/querysets/

DjangoGirlsTutorial

92Datosdinámicosenplantillas

Page 93: Tutorial de Django Girls

PlantillasdeDjango¡Eshorademostraralgunosdatos!Djangonosproveelasútilestemplatetagsparaello.

¿Quésonlastemplatetags?Verás,enHTMLnopuedesrealmenteponercódigoPython,porquelosnavegadoresnoloentienden.EllossólosabenHTML.SabemosqueHTMLesalgoestático,mientrasquePythonesmuchomásdinámico.

DjangotemplatetagsnospermitentransferircosasdePythoncomocosasenHTML,asíquetupuedesconstruirsitioswebdinámicosmásrápidoyfácil.

MostrarlaplantillapostlistEnelcapítuloanteriordimosanuestraplantillaunalistadepostsenlavariableposts.AhoralomostraremosenHTML.

ParaimprimirunavariableenunaplantilladeDjango,utilizamosllavesdoblesconelnombredelavariabledentro,así:

{{posts}}

Pruebaestoentuplantillablog/templates/blog/post_list.html(reemplazaelsegundoyeltercerpardeetiquetas<div></div>conlalínea{{posts}}),guardaelarchivoyactualizalapáginaparaverlosresultados:

Comopuedesver,todoloqueobtenemosesesto:

DjangoGirlsTutorial

93PlantillasdeDjango

Page 94: Tutorial de Django Girls

[<Post:Misegundopost>,<Post:Miprimerpost>]

EstosignificaqueDjangoloentiendecomounalistadeobjetos.¿RecuerdasdeIntroducciónaPythoncómopodemosmostrarlistas?Sí,¡conlosciclosfor!EnunaplantilladeDjango,lohacesdeestamanera:

{%forpostinposts%}

{{post}}

{%endfor%}

Pruebaestoentuplantilla.

¡Funciona!PeroqueremosquesemuestrencomolospostsestáticosquecreamosanteriormenteenelcapítulodeIntroducciónaHTML.PuedesmezclarHTMLytemplatetags.Nuestrobodyseveráasí:

<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%}

Todoloqueponesentre{%for%}y{%endfor%}serepetiráparacadaobjetoenlalista.Actualizatupágina:

DjangoGirlsTutorial

94PlantillasdeDjango

Page 95: Tutorial de Django Girls

¿Hasnotadoqueutilizamosunanotacióndiferenteestavez{{post.title}}o{{post.text}}?EstamosaccediendoadatosencadaunodeloscamposdefinidosennuestromodeloPost.Tambiénel|linebreaksestádirigiendoeltextodelospostsatravésdeunfiltroparaconvertirsaltosdelíneaenpárrafos.

UnacosamásSeríabuenoversitusitiowebseguiráfuncionandoenlaInternetpública,¿verdad?IntentemosdesplegándolaenPythonAnywherenuevamente.Aquítedejamosunayudamemoria...

Primero,subetucódigoaGitHub

$gitstatus[...]$gitadd-A.$gitstatus[...]$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."[...]$gitpush

Luego,identifícateenPythonAnywhereyveatuconsolaBash(oempiezaunanueva),yejecuta:

$cdmy-first-blog$gitpull[...]

Finalmente,vealapestañaWebypresionaReloadentuaplicaciónweb.¡Tuactualizacióndeberíapoderverse!

DjangoGirlsTutorial

95PlantillasdeDjango

Page 96: Tutorial de Django Girls

¡Felicidades!Ahorasigueadelante,tratadeagregarunnuevopostusandoelpaneldeadministradordeDjango(¡recuerdaañadirpublished_date!)yluegoactualizatupáginaparaversiaparecetunuevopost.

¿Funcionacomounencanto?¡Estamosorgullosos!Aléjatedetucomputadoraporunrato,tehasganadoundescanso.:)

DjangoGirlsTutorial

96PlantillasdeDjango

Page 97: Tutorial de Django Girls

CSS-¡Hazlobonito!Nuestroblogtodavíasevebastantefeo,¿verdad?¡Eshoradehacerlobonito!VamosausarCSSparaeso.

¿QuéesCSS?CSS(CascadingStyleSheets,quesignifica'hojasdeestiloencascada')esunlenguajeutilizadoparadescribirelaspectoyelformatodeunsitiowebescritoenlenguajedemarcado(comoHTML).Trátalocomomaquillajeparanuestrapáginaweb;).

Peronoqueremosempezardecerootravez,¿verdad?Unavezmás,usaremosalgoqueyahasidorealizadoporprogramadoresypublicadoenInternetdeformagratuita.Yasabes,reinventarlaruedanoesdivertido.

¡VamosausarBootstrap!BootstrapesunodelosframeworksHTMLyCSSmáspopularesparadesarrollarwebsbonitas:http://getbootstrap.com/

LoescribieronprogramadoresquetrabajabanparaTwitteryahoralodesarrollanvoluntariosdetodoelmundo.

InstalarBootstrapParainstalarBootstraptienesqueañadirestoal<head>detufichero.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"

Estonoañadeningúnficheroatuproyecto.SimplementeapuntaaficherosqueexistenenInternet.Adelante,abretusitiowebyactualizalapágina.¡Aquíestá!

DjangoGirlsTutorial

97CSS-Hazlobonito

Page 98: Tutorial de Django Girls

¡Sevemuchomejor!

FicherosestáticosenDjangoFinalmentenosvamosafijarenestascosasquehemosestadollamandoficherosestáticos.LosficherosestáticossontodostusCSSeimágenes;ficherosquenosondinámicos,porloquesucontenidonodependedelcontextodelapeticiónyseránigualesparatodoslosusuarios.

DóndeponerlosficherosestáticosparaDjango

Comohasvistocuandohemosejecutadocollectstaticenelservidor,Djangoyasabedóndeencontrarlosficherosestáticosparalaaplicación"admin".Ahoranecesitamosañadiralgunosficherosestáticosparanuestrapropiaaplicación,blog.

Estoloconseguimoscreandounacarpetallamadastaticdentrodelaaplicaciónblog:

djangogirls

├──blog

│├──migrations

│└──static

└──mysite

Djangoencontraráautomáticamentecualquiercarpetaquesellame"static"dentrodelascarpetasdetusaplicacionesypodráutilizarsucontenidocomoficherosestáticos.

¡TuprimerficheroCSS!

DjangoGirlsTutorial

98CSS-Hazlobonito

Page 99: Tutorial de Django Girls

CreemosunficheroCSSahora,paraañadirtupropioestiloatupáginaweb.Crearunnuevodirectoriollamadocssdentrodetudirectoriostatic.Despuéscreaunnuevoficherollamadoblog.cssdentrodeestedirectoriocss.¿Lista?

djangogirls

└───blog

└───static

└───css

└───blog.css

¡EshoradeescribiralgodeCSS!Abreelficheroblog/static/css/blog.cssentueditordecódigo.

NovamosaentrarmuchoenlapersonalizaciónyelaprendizajedeCSSaquíporqueesbastantefácilylopuedesaprenderportucuentadespuésdeestetaller.RecomendamosenormementehacerestecursodeHTMLyCSSenCodecademyparaaprendertodoloquenecesitassabersobrecómohacertussitioswebmásbonitosconCSS.

Perovamosahacerunpocoalmenos.¿Talvezpodríamoscambiarelcolordenuestrotítulo?Losordenadoresutilizancódigosespecialesparaentenderloscolores.Empiezancon#ylessiguen6letras(A-F)ynúmeros(0-9).Puedesencontrarcódigosdecolor,porejemplo,aquí:http://www.colorpicker.com/.Tambiénpuedesutilizarcolorespredefinidosutilizandosunombreeninglés,comoredygreen.

Entuficheroblog/static/css/blog.cssdeberíasañadirelsiguientecódigo:

h1a{

color:#FCA205;

}

h1aesunselectorCSS.Quieredecirqueestamosaplicandonuestrosestilosacualquierelementoaqueseencuentredentrodeunelementoh1(porejemplocuandotenemosencódigoalgocomo:<h1><ahref="">enlace</a></h1>).Enestecasoleestamosdiciendoquecambieelcolora#FCA205,queesnaranja.Porsupuesto,¡puedesponertupropiocoloraquí!

EnunficheroCSSdefinimoslosestilosparaloselementosdelficheroHTML.Loselementosseidentificanporelnombredelelemento(esdecir,a,h1,body),elatributoclass(clase)oelatributoid(identificador).Classeidsonnombresqueleasignastúmismaalelemento.Lasclasesdefinengruposdeelementosylosidsapuntanaelementosespecíficos.Porejemplo,lasiguienteetiquetasepuedeidentificarconCSSusandoelnombrea,laclaseexternal_linkoelidlink_to_wiki_page:

DjangoGirlsTutorial

99CSS-Hazlobonito

Page 100: Tutorial de Django Girls

<ahref="http://en.wikipedia.org/wiki/Django"class="external_link"id="link_to_wiki_page"

PuedesleermássobreselectoresdeCSSenw3schools.

TambiénnecesitamosdecirleanuestraplantillaHTMLquehemosañadidoCSS.Abreelficheroblog/templates/blog/post_list.htmlyañadeestalíneajustoalprincipio:

{%loadstaticfiles%}

Aquísóloestamoscargandoficherosestáticos:).Luego,entreel<head>y</head>,despuésdelosenlacesalosficherosCSSdeBootstrap(elnavegadorleelosficherosenelordenenqueestán,asíquenuestroficheropodríasobrescribirpartesdelcódigodeBootstrap),añadelasiguientelínea:

<linkrel="stylesheet"href="{%static'css/blog.css'%}">

LeacabamosdedeciranuestraplantilladóndeseencuentranuestroficheroCSS.

Ahoratuficherodeberíateneresteaspecto:

{%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>

Deacuerdo,¡guardaelficheroyactualizaelsitio!

DjangoGirlsTutorial

100CSS-Hazlobonito

Page 101: Tutorial de Django Girls

¡Buentrabajo!¿Quizánosgustaríadarleunpocodeaireanuestrositiowebyaumentartambiénelmargenenelladoizquierdo?¡Vamosaintentarlo!

body{

padding-left:15px;

}

AñadeestoatuCSS,guardaelficheroy¡miracómofunciona!

¿Quizápodríamospersonalizarlatipografíadeltítulo?Pegaestoenlasección<head>delficheroblog/templates/blog/post_list.html:

<linkhref="http://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext"rel

DjangoGirlsTutorial

101CSS-Hazlobonito

Page 102: Tutorial de Django Girls

EstalíneavaaimportarunatipografíallamadaLobsterdeGoogleFonts(https://www.google.com/fonts).

Ahoraañadelalíneafont-family:'Lobster';enelficheroCSSblog/static/css/blog.cssdentrodelbloquededeclaraciónh1a(elcódigoentrellaves{y})yactualizalapágina:

h1a{

color:#FCA205;

font-family:'Lobster';

}

¡Genial!

Comosemencionóanteriormente,CSStieneunconceptodeclasesquebásicamentepermitenombrarunapartedelcódigoHTMLyaplicarestilossóloaestaparte,sinafectaraotras.Esmuyútilsitienesdosdivsquehacenalgomuydiferente(comoelencabezadoylaentrada)ynoquieresquetenganelmismoaspecto.

¡Adelante!NombraalgunaspartesdelcódigoHTML.Añadeunaclasellamadapage-headeraldivquecontieneelencabezado,así:

<divclass="page-header">

<h1><ahref="/">DjangoGirlsBlog</a></h1>

</div>

Yahoraañadelaclasepostaldivquecontieneunaentradadelblog.

DjangoGirlsTutorial

102CSS-Hazlobonito

Page 103: Tutorial de Django Girls

<divclass="post">

<p>published:{{post.published_date}}</p>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaks}}</p>

</div>

Ahoraañadiremosbloquesdedeclaraciónadiferentesselectores.Losselectoresquecomienzancon.hacenreferenciaalasclases.HaymuchostutorialesyexplicacionessobreCSSenlawebqueteayudaránaentenderelsiguientecódigo.Porahora,simplementecopiaypegaestebloquedecódigoentuficheroblog/static/css/blog.css:

DjangoGirlsTutorial

103CSS-Hazlobonito

Page 104: Tutorial de Django Girls

.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;

}

LuegorodeaelcódigoHTMLquemuestralasentradasconlasdeclaracionesdeclases.Sustituyeesto:

DjangoGirlsTutorial

104CSS-Hazlobonito

Page 105: Tutorial de Django Girls

{%forpostinposts%}

<divclass="post">

<p>published:{{post.published_date}}</p>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaks}}</p>

</div>

{%endfor%}

enblog/templates/blog/post_list.htmlporesto:

<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>

Guardalosficherosyactualizatusitio.

¡Bien!Seveincreíble,¿verdad?Enrealidadelcódigoqueacabamosdepegarnoestandifícildeentenderydeberíassercapazdeentenderlamayoríasóloconleerlo.

NotengasmiedodejugarunpococonesteCSSeintentarcambiaralgunascosas.Sirompesalgo,notepreocupes,¡siemprepuedesdeshacerlo!

DjangoGirlsTutorial

105CSS-Hazlobonito

Page 106: Tutorial de Django Girls

Decualquierforma,tevolvemosarecomendarquehagaselcursodeHTMLyCSSdeCodeacademycomounatareapost-tallerparaqueaprendastodoloquenecesitassaberparahacertussitioswebmásbonitosconCSS.

¡¿Listaparaelsiguientecapítulo?!:)

DjangoGirlsTutorial

106CSS-Hazlobonito

Page 107: Tutorial de Django Girls

ExtendiendoPlantillasOtracosabuenaqueDjangotieneparatíeslaextensióndeplantillas.¿Quésignificaesto?SignificaquepuedesusarlasmismaspartesdetuHTMLparadiferentespáginasdetusitioweb.

Deestaformanotienesquerepetirelcódigoencadaunodelosarchivoscuandoquieresusarunamismainformaciónounmismoesquema.Ysiquierescambiaralgo,nonecesitashacerloencadaplantilla.

CreandounaplantillabaseUnaplantillabaseeslaplantillamásbásicaqueextiendesencadapáginadetusitioweb.

Vamosacrearunarchivobase.htmlenblog/templates/blog/:

blog

└───templates

└───blog

base.html

post_list.html

Luegoábreloycopiatodoloquehayenpost_list.htmlalarchivobase.html,delasiguientemanera:

DjangoGirlsTutorial

107Extenderplantillas

Page 108: Tutorial de Django Girls

{%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'

<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>

Luego,enbase.htmlreemplazaporcompletotu<body>(todoloquehayaentre<body>and</body>)conesto:

<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

108Extenderplantillas

Page 109: Tutorial de Django Girls

Básicamenteremplazamostodoentre{%forpostinposts%}{%endfor%}con:

{%blockcontent%}

{%endblock%}

¿Quésignificaesto?Acabasdecrearunblock,unatemplatetagquetepermiteinsertarHTMLenestebloqueenotrasplantillasqueextiendanabase.html.Temostraremoscomohacerestoenunmomento.

Ahoraguárdaloyabretuarchivoblog/templates/blog/post_list.htmldenuevo.Eliminatodoloquenoestédentrodelbodyyluegoeliminatambién<divclass="page-header"></div>,deformaquetuarchivoseveráasi:

{%forpostinposts%}

<divclass="post">

<divclass="date">

{{post.published_date}}

</div>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaks}}</p>

</div>

{%endfor%}

Yahoraagregaestalíneaaliniciodelarchivo:

{%extends'blog/base.html'%}

Significaqueahoraestamosextendiendodelaplantillabase.htmlenpost_list.html.Sólonosfaltaunacosa:ponertodo(exceptolalíneaqueacabamosdeagregar)entre{%blockcontent%}y{%endblockcontent%}.Comoesto:

{%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

109Extenderplantillas

Page 110: Tutorial de Django Girls

¡Esoestodo!Verificaquetusitiowebaúnfuncioneapropiadamente:)

SitienesunerrorTemplateDoesNotExistsquedigaquenohayunarchivoblog/base.htmlytienesrunserverejecutándoseenlaconsola,intentapararlo(presionandoCtrl+C-lasteclasControlyCjuntas)yreinicialoejecutandoelcomandopythonmanage.pyrunserver.

DjangoGirlsTutorial

110Extenderplantillas

Page 111: Tutorial de Django Girls

AmplíatuaplicaciónYahemoscompletadotodoslospasosnecesariosparalacreacióndenuestrositioweb:sabemoscómoescribirunmodel,url,viewytemplate.Tambiénsabemoscómohacerquenuestrositiowebsevealindo.

¡Horadepracticar!

Loprimeroquenecesitamosennuestrobloges,obviamente,unapáginaparamostrarunpost,¿cierto?

YatenemosunmodeloPost,asíquenonecesitamosañadirnadaamodels.py.

CreaunenlaceenlaplantillaVamosaempezarañadiendounenlacedentrodelarchivoblog/templates/blog/post_list.html.Hastaelmomentodeberíaverseasí:

{%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%}

Queremostenerunenlaceaunapáginadedetallesobreeltítulodelpost.Vamosacambiar<h1><ahref="">{{post.title}}</a></h1>dentrodelenlace:

<h1><ahref="{%url'blog.views.post_detail'pk=post.pk%}">{{post.title}}</a></h1>

Eshoradeexplicarelmisterioso{%url'blog.views.post_detail'pk=post.pk%}.Comoprobablementesospeches,lanotación{%%}significaqueestamosutilizandoDjangotemplatetags.¡EstavezvamosautilizarunoquevaacrearunadirecciónURLparanosotros!

DjangoGirlsTutorial

111Amplíatuaplicación

Page 112: Tutorial de Django Girls

blog.views.post_detailesunarutahaciapost_detailviewquequeremoscrear.Porfavornota:blogeselnombredenuestraaplicación(elblogdedirectorio),viewseselnombredelarchivoviews.pyypost_detaileselnombredelaview.

Ahoracuandovayamosa:http://127.0.0.1:8000/tendremosunerror(comoeradeesperar,yaquenotenemosunadirecciónURLounaviewparapost_detail).Severáasí:

VamosacrearunaURLenurls.pyparanuestroviewpost_detail!

URL:http://127.0.0.1:8000/post/1/

QueremoscrearunaURLqueapunteaDjangoaunaviewdenominadapost_detail,quemostraráunaentradadelblog.Agregalalíneaurl(r'^post/(?P<pk>[0-9]+)/$',views.post_detail),alarchivoblog/urls.py.Deberíateneresteaspecto:

```fromdjango.conf.urlsimportinclude,urlfrom.importviews

urlpatterns=[

url(r'^$',views.post_list),

url(r'^post/(?P<pk>[0-9]+)/$',views.post_detail),

]

DjangoGirlsTutorial

112Amplíatuaplicación

Page 113: Tutorial de Django Girls

Esedaunpocodemiedo,peronotepreocupes-loexplicaremosparati:comienzacon`^`otravez,"elprincipio".`post/`sólosignificaquedespuésdelcomienzo,ladirecciónURLdebecontenerlapalabra**post**y**/**.Hastaahora,bien.`(?P<pk>[0-9]+)`-estaparteesmáscomplicada.SignificaqueDjangollevarátodoloquecoloquesaquíylotransferiráaunavistacomounavariablellamada`pk`.`[0-9]`tambiénnosdicequesólopuedeserunnúmero,nounaletra(tododeberíaestarentre0y9).`+`significaquetienequehaberunoomásdígitos.Entoncesalgocomo`http://127.0.0.1:8000/post//`noesválido,pero`1234567890/post/http://127.0.0.1:8000/`esperfectamenteaceptable!-`/`-entoncesnecesitamos**/**denuevo-`$`-¡"elfinal"!

Esosignificaquesientrasen`http://127.0.0.1:8000/post/5/`entunavegador,Djangoentenderáqueestásbuscandouna*view*denominada`post_detail`ytransferirálainformaciónde`pk`queesiguala`5`aesa*view*.

`pk`eslaabreviaciónde`primarykey`.EstenombreseutilizaamenudoenproyectosdeDjango.Peropuedesnombrartusvariablescomoteguste(recuerda:¡minúsculasy`_`enlugardeespaciosenblanco!).Porejemploenlugarde`(?.¿P<pk>[0-9]+)`podríamostenerlavariable`post_id`,asíqueestoloveríascomo:`(?P<post_id>[0-9]+)`.

¡Bien!¡Actualizalapágina:http://127.0.0.1:8000/¡Boom!¡Sinembargovemosotroerror!Comoeradeesperarse.

![AttributeError][2]

[2]:images/attribute_error2.png

¿Teacuerdasdelpróximopaso?Porsupuesto:¡agregarunaview!

##post_detailview

Estaveznuestra*view*tomaráunparámetroadicional`pk`.¿Nuestra*view*necesitarecibirla,cierto?Entoncesdefiniremosnuestrafuncióncomo`defpost_detail(request,pk):`.Tenencuentaquetenemosqueusarexactamenteelmismonombrequeespecificamosenlasurls(`pk`).¡Omitirestavariableesincorrectoyresultaráenunerror!

Ahora,queremossólounpostdelblog.Paraellopodemosusarquerysetscomoeste:

Post.objects.get(pk=pk)

Peroestecódigotieneunproblema.Sinohayningún`Post`con`llaveprimaria`(`pk`)tendremosunerrormuyfeo.

![DoesNotExisterror][3]

[3]:images/does_not_exist2.png

¡Noqueremoseso!Pero,porsupuesto,Djangovieneconalgoqueseencargarádeeseproblemapornosotros:`get_object_or_404`.Encasodequenohayaningún`Post`coneldado`pk`semostraráunamásagradablepágina(`PageNotFound404`).

![Pagenotfound][4]

[4]:images/404_2.png

Labuenanoticiaesquepuedescreartupropiapágina`PageNotFound`ydiseñarlacomodesees.Peroporahoranoestanimportante,asíqueloomitiremos.

¡Eshoradeagregaruna*view*anuestroarchivo`views.py`!

Deberíamosabrir`blog/views.py`yagregarelsiguientecódigo:

fromdjango.shortcutsimportrender,get_object_or_404

Cercadeotraslíneas`from`.Yenelfinaldelarchivoañadimosnuestra*view*:

```defpost_detail(request,pk):

post=get_object_or_404(Post,pk=pk)

returnrender(request,'blog/post_detail.html',{'post':post})

DjangoGirlsTutorial

113Amplíatuaplicación

Page 114: Tutorial de Django Girls

Sí.Eshoradeactualizarlapágina:http://127.0.0.1:8000/

¡Funcionó!Pero¿quépasacuandohacesclickenunenlaceeneltítulodelpost?

¡Ohno!¡Otroerror!Peroyasabemoscómolidiarconeso,¿no?¡Tenemosqueañadirunaplantilla!

Crearemosunarchivoenblog/templates/blogllamadopost_detail.html.

Severáasí:

{%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%}

Unavezmásestamosextendiendobase.html.Enelbloquecontentqueremosmostrarlafechadepublicación(siexiste),títuloytextodenuestrosposts.Perodeberíamosdiscutiralgunascosasimportantes,¿cierto?

{%if...%}...{%endif%}esuntemplatetagquepodemosusarcuandoquerramosveralgo(¿recuerdasif...else...</code>delcapítulodeIntroducciónaPython?).Enesteescenarioqueremoscomprobarsielcampopublished_datedeunpostnoestávacío.

Bien,podemosactualizarnuestrapáginayversiPageNotFoundsehaido.

¡Yay!¡Funciona!

Unacosamás:¡Tiempodeimplementación!SeríabuenoverificarquetusitiowebaúnfuncionaráenPythonAnywhere,¿cierto?Intentemosdesplegardenuevo.

DjangoGirlsTutorial

114Amplíatuaplicación

Page 115: Tutorial de Django Girls

$gitstatus

$gitadd-A.

$gitstatus

$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."

$gitpush

Luego,enunaconsolaBashdePythonAnywhere

$cdmy-first-blog$gitpull[...]

Finalmente,vealapestañaWebyhazclickenReload.

¡Yesodeberíasertodo!Felicidades:)

DjangoGirlsTutorial

115Amplíatuaplicación

Page 116: Tutorial de Django Girls

FormulariosenDjangoLoúltimoqueharemosennuestrowebsiteescrearunapartadoparaagregaryeditarpostsenelblog.Djangoadminestábien,peroesbastantedifícildepersonalizaryhacerlobonito.Conformstendremosunpoderabsolutosobrenuestrainterfaz-podemoshacercasicualquiercosaquepodamosimaginar!

LobuenodeDjangoformsesquepodemosdefinirlodesdeceroocreandounModelFormyseguardaráelresultadodelformularioenelmodelo.

Estoesexactamenteloquequeremoshacer:crearemosunformularioparanuestromodeloPost.

ComocadaparteimportantedeDjango,formstienensupropioarchivo:forms.py.

Tenemosquecrearunarchivoconestenombreeneldirectorioblog.

blog

└──forms.py

Ok,vamosabrirloyvamosaescribirelsiguientecódigo:

fromdjangoimportforms

from.modelsimportPost

classPostForm(forms.ModelForm):

classMeta:

model=Post

fields=('title','text',)

PrimeronecesitamosimportarDjangoforms(fromdjangoimportforms)y,obviamente,nuestromodeloPost(from.modelsimportPost).

PostForm,comoprobablementesospechas,eselnombredelformulario.NecesitamosdecirleaDjangoqueesteformularioesunModelForm(asíDjangoharáalgodemagiaparanosotros)-forms.ModelFormesresponsabledeello.

Acontinuación,tenemosclassMeta,dondeledecimosaDjangoquémodelodebeutilizarparacrearesteformulario(model=Post).

DjangoGirlsTutorial

116FormulariosenDjango

Page 117: Tutorial de Django Girls

Finalmente,podemosdecirquecampo(s)queremosennuestroformulario.Enesteescenariosóloqueremostitleytext-authorserálapersonaquesehaautenticado(¡tú!)ycreated_datesedefiniráautomáticamentecuandocreemosunpost(esdecirenelcódigo),¿si?

¡Yesoestodo!Todoloquenecesitamoshacerahoraesusarelformularioenunaviewymostrarlaenunaplantilla.

Unavezmásvamosacrear:unenlacealapágina,unadirecciónURL,unavistayunaplantilla.

EnlaceaunapáginaconelformularioEshoradeabrirblog/templates/blog/base.html.Vamosaañadirunenlaceendivllamadopage-header:

<ahref="{%url'blog.views.post_new'%}"class="top-menu"><spanclass="glyphiconglyphicon-plus"

Tenencuentaquequeremosllamaranuestranuevavistapost_new.

Despuésdeagregarlalínea,tuarchivohtmldeberíateneresteaspecto:

DjangoGirlsTutorial

117FormulariosenDjango

Page 118: Tutorial de Django Girls

{%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'

<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>

Luegodeguardaryactualizarlapáginahttp://127.0.0.1:8000obviamenteverásunerrorNoReverseMatchfamiliar,¿verdad?

URLAbrimosblog/urls.pyyañadimosunalínea:

url(r'^post/new/$',views.post_new,name='post_new'),

Yelcódigofinaltendráesteaspecto:

fromdjango.conf.urlsimportinclude,url

from.importviews

urlpatterns=[

url(r'^$',views.post_list),

url(r'^post/(?P<pk>[0-9]+)/$',views.post_detail),

url(r'^post/new/$',views.post_new,name='post_new'),

]

DjangoGirlsTutorial

118FormulariosenDjango

Page 119: Tutorial de Django Girls

Despuésdeactualizarelsitio,veremosunAttributeError,puestoquenotenemoslavistapost_newimplementada.Vamosaañadirlaahora.

Vistapost_newEselmomentodeabrirelarchivoblog/views.pyyagregarlassiguienteslíneasalrestodelasfilasfrom:

from.formsimportPostForm

ynuestravista:

defpost_new(request):

form=PostForm()

returnrender(request,'blog/post_edit.html',{'form':form})

ParacrearunnuevoformularioPost,tenemosquellamaraPostForm()ypasarloalaplantilla.Volveremosaestavistapero,porahora,vamosacrearrápidamenteunaplantillaparaelformulario.

PlantillaTenemosquecrearunarchivopost_edit.htmleneldirectorioblog/templates/blog.Parahacerqueunformulariofuncionenecesitamosvariascosas:

tenemosquemostrarelformulario.Podemoshacerlo,porejemplo,conunsimple``.lalíneaanteriortienequeestardentrodeunaetiquetadeformularioHTML:<formmethod="POST">...</form>

necesitamosunbotónGuardar.LohacemosconunbotónHTML:<buttontype='submit'>Save</button>

yfinalmentejustodespuésdelaaperturade<form...>necesitamosagregar{%csrf_token%}.¡Estoesmuyimportanteyaquehacequetusformulariosseanseguros!Djangosequejarásiteolvidasdeestapartecuandointenteguardarelformulario.

DjangoGirlsTutorial

119FormulariosenDjango

Page 120: Tutorial de Django Girls

Bueno,vamosavercómoquedaráelHTMLenpost_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">Save</button>

</form>

{%endblock%}

¡Eshoradeactualizar!¡Si!¡Tuformulariosemuestra!

DjangoGirlsTutorial

120FormulariosenDjango

Page 121: Tutorial de Django Girls

Pero,¡unmomento!Siescribesalgoenloscampostítleytextytratasdeguardarloscambios-¿quépasará?

¡Nada!Unavezmásestamosenlamismapáginayeltextosehaido...noseañadeningúnpostnuevo.Entonces,¿quéhaidomal?

Larespuestaes:nada.Tenemosquetrabajarunpocomásennuestravista.

GuardarelformularioAbreblog/views.pyunavezmás.Actualmente,loquetenemosenlavistapost_newes:

defpost_new(request):

form=PostForm()

returnrender(request,'blog/post_edit.html',{'form':form})

Cuandoenviamoselformulariosomosredirigidosalamismavista,peroestaveztenemosalgunosdatosadicionalesenrequest,másespecíficamenteenrequest.POST(elnombrenotienenadaqueverconunpostdelblog,serefiereaqueestamos"publicando"-eninglés,posting-datos).¿RecuerdasqueenelarchivoHTMLladefiniciónde<form>tenía

DjangoGirlsTutorial

121FormulariosenDjango

Page 122: Tutorial de Django Girls

lavariablemethod="POST"?Todosloscamposdelformularioestanahoraenrequest.POST.NodeberíasrenombrarlavariablePOST(elúniconombrequetambiénesválidoparalavariablemethodesGET,peronotenemostiempoparaexplicarcuálesladiferencia).

Ennuestraviewtenemosdosposiblessituacionesacontemplar.Primero:cuandoaccedemosalapáginaporprimeravezyqueremosunformularioenblanco.Segundo:cuandovolvemosalaviewconlosdatosdelformularioqueacabamosdeescribir.Asíquetenemosqueañadirunacondición(utilizaremosifparaeso).

ifrequest.method=="POST":

[...]

else:

form=PostForm()

Eshoradellenarlospuntos[...].SielmethodesPOSTqueremosconstruirelPostFormconlosdatosdelformulario,¿no?Loharemoscon:

form=PostForm(request.POST)

Fácil!Losiguienteesverificarsielformularioescorrecto(todosloscamposnecesariosestándefinidosynohayvaloresincorrectos).Lohacemosconform.is_valid().

Comprobamosqueelformularioesválidoy,siesasí,¡lopodemossalvar!

ifform.is_valid():

post=form.save(commit=False)

post.author=request.user

post.save()

Básicamente,tenemosquehacerdoscosasaquí:guardamoselformularioconform.saveyañadimosunautor(yaquenohabíaningúncampodeauthorenelPostFormyestecampoesobligatorio).commit=FalsesignificaquenoqueremosguardarelmodeloPosttodavía-queremosañadirelautorprimero.Lamayoríadelasvecesutilizarásform.save(),sincommit=False,peroenestecaso,tenemosquehacerlo.post.save()conservaráloscambios(añadiendoaautor)ysecrearáunanuevopostenelblog.

Porúltimo,seríagenialsipodemosinmediatamenteiralapáginapost_detaildelnuevopostdeblog,¿no?Parahacerlonecesitamosimportaralgomás:

fromdjango.shortcutsimportredirect

DjangoGirlsTutorial

122FormulariosenDjango

Page 123: Tutorial de Django Girls

Agrégaloalprincipiodelarchivo.Yahorapodemosdecir:véalapáginapost_detaildelpostreciéncreado.

returnredirect('blog.views.post_detail',pk=post.pk)

blog.views.post_detaileselnombredelavistaalaquequeremosir.¿Recuerdasqueestaviewrequiereunavariablepk?Parapasarloalasvistasutilizamospk=post.pk,dondeposteselpostreciéncreado.

Bien,hablamosmucho,peroprobablementequeremosvercomoseveahoralavista,¿verdad?

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})

Vamosaversifunciona.Vealapáginahttp://127.0.0.1:8000/post/new/,añadeuntitleyuntext,guardalo...¡yvoilà!Seañadeelnuevopostalblogysenosredirigealapáginadepost_detail.

Probablementehasvistoquenohemosdefinidolafechadepublicación.VamosaintroducirunbotónpublicarenDjangoGirlsTutorial:Extensions.

¡Esoesgenial!

ValidacióndeformulariosAhora,vamosaenseñartequétanbuenoesDjangoforms.Unpostdelblogdebetenerloscampostitleytext.EnnuestromodeloPostnodijimos(adiferenciadepublished_date)queestoscampossonrequeridos,asíqueDjango,pordefecto,esperaqueesténdefinidos.

Tratadeguardarelformulariosintitleytext.¡Adivinaquépasará!

DjangoGirlsTutorial

123FormulariosenDjango

Page 124: Tutorial de Django Girls

Djangoseencargadevalidarquetodosloscamposenelformularioesténcorrectos.¿Noesgenial?

ComorecientementehemosutilizadolainterfazdeadministradordeDjango,elsistemapiensaqueestamosconectadas.Hayalgunassituacionesquepodríanllevarnosadesconectarnos(cerrandoelnavegador,reiniciandolabasededatos,etc.).Siestásrecibiendoerroresalcrearunpostqueindicanlafaltadeiniciodesesióndeusuario,dirígetealapáginadeadministraciónhttp://127.0.0.1:8000/admineiniciasesiónnuevamente.Estoresolveráelproblematemporalmente.HayunarreglopermanenteesperándoteenelcapítuloTarea:¡Añadirseguridadatusitioweb!despuésdeltutorialprincipal.

DjangoGirlsTutorial

124FormulariosenDjango

Page 125: Tutorial de Django Girls

EditarformularioAhorasabemoscómoagregarunnuevoformulario.Pero,¿quépasasiqueremoseditarunoexistente?Esmuysimilaraloqueacabamosdehacer.Vamosacrearalgunascosasimportantesrápidamente(sinoentiendesalgo,pregúntaleatututororevisalocapítulosanteriores,sontemasqueyahemoscubierto).

Abreelarchivoblog/templates/blog/post_detail.htmlyañadeestalínea:

<aclass="btnbtn-default"href="{%url'post_edit'pk=post.pk%}"><spanclass="glyphiconglyphicon-pencil"></span></a>

paraquelaplantillaquede:

{%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%}

Enelarchivoblog/urls.pyañadimosestalínea:

url(r'^post/(?P<pk>[0-9]+)/edit/$',views.post_edit,name='post_edit'),

Vamosareusarlaplantillablog/templates/blog/post_edit.html,asíqueloúltimoquenosfaltaesunaview.

Abramoselarchivoblog/views.pyyañadamosalfinalestalínea:

DjangoGirlsTutorial

125FormulariosenDjango

Page 126: Tutorial de Django Girls

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})

Estosevecasiexactamenteigualanuestraviewpost_new,¿no?Peronodeltodo.Primero:pasamosunparámetroextrapkdelosurls.Luego:obtenemoselmodeloPostquequeremoseditarconget_object_or_404(Post,pk=pk)ydespués,alcrearelformulariopasamosestepostcomounainstanciatantoalguardarelformulario:

form=PostForm(request.POST,instance=post)

comoalabrirunformularioconestepostparaeditarlo:

form=PostForm(instance=post)

Ok,¡vamosaprobarsifunciona!Dirígetealapáginapost_detail.Debehaberahíunbotónparaeditarenlaesquinasuperiorderecha:

DjangoGirlsTutorial

126FormulariosenDjango

Page 127: Tutorial de Django Girls

Aldarclickahí,debesverelformularioconnuestropostdelblog:

¡Siéntetelibredecambiareltítulooeltextoyguardaloscambios!

¡Felicitaciones!¡Tuaplicaciónestácadavezmáscompleta!

SinecesitasmásinformaciónsobrelosformulariosdeDjango,debesleerladocumentación:https://docs.djangoproject.com/en/1.8/topics/forms/

Unacosamás:¡Tiempodeimplementación!VeamossitodoestofuncionaenPythonAnywhere.¡Tiempodehacerotrodespliegue!

Primero,hazuncommitcontunuevocódigoysúbeloaGitHub

$gitstatus$gitadd-A.$gitstatus$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."$gitpush

Luego,enunaconsolaBashdePythonAnywhere

$cdmy-first-blog$gitpull[...]

Finalmente,vealapestañaWebyhazclickenReload.

DjangoGirlsTutorial

127FormulariosenDjango

Page 128: Tutorial de Django Girls

¡Yesodeberíasertodo!Felicidades:)

DjangoGirlsTutorial

128FormulariosenDjango

Page 129: Tutorial de Django Girls

DominioPythonAnywheretehadadoundominiogratuito,perotalveznoquierastener".pythonanywhere.com"alfinaldelaURLdetublog.Quizásquieraquetublogvivaen"www.infinite-kitten-pictures.org"o"www.3d-printed-steam-engine-parts.com"o"www.antique-buttons.com"o"www.mutant-unicornz.net",oloquequierasquesea.

AquíhablaremosbrevementesobrecómoobtenerundominioyveremoscómovincularloatuaplicaciónwebenPythonAnywhere.Sinembargo,deberíassaberquelamayoríadelosdominiossonpagos,yPythonAnywheretecobraráunvaloradicionalparausartupropionombrededominio--noesdemasiadodineroentotal,peroesprobablementealgoquequierashacersólosiestásmuycomprometidaconlacausa.

¿Donderegistrarundominio?Undominiotípicocuestaalrededorde15dólaresestadounidensesanuales.Hayopcionesmásbaratasymáscaras,dependiendodelproveedor.Hayunagrancantidaddeempresasalasquepuedescomprarundominio:unasimplebúsquedaengoogledarácientosdeopciones.

NuestraopciónfavoritaesIwantmyname.Ellossepromocionancomounaopción"indoloraparaelmanejodedominios"yrealmenteloson.

Tambiénpuedesobtenerdominiosgratuitos.dot.tkesunlugarparaobteneruno,perodeberíamosadvertirtequelosdominiosgratuitosavecessesientenalgo"baratos"--situsitiovaaserunsitioparaunnegocioprofesional,seguramentequierasconsiderarcomprarundominio"apropiado"quetermineen.com.

CómoapuntartudominioaPythonAnywhereSielegistelaopcióndeiwantmyname.com,hazclickenDomainsenelmenúyelijetunuevodominio.LuegoencuentraelvínculoamanageDNSrecords:

Ahoranecesitasencontraresteformulario:

DjangoGirlsTutorial

129Dominio

Page 130: Tutorial de Django Girls

Ycompletarloconlossiguientesdetalles:-Hostname:www-Type:CNAME-Value:tudominiodePythonAnywhere(porejemplo,djangogirls.pythonanywhere.com)-TTL:60

Enlaparteinferior,hazclickenelbotón"Agregar"yguardaloscambios.

NotaSiutilizasteunproveedordedominiosdiferente,lainterfazexactaparaencontrartusconfiguracionesdeDNS/CNAMEserádiferente,perotuobjetivoeselmismo:configurarunCNAMEqueapunteatunuevodominioenyourusername.pythonanywhere.com.

Puedetomarunosminutosparatudominioparaempezarafuncionar,¡sépaciente!

ConfiguraeldominioatravésdelaaplicaciónwebenPythonAnywhereTambiénnecesitarásdecirleaPythonAnywherequequieresusartudominiopersonalizado.

VealapáginaPythonAnywhereAccountsyhazunaactualizacióndeltipodecuenta.Laopciónmáseconómica(elplan"Hacker")estábienparaempezar.Siemprepuedeselegirunplanconmayoresprestacionesdespuéscuandotevuelvassuper-famosaytengasmillonesdevisitas.

Luego,vealapestañaWebyanotaunpardecosas:

CopialarutaatuvirtualenvyponlaenalgúnlugarseguroAbretuarchivodeconfiguraciónWSGI,copiaelcontenido,ypégaloenalgúnlugarseguro

Luego,hazclickenDeletedetuviejaaplicaciónweb.Notepreocupes,estonoeliminarátucódigo,solamentecambiaráeldominioyourusername.pythonanywhere.com.Luego,creaunanuevaaplicaciónwebysigueestospasos:

IngresatunombrededominioElije"configuraciónmanual"ElijePython3.4¡Ylisto!

Cuandoseasredirigidaalapestañaweb.

PegalarutaalvirtualenvqueguardasteanteriormenteAbretunuevoarchivodeconfiguraciónWSGIypegaelcontenidodetuviejoarchivodeconfiguración

DjangoGirlsTutorial

130Dominio

Page 131: Tutorial de Django Girls

Hazclickenactualizar,¡deberíasverquetusitioestáenlíneaenelnuevodominio!

Siteencuentrasconalgúnproblema,hazclickenelvínculo"Sendfeedback"enelsitiodePythonAnywhere,yunodesusamigablesadministradorestecontactaráparaayudarteenbreve.

DjangoGirlsTutorial

131Dominio

Page 132: Tutorial de Django Girls

¿Quésigue?¡Datemuchasfelicitaciones!¡Eresincreíble!.¡Estamosorgullosos!<3

¿Quéhacerahora?

Tomaundescansoyrelájate.Acabasdehaceralgorealmentegrande.

Despuésdeeso,asegúratede:

SeguiraDjangoGirlsenFacebookoTwitterparaestaraldía

¿Mepuedesrecomendarrecursosadicionales?

¡Sí!Enprimerlugar,sigueadelanteypruebanuestrolibrollamadoDjangoGirlsTutorial:Extensiones.

Másadelante,puedesintentarlosrecursoslistadosacontinuación.¡Estántodosmuyrecomendados!

Django'sofficialtutorialNewCodertutorialsCodeAcademyPythoncourseCodeAcademyHTML&CSScourseDjangoCarrotstutorialLearnPythonTheHardWaybookGettingStartedWithDjangovideolessonsTwoScoopsofDjango:BestPracticesforDjangobook

DjangoGirlsTutorial

132¿Quésigue?