bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


django_lliga

Diferències

Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.

Enllaç a la visualització de la comparació

Ambdós costats versió prèvia Revisió prèvia
Següent revisió
Revisió prèvia
django_lliga [2023/04/13 16:24]
enric_mieza_sanchez [Formularis]
django_lliga [2025/05/29 10:14] (actual)
enric_mieza_sanchez [Seeder per creació de dades d'exemple]
Línia 13: Línia 13:
   - Una taula de classificació per cada lliga, que compti els punts dels partits celebrats, gols a favor i en contra de cada equip.   - Una taula de classificació per cada lliga, que compti els punts dels partits celebrats, gols a favor i en contra de cada equip.
   - Una taula de "pichichis" amb el rànking de golejadors de cada lliga.   - Una taula de "pichichis" amb el rànking de golejadors de cada lliga.
 +
 +{{ futbol-chilena.png?300 }}
  
 Referències: Referències:
Línia 19: Línia 21:
   * [[Django Frontend]] ídem.   * [[Django Frontend]] ídem.
  
-{{tag> #Daw #DawMp07 #DawMp07Uf2 django framework web }}+{{tag> #Daw #DawMp07 #DawMp07Uf2 #DawMp07Uf02 django framework web }}
  
 \\ \\
 +
 +<WRAP tip>
 +Podeu veure una mostra d'aquest projecte en producció a https://lliga.up.railway.app/
 +</WRAP>
  
 ===== Crear projecte ===== ===== Crear projecte =====
Línia 35: Línia 41:
   * Partit   * Partit
  
-És fàcil tenir la temptació de posar els resultats dins de l'objecte Partit+<WRAP todo> 
 +Creeu els models esmentats: Lliga, Equip, Jugador, Partit. 
 + 
 +Podeu mirar el //quickstart// de l'article [[Django]] per iniciar el projecte i registrar els models a l'//admin panel//. 
 +</WRAP> 
 + 
 +És fàcil tenir la temptació de posar els resultats dins de l'objecte Partit, però si volem un model més sofisticat seguiu llegint... 
 + 
 +==== Millorant el model ====
  
 Els resultats dels partits, si volem que tingui possibilitat de fer rànkings de "pichichi", no podem posar els resultats en el partit. Caldrà que tinguem un model on hi hagi ''Events'' (que podran ser de tipus gol, targeta groga, targeta vermella, falta, etc.) que estaran associats a un partit. Els resultats dels partits, si volem que tingui possibilitat de fer rànkings de "pichichi", no podem posar els resultats en el partit. Caldrà que tinguem un model on hi hagi ''Events'' (que podran ser de tipus gol, targeta groga, targeta vermella, falta, etc.) que estaran associats a un partit.
Línia 186: Línia 200:
 Els //seeder// són programes que permeten la creació de dades falses per facilitar el test de l'aplicació. Els //seeder// són programes que permeten la creació de dades falses per facilitar el test de l'aplicació.
  
-En particular [[https://faker.readthedocs.io/en/master/|per Python disposem de la llibreria Faker]] que ens facilitarà molt aquesta tasca.+En particular [[https://faker.readthedocs.io/en/master/|per Python disposem de la llibreria Faker]] que ens facilitarà molt aquesta tasca. Instal·leu-la amb: 
 +  (env) $ pip install faker
  
-Podem crear el //seeder// dins una [[https://docs.djangoproject.com/en/stable/howto/custom-management-commands/|comanda personalitzada de Django]] que podrem cridar amb el ''admin.py'' tipus: +Podem crear el //seeder// dins una [[https://docs.djangoproject.com/en/stable/howto/custom-management-commands/|comanda personalitzada de Django]] que podrem cridar amb el ''manage.py'' tipus: 
-  $ ./admin.py crea_lliga "Lliga fake 2"+  $ ./manage.py crea_lliga "Lliga fake 2"
  
 L'argument "Lliga fake 2" serà el nom de la lliga que cal crear. La resta de dades les inventarem amb l'ajuda de Faker. L'argument "Lliga fake 2" serà el nom de la lliga que cal crear. La resta de dades les inventarem amb l'ajuda de Faker.
Línia 195: Línia 210:
 --> Proposta seeder crea_lliga# --> Proposta seeder crea_lliga#
  
-<file python management/commands/crea_lliga.py>+Creeu les carpetes ''futbol/management/commands'': 
 +  $ mkdir -p futbol/management/commands 
 + 
 +**On <futbol> és la carpeta de l'aplicació dins del projecte Django**. 
 + 
 +Afegiu-hi el següent arxiu: 
 + 
 +<file python lliga/management/commands/crea_lliga.py>
 from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
 from django.utils import timezone from django.utils import timezone
Línia 201: Línia 223:
 from datetime import timedelta from datetime import timedelta
 from random import randint from random import randint
 + 
 from lliga.models import * from lliga.models import *
 + 
 faker = Faker(["es_CA","es_ES"]) faker = Faker(["es_CA","es_ES"])
 + 
 class Command(BaseCommand): class Command(BaseCommand):
     help = 'Crea una lliga amb equips i jugadors'     help = 'Crea una lliga amb equips i jugadors'
 + 
     def add_arguments(self, parser):     def add_arguments(self, parser):
         parser.add_argument('titol_lliga', nargs=1, type=str)         parser.add_argument('titol_lliga', nargs=1, type=str)
 + 
     def handle(self, *args, **options):     def handle(self, *args, **options):
         titol_lliga = options['titol_lliga'][0]         titol_lliga = options['titol_lliga'][0]
-        lliga = Lliga.objects.filter(titol=titol_lliga)+        lliga = Lliga.objects.filter(nom=titol_lliga)
         if lliga.count()>0:         if lliga.count()>0:
             print("Aquesta lliga ja està creada. Posa un altre nom.")             print("Aquesta lliga ja està creada. Posa un altre nom.")
             return             return
 + 
         print("Creem la nova lliga: {}".format(titol_lliga))         print("Creem la nova lliga: {}".format(titol_lliga))
-        lliga = Lliga(  titol=titol_lliga, +        lliga = Lliga( nom=titol_lliga, temporada="temporada" )
-                        inici=timezone.now(), +
-                        final=timezone.now()+timedelta(days=11*30))+
         lliga.save()         lliga.save()
 + 
         print("Creem equips")         print("Creem equips")
         prefixos = ["RCD", "Athletic", "", "Deportivo", "Unión Deportiva"]         prefixos = ["RCD", "Athletic", "", "Deportivo", "Unión Deportiva"]
Línia 233: Línia 253:
                 prefix += " "                 prefix += " "
             nom =  prefix + ciutat             nom =  prefix + ciutat
-            equip = Equip(ciutat=ciutat,nom=nom)+            equip = Equip(ciutat=ciutat,nom=nom,lliga=lliga)
             #print(equip)             #print(equip)
             equip.save()             equip.save()
             lliga.equips.add(equip)             lliga.equips.add(equip)
 + 
             print("Creem jugadors de l'equip "+nom)             print("Creem jugadors de l'equip "+nom)
             for j in range(25):             for j in range(25):
-                nom = faker.first_name() +                nom = faker.name() 
-                cognom1 faker.last_name() +                posicio "jugador" 
-                cognom2 faker.last_name() +                edat 25 
-                jugador = Jugador(nom=nom,cognom1=cognom1,cognom2=cognom2,alias=nom+" "+cognom1)+                jugador = Jugador(nom=nom,posicio=posicio, 
 +                    edat=edat,equip=equip)
                 #print(jugador)                 #print(jugador)
                 jugador.save()                 jugador.save()
-                fitxa = Fitxa(jugador=jugador,equip=equip,inici=timezone.now(),dorsal=i+1) + 
-                fitxa.save() +
         print("Creem partits de la lliga")         print("Creem partits de la lliga")
         for local in lliga.equips.all():         for local in lliga.equips.all():
Línia 338: Línia 357:
 </file> </file>
 <-- <--
 +
 +<WRAP todo>
 +**View classificació**
 +
 +Crea la view de classificació i afegeix els següents camps:
 +  * Punts
 +  * Victòries
 +  * Empats
 +  * Derrotes
 +  * Gols a favor
 +  * Gols en contra
 +  * Gol average
 +
 +Afegiu també el nom de la lliga.
 +</WRAP>
  
 \\ \\
Línia 402: Línia 436:
 ===== Formularis ===== ===== Formularis =====
  
-Referències sobre formularis+<WRAP info> 
-  * [[https://docs.djangoproject.com/en/stable/topics/forms/|Forms]] +Podeu llegir referències sobre els potents formularis de Django a [[django_frontend#formularis|Django Formularis]]. 
-  * [[https://docs.djangoproject.com/en/stable/topics/forms/modelforms/|ModelForms]] +</WRAP>
-  * [[https://docs.djangoproject.com/en/stable/ref/models/fields/|Fields]] : camps del Form +
-  * [[https://docs.djangoproject.com/en/stable/ref/forms/fields/#fields-which-handle-relationships|Camps amb FKs]] +
-  * [[https://docs.djangoproject.com/en/stable/topics/class-based-views/generic-display/|Generic Views]]+
  
-Altres: +==== Menu form ====
-  * https://docs.djangoproject.com/en/stable/topics/http/shortcuts/+
  
-Un formulari sempre implica diverses passes: +Anem a fer un menú que ens permeti triar la lliga entre les lligues que tenim a la BD. Per tantes tracta d'un camp depenent de les dades i no pot ser //hardcoded//.
-  - Crear el formulari (pot ser senzill o més complexi necessitarà codi). +
-  - Processar les dades del formulari. +
-  - Mostrar un resultat: pot ser senzill (operació OK), o complex (mostrar classificació). Sovint és molt pràctic fer una redirecció cap a una altre //view// i repartir la complexitat en diverses parts del codi.+
  
-Cada pas abans descrit pot necessitar el seu **template** i la seva **view**. A la //view// crearem i filtrarem les dades adequades per passar-les al //template//.+{{ django:menu_lliga.png?400 }}
  
-En Django tenim, al menys, 4 aproximacions per a realitzar formularis: +Ho farem amb l'objecte ''Form'' de Django:
-  - Plantilla //hardcoded// (HTML): dona més feina però és fàcil de modificar amb coneixements bàsics de HTML. +
-  - Utilitzar objecte ''Form'' de Django. Això ens facilita la renderització i el manteniment. +
-  - Utilitzar objectes més sofisticats com ''ModelForm'' que a partir d'un model ens generarà automàticament el formulari. +
-  - Utilitzar [[https://docs.djangoproject.com/en/stable/topics/class-based-views/generic-display/|generic views com DetailView]] : les operacions tipus CRUD es poden fer amb aquests objectes genèrics. +
- +
-El processament del formulari és sempre similar (menys en el cas de les //generic views//). +
- +
-==== Menu form ====+
  
 +--> View i template per formulari de lliga#
 <file python views.py> <file python views.py>
 from django import forms from django import forms
Línia 444: Línia 464:
         if form.is_valid():         if form.is_valid():
             lliga = form.cleaned_data.get("lliga")             lliga = form.cleaned_data.get("lliga")
 +            # cridem a /classificacio/<lliga_id>
             return redirect('classificacio',lliga.id)             return redirect('classificacio',lliga.id)
     return render(request, "menu.html",{     return render(request, "menu.html",{
Línia 450: Línia 471:
 </file> </file>
  
-I la plantilla ens quedaria així de simple:+La plantilla o //template// ens quedaria així de simple:
 <file html menu.html> <file html menu.html>
 <h1>Menu Lligues</h1> <h1>Menu Lligues</h1>
Línia 461: Línia 482:
 </form> </form>
 </file> </file>
 +
 +També necessitarem modificar les URLs per poder accedir adequadament a la classificació i passar-li el ID de la lliga que volem visualitzar:
 +
 +<file python urls.py>
 +urlpatterns = [
 +    path("menu", views.menu, name="menu"),
 +    path("classificacio/<int:lliga_id>", views.classificacio, name="classificacio"),
 +]
 +</file>
 +
 +Finalment modifiquem ''views.py'' per tal que rebem el paràmetre ''lliga_id'' i filtrem la lliga que volem mostrar:
 +
 +<file python views.py>
 +def classificacio(request, lliga_id):
 +    lliga = get_object_or_404( Lliga, pk=lliga_id)
 +    equips = lliga.equip_set.all()
 +    #...
 +</file>
 +
 +<--
 +
 +\\
  
 ===== Exercicis ===== ===== Exercicis =====
 <WRAP todo> <WRAP todo>
 +**Formularis**
 +
 Elabora formularis per: Elabora formularis per:
 +  - Crear jugador (amb ModelForm).
   - Crear lliga.   - Crear lliga.
 +    * Assegura't que si ja hi ha una lliga amb el mateix nom, no ens deixi guardar.
 +    * Pots fer-ho amb Form o amb ModelForm.
   - Crear equip.   - Crear equip.
   - Assignar equips a una lliga (afegir o treure).   - Assignar equips a una lliga (afegir o treure).
 +</WRAP>
 +
 +<WRAP todo>
 +**Workflow**
  
 Elabora el //workflow// per afegir un partit i les seves dades en temps real. Haurem de fer-ho en diversos passos: Elabora el //workflow// per afegir un partit i les seves dades en temps real. Haurem de fer-ho en diversos passos:
Línia 478: Línia 530:
 </code> </code>
   - Protegeix les rutes per tal que només puguin entrar usuaris loguejats.   - Protegeix les rutes per tal que només puguin entrar usuaris loguejats.
 +</WRAP>
 +
 +<WRAP todo>
 +**View avançada**
  
 Elabora una pàgina de visualització d'un partit en temps real. Ens mostrarà el resultat actual i a continuació una llista amb els Events que van sortint en temps real. Caldrà refrescar el resultat un cop cada 5 segons. Pots implementar crides AJAX com es descriu a [[Django API]]. Elabora una pàgina de visualització d'un partit en temps real. Ens mostrarà el resultat actual i a continuació una llista amb els Events que van sortint en temps real. Caldrà refrescar el resultat un cop cada 5 segons. Pots implementar crides AJAX com es descriu a [[Django API]].
 +</WRAP>
 +
 +\\
 +
 +===== Integrant AJAX en Django =====
 +
 +Per poder utilitzar AJAX en Django caldrà disposar d'una API, pots consultar com fer-ho a [[Django API]].
 +
 +Les crides AJAX caldrà implementar-les dins el codi JS, que en el cas de Django ha d'anar dins els arxius estàtics o dins la pròpia plantilla HTML.
 +
 +==== Exercicis ====
 +
 +{{ django:edita_partit_advanced.png?450 }}
 +
 +<WRAP todo>
 +Crea els endpoints per a les APIs (recorda consultar [[Django API]]:
 +  * /api/get_lligues
 +  * /api/get_equips/<lliga_id> : ens filtrarà els equips que participen en aquesta lliga.
 +
 +Crea la pàgina ''edita_partit_advanced'' on hi hagi un formulari per editar un partit amb:
 +  * Selector de lliga
 +  * Selector d'equip local
 +  * Selector d'equip visitant
 +  * Botó "Editar": inicialment estarà ''disabled''
 +
 +Tots els selectors estan buits inicialment. Els omplirem utilitzant les APIs abans creades.
 +
 +El selector de lliga es crearà immediatament al carregar la pàgina. Els selectors d'equips es carregaran de dades quan es seleccioni lliga.
 +
 +Un cop seleccionem la lliga i els equips, pots habilitar el botó "Editar" per tal que iniciem l'entrada de  dades del partit.
 +
 +Fes un control d'errors o de casos:
 +  * S'ha seleccionat el mateix equip local i visitant: error.
 +  * Si el partit ja existeix, no cal crear-ho.
 +  * Si el partit no existeix, es crea.
 +
 +Finalment oferim el link per a editar el partit (afegir Events) en una nova //view//.
  
 </WRAP> </WRAP>
 +
 +\\
 +
 +===== Autenticació =====
 +<WRAP info>
 +Per saber més de com autenticar-nos pots llegir [[Django Auth]]
 +</WRAP>
 +
 +\\
 +
 +===== Exercicis de consultes =====
 +
 +  - Lligues que contenen la paraula "segona".
 +  - Equips que comença el seu nom amb "Athletic".
 +  - Equips que tenen "North" al nom.
 +  - Equips que acaben el seu nom en "chester".
 +  - Equips que tinguin judadors amb el nom XXX
 +  - Jugadors que hagin marcat algun gol.
 +
  
django_lliga.1681403080.txt.gz · Darrera modificació: 2023/04/13 16:24 per enric_mieza_sanchez