Spec-Zone.ru › Django REST Framework

Общие представления

Общие представления Django… были разработаны как сокращение для распространённых шаблонов использования… Они берут определённые общие фразы и шаблоны, используемые при разработке представлений, и абстрагируют их, чтобы вы могли быстро писать общие представления данных, не повторяясь.

— Документация Django

Одним из ключевых преимуществ представлений на основе классов является то, как они позволяют вам комбинировать фрагменты многократно используемого поведения. REST фреймворк использует это, предоставляя ряд предварительно созданных представлений, которые обеспечивают распространённые шаблоны.

Общие представления, предоставляемые REST фреймворком, позволяют быстро создавать API-представления, которые тесно связаны с вашими моделями данных.

Если общие представления не подходят для потребностей вашего API, вы можете перейти к использованию обычного класса APIView, или повторно использовать миксины и базовые классы, используемые общими представлениями, для создания собственного набора многократно используемых общих представлений.

Примеры

Обычно при использовании общих представлений вы переопределяете представление и устанавливаете несколько атрибутов класса.

from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from rest_framework.permissions import IsAdminUser

class UserList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAdminUser]

В более сложных случаях вы также можете переопределить различные методы класса представления. Например.

class UserList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAdminUser]

    def list(self, request):
        # Note the use of `get_queryset()` instead of `self.queryset`
        queryset = self.get_queryset()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

В очень простых случаях вы можете передавать любые атрибуты класса с помощью метода .as_view(). Например, ваш URLconf может включать запись следующего вида:

path('users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')

Справочник API

GenericAPIView

Этот класс расширяет класс APIView REST фреймворка, добавляя обычно необходимое поведение для стандартных представлений списка и детализации.

Каждое из конкретных общих представлений создаётся путём объединения GenericAPIView, с одним или несколькими классами миксинов.

Атрибуты

Основные настройки:

Следующие атрибуты контролируют базовое поведение представления.

  • queryset - Множество запросов, которое должно использоваться для возвращения объектов из этого представления. Обычно вы должны либо установить этот атрибут, либо переопределить метод get_queryset(). Если вы переопределяете метод представления, важно, чтобы вы вызвали get_queryset() вместо прямого доступа к этому свойству, так как queryset будет вычисляться один раз, и эти результаты будут кэшированы для всех последующих запросов.
  • serializer_class - Класс сериализатора, который должен использоваться для проверки и десериализации входных данных и для сериализации выходных данных. Обычно вы должны либо установить этот атрибут, либо переопределить метод get_serializer_class().
  • lookup_field - Поле модели, которое должно использоваться для поиска отдельных экземпляров модели. По умолчанию 'pk'. Обратите внимание, что при использовании гиперссылочных API вам нужно будет убедиться, что и представления API, и классы сериализаторов устанавливают поля поиска, если вам нужно использовать пользовательское значение.
  • lookup_url_kwarg - Ключевое слово URL-аргумента, которое должно использоваться для поиска объекта. URL-конфигурация должна включать ключевое слово, соответствующее этому значению. Если не указано, по умолчанию используется то же значение, что и lookup_field.

Пагинация:

Следующие атрибуты используются для управления пагинацией при использовании с представлениями списка.

  • pagination_class - Класс пагинации, который должен использоваться при пагинации результатов списка. По умолчанию совпадает со значением настройки DEFAULT_PAGINATION_CLASS, которое равно 'rest_framework.pagination.PageNumberPagination'. Установка pagination_class=None отключит пагинацию в этом представлении.

Фильтрация:

  • filter_backends - Список классов бэкэндов фильтров, которые должны использоваться для фильтрации множества запросов. По умолчанию совпадает со значением настройки DEFAULT_FILTER_BACKENDS.

Методы

Базовые методы:

get_queryset(self)

Возвращает множество запросов, которое должно использоваться для представлений списка и которое должно использоваться в качестве базы для поиска в представлениях детализации. По умолчанию возвращает множество запросов, заданное атрибутом queryset.

Этот метод всегда должен использоваться вместо прямого доступа к self.queryset, так как self.queryset вычисляется только один раз, и эти результаты кэшируются для всех последующих запросов.

Может быть переопределён для обеспечения динамического поведения, например, возвращения набора запросов, специфичных для пользователя, который делает запрос.

Например:

def get_queryset(self):
    user = self.request.user
    return user.accounts.all()

Примечание: Если serializer_class используемый в общем представлении, охватывает связи ORM, что приводит к проблеме n+1, вы можете оптимизировать свой набор запросов в этом методе, используя select_related и prefetch_related. Для получения дополнительной информации о проблеме n+1 и случаях использования упомянутых методов, обратитесь к соответствующему разделу в документации Django.

get_object(self)

Возвращает экземпляр объекта, который должен использоваться для представлений детализации. По умолчанию используется параметр lookup_field для фильтрации базового множества запросов.

Может быть переопределён для обеспечения более сложного поведения, например, поиска объекта на основе более чем одного ключевого слова URL.

Например:

def get_object(self):
    queryset = self.get_queryset()
    filter = {}
    for field in self.multiple_lookup_fields:
        filter[field] = self.kwargs[field]

    obj = get_object_or_404(queryset, **filter)
    self.check_object_permissions(self.request, obj)
    return obj

Обратите внимание, что если ваш API не включает разрешения на уровне объекта, вы можете необязательно исключить self.check_object_permissions, и просто вернуть объект из поиска get_object_or_404.

filter_queryset(self, queryset)

Принимая множество запросов, отфильтруйте его с использованием всех используемых бэкэндов фильтров, возвращая новое множество запросов.

Например:

def filter_queryset(self, queryset):
    filter_backends = [CategoryFilter]

    if 'geo_route' in self.request.query_params:
        filter_backends = [GeoRouteFilter, CategoryFilter]
    elif 'geo_point' in self.request.query_params:
        filter_backends = [GeoPointFilter, CategoryFilter]

    for backend in list(filter_backends):
        queryset = backend().filter_queryset(self.request, queryset, view=self)

    return queryset

get_serializer_class(self)

Возвращает класс, который должен использоваться для сериализатора. По умолчанию возвращает атрибут serializer_class.

Может быть переопределён для обеспечения динамического поведения, например, для использования разных сериализаторов для операций чтения и записи или для предоставления разных сериализаторов для разных типов пользователей.

Например:

def get_serializer_class(self):
    if self.request.user.is_staff:
        return FullAccountSerializer
    return BasicAccountSerializer

Обработка сохранения и удаления:

Следующие методы предоставляются классами-миксерами и обеспечивают лёгкое переопределение поведения сохранения или удаления объекта.

  • perform_create(self, serializer) - Вызывается CreateModelMixin при сохранении нового экземпляра объекта.
  • perform_update(self, serializer) - Вызывается UpdateModelMixin при сохранении существующего экземпляра объекта.
  • perform_destroy(self, instance) - Вызывается DestroyModelMixin при удалении экземпляра объекта.

Эти крючки особенно полезны для установки атрибутов, которые подразумеваются в запросе, но не являются частью данных запроса. Например, вы можете установить атрибут объекта на основе пользователя запроса или на основе ключевого слова URL.

def perform_create(self, serializer):
    serializer.save(user=self.request.user)

Эти точки переопределения также очень полезны для добавления поведения, которое происходит до или после сохранения объекта, например, отправки подтверждения по электронной почте или регистрации обновления.

def perform_update(self, serializer):
    instance = serializer.save()
    send_email_confirmation(user=self.request.user, modified=instance)

Вы также можете использовать эти крючки для обеспечения дополнительной проверки, вызвав ValidationError(). Это может быть полезно, если вам нужна логика проверки, применяемая в момент сохранения в базе данных. Например:

def perform_create(self, serializer):
    queryset = SignupRequest.objects.filter(user=self.request.user)
    if queryset.exists():
        raise ValidationError('You have already signed up')
    serializer.save(user=self.request.user)

Другие методы:

Обычно вам не нужно переопределять следующие методы, хотя вам может потребоваться вызвать их, если вы пишете пользовательские представления, используя GenericAPIView.

  • get_serializer_context(self) - Возвращает словарь, содержащий дополнительный контекст, который должен быть предоставлен сериализатору. По умолчанию включает ключи 'request', 'view' и 'format'.
  • get_serializer(self, instance=None, data=None, many=False, partial=False) - Возвращает экземпляр сериализатора.
  • get_paginated_response(self, data) - Возвращает объект пагинации Response.
  • paginate_queryset(self, queryset) - Пагинировать множество запросов, если требуется, либо возвращая объект страницы, либо None, если пагинация не настроена для этого представления.
  • filter_queryset(self, queryset) - Принимая множество запросов, отфильтруйте его с использованием всех используемых бэкэндов фильтров, возвращая новое множество запросов.

Миксины

Классы миксинов обеспечивают действия, используемые для предоставления базового поведения представления. Обратите внимание, что классы миксинов предоставляют методы действий, а не определяют методы обработчика, такие как .get() и .post() напрямую. Это позволяет более гибко комбинировать поведение.

Классы миксинов можно импортировать из rest_framework.mixins.

ListModelMixin

Предоставляет метод .list(request, *args, **kwargs), который реализует перечисление множества запросов.

Если множество запросов заполнено, это возвращает ответ 200 OK, с сериализованным представлением набора запросов в теле ответа. Данные ответа могут быть необязательно пагинатированными.

CreateModelMixin

Предоставляет метод .create(request, *args, **kwargs), который реализует создание и сохранение нового экземпляра модели.

Если объект создан, это возвращает ответ 201 Created, с сериализованным представлением объекта в теле ответа. Если представление содержит ключ url, заголовок Location ответа будет заполнен этим значением.

Если предоставленные для создания объекта данные запроса были неверными, будет возвращён ответ 400 Bad Request, с деталями об ошибке в теле ответа.

RetrieveModelMixin

Предоставляет метод .retrieve(request, *args, **kwargs), который реализует возвращение существующего экземпляра модели в ответ.

Если объект может быть получен, возвращается ответ 200 OK, с сериализованным представлением объекта в теле ответа. В противном случае будет возвращён 404 Not Found.

UpdateModelMixin

Предоставляет метод .update(request, *args, **kwargs), который реализует обновление и сохранение существующего экземпляра модели.

Также предоставляет метод .partial_update(request, *args, **kwargs), который аналогичен методу update, за исключением того, что все поля для обновления будут необязательными. Это позволяет поддержку запросов HTTP PATCH.

Если объект обновлён, возвращается ответ 200 OK, с сериализованным представлением объекта в теле ответа.

Если предоставленные для обновления объекта данные запроса были неверными, будет возвращён ответ 400 Bad Request, с деталями об ошибке в теле ответа.

DestroyModelMixin

Предоставляет метод .destroy(request, *args, **kwargs), который реализует удаление существующего экземпляра модели.

Если объект удалён, возвращается ответ 204 No Content, в противном случае будет возвращён 404 Not Found.

Классы конкретных представлений

Следующие классы являются конкретными общими представлениями. Если вы используете общие представления, это обычно уровень, на котором вы будете работать, если вам не требуется сильно настроенное поведение.

Классы представлений можно импортировать из rest_framework.generics.

CreateAPIView

Используется для только для создания конечных точек.

Предоставляет обработчик метода post.

Расширяет: GenericAPIView, CreateModelMixin

ListAPIView

Используется для только для чтения конечных точек, представляющих коллекцию экземпляров модели.

Предоставляет обработчик метода get.

Расширяет: GenericAPIView, ListModelMixin

RetrieveAPIView

Используется для только для чтения конечных точек, представляющих один экземпляр модели.

Предоставляет обработчик метода get.

Расширяет: GenericAPIView, RetrieveModelMixin

DestroyAPIView

Используется для только для удаления конечных точек для одного экземпляра модели.

Предоставляет обработчик метода delete.

Расширяет: GenericAPIView, DestroyModelMixin

UpdateAPIView

Используется для только для обновления конечных точек для одного экземпляра модели.

Предоставляет обработчики методов put и patch.

Расширяет: GenericAPIView, UpdateModelMixin

ListCreateAPIView

Используется для чтения и записи конечных точек, представляющих коллекцию экземпляров модели.

Предоставляет обработчики методов get и post.

Расширяет: GenericAPIView, ListModelMixin, CreateModelMixin

RetrieveUpdateAPIView

Используется для чтения или обновления конечных точек, представляющих один экземпляр модели.

Предоставляет обработчики методов get, put и patch.

Расширяет: GenericAPIView, RetrieveModelMixin, UpdateModelMixin

RetrieveDestroyAPIView

Используется для чтения или удаления конечных точек, представляющих один экземпляр модели.

Предоставляет обработчики методов get и delete.

Расширяет: GenericAPIView, RetrieveModelMixin, DestroyModelMixin

RetrieveUpdateDestroyAPIView

Используется для чтения, записи и удаления конечных точек, представляющих один экземпляр модели.

Предоставляет обработчики методов get, put, patch и delete.

Расширяет: GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin

Настройка универсальных представлений

Зачастую вам захочется использовать существующие универсальные представления, но с некоторыми слегка измененными поведением. Если вы обнаруживаете, что повторно используете некоторую часть настраиваемого поведения в нескольких местах, возможно, вам стоит переструктурировать поведение в общий класс, который затем можно применять к любому представлению или набору представлений по мере необходимости.

Создание пользовательских миксинов

Например, если вам нужно искать объекты по нескольким полям в URL-конфигурации, вы можете создать класс миксина, как показано ниже:

class MultipleFieldLookupMixin:
    """
    Apply this mixin to any view or viewset to get multiple field filtering
    based on a `lookup_fields` attribute, instead of the default single field filtering.
    """
    def get_object(self):
        queryset = self.get_queryset()             # Get the base queryset
        queryset = self.filter_queryset(queryset)  # Apply any filter backends
        filter = {}
        for field in self.lookup_fields:
            if self.kwargs.get(field): # Ignore empty fields.
                filter[field] = self.kwargs[field]
        obj = get_object_or_404(queryset, **filter)  # Lookup the object
        self.check_object_permissions(self.request, obj)
        return obj

Затем вы можете просто применить этот миксин к представлению или набору представлений всякий раз, когда вам нужно применить настраиваемое поведение.

class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_fields = ['account', 'username']

Использование пользовательских миксинов является хорошим вариантом, если у вас есть настраиваемое поведение, которое нужно использовать.

Создание пользовательских базовых классов

Если вы используете миксин в нескольких представлениях, вы можете сделать это еще дальше и создать свой набор базовых представлений, которые можно будет использовать во всем проекте. Например:

class BaseRetrieveView(MultipleFieldLookupMixin,
                       generics.RetrieveAPIView):
    pass

class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,
                                    generics.RetrieveUpdateDestroyAPIView):
    pass

Использование пользовательских базовых классов является хорошим вариантом, если у вас есть настраиваемое поведение, которое постоянно повторяется в большом количестве представлений во всем проекте.

PUT как создание

До версии 3.0 миксины REST-фреймворка обрабатывали PUT как операцию обновления или создания в зависимости от того, существует ли объект или нет.

Разрешение PUT как операций создания является проблематичным, поскольку оно обязательно раскрывает информацию о существовании или несуществовании объектов. Также неясно, что прозрачное разрешение повторного создания ранее удаленных экземпляров обязательно является лучшим по умолчанию поведением, чем просто возвращение ответов 404.

Оба стиля "PUT как 404" и "PUT как создание" могут быть действительными в разных обстоятельствах, но начиная с версии 3.0 мы теперь используем поведение 404 в качестве значения по умолчанию, поскольку оно проще и понятнее.

Если вам нужно универсальное поведение PUT-как-создание, вы можете включить что-то вроде этого AllowPUTAsCreateMixin класса как миксин в свои представления.

Пакеты сторонних производителей

Следующие пакеты сторонних производителей предоставляют дополнительные реализации универсальных представлений.

Django Rest Multiple Models

Django Rest Multiple Models предоставляет универсальное представление (и миксин) для отправки нескольких сериализованных моделей и/или наборов запросов через один API-запрос.

mixins.pygenerics.py

Copyright © 2011–present Encode OSS Ltd.
Licensed under the BSD License.
https://www.django-rest-framework.org/api-guide/generic-views/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API