Создание Django API используя Django Rest Framework часть 3

Spread the love

Это третья часть из серии статей про Django API. Первая часть находится здесь. Вторая здесь. В этой статье мы рассмотрим использование наборы представлений класс viewsets от Django REST Framework. Основное отличие viewsets от GenericAPIView и APIView, в том что это еще один дополнительный абстрагирующий класс, который с одной стороны позволяет уменьшить базовый код а с другой имеет большие возможности по кастомизации и расширению.

И так начнем, с изменений в файле представления. Используем базовый класс viewsets.ViewSet унаследуем от него наш класс ArticleView и определим методы получения всех статей (list) и одну выбранную статью (retrieve). Для этого внесем следующие изменения в article/views.py:

from django.shortcuts import get_object_or_404
from rest_framework import viewsets
from rest_framework.response import Response

from .models import Article
from .serializers import ArticleSerializer


class ArticleView(viewsets.ViewSet):
    """
    A simple ViewSet that for listing or retrieving users.
    """
    def list(self, request):
        queryset = Article.objects.all()
        serializer = ArticleSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = Article.objects.all()
        user = get_object_or_404(queryset, pk=pk)
        serializer = ArticleSerializer(user)
        return Response(serializer.data)

Далее нам нужно связать наши методы list и retrieve с URL API. Для этого внесите изменения в article/urls.py:

from django.urls import path

from .views import ArticleView


app_name = "articles"

# app_name will help us do a reverse look-up latter.
urlpatterns = [
    path('articles/', ArticleView.as_view({'get': 'list'})),
    path('articles/<int:pk>', ArticleView.as_view({'get': 'retrieve'})),
]

Если теперь обратится по URL: http://127.0.0.1:8000/api/articles/ или http://127.0.0.1:8000/api/articles/1/ то должно все работать как раньше.

Теперь воспользуется новым для нас классом роутера DRF DefaultRouter. Этот класс позволяет значительно уменьшить код в URL. Зарегистрируем наш класс ArticleView в этом классе и позволяем ему теперь автоматически генерировать обработчики url. Удалите весь старый код из article/urls.py и внесите следующие изменения в этот файл:

from rest_framework.routers import DefaultRouter

from .views import ArticleView

router = DefaultRouter()
router.register(r'articles', ArticleView, basename='user')

urlpatterns = router.urls

Теперь если обратится по URL: http://127.0.0.1:8000/api/articles/ или http://127.0.0.1:8000/api/articles/1/ то опять все должно работать как раньше. Но обратите внимание мы реализовали только два метода API получения списка статей и получение одной выбранной статье.

Что бы реализовать методы создания, редактирования и удаления мы можем определить эти методы вручную или воспользоваться классом viewsets.ModelViewSet в котором уже все сделано за нас. Внесите следующие изменения в файл article/views.py:

from rest_framework import viewsets

from .models import Article
from .serializers import ArticleSerializer


class ArticleViewSet(viewsets.ModelViewSet):

    serializer_class = ArticleSerializer
    queryset = Article.objects.all()

И соотвествующие изменения в файл article/urls.py

from rest_framework.routers import DefaultRouter

from .views import ArticleViewSet


router = DefaultRouter()
router.register(r'articles', ArticleViewSet, basename='user')

urlpatterns = router.urls

Теперь мы можем создавать, редактировать и удалять

Используя viewsets мы буквально в пару строк получили полностью рабочий CRUD для выбранной таблицы.
На этом я пожалуй хотел завершить эту статью. В этой серии статей мы очень кратко рассмотрели и сравнили возможности классов DRF APIView, GenericAPIView, ViewSets для создания CRUD. На самом деле у этих классов гораздо больше возможностей и особенностей их применения и если вы захотите изучить их глубже обратитесь к официальной документации DRF.

Была ли вам полезна эта статья?
[53 / 4.7]

Spread the love
Подписаться
Уведомление о
guest
9 Комментарий
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Андрей
Андрей
5 лет назад

Благодарю за перевод!

Пропущено слово с «другой» между «с» и «имеет»:
» который с одной стороны позволяет уменьшить базовый код а с имеет большие возможности»

Никита
Никита
4 лет назад

Поскольку при создании новой записи вы не указываете\выбираете автора, будет выпадать ошибка о том, что author_id не может быть NULL.

Для правильной работы в serializer нужно добавить:
def create(self, validated_data):
validated_data[‘author_id’] = your_author_id
return super(ArticleSerializer, self).create(validated_data)
для неявного указания автора.

Иван
Иван
4 лет назад
Reply to  Никита

Достаточно разместить в ArticleViewSet функцию perform_create из предыдущей статьи.

iLq
iLq
4 лет назад

basename=’user’ — тут выглядит немного странно и сбивает с толку. Это недосмотр или всё корректно?

edteam
Администратор
4 лет назад
Reply to  iLq

Вы правы, автор статьи немного недосмотрел

Анонимно
Анонимно
4 лет назад

но почему во всех подобных статьях старательно игнорируют загрузку файлов?

Дмитрий
Дмитрий
3 лет назад

Панимаю,уже второй день найти не могу

Анонимно
Анонимно
2 лет назад

При редактировании через Postman показывает код страницы 500. Почему именно с редактированием ошибка? С удалением, получением и созданием статей проблем нет