bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


django

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 [2023/06/29 15:29]
enric_mieza_sanchez [Configurar Nginx per a servir arxius estàtics]
django [2024/06/27 13:47] (actual)
enric_mieza_sanchez [Versions]
Línia 13: Línia 13:
  
 Referències: Referències:
 +  * [[django_pres|Presentació de diapositives Django]] en aquesta wiki.
   * Web oficial: https://www.djangoproject.com   * Web oficial: https://www.djangoproject.com
   * El magnífic [[https://docs.djangoproject.com/en/stable/intro/tutorial01/|tutorial de la web oficial]].   * El magnífic [[https://docs.djangoproject.com/en/stable/intro/tutorial01/|tutorial de la web oficial]].
 +  * [[django_lliga|Exemple app Django per gestió d'una lliga de futbol]] en aquesta wiki, molt recomanat fer-ho després d'haver completat el Django Tutorial oficial.
   * Un altre bon [[https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django|tutorial de MDN Mozilla Web Docs]].   * Un altre bon [[https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django|tutorial de MDN Mozilla Web Docs]].
  
Línia 48: Línia 50:
 A l'article [[Python venv]] teniu detalls a fons de com utilitzar aquestes eines. A l'article [[Python venv]] teniu detalls a fons de com utilitzar aquestes eines.
  
-Resumidament, necessitem crear l'entorn virtual, entrar-hi i instal·lar Django:+Resumidament, necessitem crear l'entorn virtual, entrar-hi i instal·lar Django en una versió LTS (x.2): 
 + 
 +<tabbox Versió GNU/Linux>
   $ python3 -m venv env   $ python3 -m venv env
   $ source env/bin/activate   $ source env/bin/activate
-  (env) $ pip install django+  (env) $ pip install django==4.2 
 +<tabbox Versió Windows> 
 +  > python3 -m venv env 
 +  > env\Scripts\Activate.bat 
 +  (env) > pip install django==4.2 
 +</tabbox> 
 + 
 +<WRAP tip> 
 +Si bé el més habitual és tenir el ''virtualenv'' dins la carpeta del projecte, en aquest cas l'hem de tenir a fora forçosament, ja que encara no hem creat l'esquelet. 
 +</WRAP>
  
 \\ \\
Línia 70: Línia 83:
  
 Visita el //admin panel// a ''http://localhost:8000/admin/'' Visita el //admin panel// a ''http://localhost:8000/admin/''
 +
 +Per seguir amb la creació de models, caldrà crear al menys una aplicació dins del projecte Django:
 +  (env) $ ./manage.py startapp myapp
 +
 +Donar d'alta la nova app afegint aquestes línies als arxius:
 +<file pyhton settings.py>
 +# ...
 +INSTALLED_APPS = [
 +    "myapp.apps.MyappConfig",
 +# ...
 +</file>
 +
 +I activar els models a l'admin panel a:
 +<file python admin.py>
 +from django.contrib import admin
 +from .models import *
 +
 +admin.site.register(MyModel1)
 +admin.site.register(MyModel2)
 +# ...
 +</file>
 +
 +Cada cop que modifiquem el model de dades del projecte caldrà afegir:
 +  (env) $ ./manage.py makemigrations
 +  (env) $ ./manage.py migrate
 +
 +\\
 +
 +===== ORM, models i migracions =====
 +**Un //Object-Relational Mapper// és una eina que facilita l'accés a dades mapejant les taules i relacions en objectes (classes) del llenguatge de programació**. Això permet una abstracció de la base de dades concreta que s'està emprant i no haver d'utilitzar SQL, sinó crides a mètodes dels objectes instanciats.
 +
 +Un **model**, en el context d'un ORM, **és una //class// que està mapejada a una taula de la base de dades**. Així, per exemple, es pot crear la següent //class// a l'arxiu ''models.py'' de Django:
 +
 +<code python>
 +from django.db import models
 +
 +class Llibre (models.Model):
 +    titol = models.CharField(max_length=100)
 +    autor = models.CharField(max_length=200)
 +    resum = models.TextField(null=True,blank=True)
 +    data_edicio = models.DateField()
 +</code>
 +
 +Per crear un llibre i guardar-lo a la taula, enlloc d'emprar SQL, amb el ORM faríem:
 +<code python>
 +llibre = Llibre()
 +llibre.titol = "El mag del Kremlin"
 +llibre.autor = "Giuliano da Empoli"
 +import datetime
 +llibre.data_edicio = datetime.datetime(2023, 3, 29)
 +# per persistir l'objecte a la BD cal cridar el mètode save()
 +llibre.save()
 +</code>
 +
 +En el context dels //frameworks// de desenvolupament, **una eina de migració gestiona les versions i evolució dels esquemes de les bases de dades**.
 +
 +Durant el desenvolupament convé planificar amb anterioritat l'esquema de la base de dades per tal que pateixi el mínim de modificacions. Cada cop que es modifica la base de dades hi ha un gran risc de que parts del codi deixin de funcionar o de que perdem dades en el canvi (migració) d'una versió de l'esquema a la següent. Malgrat tot, preveure totes les situacions es fa impossible i aplicar canvis a l'esquema de la base de dades es fa imprescindible, per molt que es vulgui minimitzar. L'ús d'eines de migració milloren aquesta gestió i permeten una transició ordenada i, sobretot, automatitzada, d'un esquema al següent.
 +
 +{{:django:migracions.png?600}}
 +
 +El mecanisme és simple: cal un arxiu de migració que realitzi els canvis a la BD a cada evolució. Cada migració pot implicar un canvi simple com afegir o esborrar una columna fins a grans canvis com afegir multitud de taules i relacions.
 +
 +Tenim dos exemples complementaris i paradigmàtics en la gestió de les migracions: els dels //frameworks// Django i Laravel:
 +  * En **Laravel** el desenvolupador ha d'escriure un script de migració per aplicar els canvis explícits a la base de dades, com eliminar una columna o crear noves taules i relacions.
 +  * En **Django** el desenvolupador modifica directament el model amb l'ORM. Amb la instrucció ''makemigrations'' l'arxiu de migració es genera automàticament. El //framework// analitza el codi del model actual i l'anterior, i genera les ordres adequades dins un script de migració.
 +
 +En el projecte que estavem desenvolupant, podem crear models i després realitzar les migracions executant:
 +  (env1) $ ./manage.py makemigrations
 +  (env1) $ ./manage.py migrate
 +
 +Veurem que ara **apareix un arxiu ''db.sqlite3'' a l'arrel del projecte** on s'hauran creat algunes taules, en particular ''users'' i ''groups'', que son objectes //builtin// de Django (venen predefinits tot i que es poden modificar). SQLite és un SGBD senzill per BD locals en un sol arxiu amb propòsits de desenvolupament (no és apta per a desplegament).
 +
 +Per visualitzar les taules podem crear un superusuari i entrar a l'//admin panel//:
 +  (env1) $ ./manage.py createsuperuser
 +  (env1) $ ./manage.py runserver
 +
 +Entrem a http://localhost:8000/admin/ amb l'usuari i contrasenya creats i podrem veure, crear i modificar usuaris i grups i les diferents característiques d'aquests.
 +
 +{{:django:django-admin-panel-1.png?500}}
  
 \\ \\
Línia 94: Línia 186:
   * Les carpetes de [[virtualenv]]. El ''virtualenv'' es crearà de nou cada cop que clonem un repositori.   * Les carpetes de [[virtualenv]]. El ''virtualenv'' es crearà de nou cada cop que clonem un repositori.
  
-Una versió mínima dels arxius i carpetes que NO volem que es puguin al repo seria aquest:+Una versió mínima dels arxius i carpetes que NO volem que es pugin al repo seria aquest:
  
 <file .gitignore .gitignore> <file .gitignore .gitignore>
Línia 116: Línia 208:
  
 Aquí hauries de enllaçar el teu repositori local amb el remot (per ex. de Github): Aquí hauries de enllaçar el teu repositori local amb el remot (per ex. de Github):
-  (env) $ git remote add ... +  (env) $ git remote add origin https://github.com/... 
-  (env) $ git push+  (env) $ git push -u origin main
  
 \\ \\
Línia 155: Línia 247:
  
 En algun cas es poden trobar problemes per fer funcionar un projecte, si el sistema operatiu és diferent. En aquests casos potser és millor simplificar el ''requirements.txt'' posant els //packages// imprescindibles i deixar que el propi gestor ''pip'' trobi les dependències. En aquest cas no ho faríem amb el ''pip freeze'', sinó que crearíem el fitxe a mà: En algun cas es poden trobar problemes per fer funcionar un projecte, si el sistema operatiu és diferent. En aquests casos potser és millor simplificar el ''requirements.txt'' posant els //packages// imprescindibles i deixar que el propi gestor ''pip'' trobi les dependències. En aquest cas no ho faríem amb el ''pip freeze'', sinó que crearíem el fitxe a mà:
-  django==3.2+  django==4.2
   django-environ   django-environ
   mysqlclient   mysqlclient
Línia 161: Línia 253:
 Hem de tenir en compte el cicle de vida de les versions de Django que fem servir. Les versions LTS són les //Long Term Service// que ens donaran cobertura durant més temps. Podem veure la [[https://www.djangoproject.com/download/#supported-versions|política de versions a la web de descàrrega de Django]]: Hem de tenir en compte el cicle de vida de les versions de Django que fem servir. Les versions LTS són les //Long Term Service// que ens donaran cobertura durant més temps. Podem veure la [[https://www.djangoproject.com/download/#supported-versions|política de versions a la web de descàrrega de Django]]:
  
-{{django-release-roadmap.png}}+{{https://static.djangoproject.com/img/release-roadmap.4cf783b31fbe.png}}
  
-Ara utilitzarem la 3.2 (LTS) però caldrà tenir cura d'actualitzar a la següent LTS (4.2) abans de que el suport de l'actual 3.2 finalitzi, com a màxim durant el primer trimestre de 2023.+A data de juny de 2024 utilitzarem la 4.2 (LTS) però caldrà tenir cura d'actualitzar a la següent LTS (5.2) abans de que el suport de l'actual finalitzi.
  
 \\ \\
Línia 201: Línia 293:
   * Afegir ''.env'' al ''.gitignore'' per tal de no pujar per error l'arxiu de variables d'entorn a producció.   * Afegir ''.env'' al ''.gitignore'' per tal de no pujar per error l'arxiu de variables d'entorn a producció.
   * Crear un arxiu d'exemple amb les variables d'entorn necessàries per facilitar la posada en marxa, però enlloc d'anomenar-lo ''.env'', que es diugui ''.env.example''    * Crear un arxiu d'exemple amb les variables d'entorn necessàries per facilitar la posada en marxa, però enlloc d'anomenar-lo ''.env'', que es diugui ''.env.example'' 
 +</WRAP>
 +
 +<WRAP tip>
 +Per fer una llista com ''ALLOWED_HOSTS'' dins el ''.env'' podem seguir [[https://stackoverflow.com/questions/60410625/get-django-allowed-hosts-env-variable-formated-right-in-settings-py|aquest fil amb possibles solucions]]. Potser la més elegant és fer-ho com a list:
 +<file python settings.py>
 +ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
 +</file>
 +
 +<file env .env>
 +ALLOWED_HOSTS=localhost,127.0.0.1,mysite.com
 +</file>
 </WRAP> </WRAP>
  
Línia 209: Línia 312:
  
 Per utilitzar MySQL caldrà instal·lar els binaris necessaris al sistema operatiu. Per a Ubuntu: Per utilitzar MySQL caldrà instal·lar els binaris necessaris al sistema operatiu. Per a Ubuntu:
-  $ sudo apt install libmysqlclient-dev gcc python3-dev python3-mysqldb+  $ sudo apt install libmysqlclient-dev python3-dev python3-mysqldb gcc pkgconf
  
 I també els connectors del virtualenv de Python: I també els connectors del virtualenv de Python:
Línia 284: Línia 387:
 Django no ha de servir mai arxius estàtics, ja que és menys eficient que el Web Server, que està pensat per a això específicament. El següent diagrama mostra com es durà a terme la posada en producció final: Django no ha de servir mai arxius estàtics, ja que és menys eficient que el Web Server, que està pensat per a això específicament. El següent diagrama mostra com es durà a terme la posada en producció final:
  
-{{diagrama_django_produccio.png?direct}}+{{:django:diagrama_django_produccio.png?direct}}
  
 <WRAP todo> <WRAP todo>
Línia 296: Línia 399:
 Comprova que accedint al panell d'administració ''/admin'' es visualitzen els CSS correctament. Comprova que accedint al panell d'administració ''/admin'' es visualitzen els CSS correctament.
  
-Troubleshooting (possibles errades): +**Troubleshooting (possibles errades):** 
-  * Revisa la configuració de ''mysite.conf'' de Nginx. +  * Revisa que has parat (stop) i inhabilitat Apache (possible col·lisió de ports). 
-  * Revisa l'arxiu ''/etc/polls''+  * Revisa la configuració de ''mysite.conf'' de Nginx. Millor que deixis només activada el //mysite// i desactivis la //default// (links simbòlics)
 +  * Revisa els errors de Nginx amb ''sudo journalctl -xeu nginx.service'' 
 +  * Si no veus el CSS fes CTRL+u , mira el codi font i clica un arxiu CSS aviam quin error et dona. 
 +  * Comprova que has afegit ''STATIC_ROOT = BASE_DIR 'static/''' al ''settings.css'' 
 +  * Comprova que has executat ''./manage.py collectstatic'' i que no dona errors. 
 +  * Si tens un ''Internal Server Error'' probablement hagis fet malament la comanda ''uwsgi'' (hauràs posat mysite.wsgi quan en realitat la teva carpeta es diu diferent de mysite).
  
 <WRAP important> <WRAP important>
Línia 305: Línia 413:
  
 </WRAP> </WRAP>
 +
 +
 +==== Engegant Django app amb Supervisor ====
  
 <WRAP todo> <WRAP todo>
django.1688052554.txt.gz · Darrera modificació: 2023/06/29 15:29 per enric_mieza_sanchez