В уроке 5 по созданию API на Django REST Framework, мы рассмотрим расширенное создание запросов, например когда в списке статей мы можем воспользоваться возможностью добавления материала.
В прошлом уроке мы рассмотрели базовые запросы: Django REST Framework создание API: Урок 4, CRUD запросы на основе классов
Давайте приступим к работе с расширенными запросами, принимаемыми виды запросов как GET, так и POST.
Запрос на получение списка статей, а также возможность добавлять статью (ListCreateAPIView
)
modules/blog/views/articles.py
from modules.blog.models import Article
from modules.blog.serializers import ArticleSerializer
from rest_framework import generics
from django.template.defaultfilters import slugify
class ArticleListCreateAPIView(generics.ListCreateAPIView):
"""
Представление для просмотра списка статей и добавления (GET/POST)
"""
queryset = Article.objects.all()
serializer_class = ArticleSerializer
def perform_create(self, serializer):
"""
Метод создания статьи в БД
"""
# Если не задан слаг, генерируем его из заголовка
slug = serializer.validated_data.get('slug')
if slug is None:
slug = slugify(serializer.validated_data.get('title'))
serializer.save(slug=slug)
print(serializer.validated_data)
return super().perform_create(serializer)
Пояснение:
queryset
- передаем список статей (Article.objects.all()
)serializer_class
- передаем наш сериалайзер, что создали в третьем уроке для модели статьи.perform_create
- метод, в котором мы можем задавать различные параметры для создаваемого объекта, аналогично методу сохранения в CreateView с формами.- Данный метод позволяет получить список статей обратившись по заданному URL с помощью GET запроса, а также дополняет возможностью добавить материал по заданному URL с помощью POST запроса.
- Также есть дополнительные методы, о них можете почитать в официальной документации: Generic views - Django REST framework
Необязательно для тех, кто делает все в файле views.py. Добавлю импорты в __init__.py:
from modules.blog.views.articles import ArticleListCreateAPIView
__all__ = '__all__'
Добавлю обработку нашего контроллера в urls.py
modules/blog/urls.py
from django.urls import path
from modules.blog import views
urlpatterns = [
path('articles/', views.ArticleListCreateAPIView.as_view(), name='api_articles_list_create'),
]
Проверю GET запрос на получение списка статей, отправив запрос на страницу: http://127.0.0.1:8000/api/articles/

Отлично, GET запрос работает.
Теперь я отправлю POST запрос на добавление новой статьи на этот же адрес: http://127.0.0.1:8000/api/articles/


Отлично, POST запрос отработал, а также сработал метод: perform_create
для создания слага.
Запрос на получение отдельной статьи, а также возможность обновить статью (RetrieveUpdateAPIView
)
modules/blog/views/articles.py
from modules.blog.models import Article
from modules.blog.serializers import ArticleSerializer
from rest_framework import generics
class ArticleRetrieveAPIView(generics.RetrieveUpdateAPIView):
"""
Представление для просмотра детальной статьи и изменение (GET/PUT)
"""
queryset = Article.objects.all()
serializer_class = ArticleSerializer
lookup_field = 'slug'
def perform_update(self, serializer):
"""
Метод обновления статьи в БД
"""
instance = serializer.save()
print(instance)
return super().perform_update(serializer)
Пояснение:
queryset
- передаем список статей (Article.objects.all()
)serializer_class
- передаем наш сериалайзер, что создали в третьем уроке для модели статьи.lookup_field
- поле, по которому будет получаться статья. Я передаюslug
.perform_update
- метод, в котором мы можем управлять параметрами объекта.- Данный метод позволяет получить статью по pk либо slug обратившись по заданному URL с помощью GET запроса, а также дополняет возможностью изменить материал по заданному URL с помощью PUT запроса.
- Также есть дополнительные методы, о них можете почитать в официальной документации: Generic views - Django REST framework
Необязательно для тех, кто делает все в файле views.py. Добавлю импорты в __init__.py:
from modules.blog.views.articles import ArticleListCreateAPIView, ArticleRetrieveUpdateAPIView
__all__ = '__all__'
Добавлю обработку нашего контроллера в urls.py
modules/blog/urls.py
from django.urls import path
from modules.blog import views
urlpatterns = [
path('articles/', views.ArticleListCreateAPIView.as_view(), name='api_articles_list_create'),
path('articles/<str:slug>/', views.ArticleRetrieveUpdateAPIView.as_view(), name='api_articles_detail_update')
]
Проверю GET запрос на получение одной статьи по SLUG, отправив запрос на страницу: http://127.0.0.1:8000/api/articles/test-article-4/

Отлично, GET запрос работает.
Теперь я отправлю PUT запрос на изменение текущей статьи на эту же ссылку: http://127.0.0.1:8000/api/articles/test-article-4/


Отлично, PUT запрос также отработал на тот же адрес. Таким образом Вы можете через одну ссылку редактировать или просматривать статью через API интерфейс в зависимости от запроса и Ваших целей.
Есть аналогичный запрос для детального просмотра материала и его удаления (RetrieveDestroyAPIView
). Представление аналогичное, только вместо PUT запроса будет доступен DELETE запрос, что приведет к возможности удаления статьи. Рассматривать мы его не будем, но я Вам покажу запрос на детальный просмотр, обновление и удаление материала, а именно: RetrieveUpdateDestroyAPIView
, с помощью него Вы можете открыть детально статью (GET), удалить ее (DELETE), либо обновить (PUT).
modules/blog/views/articles.py
from modules.blog.models import Article
from modules.blog.serializers import ArticleSerializer
from rest_framework import generics
class ArticleRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
"""
Представление для просмотра детальной статьи и изменение, удаление (GET/PUT/DELETE)
"""
queryset = Article.objects.all()
serializer_class = ArticleSerializer
lookup_field = 'slug'
def perform_update(self, serializer):
"""
Метод обновления статьи в БД
"""
instance = serializer.save()
print(instance)
return super().perform_update(serializer)
Пояснение:
queryset
- передаем список статей (Article.objects.all()
)serializer_class
- передаем наш сериалайзер, что создали в третьем уроке для модели статьи.lookup_field
- поле, по которому будет получаться статья. Я передаюslug
.perform_update
- метод, в котором мы можем управлять параметрами объекта.- Данный метод позволяет получить статью по pk либо slug обратившись по заданному URL с помощью GET запроса, а также дополняет возможностью изменить материал по заданному URL с помощью PUT запроса, и удалить материал с помощью DELETE запроса.
- Также есть дополнительные методы, о них можете почитать в официальной документации: Generic views - Django REST framework
Необязательно для тех, кто делает все в файле views.py. Добавлю импорты в __init__.py:
from modules.blog.views.articles import ArticleListCreateAPIView, ArticleRetrieveUpdateDestroyAPIView
__all__ = '__all__'
Добавлю обработку нашего контроллера в urls.py
modules/blog/urls.py
from django.urls import path
from modules.blog import views
urlpatterns = [
path('articles/', views.ArticleListCreateAPIView.as_view(), name='api_articles_list_create'),
path('articles/<str:slug>/', views.ArticleRetrieveUpdateDestroyAPIView.as_view(), name='api_articles_detail_update_delete')
]
Проверю GET запрос на получение одной статьи по SLUG, отправив запрос на страницу: http://127.0.0.1:8000/api/articles/test-article-2/

Отлично, GET запрос работает.
Теперь я отправлю PUT запрос на изменение текущей статьи на эту же ссылку: http://127.0.0.1:8000/api/articles/test-article-2/

Изменение успешно применено, PUT запрос работает.
И последний запрос DELETE я отправлю на удаление текущей статьи на эту же ссылку: http://127.0.0.1:8000/api/articles/test-article-2/

Отлично, запрос DELETE также отработал и статья была удалена.
Если посмотреть интерфейс DRF, то Вы сможете увидеть на скриншоте снизу возможность редактировать, возможность удалить и сами данные отдельной статьи полученной по SLUG.

Таким образом, с помощью смешанных представлений Вы можете создать всего два представления:
ListCreateAPIView
RetrieveUpdateDestroyAPIView
Вместо пяти представлений:
ListAPIView
CreateAPIView
RetrieveAPIView
UpdateAPIView
DestroyAPIView