bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


django_api

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_api [2022/02/23 13:05]
enrique_mieza_sanchez [Treballant APIs amb Django REST framework]
django_api [2023/04/14 17:06] (actual)
enric_mieza_sanchez [APIs simples amb JsonResponse]
Línia 1: Línia 1:
 ====== APIs amb Django ====== ====== APIs amb Django ======
-Les API o //Application Programming Interface// ens permeten accedir de forma controlada a les dades d'una aplicació web, típicament a través del format JSON, tot i que inicialment es fes servir XML).+Les API o //Application Programming Interface// ens permeten accedir de forma controlada a les dades d'una aplicació web, típicament a través del format JSON, tot i que inicialment es fes servir XML
 + 
 +Es basen en l'[[https://es.wikipedia.org/wiki/Transferencia_de_Estado_Representacional|arquitectura software REST]]. Aquesta estableix estàndards per a HTTP que faciliten la interoperativitat, en particular: 
 +  * **Mètodes** equivalents al CRUD de BD: **GET, POST, PUT, DELETE** (però poden definir-se més). 
 +  * [[https://restfulapi.net/http-status-codes/|HTTP Status code]]: per definir l'estat de la connexió
  
 Referències teoria i documentació: Referències teoria i documentació:
Línia 7: Línia 11:
   * [[https://cacauet.org/wiki/index.php/Serveis_web_amb_Laravel#Especificacions_d.27una_API|Exemple API vota karaoke]]   * [[https://cacauet.org/wiki/index.php/Serveis_web_amb_Laravel#Especificacions_d.27una_API|Exemple API vota karaoke]]
  
-{{tag> #FpInfor #DawMp07 #DawMp07Uf4 #DawMp07Uf04 django web api framework }}+{{tag> #FpInfor #DawMp07 #DawMp07Uf4 #DawMp07Uf04 django web api framework rest }}
  
 \\ \\
Línia 17: Línia 21:
 Aquestes crides AJAX es poden resoldre amb una simple [[https://docs.djangoproject.com/en/4.0/ref/request-response/#jsonresponse-objects|JsonResponse]]. Aquestes crides AJAX es poden resoldre amb una simple [[https://docs.djangoproject.com/en/4.0/ref/request-response/#jsonresponse-objects|JsonResponse]].
  
-Per exemple, seguint el tutorial de Django "polls", podem implementar una //view// que ens retorni les dades de les ''Question'' en format JSON d'aquesta manera:+Per exemple, seguint el tutorial de Django "polls", podem implementar una //view// que ens retorni les dades de les ''Question'' en format JSON d'aquesta manera. Per distingir de les views HTML farem un arxiu ''api.py'' que sabem que retornarà objectes JSON:
  
-<file python views.py>+<file python api.py>
 from django.http import JsonResponse from django.http import JsonResponse
 from polls.models import * from polls.models import *
Línia 26: Línia 30:
  
 def get_questions(request): def get_questions(request):
-    qs = Question.objects.all().values()+    jsonData list( Question.objects.all().values()
     return JsonResponse({     return JsonResponse({
             "status": "OK",             "status": "OK",
-            "questions":list(qs)+            "questions": jsonData,
         }, safe=False)         }, safe=False)
 </file> </file>
 +
 +<WRAP info>
 +Observa bé què cal per poder serialitzar els objectes del model:
 +  jsonData = list( Question.objects.all().values() )
 +
 +  - Tenim un queryset de Questions
 +  - Seleccionem només els valors amb ''.values()''
 +  - Transformem en una llista amb ''list( ... )''
 +</WRAP>
  
 Recorda que abans caldrà que implementis un //endpoint//, per exemple a ''/get_questions'' dins de ''urls.py'': Recorda que abans caldrà que implementis un //endpoint//, per exemple a ''/get_questions'' dins de ''urls.py'':
Línia 38: Línia 51:
 from django.urls import path from django.urls import path
  
-from . import views+from . import views, api
  
 urlpatterns = [ urlpatterns = [
     path('', views.index, name='index'),     path('', views.index, name='index'),
     #...     #...
-    path('get_questions', views.get_questions, name='get_questions'),+    path('get_questions', api.get_questions, name='get_questions'),
 ] ]
 </file> </file>
Línia 51: Línia 64:
   {"questions": [{"id": 1, "question_text": "Qu\u00e8 vols per sopar?", "pub_date": "2022-02-17T09:42:57Z"}, {"id": 2, "question_text": "Qui guanyar\u00e0 la lliga?", "pub_date": "2022-02-17T09:43:13Z"}]}   {"questions": [{"id": 1, "question_text": "Qu\u00e8 vols per sopar?", "pub_date": "2022-02-17T09:42:57Z"}, {"id": 2, "question_text": "Qui guanyar\u00e0 la lliga?", "pub_date": "2022-02-17T09:43:13Z"}]}
  
 +<WRAP tip>
 Si voleu un //pretty print// del JSON a la línia de comandes podeu fer: Si voleu un //pretty print// del JSON a la línia de comandes podeu fer:
   $ curl localhost:8000/polls/get_questions | python3 -m json.tool   $ curl localhost:8000/polls/get_questions | python3 -m json.tool
  
-{{ django_get_questions_api.png?400 }}+I per acabar-ho d'adobar, afegim colors amb ''pygmentize -l json'': 
 +  $ curl localhost:8000/polls/get_questions | python3 -m json.tool | pygmentize -l json 
 +</WRAP> 
 + 
 +El //browser// sempre és un tiro segur molt còmode: 
 +{{ django_get_questions_api.png?500 }}
  
 \\ \\
Línia 80: Línia 99:
  
 <WRAP tip> <WRAP tip>
 +== Decorator @user_passes_test ==
 Existeixen altres //decorators// que ens faciliten fer un "tunning" més fi de les nostres //views//. En particular pots mirar [[https://docs.djangoproject.com/es/3.2/topics/auth/default/#django.contrib.auth.decorators.user_passes_test|el decorator user_passes_test]] per assegurar-te que l'usuari logat compleix amb certes condicions, com pertànyer a cert grup d'usuaris amb determinats privilegis. Existeixen altres //decorators// que ens faciliten fer un "tunning" més fi de les nostres //views//. En particular pots mirar [[https://docs.djangoproject.com/es/3.2/topics/auth/default/#django.contrib.auth.decorators.user_passes_test|el decorator user_passes_test]] per assegurar-te que l'usuari logat compleix amb certes condicions, com pertànyer a cert grup d'usuaris amb determinats privilegis.
 </WRAP> </WRAP>
Línia 97: Línia 117:
  
   - Aplica el quickstart del Django REST Framework al tutorial "polls" oficial de Django.   - Aplica el quickstart del Django REST Framework al tutorial "polls" oficial de Django.
-  - Crea serializers per als objectes User, Question i Choice+  - Crea serializers per als objectes ''User''''Question'' ''Choice''.
   - Realitza requests des de la línia de comandes amb ''curl'' per a llistar els diferents tipus objectes (llista complerta i detalls d'un en particular).   - Realitza requests des de la línia de comandes amb ''curl'' per a llistar els diferents tipus objectes (llista complerta i detalls d'un en particular).
  
Línia 121: Línia 141:
   curl -u admin:admin123 http://127.0.0.1:8000/api/users/   curl -u admin:admin123 http://127.0.0.1:8000/api/users/
  
-O en la versió amb indentació o "pretty print":+<WRAP info> 
 +De vegades ens pot interessar una alternativa enviant les dades codificades en base64 en els //headers//: 
 +  curl -H 'Authorization:Basic YWRtaW46YWRtaW4xMjM=' http://127.0.0.1:8000/api/users/ 
 + 
 +Per obtenir el //hash// en base64 es pot fer: 
 +  echo -n "admin:admin123" | openssl base64 
 +</WRAP> 
 + 
 +<WRAP tip> 
 +O en la versió amb indentació o "pretty print" (això és una implementació particular de Django, en altres no funciona):
   curl -H 'Accept: application/json; indent=4' -u admin:admin123 http://127.0.0.1:8000/api/users/   curl -H 'Accept: application/json; indent=4' -u admin:admin123 http://127.0.0.1:8000/api/users/
 +</WRAP>
  
 <WRAP todo> <WRAP todo>
Línia 128: Línia 158:
   - Cerca com ha de ser una query per a enregistrar un nou usuari.   - Cerca com ha de ser una query per a enregistrar un nou usuari.
   - Comprova que si no ens autentiquem no ens deixa enregistrar-lo.   - Comprova que si no ens autentiquem no ens deixa enregistrar-lo.
 +    * Quin //status code// ens dóna amb l'error d'autenticació? (Utilitza la comanda amb el flag ''curl -i'' per visualitzar els //headers// amb la info).
 +  - Comprova què passa si intentem insertar un User amb un username preexistent.
 +    * Quin //status code// ens dóna amb l'error? 
 </WRAP> </WRAP>
  
Línia 170: Línia 203:
  
 Per utilitzar el Token: Per utilitzar el Token:
-  curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'+  curl http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
  
 +\\
 +
 +===== Objectes aniuats =====
 <WRAP todo> <WRAP todo>
-Exercici:+Exercici amb objectes aniuats:
   - Crea els serializers per al tutorial oficial Django "polls", per als objectes ''Question'' i ''Choice''.   - Crea els serializers per al tutorial oficial Django "polls", per als objectes ''Question'' i ''Choice''.
   - Configura el ''QuestionSerializer'' per tal que tingui aniuat ("nested") les ''Choice'', de manera que quan demanem una (o vàries) ''Question'' ens surti també la info de les seves ''Choice'' internes.   - Configura el ''QuestionSerializer'' per tal que tingui aniuat ("nested") les ''Choice'', de manera que quan demanem una (o vàries) ''Question'' ens surti també la info de les seves ''Choice'' internes.
Línia 180: Línia 216:
  
 \\ \\
 +
 +===== URLs personalitzades amb TokenAuthentication del REST framework =====
 +
 +Si volem fer les nostres pròpies URLs per a la API i volem afegir-hi algun dels mètdodes d'autenticació del REST framework, ho podem fer així:
 +
 +<code python>
 +from rest_framework.authentication import TokenAuthentication, BasicAuthentication
 +from rest_framework.permissions import IsAuthenticated
 +from rest_framework.decorators import api_view, authentication_classes, permission_classes
 +from django.http import JsonResponse
 +
 +@api_view(['GET'])
 +@authentication_classes([TokenAuthentication, BasicAuthentication])
 +@permission_classes([IsAuthenticated])
 +def pin_request(request):
 +    return JsonResponse({
 +        "usuari":request.user.username,
 +        "PIN":3142
 +        })
 +
 +urlpatterns += [
 +    path('api/pin_request', pin_request )
 +]
 +</code>
 +
 +\\
 +
  
django_api.1645621508.txt.gz · Darrera modificació: 2022/02/23 13:05 per enrique_mieza_sanchez