Inici de sessió d'usuari


Capítol 3: La base de les pàgines web dinàmiques


En el capítol anterior, hem explicat com crear un projecte de Django i executar el servidor de desenvolupament. Per descomptat, aquest lloc no fa res que sigui útil -- tot el que fa és mostrar el missatge "it worked!" "(Funciona!). Mirem de canviar-ho.

Aquest capítol explica com crear pàgines web dinàmiques amb Django.

La teva primera vista: Contingut Dinàmic

Com a primera fita, crearem una pàgina web que mostre la data i hora actual. Aquest és un bon exemple de pàgina web dinàmica, ja que els continguts de la pàgina no són estàtics -- és a dir, els continguts canvien d'acord amb els resultats d'un càlcul. (en aquest cas, el càlcul de l'hora actual).

Aquest exemple tant simple no involucra cap base de dades ni cap conjunt de dades d'usuari -- només la sortida de rellotge intern del teu servidor.

Per crear aquesta pàgina, escriurem una funció vista. Un funció vista, ó vista per ser més escuets, és una funció simple de Python que agafa una petició web i retorna una resposta web. Aquesta resposta pot ser un contingut HTML o una pàgina web, o una redirecció, o un error 404, o un document XML, o una imatge... o qualsevol cosa. La pròpia vista conté la lògica necessària per retornar aquesta resposta.

Aquí hi ha una vista que retorna la data i hora actual, com un document HTML:

from django.http import HttpResponse
import datetime

def datahora_actual(request):
    ara = datetime.datetime.now()
    html = "<html><body>Ara són les %s.</body></html>" % ara
    return HttpResponse(html)

Anem pas a pas per aquest tros de codi:

  • Primer, importem la classe HttpResponse, que resideix en el mòdul django.http.
  • Després, importem el mòdul datetime de la llibreria estàndard de Python -- un conjunt de mòduls útils que vénen amb Python. El mòdul datetime conté diverses funcions i classes per treballar amb dates i hores, incloent-hi una funció que retorna l'hora actual.
  • Després, definim una funció anomenada datahora_actual. Aquesta funció vista, agafa l'objecte HttpRequest com a primer paràmetre. Cada funció vista pren l'objecte HttpRequest com a primer paràmetre. En aquest cas, anomenem aquest paràmetre request.
    Fixa't que el nom de la funció vista no ens ha de preocupar. Django no es preocupa que està cridant, i no ha de tenir un cert tipus de nom que Django hagi de reconèixer. Aquí l'anomenem datahora_actual, perquè aquest nom, indica clarament el que fa, però podríem haver-la anomenat super_duper_hora_actual, o alguna cosa igual de revolucionaria. Django no s'hi fixa. (Com s'ho fa Django per trobar aquesta funció, llavors? Ja ho veurem quan sigui l'hora)
  • La primera línia de codi dins d'aquesta funció calcula l'hora actual, com un objecte datetime.datetime, i ho emmagatzema en la variable local ara.
  • La segona línia de codi dins de la funció construeix una resposta HTML utilitzant les capacitats de formatejar strings de Python. El %s dins de la cadena, i el signe de percentatge de després de la cadena significa "substitueix el %s amb el valor de la variable ara".
    Una nota per als puristes de l'HTML: Si, sabem que hem obviat un DOCTYPE, un <head>, etc. Però volem ser simples).
  • Finalment, la vista retorna un objecte HttpResponse que conté l'HTML generat. Cada funció vista és responsabilitza de retornar un objecte HttpResponse. (Hi ha excepcions, però ja les veurem més endavant.)

El teu primer URLconf

Recapitulant, aquesta funció vista retornar una pàgina HTML que inclou la data i hora actual. Però on ha de residir aquest codi? com explicar a Django que l'utilitzi?

La resposta a la primera pregunta és: El codi pot ser on vulguis, tant enllà com el teu propi cami Python. No hi ha cap altre requeriment -- cap manera "màgica" de dir-ho. Per aquest motiu, crearem un fitxer anomenat views.py, copieu el codi en aquest fitxer i guardeu-lo en el directori el_meu_lloc que heu creat en el capítol anterior.

El teu camí Python
El camí Python és el llistat de directoris del teu sistema on Python mira quan utilitzes la clàusula import de Python.

Per exemple, diguem que el teu camí Python és ['','/usr/lib/python2.4./site-packages','/home/el_meu_codi']. Si executes el codi Python from foo import bar. Python primer comprova per un mòdul anomenat foo.py en el directori actual. (La primera entrada en el camí de Python, una cadena buida, significa "el directori actual"). Si aquest fitxer no existeix, Python mira pel fitxer /usr/lib/python2.4./site-packages/foo.py. Si aquest tampoc existeix, ho provarà a /home/el_meu_codi/foo.py. Finalment, si tampoc existeix, enviarà un ImportError.

Si estàs interessat per veure el valor del teu camí Python, engega l'intèrpret interactiu de Python i escriu import sys, seguit per print sys.path.

Generalment, no t'hauràs de preocupar de el camí de Python -- Python i Django s'ocupen d'aquestes coses automàticament. (Si ets curiós, configurar el camí Python, és una de les coses que el fitxer manage.py realitza).

Com podria explicar-te la forma en que Django utilitza el codi vista? Aquí és on entra en acció dels URLconfs.

Un URLconf és com una taula de continguts per al teu lloc web fet amb Django, és un mapejat entre els patrons URL i les funcions vista que haurien de cridar-se per aquestes URL. És com li dius a Django "Per aquesta URL, crida aquest codi, i per aquesta URL, crida aquest altre".

Quan executes el django-admin.py startproject del capítol anterior, l'escript crea un URLconf per tu automàticament: el fitxer urls.py. Edita'l. Per defecte, hi ha quelcom semblant a això:

from django.conf.urls.defaults import * 

urlpatterns = patterns('',     
    # Example:     
    # (r'^mysite/', include('mysite.apps.foo.urls.foo')),     

    # Uncomment this for admin: 
#     (r'^admin/', include('django.contrib.admin.urls')), 
) 

Passem per cada línia d'aquest codi:

  • La primera línia importa tots els objectes des del mòdul django.conf.urls.defaults, incloent-hi una funció anomenada patterns.
  • La segona línia crida a la funció patterns() i guarda el resultat dins una variable anomenada urlpatterns. La funció patterns() només se li passa un argument -- una cadena de text buida. La resta de línies estan comentades.

La principal cosa per veure és la variable urlpatterns. Aquesta defineix el mapa entre URLs i el codi que les enllaça.

Per defecte, tot està comentat -- la teva aplicació Django està en blanc. (Amb una nota a part, Django sap que ha de mostrar la pàgina "Funciona!" de l'anterior capítol: Si el teu URLconf és buid, Django assumeix que has començat un nou projecte, i et mostra el missatge).

Edita aquest fitxer per mostra la vista datahora_actual:

from django.conf.urls.defaults import * 
from el_meu_lloc.views import datahora_actual

urlpatterns = patterns('',     
     (r'^ara/', datahora_actual), 
) 

Hem fet dos canvis. Primer, hem importat la vista datahora_actual del mòdul (el_meu_lloc/views.py). Després, afegim la línia (r'^ara/', datahora_actual), . Aquesta línia es refereix a un patróURL -- és una tupla Python en que el primer element és una expressió regular simple i el segon element és la funció vista a utilitzar en aquest patró.

En resum, li hem dit a Django que qualsevol petició a la URL /ara/ ha d'enllaçar amb la funció vista datahora_actual.

Unes quantes coses que cal dir:

  • Fixa't que, en aquest exemple, hem passat la funció vista datahora_actual com un objecte sense cridar la funció. Aquesta és una característica de Python (i d'altres llenguatges dinàmics): Les funcions són objectes de primera classe, que vol dir que pots passar-los com qualsevol altre tipus de variable. Impressionant, oi?
  • No cal afegir un barra a l'inici de l'expressió '^ara/ que encaixi amb /ara/. Django automàticament afegeix la barra abans de cada expressió.
  • El caràcter barret ('^') i el símbol de dolar ('$') són importants. El barret significa "requereix que el patró encaixi amb l'inici de la cadena", i el signe de dolar significa "requereix que el patró encaixi amb el final de la cadena".
    Aquest concepte s'explica millor amb un exemple. Si he utilitzar el patró '^ara/' (sense el símbol dolar al final), llavors qualsevol URL que comenci amb ara/ hi encaixarà -- com /ara/foo i /ara/bar, no només /ara/. De forma semblant, si no posem en caràcter d'inici, Django encaixarà qualsevol lURL que finalitzi amb ara/ -- per exemple, /foo/bar/ara/. Aixi, utilitzarem tant el símbol de barret com el de dolar per assegurar-nos que només hi encaixa la URL /ara/. Ni més i menys.

Per provar els nostres canvis a la URLconf, engega el servidor de desenvolupament de Django, com s'ha fet en el capítol 1, executant la comanda python manage.py runserver. (si ja el tenies en marxa. El servidor automàticament detecta els canvis en el teux codi Python i el recarrega quan cal, no has de re-iniciar el servidor a cada canvi). El servidor s'executa en l'adreça http://127.0.0.1:8000/, així obre el navegador web i ves a la direcció http://127.0.0.1:8000/ara/ -- i podràs veure la sortida de la teva vista de Django.

Visca! Ja has fet la teva primera pàgina web amb Django.

Com Django processa una petició

Hauríem de dir algunes coses sobre el que ha passat. Aquí hi ha una explicació de que passa quan s'executa el servidor de desenvolupament Django i es fan peticions a pàgines web:

  • La comanda python manage.py runserver mira el fitxer anomenat settings.py. Aquest fitxer conté totes les opcions de configuració opcions per una instància de Django, però una de les opcions mes important és l'anomenada ROOT_URLCONF. L'opció ROOT_URLCONF diu a Django quin mòdul Python hauria d'usar-se com la URLconf per aquest lloc web.
    Recorda quan django-admin.py startproject ha creat els fitxers sttings.py i urls.py? Bé, el fitxer auto-generat settings.py té una ROOT_URLCONF que apunta al fitxer autogenerat urls.py. Convenient.
  • Quan una petició comença amb -- diguem una petició a la URL /ara/ -- Django carrega el fitxer URLconf. Llavors comprova cada URLpatterns en l'ordre del fitxer URLconf, comparant la petició URL amb cada patró, fins que en troba un que hi encaixi. Quan en troba un, crida a la funció vista associada amb el patró, passant un objecte HttpRequest com a primer paràmetre a la funció. (Més sobre l'HttpRequest després).
  • La funció vista té la responsabilitat de retornar un objecte HttpResponse.

Amb aquest coneixement, coneixes les bases de com es fan pàgines amb Django. És realment simple -- només escriu les funcions vista i les mapejes a les URL via el fitxer URLconfs.

URLConfs i acoblament dèbil

Ara és un bon moment per explicar una de les claus de la filosofia de les URLconfs, i de Django en general: el principi de l'acoblament dèbil. Per resumir, un acoblament dèbil és una aproximació de desenvolupament de programari que valora la importància de fer peces intercanviables. Si dues de peces de codi estan "dèbilment acoblades", llavors fer canvies a una de les peces tindran un petit o cap efecte sobre les altres.

URLconfs de Django és un bon exemple d'aquest principi posat en pràctica. En un aplicació web Django, les definicions de les URL i les funcions de vista a qui criden estan dèbilment acoblades; això és, la decisió que una URL ha de prendre per una funció donada, i la implementació de la pròpia funció, resideix en dos llocs diferents. Això permet al desenvolupador canviar una peça sense afectar-ne a una altra.

En canvi, altres plataformes de desenvolupament web acoblen la URL al programa. La base del PHP (http://www.php.net/, per exemple, la URL de la teva aplicació és designada per el lloc del codi del teu sistema de fitxers. En el marc-de-treball web CherryPy (http://cherrypy.org/, la URL de la teva aplicació correspón a el nom del mètode on el teu codi resideix. Això podria semblar com una drecera convenient, però pot ser immanejable a llarg temps.

Per exemple, considera la funció vista que hem escrit abans, que mostra la data i l'hora actual. Si canviem la URL de l'aplicació -- diguem, que ho movem de /ara/ a /horaactual/ -- nosaltres només haurem de fer un petit canvi en el URLconf, sense haver de preocupar-nos de la implementació interna de la funció. De forma semblant, si hem fet un canvi a la funció vista -- alternant-ne la seva lògica -- podríem fer que sense que afectés a la URL. Tanmateix, si nosaltres volem mostrar la funcionalitat de la data actual en diverses URL, només haurem de modificar el URLconf sense haver de tocar el codi de la vista.

Això és una acció d'acoblament dèbil. I continuarem mostrant exemples d'aquesta important filosofia en aquest llibre.

Els errors 404

En el nostre URLconf només hem definit una única URLpattern -- la que enllaça amb la petició a la URL /ara/. Que passa quan es demanin diferents URL?

Per trobar-les, intenta executar el servidor de desenvolupament Django i obre la pàgina http://127.0.0.1:8000/hello/ o http://127.0.0.1:8000/no-existeix/ o fin i tot http://127.0.0.1:8000/ (l'arrel del lloc).

Podràs veure el missatge "Page not found" (Pàgina no trobada). (Maco, oi? La la gent de Django els agraden els colors pastel). Django mostra aquest missatge perquè la teva petició d'URL no està definida en el teu URLconf.

La utilitat d'aquesta pàgina va més enllà dels missatges d'error 404. També t'explica precisament quin URLconf utilitzes i cada patró que hi ha. A partir d'aquesta informació, hauries de poder descobrir perquè la petició a la URL envia un error 404.

Naturalment, aquesta informació només t'interessa a tu, el desenvolupador web. Si estàs desenvolupant la web de producció a Internet, no hauríem de mostrar aquesta informació al públic. Per aquesta raó, la pàgina "Page not fount" només es mostra en el teu projecte Django en mode debug. Ja explicarem com desactivar el mode de debug més endavant. Per ara, només cal que sàpigues que cada cop que crees un projecte Django aquest comença en mode debug.

La teva segona vista: URLs dinàmiques

En la teva primera vista d'exemple, els continguts de la pàgina -- la data i hora actual -- eren dinàmiques, però la URL ("/ara/") era estàtica. En la majoria d'aplicacions web dinàmiques, en la URL conté paràmetres que influencien la sortida de la pàgina.

Un altre (lleugerament canviat) exmeple, et permetrà crear una segona vista, que mostri la data i hora actuals desplaçats un cert nombre d'hores. L'objectiu és fer-ho d'una manera més artística de manera que la pàgina /ara/mes1hora/ mostri la data i hora, una hora en el futur, la pàgina /ara/mes2hores/ mostri la data i hora, dues hores en el futur, la pàgina /ara/mes3hores/ mostri la data i hora, tres hores en el futur, i continuant.

Una persona novell pensaria codificar una funció vista per a cada hora desplaçada, resultat que podria veure's en aquest URLconf:

urlpatterns = patterns('', 
    (r'^ara/$', current_datetime),  
    (r'^ara/mes1hora/$', una_hora_endavant), 
    (r'^ara/mes3hores/$', dues_hores_endavant), 
    (r'^ara/mes3hores/$', tres_hores_endavant),  
    (r'^ara/mes4hores/$', quatre_hores_endavant), 
) 

Centament, aquestes línies fan mal als ulls. No només seria un resultat redundant, ja que l'aplicació està limitada a suportar només els rangs d'hores prefixades -- una, dues, tres o quatre hores. Si, de cop i volta, nosaltres volem crear una pàgina que mostri el temps de cinc hores en el futur, haurem de crear una altra vista separada i una línia al URLconf, fomentem la duplicació i la no és sa. Necessitem fer una mica d'abstracció.

Unes paraules sobre les URLs maques

Si has experimentat amb altres plataformes de desenvolupament web, com PHP o Java, pots estar pensant: "Ei, utilitzen paràmetres en la URL!". Que que són quelcom així /ara/mes?hores=3, on les hores han d'assignar-se en el paràmetre hores en la cadena de la URL (la part després de ?).

Pots fer això amb Django -- i t'ho explicarem més tard, si realment vols saber-ho -- però una de les filosofies del cor de Django és que les URLs ha de ser precioses. La URL /ara/mes3hores/ és més neta, simple, més llegible, facil de recitar per qualsevol persona i ... són molt més maques les url planes que els basades en paràmetres. Els URLS maques són un signe de qualitat en una aplicació Web.

El sistema de URLconf de Django encoratja a fer URLs maques fent que sigui més senzill fer-ho així que no fer-ho.

Els comodins dels patrons URL

Continuant amb l'exemple de hores_endavant, posarem comodins en els patrons URL. Com hem dit abans, els patrons URL són una expressió regular, i, per tant, podem utilitzar els patrons de les expressions regulars \d+ per encaixar amb dos o més dígits:

from django.conf.urls.defaults import * 
from mysite.views import current_datetime, hours_ahead 

urlpatterns = patterns('',  
    (r'^ara/$', datahora_actual), 
    (r'^ara/mes\d+hores/$', hores_endavant), 
) 

Aquest patró URL encaixa amb qualsevol URL com /ara/mes2hores/, /ara/mes25hores/ o fins i tot /ara/mes100000000000hores/. Pensa, si vols que el límit siguin 99 hores. Això vol dir que nosaltres no hem de permetre més de 2 dígits; en la sintaxi d'expressió regular, això és trasllada en \d{1,2}:

(r'^ara/mes\d{1,2}hores/$', hores_endavant), 

(Quan construïm aplicacions web, és important considerar el màxim de dades d'entrada possible, i decidir si l'aplicació ha de suportar aquestes entrades o no. Nosaltres hem limitat el nombre d'hores a 99.

Expressions regulars

Les expressions regulars (o "regexes") són una forma compacta d'especificar patrons de text. Encara que el URLconfs de Django permete gualsevol regexe, probablement només n'utilitzaràs uns quants en la pràctica. Aquí hi ha una selecció dels patrons més comuns:

Simbol Equivalència
.(punt) Qualsevol caràcter
\d Qualsevol dígit
[A-Z] Qualsevol caràcter entre A-Z (majúscules)
[a-z] Qualsevol caràcter entre a-z (minúscules)
[A-Za-z] Qualsevol caràcter entre a-z (majúscules/minúscules)
[^/]+ Qualsevol caràcter fins a la barra (excloent-la)
+ Un o més dels caràcters prèvis (\d+ equival a un o més dígits)
? Zero o un dels caràcters prèvis (\d? equival a zero o un dígits)
* Zero o més dels caràcters prèvis (\d* equival a zero o més dígits)
{1,3} Entre un i tres (nclosos) dels caràcters prèvis

Per saber-ne més sobre les expressions regulars, mira l'Apendix XXX, Expressions Regulars.

Ara que ja hem fet un resum sobre les URL, necessitem un forma de passar aquestes dades a la funció vista, per a que poguem utilitzar una única funció vista per a qualsevol marge d'hores arbitrari. Això ho farem situant parèntesis entre les dades en el patró URL que hem guardat. En el cas del nostre exemple, volem guardar el nombre entrat dins la URL -- així que posarem els parèntesi al voltant de \d{1,2}:

(r'^ara/mes(\d{1,2})hores/$', hores_endavant), 

Si estàs familiaritzat amb les expressions regulars, estaràs com a casa; estem utilitzant parèntesis per capturar les dades que hi equivalen.

Al final del URLconf, hi inclourem la nostra vista datahora_actual, i queda més o menys així:

from django.conf.urls.defaults import * 
from el_meu_lloc.views import datahora_actual, hores_endavant 

urlpatterns = patterns('',
    (r'^ara/$', datahora_actual), 
    (r'^ara/mes(\d{1,2})hores/$', hores_endavant), 
)

Amb això, ara hem d'escriure la vista.

Ordre de codificació
En aquest cas, hem escrit primer el patró URL i després la vista, però en l'exemple anterior, ho hem escrit al revés. Quin tècnica és la millor?

Bé, cadascú és diferents.
Si, és un tipus de persona visionaria, potser t'interessa escriure tots els patrons URL de la teva aplicació, al començament del projecte, i després codificar les vistes. Això, té l'avantatge que et dona una llista PER FER clara, i essencialment et defineix el paràmetres requerits per les funcions vista que et caldrà escriure.
Si, ets més aviat, un programador de petites coses, potser prefereixes escriure primer les vistes, i després ancorar-les a les URL. També és correcte.
En definitiva, acostuma al que et vagi millor a la teva manera de pensar. Qualsevol aproximació és vàlida.

La vista hores_endavant és molt semblant a datahora_actual que hem escrit abans, amb una diferència: aquesta pren un argument extra, el nombre d'hores de diferència. Així:

from django.http import HttpResponse 
import datetime 

def hores_endavant(request, offset):
     offset = int(offset)
     dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
     html = "D'aquí %s hores, seran les %s." % (offset, dt)
     return HttpResponse(html) 

Passem per cada línia del codi:

  • Igual que en la vista datahora_actual importem la classe django.http.HttpResponse i el mòdul datahora.
  • La funció vista, hores_endavant, pren dos paràmetres: request i offset.
    • request és un objecte HttpRequest, igual que a datahora_endavant. Ho direm una altra vegada: Cada vista sempre agafa com a primer paràmetre l'objecte HttpRequest.
    • offset és una cadena de text capturada pels parèntesi en el patró URL. Per exemple, si la petició URL fos /ara/mes3hores/, llavors offset seria una cadena '3'. Si la petició fos /ara/mes21hores/, llavors offset seria una cadena de text '21'. Fixa't que la captura de cadenes sempre són cadenes, no enters, encara que només estigui format per dígits, com el '21'.
      Hem decidit anomenar la variables offset, però la pots anomenar que més t'agradi, tal llarg com qualsevol identificador vàlid. El nom de la variable no ens ha de preocupar; tot el que t'ha de preocupar és que sigui el segon argument de la funció (després de request).
  • El primer que fem dins de la funció, és cridar int() sobre offset. Això converteix la cadena de text en un enter.
    Fixeu-vos que Python envia una excepció ValueError si crides a int() amb un valor que no pot convertir-se en enter, com una cadena 'foo'. Tanmateix, no hem de preocupar-nos de capturar l'excepció, perquè podem estar segurs que offset serà un dígit que contindrà només dígits. Ho sabem perquè el patró de la expressió regular captura només dígits. Això il·lustra una altra bona característica de les URLconfs: Proporcions un cert nivell de validació d'entrada.
  • La següent línia de la funció mostra perquè em cridat la funció int(). En aquesta línia, calculem l'hora actual més una temps més de offset hores, guardant el resultat a dt. La funció datetime.timedelta requereix que el paràmetre hours sigui un enter.
  • Després, construïm la sortida HTML d'aquesta funció vista, tal com ho hem fet a datahora_actual. Una petita diferència en aquesta línia respecte l'anterior és que utilitza la capacitat de formatar cadenes amb Python amb dos valors, no només un. Veiem, que hi ha dos símbols %s en la cadena de text i una tupla de valors a insterar -- (offset, dt).
  • Finalment, retornem una HttpResponse del HTML -- igual que en la funció datahora_actual.

Amb aquesta funció vista i URLconf escrita, engeguem el servidor de desenvolupament Django (si no està en marxa), i visita http://127.0.0.1:8000/ara/mes3hores/ per verificar la feina. Després prova http://127.0.0.1:8000/ara/mes5hores/. Després http://127.0.0.1:8000/ara/mes24hores/. Finalment, visita http://127.0.0.1:8000/ara/mes100hores/ per verificar que el patró només accepta número d'un o dos dígits. Django hauria de mostrar un error "Pagina no trobada", igual que els que hem vist "4040 errors" en la secció anterior. La URL http://127.0.0.1:8000/ara/meshores/ (sense especificar hora) també hauria de retornar un error 404.

Si has seguit tot el que hem codificat, ara el teu fitxer views.py ara conté dues vistes. (Hem omès la vista datahora_actual dels exemples per claredat). Tot junt, seria això:

from django.http import HttpResponse 
import datetime 

def current_datetime(request):
     now = datetime.datetime.now()
     html = "It is now %s." % now
     return HttpResponse(html) 


def hores_endavant(request, offset):
     offset = int(offset)
     dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
     html = "D'aquí %s hores, seran les %s." % (offset, dt)
     return HttpResponse(html) 

Les pàgines d'error maques de Django

Atura't un moment per admirar l'aplicació que hem fet... i prou!

Ara introdueix deliberadament un error Python en el fitxer views.py, comentant la línia offset = int(offset) de la vista hores_endavant:

def hores_endavant(request, offset):
     # offset = int(offset)
     dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
     html = "D'aquí %s hores, seran les %s." % (offset, dt)
     return HttpResponse(html) 

Ara re-iniciem el servidor de desenvolupament i carreguem l'adreça /ara/mes3hores/. Hi veuràs una pàgina d'error amb un munt d'informació molt significativa, incloent-hi el missatge TypeError mostrat a dalt de tot: "unsupported type for timedelta hours component: str".

Que ha passat?

Bé, la funció datetime.timedelta esperava que el paràmetre hours fos un enter, i comentat la línia, no l'hem convertit a enter. Això ha causat que datetime.timedelta aixequés un error TypeError. És el típic tipus d'error petit que tot programació fa algun cop.

Aquest exemple mostra les pàgines d'error de Django. Preneu-vos una mica de temps per explorar la pàgina d'error i coneixeu la diversa informació que et mostra.

Algunes coses a destacar:

  • A dalt de tot, tens la informació de l'excepció: el tipus, qualsevol paràmetre (p.e: el missatge unsupported type en aquest cas), el fitxer on s'ha aixecat l'excepció i la línia i els seu número.
  • Sota això, la pàgina mostra la traça complerta de Python sobre aquesta excepció. Això és semblant a la traça que ens mostra l'intèrpret de comandes de Python, excepte que aquest és més interactiu. Per a cada marc en la pila, Django mostra el nom del fitxer, el nom del mètode, el número de línia i el codi font de la línia.
    Si fas clic en el codi de la línia (en gris fosc), i veuràs les línies anteriors a la línia d'error, per veure el context.
    Fes clic a "local vars" sota qualsevol marc en la vista per veure una taula de totes les variables locals, i els seus valors, en aquests marc, en el moment exacte en que la excepció s'ha aixecat. Aquesta informació de depuració és in-valorable.
  • Fixeu-vos el text "Switch to copy-and-paste view" que hi ha just sota la capçalera de la traça "Traceback". Fes clic en aquelles paraules, i la traça canviar+a a una versió que serà fàcil de copiar i enganxar. Fes-ho quan vulguis compartir la traça de l'excepció per obtenir suport -- així com per parlar amb usuaris de Django en el xat IRC o en les llistes de correu.
  • Després, la secció "Request information" inclou informació sobre la petició Web d'entrada que a causat l'error: la informació GET i POST, els valors de les galetes i meta informació com les capçaleres CGI. Si aquesta informació t'ha sembla un guiri-gall, no et preocupes -- ho tornarem a explica més tard.
    A sota, la secció "Settings" llista la configuració d'aquesta instal·lació en particular de Django. Una altra vegada, ho explicarem més tar en aquest llibre. Per ara, fes una mirada a la configuració per fer-te una idea de la informació disponible.

Exercicis

No ho hem traduït: