Skip to content

Commit 9fed88c

Browse files
authored
Merge pull request #297 from rg3915/pelican
DRF Quickstart atualizado
2 parents 3e23253 + 8262298 commit 9fed88c

File tree

4 files changed

+348
-25
lines changed

4 files changed

+348
-25
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
title: Django Rest Framework - #3 Class Based Views
2+
Slug: django-rest-framework-class-based-views
3+
Date: 2018-02-15 23:00
4+
Tags: Python, Django, REST
5+
Author: Regis da Silva
6+
Email: regis.santos.100@gmail.com
7+
Github: rg3915
8+
Twitter: rg3915
9+
Category: Python, Django, REST
10+
11+
* 0 - [Quickstart][10]
12+
* 1 - [Serialization][11]
13+
* 2 - [Requests & Responses][12]
14+
* 3 - **Class based views**
15+
16+
Este post é continuação do post [Django Rest Framework Requests & Responses][12].
17+
18+
Finalmente chegamos as views baseadas em classes. A grande vantagem é que com poucas linhas de código já temos nossa API pronta.
19+
20+
Veja como fica a [views.py](https://github.com/rg3915/drf/blob/b0aa989ffc756e6dc5f65e172dfb43d47127d743/core/views.py):
21+
22+
```python
23+
from django.http import Http404
24+
from rest_framework.views import APIView
25+
from rest_framework.response import Response
26+
from rest_framework import status
27+
from core.models import Person
28+
from core.serializers import PersonSerializer
29+
30+
31+
class PersonList(APIView):
32+
"""
33+
List all persons, or create a new person.
34+
"""
35+
36+
def get(self, request, format=None):
37+
persons = Person.objects.all()
38+
serializer = PersonSerializer(persons, many=True)
39+
return Response(serializer.data)
40+
41+
def post(self, request, format=None):
42+
serializer = PersonSerializer(data=request.data)
43+
if serializer.is_valid():
44+
serializer.save()
45+
return Response(serializer.data, status=status.HTTP_201_CREATED)
46+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
47+
48+
49+
class PersonDetail(APIView):
50+
"""
51+
Retrieve, update or delete a person instance.
52+
"""
53+
54+
def get_object(self, pk):
55+
try:
56+
return Person.objects.get(pk=pk)
57+
except Person.DoesNotExist:
58+
raise Http404
59+
60+
def get(self, request, pk, format=None):
61+
person = self.get_object(pk)
62+
serializer = PersonSerializer(person)
63+
return Response(serializer.data)
64+
65+
def put(self, request, pk, format=None):
66+
person = self.get_object(pk)
67+
serializer = PersonSerializer(person, data=request.data)
68+
if serializer.is_valid():
69+
serializer.save()
70+
return Response(serializer.data)
71+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
72+
73+
def delete(self, request, pk, format=None):
74+
person = self.get_object(pk)
75+
person.delete()
76+
return Response(status=status.HTTP_204_NO_CONTENT)
77+
```
78+
79+
E `urls.py`:
80+
81+
```python
82+
urlpatterns = [
83+
path('persons/', views.PersonList.as_view()),
84+
path('persons/<int:pk>/', views.PersonDetail.as_view()),
85+
]
86+
```
87+
88+
## Usando Mixins
89+
90+
Repare que no exemplo anterior tivemos que definir os métodos `get()`, `post()`, `put()` e `delete()`. Podemos reduzir ainda mais esse código com o uso de mixins.
91+
92+
```python
93+
from rest_framework import mixins
94+
from rest_framework import generics
95+
from core.models import Person
96+
from core.serializers import PersonSerializer
97+
98+
99+
class PersonList(mixins.ListModelMixin,
100+
mixins.CreateModelMixin,
101+
generics.GenericAPIView):
102+
queryset = Person.objects.all()
103+
serializer_class = PersonSerializer
104+
105+
def get(self, request, *args, **kwargs):
106+
return self.list(request, *args, **kwargs)
107+
108+
def post(self, request, *args, **kwargs):
109+
return self.create(request, *args, **kwargs)
110+
111+
112+
class PersonDetail(mixins.RetrieveModelMixin,
113+
mixins.UpdateModelMixin,
114+
mixins.DestroyModelMixin,
115+
generics.GenericAPIView):
116+
queryset = Person.objects.all()
117+
serializer_class = PersonSerializer
118+
119+
def get(self, request, *args, **kwargs):
120+
return self.retrieve(request, *args, **kwargs)
121+
122+
def put(self, request, *args, **kwargs):
123+
return self.update(request, *args, **kwargs)
124+
125+
def delete(self, request, *args, **kwargs):
126+
return self.destroy(request, *args, **kwargs)
127+
```
128+
129+
## Usando generic class-based views
130+
131+
E para finalizar usamos `ListCreateAPIView` e `RetrieveUpdateDestroyAPIView` que já tem todos os métodos embutidos.
132+
133+
```python
134+
from rest_framework import generics
135+
from core.models import Person
136+
from core.serializers import PersonSerializer
137+
138+
139+
class PersonList(generics.ListCreateAPIView):
140+
queryset = Person.objects.all()
141+
serializer_class = PersonSerializer
142+
143+
144+
class PersonDetail(generics.RetrieveUpdateDestroyAPIView):
145+
queryset = Person.objects.all()
146+
serializer_class = PersonSerializer
147+
```
148+
149+
Versão final de [views.py](https://github.com/rg3915/drf/blob/263ca63e5c8e2dd2e0f5d6c88c5733fcfdab4f74/core/views.py).
150+
151+
Abraços.
152+
153+
[10]: http://pythonclub.com.br/django-rest-framework-quickstart.html
154+
[11]: http://pythonclub.com.br/django-rest-framework-serialization.html
155+
[12]: http://pythonclub.com.br/django-rest-framework-requests-responses.html

content/django-rest-framework-quickstart.md

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,55 @@ Category: Python, Django, REST
1010

1111
Veremos aqui uma forma rápida de criar uma API REST com [Django Rest Framework][0].
1212

13-
Este tutorial é a parte 0/6 de uma série de posts sobre DRF.
13+
> Este artigo foi atualizado em 14 de Fevereiro de 2018.
14+
15+
Este artigo está usando:
16+
17+
* Python 3.5.2
18+
* Django 2.0.2
19+
* djangorestframework 3.7.7
20+
21+
Favor clonar o projeto do [GitHub](https://github.com/rg3915/drf#clonando-o-projeto), favor ler o README para instalação.
22+
23+
Repare nas alterações das urls na nova versão do Django.
24+
25+
```python
26+
urls.py
27+
from django.urls import include, path
28+
from django.contrib import admin
29+
30+
urlpatterns = [
31+
path('', include('core.urls')),
32+
path('admin/', admin.site.urls),
33+
]
34+
```
35+
36+
```python
37+
# core/urls.py
38+
from django.urls import path
39+
from core import views
40+
41+
urlpatterns = [
42+
path('persons/', views.person_list),
43+
path('persons/<int:pk>/', views.person_detail),
44+
]
45+
```
46+
47+
Além disso, tivemos alterações significativas em [settings.py](https://github.com/rg3915/drf/blob/master/myproject/settings.py).
1448

1549
**Obs**: *Tem coisas que é melhor nem traduzir. ;)*
1650

1751
* 0 - **Quickstart**
1852
* 1 - [Serialization][11]
1953
* 2 - Requests & Responses
2054
* 3 - Class based views
21-
* 4 - Authentication & permissions
22-
* 5 - Relationships & hyperlinked APIs
23-
* 6 - Viewsets & routers
2455

2556
> **Obs**: se você não sabe [Django][3] sugiro que leia este [tutorial][4] antes.
2657
2758
## Começando
2859

2960
```bash
30-
$ virtualenv -p python3 env
61+
$ python3 -m venv .venv
3162
$ source env/bin/activate
3263
$ mkdir drf-quickstart
3364
$ cd drf-quickstart
@@ -41,10 +72,15 @@ $ python manage.py createsuperuser --username='admin' --email=''
4172

4273
Veja o meu requirements.txt
4374

44-
Django==1.8.6
45-
argparse==1.2.1
46-
djangorestframework==3.3.1
47-
wsgiref==0.1.2
75+
```bash
76+
dj-database-url==0.4.2
77+
Django==2.0.2
78+
django-extensions==1.9.9
79+
django-filter==1.1.0
80+
djangorestframework==3.7.7
81+
drf-nested-routers==0.90.0
82+
python-decouple==3.1
83+
```
4884

4985
## Editando `settings.py`
5086

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
title: Django Rest Framework - #2 Requests and Responses
2+
Slug: django-rest-framework-requests-responses
3+
Date: 2018-02-14 23:00
4+
Tags: Python, Django, REST
5+
Author: Regis da Silva
6+
Email: regis.santos.100@gmail.com
7+
Github: rg3915
8+
Twitter: rg3915
9+
Category: Python, Django, REST
10+
11+
* 0 - [Quickstart][10]
12+
* 1 - [Serialization][11]
13+
* 2 - **Requests & Responses**
14+
* 3 - Class based views
15+
16+
Este post é continuação do post [Django Rest Framework Serialization][11].
17+
18+
O uso de *requests* e *responses* torna nossa api mais flexível. A funcionalidade principal do objeto **Request** é o atributo `request.data`, que é semelhante ao `request.POST`, mas é mais útil para trabalhar com APIs.
19+
20+
## Objeto Response
21+
22+
Introduzimos aqui um objeto `Response`, que é um tipo de `TemplateResponse` que leva conteúdo não renderizado e usa a negociação de conteúdo para determinar o tipo de conteúdo correto para retornar ao cliente.
23+
24+
```python
25+
return Response(data) # Renderiza para o tipo de conteúdo conforme solicitado pelo cliente.
26+
```
27+
28+
Repare também no uso de *status code* pré definidos, exemplo: `status.HTTP_400_BAD_REQUEST`.
29+
30+
E usamos o decorador `@api_view` para trabalhar com funções. Ou `APIView` para classes.
31+
32+
Nosso código ficou assim:
33+
34+
```python
35+
# views.py
36+
from rest_framework import status
37+
from rest_framework.decorators import api_view
38+
from rest_framework.response import Response
39+
from core.models import Person
40+
from core.serializers import PersonSerializer
41+
42+
43+
@api_view(['GET', 'POST'])
44+
def person_list(request):
45+
"""
46+
List all persons, or create a new person.
47+
"""
48+
if request.method == 'GET':
49+
persons = Person.objects.all()
50+
serializer = PersonSerializer(persons, many=True)
51+
return Response(serializer.data)
52+
53+
elif request.method == 'POST':
54+
serializer = PersonSerializer(data=request.data)
55+
if serializer.is_valid():
56+
serializer.save()
57+
return Response(serializer.data, status=status.HTTP_201_CREATED)
58+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
59+
60+
61+
@api_view(['GET', 'PUT', 'DELETE'])
62+
def person_detail(request, pk):
63+
"""
64+
Retrieve, update or delete a person instance.
65+
"""
66+
try:
67+
person = Person.objects.get(pk=pk)
68+
except Person.DoesNotExist:
69+
return Response(status=status.HTTP_404_NOT_FOUND)
70+
71+
if request.method == 'GET':
72+
serializer = PersonSerializer(person)
73+
return Response(serializer.data)
74+
75+
elif request.method == 'PUT':
76+
serializer = PersonSerializer(person, data=request.data)
77+
if serializer.is_valid():
78+
serializer.save()
79+
return Response(serializer.data)
80+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
81+
82+
elif request.method == 'DELETE':
83+
person.delete()
84+
return Response(status=status.HTTP_204_NO_CONTENT)
85+
```
86+
87+
Veja no [GitHub](https://github.com/rg3915/drf/commit/69205da9262415eaf83ff04f22a635e912880a60).
88+
89+
90+
## Usando sufixo opcional
91+
92+
Em `core/urls.py` acrescente
93+
94+
```python
95+
from rest_framework.urlpatterns import format_suffix_patterns
96+
97+
...
98+
99+
urlpatterns = format_suffix_patterns(urlpatterns)
100+
```
101+
102+
E em `views.py` acrescente `format=None` como parâmetro das funções a seguir:
103+
104+
```python
105+
def person_list(request, format=None):
106+
107+
def person_detail(request, pk, format=None):
108+
```
109+
110+
Com isso você pode chamar a api da seguinte forma:
111+
112+
```bash
113+
http http://127.0.0.1:8000/persons.json # ou
114+
http http://127.0.0.1:8000/persons.api
115+
```
116+
117+
Até a próxima.
118+
119+
[10]: http://pythonclub.com.br/django-rest-framework-quickstart.html
120+
[11]: http://pythonclub.com.br/django-rest-framework-serialization.html

0 commit comments

Comments
 (0)