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/05/12 14:42]
enric_mieza_sanchez [Exercici lliga de futbol en Django]
django_lliga [2026/03/10 17:08] (actual)
enric_mieza_sanchez [Implementar admin panel]
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 }}
  
 \\ \\
Línia 39: 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 117: Línia 127:
 Vigileu, però, la versió de la documentació que consulteu. Vigileu, però, la versió de la documentació que consulteu.
  
 +<WRAP todo>
 Customitza les interfícies del //admin panel// per tal que puguis: Customitza les interfícies del //admin panel// per tal que puguis:
   * Partits:   * Partits:
Línia 128: Línia 139:
       * només mostri els jugadors dels dos equips del partit.       * només mostri els jugadors dels dos equips del partit.
       * només mostri els dos equips del partit.        * només mostri els dos equips del partit. 
 +</WRAP>
  
 {{ django:partit-event-inline.png }} {{ django:partit-event-inline.png }}
Línia 163: Línia 175:
 </file> </file>
  
-Podem millorar el EventInline restringint els jugadors que només ens mostri els dels equips del partit:+Podem millorar el ''EventInline'' restringint els jugadors que només ens mostri els dels equips del partit:
  
 <file python admin.py> <file python admin.py>
Línia 171: Línia 183:
     ordering = ("temps",)     ordering = ("temps",)
     def formfield_for_foreignkey(self, db_field, request, **kwargs):     def formfield_for_foreignkey(self, db_field, request, **kwargs):
-        # filtrem els jugadors i només deixem els que siguin d'algun dels 2 equips (local o visitant) +        if "object_id" not in request.resolver_match.kwargs: 
-        if db_field.name == "jugador":+            # si no hi ha "object_id" no fem res (sol cridar-se en el "add Partit" 
 +            pass 
 +        elif db_field.name == "jugador": 
 +            Filtrem els jugadors i només deixem els que siguin d'algun dels 2 equips (local o visitant)
             partit_id = request.resolver_match.kwargs['object_id']             partit_id = request.resolver_match.kwargs['object_id']
             partit = Partit.objects.get(id=partit_id)             partit = Partit.objects.get(id=partit_id)
-            jugadors_local [fitxa.jugador.id for fitxa in partit.local.fitxa_set.all()] +            # Obtenim dos querysets amb els jugadors locals i visitants 
-            jugadors_visitant [fitxa.jugador.id for fitxa in partit.visitant.fitxa_set.all()] +            jugadors_locals = partit.local.jugadors.all() 
-            jugadors jugadors_local + jugadors_visitant +            jugadors_visitants = partit.visitant.jugadors.all() 
-            kwargs["queryset"] = Jugador.objects.filter(id__in=jugadors) +            # Fusionem els dos querysets amb | (Union en BD) 
-        return super().formfield_for_foreignkey(db_field, request, **kwargs)            +            kwargs["queryset"] = jugadors_locals | jugadors_visitants 
 +        return super().formfield_for_foreignkey(db_field, request, **kwargs)
 </file> </file>
 +
 +<WRAP todo>
 +Modifica el EventIinline perquè també filtri els equips que es mostren en el desplegable. Només ha de mostrar els dos equips que s'enfronten.
 +</WRAP>
  
 <-- <--
Línia 190: Línia 210:
 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 199: Línia 220:
 --> 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 205: Línia 233:
 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 237: Línia 263:
                 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 342: Línia 367:
 </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 434: Línia 474:
         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 440: Línia 481:
 </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 450: Línia 491:
  <input type="submit" name="submit">  <input type="submit" name="submit">
 </form> </form>
 +</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> </file>
  
Línia 461: Línia 520:
  
 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.     * Assegura't que si ja hi ha una lliga amb el mateix nom, no ens deixi guardar.
Línia 534: Línia 594:
  
 \\ \\
 +
 +===== 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.1683902563.txt.gz · Darrera modificació: 2023/05/12 14:42 per enric_mieza_sanchez