Руководство по серверному API

Фреймворк VST Utils использует Django, Django Rest Framework, drf-yasg и Celery.

Модели

Модель - это единственный и окончательный источник истины о ваших данных. Она содержит основные поля и поведение для данных, которые вы храните. Хорошей практикой считается избегать написания собственных view и сериализаторов, поскольку BModel предоставляет богатый набор мета-атрибутов для их автоматической генерации в большинстве ситуаций.

Переопределение стандартных классов моделей Django в модуле vstutils.models.

class vstutils.models.BModel(*args, **kwargs)[исходный код]

Стандартный класс модели, генерирующий viewset, отдельные сериализаторы для list() и retrieve(), фильтры, api endpoint-ы и вложенные view.

Примеры:
from django.db import models
from rest_framework.fields import ChoiceField
from vstutils.models import BModel

class Stage(BModel):
    name = models.CharField(max_length=256)
    order = models.IntegerField(default=0)

    class Meta:
        default_related_name = "stage"
        ordering = ('order', 'id',)
        # fields which would be showed on list.
        _list_fields = [
            'id',
            'name',
        ]
        # fields which would be showed on detail view and creation.
        _detail_fields = [
            'id',
            'name',
            'order'
        ]
        # make order as choices from 0 to 9
        _override_detail_fields = {
            'order': ChoiceField((str(i) for i in range(10)))
        }


class Task(BModel):
    name = models.CharField(max_length=256)
    stages = models.ManyToManyField(Stage)
    _translate_model = 'Task'

    class Meta:
        # fields which would be showed.
        _list_fields = [
            'id',
            'name',
        ]
        # create nested views from models
        _nested = {
            'stage': {
                'allow_append': False,
                'model': Stage
            }
        }

В данном случае создаются модели, которые затем будут конвертированы во view, где:

  • POST/GET на /api/version/task/ - создает новую задачу или получает список всех задач

  • PUT/PATCH/GET/DELETE на /api/version/task/:id/ - обновляет, получает или удаляет экземпляр задачи

  • POST/GET to /api/version/task/:id/stage/ - создает новую стадию или получает список всех стадий в задаче

  • PUT/PATCH/GET/DELETE на /api/version/task/:id/stage/:stage_id - обновляет, получает или удаляет экземпляр стадии в задаче.

Чтобы добавить view к API, вставьте следующий код в settings.py:

API[VST_API_VERSION][r'task'] = {
    'model': 'your_application.models.Task'
}

Для первичного доступа к сгенерированному view, наследуйтесь от свойства Task.generated_view.

Чтобы упростить процесс перевода на фронтенде, используйте атрибут _translate_model вместе с названием модели.

Список мета-атрибутов для генерации view:

  • _view_class - список дополнительных классов view для наследования. Класс, унаследованный от ViewSet или строка для его импорта. Константы также поддерживаются:

    • read_only - для создания view, поддерживающего только просмотр;

    • list_only - для создания view, поддерживающего только список;

    • history - для создания view, поддерживающего только просмотр и удаление записей.

    Представление, поддерживающее все CRUD-операции, применяется по умолчанию.

  • _serializer_class - класс API сериализатора; используйте этот атрибут, чтобы указать родительский класс автоматически сгенерированных сериализаторов. По умолчанию используется vstutils.api.serializers.VSTSerializer. Принимает строку для импорта, класс сериализатора или django.utils.functional.SimpleLazyObject.

  • _serializer_class_name - название модели для OpenAPI definitions. Это название будет в сгенерированном интерфейсе администратора. По умолчанию используется имя класса.

  • _list_fields или _detail_fields - список полей, которые будут отображены в списке или детальной записи соответственно. То же, что и мета-атрибут «fields» в сериализаторах DRF.

  • _override_list_fields или _override_detail_fields - сопоставление имен и типов полей, которые будут переопределены в атрибутах сериализатора (думайте об этом как о переопределении полей в ModelSerializer из DRF).

  • _properties_groups - словарь, где ключами являются названия групп, а значениями - списки полей (строки). Позволяет группировать поля в секции на фронтенде.

  • _view_field_name - поле, которое будет использовано для вывода заголовка детальной записи.

  • _non_bulk_methods - список методов, которые не должны использовать bulk для запросов.

  • _extra_serializer_classes - сопоставление с дополнительными сериализаторами во viewset. Это может быть, например, сериализатор, который будет вычислять что-то в действии (имя сопоставления). Значением может быть строка для импорта. Важное замечание: при установке атрибута model в значение None будет использован стандартный механизм генерации сериализаторов, что позволит получить поля из list или detail сериализаторов (установите мета-атрибут сериализатора __inject_from__ в list или detail соответственно). В некоторых случаях необходимо передать модель в сериализатор. Для этих целей используйте константу LAZY_MODEL в качестве мета-атрибута. Каждый раз, когда сериализатор будет использован, конкретная модель, в которой он объявлен, будет подставлена.

  • _filterset_fields - список или словарь имен filterset для API-фильтрации. По умолчанию используется список полей list-view. При обработке списка полей проверяет наличие специальных имен полей и наследует дополнительные родительские классы. Если в списке есть id, класс будет наследован от vstutils.api.filters.DefaultIDFilter. Если есть name - от vstutils.api.filters.DefaultNameFilter. Если есть и id, и name, то класс будет наследован от обоих. Возможные значения включают list полей, которые нужно фильтровать, или dict, где ключ - имя поля, а значение - класс Filter. Использование словаря расширяет функциональность атрибута и дает возможность переопределить класс фильтра для отдельных полей (значение None выключает переопределение).

  • _search_fields - кортеж или список полей, которые должны использоваться в поисковых запросах. По умолчанию (или если установлено None) - все фильтруемые поля в detail view.

  • _copy_attrs - список полей экземпляра модели, указывающий, что экземпляр может быть скопирован с этими атрибутами.

  • _nested - сопоставление ключ-значение вложенных view (ключ - имя вложенного view, kwargs для декоратора vstutils.api.decorators.nested_view, но поддерживает атрибут model в качестве вложенного). model может быть строкой для импорта. Используйте параметр override_params в тех случаях, когда необходимо перегрузить параметры генерируемого представления в качестве вложенного (работает только когда задан model как вложенное представление).

  • _extra_view_attributes - сопоставление ключ-значение дополнительных атрибутов view, имеет меньший приоритет перед сгенерированными атрибутами.

Как правило, вы также можете добавить другие атрибуты для переопределения или расширения списка классов обработки по умолчанию. Поддерживаются filter_backends, permission_classes, authentication_classes, throttle_classes, renderer_classes и parser_classes. Список мета-атрибутов для настройки выглядит так:

  • _pre_{attribute} - Список классов, включаемых до классов по умолчанию.

  • _{attribute} - Список классов, включаемых после классов по умолчанию.

  • _override_{attribute} - булев флаг, указывающий, что атрибут переопределяет стандартный viewset (в противном случае расширяет). По умолчанию: False.

Примечание

Возможно, вам потребуется создать экшен в сгенерированном view. Используйте декоратор vstutils.models.decorators.register_view_action с аргументом detail, чтобы применить его к списку или детальной записи. В этом случае декорированный метод будет принимать экземпляр view в self.

Примечание

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

Примечание

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

General description for all actions.

action_name:
    Description for this action.

another_action:
    Description for another action.

Метод get_view_class() — это служебный метод в ORM Django моделях, предназначенный для облегчения настройки и создания экземпляров представлений Django Rest Framework (DRF). Это позволяет разработчикам определить и настроить различные аспекты класса представления DRF.

Примеры:
# Create simple list view with same fields
TaskViewSet = Task.get_view_class(view_class='list_only')

# Create view with overriding nested view params
from rest_framework.mixins import CreateModelMixin

TaskViewSet = Task.get_view_class(
    nested={
        "milestones": {
            "model": Stage,
            "override_params": {
                "view_class": ("history", CreateModelMixin)
            },
        },
    },
)

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

hidden

Если hidden установлено в True, вхождение будет исключено из запроса в BQuerySet.

id

Первичное поле для выборки и поиска в API.

class vstutils.models.Manager(*args, **kwargs)[исходный код]

Стандартный VSTUtils-менеджер. Используется классами BaseModel и BModel. Использует BQuerySet в качестве базового.

class vstutils.models.queryset.BQuerySet(model=None, query=None, using=None, hints=None)[исходный код]

Представляет ленивый поиск в базе данных множества объектов. Позволяет перегрузить итерируемый класс по умолчанию с помощью атрибута custom_iterable_class (класс с методом __iter__, возвращающий генератор объектов модели) и стандартный класс запроса с помощью атрибута custom_query_class (дочерний класс django.db.models.sql.query.Query).

cleared()[исходный код]

Фильтрует queryset для моделей с атрибутом hidden, исключая все скрытые объекты.

get_paginator(*args, **kwargs)[исходный код]

Возвращает инициализированные объекты класса vstutils.utils.Paginator через текущий экземпляр QuerySet. Все аргументы и (args) и именованные аргументы (kwargs) попадают в конструктор класса Paginator.

paged(*args, **kwargs)[исходный код]

Возвращает разбитые на страницы данные при помощи пользовательского класса Paginator. Используйте PAGE_LIMIT из глобальных настроек по умолчанию.

class vstutils.models.decorators.register_view_action(*args, **kwargs)[исходный код]

Декоратор для превращения методов модели в сгенерированные view экшены. Когда метод декорируется, он становится частью сгенерированного view, и ссылка self внутри метода указывает на объект view. Это позволяет расширять функциональность сгенерированных view с помощью пользовательских экшенов.

Декоратор register_view_action поддерживает различные аргументы, и вы можете обратиться к документации для vstutils.api.decorators.subaction(), чтобы изучить полный список поддерживаемых аргументов. Эти аргументы предоставляют гибкость в определении поведения и характеристик сгенерированных экшенов view.

Примечание

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

Примечание

Во многих случаях действие может не требовать параметров и может быть выполнено, отправив пустой запрос. Для упрощения разработки и повышения эффективности декоратор register_view_action устанавливает сериализатор по умолчанию на vstutils.api.serializers.EmptySerializer. Это означает, что действие не ожидает входных данных, что удобно для действий, которые работают без дополнительных параметров.

Пример:

В этом примере показано, как использовать декоратор для создания пользовательского действия в представлении модели. Метод empty_action становится частью сгенерированного view и не ожидает входных параметров.

from vstutils.models import BModel
from vstutils.models.decorators import register_view_action
from vstutils.api.responses import HTTP_200_OK


class MyModel(BModel):
    # ... model fields ...

    @register_view_action(detail=False, inherit=True)
    def empty_action(self, request, *args, **kwargs):
        # in this case `self` will be reference within the method points to the view object
        return HTTP_200_OK('OK')

Vstutils поддерживает модели, которые не требуют прямого взаимодействия с базой данных или не являются непосредственно таблицами в базе. Эти модели проявляют разнообразные поведения, такие как извлечение данных непосредственно из атрибутов класса, загрузка данных из файлов или реализация собственных механизмов получения данных. Замечательно, что существуют модели, которые, в каком-то смысле, реализуют механизм SQL представлений с предопределенными запросами. Эта гибкость позволяет разработчикам определять широкий спектр моделей, от моделей, существующих только в памяти, до тех, которые без проблем интегрируют внешние источники данных. Система моделей Vstutils не ограничивается традиционными структурами, поддерживаемыми базой данных, предоставляя гибкое основание для создания различных представлений данных.

class vstutils.models.custom_model.ExternalCustomModel(*args, **kwargs)[исходный код]

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

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

Для эффективного использования этой модели разработчики должны реализовать метод класса get_data_generator(). Этот метод получает объект запроса с необходимыми параметрами, позволяя разработчикам настраивать взаимодействие с внешними сервисами.

Пример:

class MyExternalModel(ExternalCustomModel):
    # ... model fields ...

    class Meta:
        managed = False

    @classmethod
    def get_data_generator(cls, query):
        data = ... # some fetched data from the external resource or generated from memory calculations.
        for row in data:
            yield row
classmethod get_data_generator(query)[исходный код]

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

Объект запроса может содержать следующие параметры:

  • filter (dict): Словарь, задающий критерии фильтрации.

  • exclude (dict): Словарь, задающий критерии исключения.

  • order_by (list): Список, задающий порядок сортировки.

  • low_mark (int): Нижний индекс для среза (если задан срез).

  • high_mark (int): Верхний индекс для среза (если задан срез).

  • is_sliced (bool): Булево значение, указывающее, является ли запрос срезом.

Параметры:

query (dict) – Объект, содержащий параметры фильтрации, лимитирования и сортировки.

Результат:

Генератор, возвращающий запрошенные данные.

Тип результата:

Generator

Исключение:

NotImplementedError – Если метод не реализован в производном классе.

class vstutils.models.custom_model.FileModel(*args, **kwargs)[исходный код]

Кастомная модель, загружающая данные из YAML-файла вместо базы данных. Путь к файлу указывается в атрибуте FileModel.file_path.

Примеры:

Предположим, что исходный файл хранится в /etc/authors.yaml со следующим содержимым:

- name: "Sergey Klyuykov"
- name: "Michael Taran"

Вы можете создать кастомную модель, используя этот файл:

from vstutils.custom_model import FileModel, CharField

class Authors(FileModel):
    name = CharField(max_length=512)

    file_path = '/etc/authors.yaml'
class vstutils.models.custom_model.ListModel(*args, **kwargs)[исходный код]

Модель, использующая список или словарь для хранения данных (атрибут ListModel.data) вместо базы данных. Полезна в том случае, если у вас простой набор данных.

Примеры:
from vstutils.custom_model import ListModel, CharField


class Authors(ListModel):
    name = CharField(max_length=512)

    data = [
        {"name": "Sergey Klyuykov"},
        {"name": "Michael Taran"},
    ]

Иногда может быть необходимо переключаться между источниками данных. Для этих целей следует использовать функцию setup_custom_queryset_kwargs, которая принимает именованные аргументы, отправляющиеся затем в функцию инициализации данных. Один из таких аргументов для ListModel - date_source, принимающий любой итерируемый объект.

Примеры:
from vstutils.custom_model import ListModel, CharField


class Authors(ListModel):
    name = CharField(max_length=512)

qs = Authors.objects.setup_custom_queryset_kwargs(data_source=[
    {"name": "Sergey Klyuykov"},
    {"name": "Michael Taran"},
])

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

Переменные:

data (list) – Список кортежей данных. Пустой по умолчанию.

class vstutils.models.custom_model.ViewCustomModel(*args, **kwargs)[исходный код]

Реализует механизм программирования SQL View над другими моделями.

Эта модель предоставляет механизм для реализации поведения, аналогичного SQL View, над другими моделями. В методе get_view_queryset() подготавливается базовый запрос, и все последующие действия реализуются поверх него.

Примеры:

class MyViewModel(ViewCustomModel):
    # ... model fields ...

    class Meta:
        managed = False

    @classmethod
    def get_view_queryset(cls):
        return SomeModel.objects.annotate(...)  # add some additional annotations to query
classmethod get_view_queryset()[исходный код]

Этот метод класса должен быть реализован в производных классах для определения пользовательской логики создания базового queryset для SQL View.

Результат:

Базовый queryset для SQL View.

Тип результата:

django.db.models.query.QuerySet

Исключение:

NotImplementedError – Если метод не реализован в производном классе.

Поля Модели

class vstutils.models.fields.FkModelField(to, on_delete, related_name=None, related_query_name=None, limit_choices_to=None, parent_link=False, to_field=None, db_constraint=True, **kwargs)[исходный код]

Расширяет django.db.models.ForeignKey. Используйте это поле в vstutils.models.BModel, чтобы получить vstutils.api.FkModelField в сериализаторе. Чтобы установить Foreign Key отношение, задайте значение to - класс модели или строка для импорта, как в django.db.models.ForeignKey

class vstutils.models.fields.HTMLField(*args, db_collation=None, **kwargs)[исходный код]

Расширяет класс django.db.models.TextField. Простое поле для хранения HTML-разметки. Поле основано на базе django.db.models.TextField, поэтому не поддерживает индексацию и не рекомендовано для использования в фильтрах.

class vstutils.models.fields.MultipleFieldFile(instance, field, name)[исходный код]

Подклассы django.db.models.fields.files.FieldFile. Предоставляют MultipleFieldFile.save() и MultipleFieldFile.delete() для управления базовым файлом, а также для обновления соответствующего экземпляра модели.

delete(save=True)[исходный код]

Удаляет файл из хранилища и из атрибута объекта.

save(name, content, save=True)[исходный код]

Сохраняет изменения в файле в хранилище и атрибут объекта.

class vstutils.models.fields.MultipleFileDescriptor(field)[исходный код]

Подклассы django.db.models.fields.files.FileDescriptor для обработки списка файлов. Возвращает список MultipleFieldFile при обращении, поэтому вы можете написать такой код:

from myapp.models import MyModel
instance = MyModel.objects.get(pk=1)
instance.files[0].size
get_file(file, instance)[исходный код]

Всегда возвращает валидный объект attr_class. За деталями реализации обратитесь к django.db.models.fields.files.FileDescriptor.__get__().

class vstutils.models.fields.MultipleFileField(**kwargs)[исходный код]

Подклассы django.db.models.fields.files.FileField. Поле для хранения списка файлов, содержащихся в хранилище. Все аргументы передаются в FileField.

attr_class

alias of MultipleFieldFile

descriptor_class

alias of MultipleFileDescriptor

class vstutils.models.fields.MultipleFileMixin(**kwargs)[исходный код]

Миксина, предназначенная для использования вместе с django.db.models.fields.files.FieldFile для преобразования его в Field вместе со списком файлов.

get_prep_value(value)[исходный код]

Подготовка значения для вставки в базу данных

pre_save(model_instance, add)[исходный код]

Вызов метода .save() для каждого файла списка

class vstutils.models.fields.MultipleImageField(**kwargs)[исходный код]

Поле для хранения списка изображения, содержащихся в хранилище. Все аргументы передаются в django.db.models.fields.files.ImageField, кроме height_field и width_field, так как они пока не реализованы.

attr_class

alias of MultipleImageFieldFile

descriptor_class

alias of MultipleFileDescriptor

class vstutils.models.fields.MultipleImageFieldFile(instance, field, name)[исходный код]

Подклассы MultipleFieldFile и ImageFile mixin, обрабатывают удаление _dimensions_cache, когда файл удаляется.

class vstutils.models.fields.MultipleNamedBinaryFileInJSONField(*args, db_collation=None, **kwargs)[исходный код]

Расширяет django.db.models.TextField. Используйте это поле в vstutils.models.BModel, чтобы получить vstutils.api.MultipleNamedBinaryFileInJSONField в сериализаторе.

class vstutils.models.fields.MultipleNamedBinaryImageInJSONField(*args, db_collation=None, **kwargs)[исходный код]

Расширяет django.db.models.TextField. Используйте это поле в vstutils.models.BModel, чтобы получить vstutils.api.MultipleNamedBinaryImageInJSONField в сериализаторе.

class vstutils.models.fields.NamedBinaryFileInJSONField(*args, db_collation=None, **kwargs)[исходный код]

Расширяет django.db.models.TextField. Используйте это поле в vstutils.models.BModel, чтобы получить vstutils.api.NamedBinaryFileInJSONField в сериализаторе.

class vstutils.models.fields.NamedBinaryImageInJSONField(*args, db_collation=None, **kwargs)[исходный код]

Расширяет django.db.models.TextField. Используйте это поле в vstutils.models.BModel, чтобы получить vstutils.api.NamedBinaryImageInJSONField в сериализаторе.

class vstutils.models.fields.WYSIWYGField(*args, db_collation=None, **kwargs)[исходный код]

Расширяет django.db.models.TextField. Простое поле для хранения строк в формате Markdown. Поле основано на django.db.models.TextField, поэтому не поддерживает индексацию и не рекомендовано для использования в фильтрах.

Веб-API

Веб-API основано на Django Rest Framework. Предоставляет дополнительные вложенные функции.

Поля

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

Дополнительные поля сериализатора для генерации OpenAPI и графического интерфейса.

class vstutils.api.fields.AutoCompletionField(*args, **kwargs)[исходный код]

Поле сериализатора, обеспечивающее автодополнение на фронтенде с использованием указанного списка объектов.

Параметры:
  • autocomplete (list, tuple, str) – Ссылка для автодополнения. Можно установить список или кортеж с значениями или указать имя определения схемы OpenAPI. Для имени определения, GUI найдет оптимальную ссылку и отобразит значения на основе аргументов autocomplete_property и autocomplete_represent.

  • autocomplete_property (str) – Указывает, какой атрибут из модели определения схемы OpenAPI использовать в качестве значения. По умолчанию „id“.

  • autocomplete_represent – Указывает, какой атрибут из модели определения схемы OpenAPI использовать в качестве представленного значения. По умолчанию „name“.

  • use_prefetch (bool) – Загружать значения на фронтенде в режиме просмотра списка. Значение по умолчанию — True.

Примечание

Эта функциональность работает только в графическом интерфейсе. В API она ведет себя так же, как и VSTCharField.

Использование:

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

Пример:

from vstutils.api import serializers
from vstutils.api.fields import AutoCompletionField


class MyModelSerializer(serializers.BaseSerializer):
    name = AutoCompletionField(autocomplete=['Option 1', 'Option 2', 'Option 3'])

# or

class MyModelSerializer(serializers.BaseSerializer):
    name = AutoCompletionField(
        autocomplete='MyModelSchema',
        autocomplete_property='custom_property',
        autocomplete_represent='display_name'
    )
class vstutils.api.fields.Barcode128Field(*args, **kwargs)[исходный код]

Поле для представления данных в виде штрихкода (Code 128) в пользовательском интерфейсе.

Это поле принимает и проверяет данные в виде допустимой ASCII-строки. Оно предназначено для отображения данных в виде штрихкода Code 128 в графическом пользовательском интерфейсе. Основные данные сериализуются или десериализуются с использованием указанного дочернего поля.

Параметры:

child (rest_framework.fields.Field) – Исходное поле данных для сериализации или десериализации. По умолчанию: rest_framework.fields.CharField

Пример:

Предположим, у вас есть модель с полем product_code, и вы хотите отображать его представление в виде штрихкода Code 128 в графическом интерфейсе пользователя. Вы можете использовать Barcode128Field в своем сериализаторе:

class Product(BModel):
    product_code = models.CharField(max_length=20)

class ProductSerializer(VSTSerializer):
    barcode = Barcode128Field(child=serializers.CharField(source='product_code'))

    class Meta:
        model = Product
        fields = '__all__'
class vstutils.api.fields.BinFileInStringField(*args, **kwargs)[исходный код]

Это поле расширяет функциональность FileInStringField и специально предназначено для обработки бинарных файлов. В интерфейсе пользователя оно выступает в качестве поля для загрузки файлов, принимая бинарные файлы от пользователя, которые затем конвертируются в строку в формате base64 и сохраняются в данном поле.

Параметры:

media_types (tuple, list) – Список MIME-типов, доступных для выбора пользователем. Поддерживается синтаксис с использованием *. По умолчанию ['*/*']

Примечание

Эта функциональность работает только в графическом интерфейсе. В API она ведет себя так же, как и VSTCharField.

class vstutils.api.fields.CSVFileField(*args, **kwargs)[исходный код]

Поле, расширяющее FileInStringField, используется для работы с csv файлами. Обеспечивает отображение загруженных данных в виде таблицы.

Параметры:
  • items (Serializer) – Конфигурация таблицы. Это сериализатор drf или vst, включающий CharField’ы, которые являются ключами словарей, и именами колонок в таблице. В ключи сериализуются данные из csv. Поля должны быть в том порядке, в котором вы хотите видеть их в таблице. Следующие опции могут также быть включены: - label: удобочитаемое название колонки - required: определяет, будет ли поле обязательным. По умолчанию False.

  • min_column_width (int) – Минимальная ширина ячейки. По умолчанию 200 px.

  • delimiter (str) – Символ-разделитель.

  • lineterminator (str) – Последовательность символов новой строки. Оставьте пустым для выбора автоматически. Возможные значения: \r, \n, \r\n.

  • quotechar (str) – Символ, используемый в качестве кавычек для полей.

  • escapechar (str) – Символ, используемый для экранирования кавычки в поле.

  • media_types (tuple,list) – Список MIME-типов, доступных для выбора пользователем. Поддерживается синтаксис с использованием *. По умолчанию ['text/csv']

class vstutils.api.fields.CommaMultiSelect(*args, **kwargs)[исходный код]

Поле, позволяющее пользователям вводить несколько значений, разделенных указанным разделителем (по умолчанию «,»). Извлекает список значений из другой модели или пользовательского списка и предоставляет автодополнение аналогично AutoCompletionField. Это поле подходит для полей-свойств модели, где основная логика уже реализована, или для использования с model.CharField.

Параметры:
  • select (str, tuple, list) – Имя определения схемы OpenAPI или список со значениями.

  • select_separator (str) – Разделитель значений. По умолчанию - запятая.

  • select_represent (select_property,) – Эти параметры работают аналогично autocomplete_property и autocomplete_represent. По умолчанию - name.

  • use_prefetch (bool) – Загружать значения на фронтенде в режиме просмотра списка. Значение по умолчанию - False.

  • make_link (bool) – Отображать значения как ссылки на модель. По умолчанию - True.

  • dependence (dict) – Словарь, где ключи - это имена полей из той же модели, а значения - названия query-фильтров. Если хотя бы одно из полей, от которых существует зависимость, не допускает null, обязательно или установлено в null, список автодополнения будет пустым, и поле будет отключено.

Пример:

from vstutils.api import serializers
from vstutils.api.fields import CommaMultiSelect

class MyModelSerializer(serializers.BaseSerializer):
    tags = CommaMultiSelect(
        select="TagsReferenceSchema",
        select_property='slug',
        select_represent='slug',
        use_prefetch=True,
        make_link=False,
        dependence={'some_field': 'value'},
    )

# or

class MyModelSerializer(serializers.BaseSerializer):
    tags = CommaMultiSelect(select=['tag1', 'tag2', 'tag3'])

Примечание

Эта функциональность работает только в графическом интерфейсе. В API она ведет себя так же, как и VSTCharField.

class vstutils.api.fields.CrontabField(*args, **kwargs)[исходный код]

Простое поле, аналогичное crontab, содержащее расписание cron-записей для указания времени. Поле crontab имеет пять полей для указания дня, даты и времени. * в поле значений выше означает все допустимые значения, указанные в скобках для данного столбца.

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

Поля времени и даты:

Поля

допустимое значение

minute

0-59

hour

0-23

day of month

1-31

month

1-12

day of week

0-7 (0 или 7 - Sunday)

Значение по умолчанию для каждого поля, если не указано, составляет

.---------------- minute (0 - 59)
| .-------------- hour (0 - 23)
| | .------------ day of month (1 - 31)
| | | .---------- month (1 - 12)
| | | | .-------- day of week (0 - 6) (Sunday=0 or 7)
| | | | |
* * * * *
class vstutils.api.fields.DeepFkField(only_last_child=False, parent_field_name='parent', **kwargs)[исходный код]

Расширяет FkModelField, специально разработанный для иерархических отношений на фронтенде.

Это поле предназначено для работы с отношениями ForeignKey в иерархической или древовидной структуре. Оно отображается в виде дерева на фронтенде, предоставляя четкое визуальное представление отношений родитель-ребенок.

Предупреждение

Это поле специально не поддерживает параметр dependence, так как работает в структуре дерева. Использование параметра filters следует приглядеться с осторожностью, поскольку неправильные фильтры могут нарушить иерархию дерева.

Параметры:
  • only_last_child (bool) – Если True, поле ограничит выбор узлов без детей. Значение по умолчанию - False. Полезно, когда вы хотите обеспечить выбор листовых узлов.

  • parent_field_name (str) – Имя поля родителя в связанной модели. Значение по умолчанию - parent. Должно быть установлено в поле ForeignKey в связанной модели, представляющее отношения родитель-ребенок. Например, если у вашей связанной модели есть ForeignKey, например, parent = models.ForeignKey(„self“, …), то parent_field_name должно быть установлено в „parent“.

Примеры:

Предположим, у вас есть связанная модель с полем ForeignKey, представляющим отношения родитель-ребенок:

class Category(BModel):
    name = models.CharField(max_length=255)
    parent = models.ForeignKey('self', null=True, default=None, on_delete=models.CASCADE)

Чтобы использовать DeepFkField с этой связанной моделью в сериализаторе, вы установили бы parent_field_name в „parent“:

class MySerializer(VSTSerializer):
    category = DeepFkField(select=Category, parent_field_name='parent')

В этом примере предполагается, что у вас есть связанная модель Category с полем ForeignKey „parent“. Затем DeepFkField отобразит категории в виде дерева на фронтенде, предоставляя интуитивно понятный механизм выбора для иерархических отношений.

Примечание

Действует только в графическом интерфейсе. Работает аналогично rest_framework.fields.IntegerField в API.

class vstutils.api.fields.DependEnumField(*args, **kwargs)[исходный код]

Поле, расширяющее DynamicJsonTypeField, но его значение не преобразуется в json, а остается как есть. Полезно при использовании property в модели или для экшенов.

Параметры:
  • field (str) – поле в модели, изменение значения которого будет менять тип текущего значения.

  • types – сопоставление ключ-значение, где ключом является значение поля-подписчика, а значением - тип (формата OpenAPI) текущего поля.

  • choices (dict) – варианты выбора для разных значений подписанных полей. Использует сопоставление, где ключом является подписанное поле, а значением - список значений для выбора.

Примечание

Действует только в графическом интерфейсе. В API работает аналогично VSTCharField без изменения значения.

class vstutils.api.fields.DependFromFkField(*args, **kwargs)[исходный код]

Специализированное поле, расширяющее DynamicJsonTypeField и проверяющее данные поля на основе field_attribute, выбранного в связанной модели. Данные поля проверяются на соответствие типу, определенному выбранным значением field_attribute.

Примечание

По умолчанию любое значение field_attribute проверяется как VSTCharField. Чтобы изменить это поведение, установите атрибут класса {field_attribute}_fields_mapping в связанной модели. Атрибут должен быть словарем, где ключи - это строковые представления значений field_attribute, а значения - экземпляры rest_framework.Field для проверки. Если значение не найдено в словаре, то тип по умолчанию будет VSTCharField.

Параметры:
  • field (str) – Поле в модели, значение которого определяет тип текущего значения. Поле должно быть типа FkModelField.

  • field_attribute (str) – Атрибут экземпляра связанной модели, содержащий имя типа.

  • types (dict) – Отображение ключ-значение, где ключ - это значение подписанного поля, а значение - тип (в формате OpenAPI) текущего поля.

Предупреждение

field_attribute в связанной модели должно быть типа rest_framework.fields.ChoicesField, иначе в графическом интерфейсе поле будет отображаться как обычное текстовое.

Пример:

Предположим, у вас есть модель с полем ForeignKey related_model и полем type_attribute в RelatedModel, которое определяет тип данных. Вы можете использовать DependFromFkField для динамической адаптации сериализации на основе значения type_attribute:

class RelatedModel(BModel):
    # ... other fields ...
    type_attribute = models.CharField(max_length=20, choices=[('type1', 'Type 1'), ('type2', 'Type 2')])

    type_attribute_fields_mapping = {
        'type1': SomeSerializer(),
        'type2': IntegerField(max_value=1337),
    }

class MyModel(BModel):
    related_model = models.ForeignKey(RelatedModel, on_delete=models.CASCADE)

class MySerializer(VSTSerializer):
    dynamic_field = DependFromFkField(
        field='related_model',
        field_attribute='type_attribute'
    )

    class Meta:
        model = MyModel
        fields = '__all__'
class vstutils.api.fields.DynamicJsonTypeField(*args, **kwargs)[исходный код]

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

Параметры:
  • field (str) – Поле в модели, изменение значения которого будет динамически определять тип текущего поля.

  • types (dict) – Отображение ключ-значение, где ключ - это значение подписанного поля, а значение - тип (в формате OpenAPI) текущего поля.

  • choices (dict) – Варианты выбора для разных значений подписанных полей. Использует отображение, где ключ - это значение подписанного поля, а значение - список значений для выбора.

  • source_view (str) – Позволяет использовать данные родительских представлений в качестве источника для создания поля. Можно указать точный путь представления (/user/{id}/) или относительный указатель родителя (<<parent>>.<<parent>>.<<parent>>). Например, если текущая страница - /user/1/role/2/, а source_view - <<parent>>.<<parent>>, то будут использованы данные из /user/1/. Поддерживаются только детальные представления.

Пример:

Предположим, у вас есть сериализатор MySerializer с полем field_type (например, ChoiceField) и соответствующим полем object_data. Поле object_data может иметь разные типы в зависимости от значения field_type. Вот пример конфигурации:

class MySerializer(VSTSerializer):
    field_type = serializers.ChoiceField(choices=['serializer', 'integer', 'boolean'])
    object_data = DynamicJsonTypeField(
        field='field_type',
        types={
            'serializer': SomeSerializer(),
            'integer': IntegerField(max_value=1337),
            'boolean': 'boolean',
        },
    )

В этом примере поле object_data динамически адаптирует свой тип в зависимости от выбранного значения field_type. Аргумент types определяет разные типы для каждого возможного значения field_type, позволяя гибкую и динамичную сериализацию.

class vstutils.api.fields.FileInStringField(*args, **kwargs)[исходный код]

Поле, расширяющее VSTCharField. Сохраняет содержимое файла в виде строки.

Поле должно быть текстовым (не бинарным). Сохраняется в модель как есть.

Параметры:

media_types (tuple, list) – Список MIME-типов, доступных для выбора пользователем. Поддерживается синтаксис с использованием *. По умолчанию ['*/*']

Примечание

Действует только в графическом интерфейсе. В API ведет себя так же, как и VSTCharField.

class vstutils.api.fields.FkField(*args, **kwargs)[исходный код]

Реализация ForeignKeyField, предназначенная для использования в сериализаторах. Это поле позволяет указать, какое поле связанной модели будет храниться в этом поле (по умолчанию: «id»), а какое поле будет представлять значение на фронтенде.

Параметры:
  • select (str) – Имя определения схемы OpenAPI.

  • autocomplete_property (str) – Указывает, какой атрибут из модели определения схемы OpenAPI использовать в качестве значения. По умолчанию „id“.

  • autocomplete_represent – Указывает, какой атрибут из модели определения схемы OpenAPI использовать в качестве представленного значения. По умолчанию „name“.

  • field_type (type) – Определяет тип поля autocomplete_property для дальнейшего описания в схеме и преобразования этого типа из API. По умолчанию пропускается, но требует объекты int или str.

  • use_prefetch (bool) – Загружать значения на фронтенде в режиме просмотра списка. Значение по умолчанию — True.

  • make_link (bool) – Отображать значение как ссылку на модель. Значение по умолчанию — True.

  • dependence (dict) – Словарь, где ключи - это имена полей из той же модели, а значения - названия query-фильтров. Если хотя бы одно из полей, от которых существует зависимость, не допускает null, обязательно или установлено в null, список автодополнения будет пустым, а поле будет отключено. Есть несколько специальных ключей dependence-словаря, с помощью которых можно получить данные, хранящиеся на фронтенде, не делая лишних запросов в базу данных: '<<pk>>' получает первичный ключ текущего экземпляра, '<<view_name>>' получает имя view из компонента Vue, '<<parent_view_name>>' получает имя родительского view из компонента Vue, '<<view_level>>' получает уровень view, '<<operation_id>>' получает operation_id, '<<parent_operation_id'>> получает родительский operation_id.

Примеры:
field = FkField(select=Category, dependence={'<<pk>>': 'my_filter'})

Этот фильтр получит первичный ключ текущего объекта и выполнит запрос на фронтенде /category?my_filter=3, где 3 - первичный ключ текущего экземпляра.

Параметры:

filters (dict) – Словарь, где ключи - это имена полей из связанной модели (указанной в этом FkField), а значения - значения этого поля.

Примечание

Пересечение dependence.values() и filters.keys() вызовет ошибку для предотвращения неоднозначной фильтрации.

Примечание

Действует только в графическом интерфейсе. Работает аналогично rest_framework.fields.IntegerField в API.

class vstutils.api.fields.FkModelField(*args, **kwargs)[исходный код]

Расширяет FkField, но хранит указанный класс модели. Это поле полезно для установки полей django.db.models.ForeignKey в модели.

Параметры:
  • select (vstutils.models.BModel,vstutils.api.serializers.VSTSerializer) – класс модели (основанный на vstutils.models.BModel) или сериализатор, используемый в API и имеющий свой путь в схеме OpenAPI.

  • autocomplete_property (str) – этот аргумент указывает, какие атрибуты будут взяты из model definition схемы OpenAPI в качестве используемого значения. По умолчанию id.

  • autocomplete_represent – этот аргумент указывает, какие атрибуты будут взяты из model definition схемы OpenAPI в качестве отображаемого значения. По умолчанию name.

  • use_prefetch – делает prefetch для значений на фронтенде в list-view. True по умолчанию.

  • make_link – Отображает значение как ссылку на модель. По умолчанию True.

Предупреждение

Класс модели получает объект из базы данных в процессе выполнения .to_internal_value. Будьте осторожны при выполнении массовых сохранений.

Предупреждение

Permission’ы модели, на которую ссылается это поле, не проверяются. Следует их проверять вручную в сигналах или валидаторах.

class vstutils.api.fields.HtmlField(*args, **kwargs)[исходный код]

Специализированное поле для обработки HTML-текстового контента, отмеченного форматом: html.

Примечание

Это поле предназначено для использования в графическом интерфейсе пользователя (GUI) и работает аналогично VSTCharField в API.

Пример:

Если у вас есть модель с полем html_content, в котором хранится HTML-форматированный текст, вы можете использовать HtmlField в своем сериализаторе для обработки этого контента в графическом интерфейсе пользователя:

class MyModel(BModel):
    html_content = models.TextField()

class MySerializer(VSTSerializer):
    formatted_html_content = HtmlField(source='html_content')

    class Meta:
        model = MyModel
        fields = '__all__'
class vstutils.api.fields.MaskedField(*args, **kwargs)[исходный код]

Расширяет класс „rest_framework.serializers.CharField“. Поле, применяющее маску к значению.

Это поле предназначено для применения маски к значению на фронтенде. Оно расширяет класс „rest_framework.serializers.CharField“ и позволяет использовать библиотеку IMask для определения масок.

Параметры:

mask (dict, str) – Маска, которая будет применена к значению. Это может быть как словарь, так и строка в формате библиотеки IMask.

Пример:

В сериализаторе включите это поле для применения маски к значению:

class MySerializer(serializers.Serializer):
    masked_value = MaskedField(mask='000-000')

В этом примере предполагается, что сериализатор имеет поле masked_value, представляющее значение с предопределенной маской. MaskedField применит указанную маску на фронтенде, предоставляя маскированный ввод для пользователей.

Примечание

Эффективность этого поля ограничивается фронтендом, и маска применяется при вводе пользователя.

class vstutils.api.fields.MultipleNamedBinaryFileInJsonField(*args, **kwargs)[исходный код]

Расширяет NamedBinaryFileInJsonField, но использует список JSON’ов. Позволяет оперировать несколькими файлами через список объектов NamedBinaryFileInJsonField.

Атрибуты: NamedBinaryInJsonField.file: если True, принимает только подклассы File в качестве входных данных. Если False, принимает только значения типа string. По умолчанию: False.

file_field

alias of MultipleFieldFile

class vstutils.api.fields.MultipleNamedBinaryImageInJsonField(*args, **kwargs)[исходный код]

Расширяет MultipleNamedBinaryFileInJsonField, но использует список JSON’ов. Используется для оперирования несколькими изображениями и работает как список объектов NamedBinaryImageInJsonField.

Параметры:

background_fill_color (str) – Цвет для заполнения области, не покрытой изображением после обрезки. По умолчанию прозрачный, но будет черным, если формат изображения не поддерживает прозрачность. Может быть любым допустимым цветом CSS.

class vstutils.api.fields.NamedBinaryFileInJsonField(*args, **kwargs)[исходный код]

Поле, представляющее бинарный файл в формате JSON.

Параметры:
  • file (bool) – Если True, принимает только подклассы File в качестве входных данных. Если False, принимает только строковые входные данные. По умолчанию: False.

  • post_handlers (tuple,list) – Функции для обработки файла после валидации. Каждая функция принимает два аргумента: binary_data (байты файла) и original_data (ссылка на исходный JSON-объект). Функция должна возвращать обработанный binary_data.

  • pre_handlers (tuple,list) – Функции для обработки файла перед валидацией. Каждая функция принимает два аргумента: binary_data (байты файла) и original_data (ссылка на исходный JSON-объект). Функция должна возвращать обработанный binary_data.

  • max_content_size (int) – Максимально допустимый размер содержимого файла в байтах.

  • min_content_size (int) – Минимально допустимый размер содержимого файла в байтах.

  • min_length (int) – Минимальная длина имени файла. Применяется только при file=True.

  • max_length (int) – Максимальная длина имени файла. Применяется только при file=True.

Это поле предназначено для хранения бинарных файлов вместе с их именами в полях модели django.db.models.CharField или django.db.models.TextField. Все манипуляции, связанные с декодированием и кодированием данных бинарного содержимого, выполняются на клиенте, что накладывает разумные ограничения на размер файла.

Кроме того, это поле может создать django.core.files.uploadedfile.SimpleUploadedFile из входящего JSON и сохранить его как файл в django.db.models.FileField, если атрибут file установлен в значение True.

Пример:

В сериализаторе включите это поле для обработки бинарных файлов:

class MySerializer(serializers.ModelSerializer):
    binary_data = NamedBinaryFileInJsonField(file=True)

В этом примере предполагается, что в сериализаторе поле binary_data представляет информацию о бинарном файле в формате JSON. Поле NamedBinaryFileInJsonField обеспечит обработку хранения и извлечения бинарных файлов удобным для пользователя образом.

Бинарный файл представлен в формате JSON со следующими свойствами:

  • name (str): Имя файла.

  • mediaType (str): MIME-тип файла.

  • content (str или File): Содержимое файла. Если file установлен в True, это будет ссылка на файл; в противном случае содержимое будет закодировано base64.

Предупреждение

Приложение клиента отобразит содержимое в виде ссылки для скачивания. Пользователи будут взаимодействовать с бинарным файлом через приложение, а обмен между Rest API и клиентом будет происходить через представленный объект JSON.

class vstutils.api.fields.NamedBinaryImageInJsonField(*args, **kwargs)[исходный код]

Поле, представляющее изображение в формате JSON, расширяющее NamedBinaryFileInJsonField.

Параметры:

background_fill_color (str) – Цвет для заполнения области, не покрытой изображением после обрезки. По умолчанию прозрачный, но будет черным, если формат изображения не поддерживает прозрачность. Может быть любым допустимым цветом CSS.

Это поле предназначено для хранения бинарных файлов вместе с их именами в полях модели django.db.models.CharField или django.db.models.TextField. Оно расширяет возможности NamedBinaryFileInJsonField для специальной обработки изображений.

Кроме того, это поле проверяет изображение с использованием следующих валидаторов: - vstutils.api.validators.ImageValidator - vstutils.api.validators.ImageResolutionValidator - vstutils.api.validators.ImageHeightValidator

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

Бинарный файл представлен в формате JSON со следующими свойствами:

  • name (str): Имя файла изображения.

  • mediaType (str): MIME-тип файла изображения.

  • content (str или File): Содержимое файла изображения. Если file установлен в True, это будет ссылка на файл; в противном случае содержимое будет закодировано base64.

Предупреждение

Приложение клиента отобразит содержимое как изображение. Пользователи будут взаимодействовать с изображением через приложение, и обмен между Rest API и клиентом будет происходить через представленный объект JSON.

class vstutils.api.fields.PasswordField(*args, **kwargs)[исходный код]

Расширяет CharField, но в схеме имеет format = password. В пользовательском интерфейсе отображает все символы как звездочки вместо реально введенных данных.

class vstutils.api.fields.PhoneField(*args, **kwargs)[исходный код]

Расширяет класс „rest_framework.serializers.CharField“. Поле для представления номера телефона в международном формате.

Это поле предназначено для захвата и валидации номеров телефонов в международном формате. Оно расширяет класс „rest_framework.serializers.CharField“ и добавляет пользовательскую валидацию для обеспечения того, что номер телефона содержит только цифры.

Пример:

В сериализаторе включите это поле для обработки номеров телефонов:

class MySerializer(VSTSerializer):
    phone_number = PhoneField()

В этом примере предполагается, что сериализатор имеет поле phone_number, представляющее номер телефона в международном формате. PhoneField затем обработает валидацию и представление номеров телефонов, облегчая пользователям ввод стандартизированных номеров телефонов.

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

class vstutils.api.fields.QrCodeField(*args, **kwargs)[исходный код]

Универсальное поле для кодирования различных типов данных в QR-коды.

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

Параметры:

child (rest_framework.fields.Field) – Исходное поле данных для сериализации или десериализации. По умолчанию: rest_framework.fields.CharField

Пример:

Предположим, у вас есть модель с полем data, и вы хотите отображать его представление в виде QR-кода в графическом интерфейсе пользователя. Вы можете использовать QrCodeField в своем сериализаторе:

class MyModel(BModel):
    data = models.CharField(max_length=255)

class MySerializer(VSTSerializer):
    qr_code_data = QrCodeField(child=serializers.CharField(source='data'))

    class Meta:
        model = MyModel
        fields = '__all__'

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

class vstutils.api.fields.RatingField(min_value=0, max_value=5, step=1, front_style='stars', **kwargs)[исходный код]

Расширяет класс „rest_framework.serializers.FloatField“. Это поле представляет собой ввод рейтинга пользователем на фронтенде. Пределы оценок могут быть заданы с помощью „min_value=“ и „max_value=“, по умолчанию 0 и 5 соответственно. Минимальный шаг между оценками определяется параметром „step=“, по умолчанию 1. Внешний вид на фронтенде может быть выбран с помощью „front_style=“, доступные варианты перечислены в „self.valid_front_styles“.

Для стиля „slider“ вы можете указать цвет слайдера, передав валидный цвет в „color=“. Для стиля „fa_icon“ вы можете указать иконку FontAwesome, которая будет использована для отображения рейтинга, передав валидный код иконки FontAwesome в „fa_class=“.

Параметры:
  • min_value (float, int) – минимальный уровень

  • max_value (float, int) – максимальный уровень

  • step (float, int) – минимальный шаг между уровнями

  • front_style (str) – визуализация поля на фронтенде. Допустимы: [„stars“, „slider“, „fa_icon“].

  • color (str) – цвет элемента рейтинга (star, icon или slider) в формате css

  • fa_class (str) – код иконки FontAwesome

class vstutils.api.fields.RedirectCharField(*args, **kwargs)[исходный код]

Поле для редиректа по строке. Часто используется в экшенах для редиректа после выполнения.

Примечание

Действует только в графическом интерфейсе. Работает аналогично rest_framework.fields.IntegerField в API.

class vstutils.api.fields.RedirectFieldMixin(**kwargs)[исходный код]

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

Параметры:
  • operation_name (str) – префикс для operation_id, например, если operation_id = history_get, то operation_name = history

  • depend_field (str) – имя поля, от которого оно зависит, его значение будет использовано для operation_id

  • concat_field_name (bool) – если True, то имя поля будет добавлено в конец operation_id

class vstutils.api.fields.RedirectIntegerField(*args, **kwargs)[исходный код]

Поля для редиректа по id. Часто используется в экшенах для редиректа после выполнения.

Примечание

Действует только в графическом интерфейсе. Работает аналогично rest_framework.fields.IntegerField в API.

class vstutils.api.fields.RelatedListField(related_name, fields, view_type='list', serializer_class=None, **kwargs)[исходный код]

Расширяет класс VSTCharField. Представляет обратное ForeignKey отношение в виде списка связанных экземпляров.

Это поле позволяет представить обратное ForeignKey отношение в виде списка связанных экземпляров. Для использования укажите related_name (related manager для обратного ForeignKey) и fields (список или кортеж полей из связанной модели, которые должны быть включены).

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

Параметры:
  • related_name (str) – Имя related manager для обратного ForeignKey.

  • fields (list[str], tuple[str]) – Список связанных полей модели.

  • view_type (str) – Определяет, как поля будут представлены на фронтенде. Должен быть либо list, либо table.

  • fields_custom_handlers_mapping (dict) – Отображение пользовательских обработчиков, где ключ: field_name, значение: callable_obj, принимающий параметры: instance[dict], fields_mapping[dict], model, field_name[str].

  • serializer_class (type) – Сериализатор для настройки типов полей. Если сериализатор не предоставлен, будет использован VSTCharField для каждого поля из списка fields.

class vstutils.api.fields.SecretFileInString(*args, **kwargs)[исходный код]

Поле, расширяющее FileInStringField, но скрывающее свое значение в интерфейсе администратора.

Поле должно быть текстовым (не бинарным). Сохраняется в модель как есть.

Параметры:

media_types (tuple, list) – Список MIME-типов, доступных для выбора пользователем. Поддерживается синтаксис с использованием *. По умолчанию ['*/*']

Примечание

Действует только в графическом интерфейсе. В API ведет себя так же, как и VSTCharField.

class vstutils.api.fields.TextareaField(*args, **kwargs)[исходный код]

A specialized field that allows the input and display of multiline text.

Примечание

Это поле предназначено для использования в графическом интерфейсе пользователя (GUI) и работает аналогично VSTCharField в API.

Пример:

Suppose you have a model with a description field that can contain multiline text. You can use TextareaField in your serializer to enable users to input and view multiline text in the GUI:

class MyModel(BModel):
    description = models.TextField()

class MySerializer(VSTSerializer):
    multiline_description = TextareaField(source='description')

    class Meta:
        model = MyModel
        fields = '__all__'
class vstutils.api.fields.UptimeField(*args, **kwargs)[исходный код]

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

Это поле действует только в графическом интерфейсе и ведет себя аналогично rest_framework.fields.IntegerField в API.

Класс UptimeField преобразует время в секундах в удобочитаемое представление на фронтенде. Он интеллектуально выбирает наиболее подходящий шаблон из следующих:

  • HH:mm:ss (e.g., 23:59:59)

  • dd HH:mm:ss (e.g., 01d 00:00:00)

  • mm dd HH:mm:ss (e.g., 01m 30d 00:00:00)

  • yy mm dd HH:mm:ss (e.g., 99y 11m 30d 22:23:24)

Пример:

class MySerializer(serializers.ModelSerializer):
    uptime = UptimeField()

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

Примечание

Действует только в графическом интерфейсе. Работает аналогично rest_framework.fields.IntegerField в API.

class vstutils.api.fields.VSTCharField(*args, **kwargs)[исходный код]

CharField (расширяет rest_framework.fields.CharField). Это поле преобразует любой json в строку для модели.

class vstutils.api.fields.WYSIWYGField(*args, **kwargs)[исходный код]

Расширяет класс TextareaField для отображения редактора https://ui.toast.com/tui-на фронтенде.

Это поле специально разработано для отображения WYSIWYG-редактора на фронтенде с использованием https://ui.toast.com/tui-editor. Сохраняет данные в формате markdown и экранирует все HTML-теги.

Параметры:

escape (bool) – Экранирование HTML-тегов для входных данных. Включено по умолчанию для предотвращения уязвимостей HTML-инъекций.

Пример:

Включите это поле в сериализаторе, чтобы отобразить WYSIWYG-редактор на фронтенде:

class MySerializer(serializers.Serializer):
    wysiwyg_content = WYSIWYGField()

В этом примере предполагается, что сериализатор имеет поле wysiwyg_content, представляющее данные, которые должны быть отображены в WYSIWYG-редакторе на фронтенде. WYSIWYGField гарантирует, что содержимое сохраняется в формате markdown, и HTML-теги экранируются для повышения безопасности.

Предупреждение

Рекомендуется включить опцию escape для предотвращения потенциальных уязвимостей HTML-инъекций.

Примечание

Отображение на фронтенде достигается с использованием https://ui.toast.com/tui-editor.

Валидаторы

Классы для валидации полей.

class vstutils.api.validators.FileMediaTypeValidator(extensions=None, **kwargs)[исходный код]

Базовый класс для валидации изображений. Проверяет media types.

Параметры:

extensions (typing.Union[typing.Tuple, typing.List, None]) – Кортеж или список файловых расширений, которые должны проходить проверку.

Выбрасывает rest_framework.exceptions.ValidationError в случае, если расширение файла не присутствует в списке

class vstutils.api.validators.ImageBaseSizeValidator(extensions=None, **kwargs)[исходный код]

Проверяет размер изображения. Чтобы использовать этот класс для валидации ширины или высоты, переопределите self.orientation в („height“,), („width“,) или („height“, „width“)

Выбрасывает rest_framework.exceptions.ValidationError, если not(min <= (height or width) <= max)

Параметры:

extensions (typing.Union[typing.Tuple, typing.List, None]) –

class vstutils.api.validators.ImageHeightValidator(extensions=None, **kwargs)[исходный код]

Обертка для ImageBaseSizeValidator, проверяющая только высоту

Параметры:
  • min_height – минимальная валидная высота изображения

  • max_height – максимальная валидная высота изображения

  • extensions (typing.Union[typing.Tuple, typing.List, None]) –

class vstutils.api.validators.ImageOpenValidator(extensions=None, **kwargs)[исходный код]

Валидатор изображения, который проверяет, может ли изображения быть распаковано из b64 в объект PIL Image. Не будет работать, если не установлен Pillow.

Выбрасывает rest_framework.exceptions.ValidationError, если PIL выбрасывает ошибку при попытке открыть изображение

Параметры:

extensions (typing.Union[typing.Tuple, typing.List, None]) –

class vstutils.api.validators.ImageResolutionValidator(extensions=None, **kwargs)[исходный код]

Обертка для ImageBaseSizeValidator, проверяющая как высоту, так и ширину.

Параметры:
  • min_height – минимальная валидная высота изображения

  • max_height – максимальная валидная высота изображения

  • min_width – минимальная валидная ширина изображения

  • max_width – максимальная валидная ширина изображения

  • extensions (typing.Union[typing.Tuple, typing.List, None]) –

class vstutils.api.validators.ImageValidator(extensions=None, **kwargs)[исходный код]

Базовый класс для валидации изображения. Проверяет формат изображения. Не будет работать, если Pillow не установлен. Базовый класс для валидации изображения. Проверяет media types.

Параметры:

extensions (typing.Union[typing.Tuple, typing.List, None]) – Кортеж или список файловых расширений, которые должны проходить проверку.

Выбрасывает rest_framework.exceptions.ValidationError в случае, если расширение файла не присутствует в списке

property has_pillow

Проверьте, установлен ли Pillow

class vstutils.api.validators.ImageWidthValidator(extensions=None, **kwargs)[исходный код]

Обертка для ImageBaseSizeValidator, проверяющая только ширину

Параметры:
  • min_width – минимальная валидная ширина изображения

  • max_width – максимальная валидная ширина изображения

  • extensions (typing.Union[typing.Tuple, typing.List, None]) –

class vstutils.api.validators.RegularExpressionValidator(regexp=None)[исходный код]

Класс для валидации на основе регулярного выражения

Исключение:

rest_framework.exceptions.ValidationError – в случае, если значение не соответствует регулярному выражению

Параметры:

regexp (typing.Optional[typing.Pattern]) –

class vstutils.api.validators.UrlQueryStringValidator(regexp=None)[исходный код]

Класс для валидации строки url query, например a=&b=1

Параметры:

regexp (typing.Optional[typing.Pattern]) –

vstutils.api.validators.resize_image(img, width, height)[исходный код]

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

Параметры:
  • img (PIL.Image) – объект Pillow Image

  • width (int) – Необходимая ширина

  • height (int) – Необходимая высота

Результат:

объект Pillow Image

Тип результата:

PIL.Image

vstutils.api.validators.resize_image_from_to(img, limits)[исходный код]

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

Параметры:
  • img (PIL.Image) – объект Pillow Image

  • limits (dict) – Словарь с максимальным/минимальным ограничениями, например {'width': {'min': 300, 'max: 600'}, 'height':  {'min': 400, 'max: 800'}}

Результат:

объект Pillow Image

Тип результата:

PIL.Image

Сериализаторы

Стандартные классы сериализаторов для web-api. Читайте подробнее в документации сериализаторов Django REST Framework Serializers.

class vstutils.api.serializers.BaseSerializer(*args, **kwargs)[исходный код]

Сериализатор по умолчанию с логикой для работы с объектами.

Этот сериализатор служит базовым классом для создания сериализаторов для работы с объектами, не являющимися моделями. Он расширяет класс „rest_framework.serializers.Serializer“ и включает дополнительную логику для обработки создания и обновления объектов.

Примечание

Вы также можете настроить generated_fields в атрибуте класса Meta, чтобы получить сериализатор с полями CharField по умолчанию. Настройте атрибут generated_field_factory чтобы изменить фабричный метод по умолчанию.

Пример:

class MySerializer(BaseSerializer):
    class Meta:
        generated_fields = ['additional_field']
        generated_field_factory = lambda f: drf_fields.IntegerField()

В этом примере класс MySerializer расширяет BaseSerializer и включает дополнительное созданное поле.

class vstutils.api.serializers.DisplayMode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[исходный код]

Для любого сериализатора, показанного на фронтенде, аттрибут _display_mode может принимать одно из следующих значений.

DEFAULT = 'DEFAULT'

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

STEP = 'STEP'

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

class vstutils.api.serializers.EmptySerializer(*args, **kwargs)[исходный код]

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

class vstutils.api.serializers.VSTSerializer(*args, **kwargs)[исходный код]

Сериализатор модели по умолчанию, основанный на rest_framework.serializers.ModelSerializer. Узнайте больше в документации DRF о том, как создавать сериализаторы модели. Этот сериализатор сопоставляет поля модели с расширенным набором полей сериализатора.

Список доступных пар, указанных в VSTSerializer.serializer_field_mapping. Например, чтобы установить vstutils.api.fields.FkModelField в сериализаторе, используйте vstutils.models.fields.FkModelField в модели.

Пример:

class MyModel(models.Model):
    name = models.CharField(max_length=255)

class MySerializer(VSTSerializer):
    class Meta:
        model = MyModel

В этом примере класс MySerializer расширяет VSTSerializer и ассоциируется с моделью MyModel.

Представления

VSTUtils расширяет стандартное поведение ViewSets из Django REST Framework (DRF), предоставляя встроенные механизмы для управления представлениями моделей, которые удовлетворяют наиболее часто встречающимся паттернам разработки. Это улучшение фреймворка упрощает процесс создания надежных и масштабируемых веб-приложений, предлагая богатый набор инструментов и утилит, которые автоматизируют большую часть шаблонного кода, необходимого при разработке API. Благодаря этим расширениям, разработчики могут легко реализовать пользовательскую бизнес-логику, валидацию данных и контроль доступа с минимальными усилиями, тем самым значительно сокращая время разработки и улучшая поддерживаемость кода.

class vstutils.api.base.CopyMixin(**kwargs)[исходный код]

Миксина для viewset’ов, добавляющая copy endpoint во view.

copy(request, **kwargs)[исходный код]

Endpoint, который копирует экземпляр с его зависимостями.

copy_field_name = 'name'

Имя поля, которое получит префикс.

copy_prefix = 'copy-'

Значение префикса, которое будет добавлено к новому имени экземпляра.

Список связанных имен, которые будут скопированы в новый экземпляр.

class vstutils.api.base.FileResponseRetrieveMixin(**kwargs)[исходный код]

Миксина ViewSet для получения FileResponse из моделей с файловыми полями.

Пример:

import datetime
import os
from django.db import models
from django.db.models.functions import Now
from rest_framework import permissions, fields as drf_fields
from vstutils.api.serializers import BaseSerializer, DataSerializer
from vstutils.models.decorators import register_view_action
from vstutils.models.custom_model import ListModel, FileModel, ViewCustomModel
from vstutils.api import fields, base, responses

from .cacheable import CachableModel


class TestQuerySerializer(BaseSerializer):
    test_value = drf_fields.ChoiceField(required=True, choices=("TEST1", "TEST2"))


class FileViewMixin(base.FileResponseRetrieveMixin):
    # required always
    instance_field_data = 'value'
    # required for response caching in browser
    instance_field_timestamp = 'updated'
    @register_view_action(
        methods=['get'],
        detail=False,
        query_serializer=TestQuerySerializer,
        serializer_class=DataSerializer,
        suffix='Instance'
    )
    def query_serializer_test(self, request):
        query_validated_data = self.get_query_serialized_data(request)
        return responses.HTTP_200_OK(query_validated_data)

    @register_view_action(
        methods=['get'],
        detail=False,
        query_serializer=TestQuerySerializer,
        is_list=True
    )
    def query_serializer_test_list(self, request):
        return self.list(request)
serializer_class_retrieve

alias of FileResponse

class vstutils.api.base.GenericViewSet(**kwargs)[исходный код]

Базовый класс для всех view. Расширяет стандартные функции классов DRF. Здесь представлены некоторые из возможностей:

  • Предоставляет атрибуты model вместо queryset.

  • Позволяет устанавливать сериализаторы отдельно для каждого экшена через словарь action_serializers или атрибуты, имя которых соответствует шаблону serializer_class_[action name].

  • Позволяет отдельно указать сериализаторы для view списков и детальной записи.

  • Оптимизирует запросы в базу данных для GET-запросов, делая выборку, если возможно, только тех полей, которые нужны сериализатору.

create_action_serializer(*args, **kwargs)[исходный код]

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

Параметры:
  • autosave (bool) – Включает/выключает выполнение сохранения сериализатором, если передан именованный аргумент data. Включено по умолчанию.

  • custom_data (dict) – Словарь с данными, которые будут переданы в validated_data без валидации.

  • serializer_class (None,type[rest_framework.serializers.Serializer]) – Класс сериализатора для текущего выполнения. Может быть полезно, когда сериализаторы запроса и ответа различны.

параметр:

data: Стандартный аргумент класса сериализатора с сериализуемыми данными. Включает в себя валидацию и сохранение.

параметр:

instance: Стандартный аргумент класса сериализатора с сериализуемым экземпляром.

Результат:

Готовый сериализатор с логикой выполнения по умолчанию.

Тип результата:

rest_framework.serializers.Serializer

get_query_serialized_data(request, query_serializer=None, raise_exception=True)[исходный код]

Позволяет получить данные запроса и сериализовать значения, если существует атрибут query_serializer_class или атрибут был передан.

Параметры:
  • request – объект DRF запроса.

  • query_serializer – класс сериализатора, для обработки параметров в query_params.

  • raise_exception – флаг, который говорит о том нужно ли выбросить исключение при валидации в сериализаторе или нет.

get_serializer(*args, **kwargs)[исходный код]

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

Позволяет использовать django.http.StreamingHttpResponse в качестве инициализации сериализатора.

get_serializer_class()[исходный код]

Позволяет задать класс сериализатора для каждого экшена.

nested_allow_check()[исходный код]

Просто выбросьте исключение или пропустите (pass). Используется во вложенных view для упрощения проверки доступа.

class vstutils.api.base.HistoryModelViewSet(**kwargs)[исходный код]

Стандартный viewset, как, например ReadOnlyModelViewSet, но для данных исторического характера (позволяет удалять записи, но не создавать или обновлять). Наследуется от GenericViewSet.

class vstutils.api.base.ModelViewSet(**kwargs)[исходный код]

Viewset, предоставляющий CRUD-экшены над моделью. Наследуется от GenericViewSet.

Переменные:
Примеры:
from vstutils.api.base import ModelViewSet
from . import serializers as sers


class StageViewSet(ModelViewSet):
    # This is difference with DRF:
    # we use model instead of queryset
    model = sers.models.Stage
    # Serializer for list view (view for a list of Model instances
    serializer_class = sers.StageSerializer
    # Serializer for page view (view for one Model instance).
    # This property is not required, if its value is the same as `serializer_class`.
    serializer_class_one = sers.StageSerializer
    # Allowed to set decorator to custom endpoint like this:
    # serializer_class_create - for create method
    # serializer_class_copy - for detail endpoint `copy`.
    # etc...
class vstutils.api.base.ReadOnlyModelViewSet(**kwargs)[исходный код]

Стандартный viewset, как, например vstutils.api.base.ModelViewSet для readonly-моделей. Наследуется от GenericViewSet.

class vstutils.api.decorators.nested_view(name, arg=None, methods=None, *args, **kwargs)[исходный код]

По умолчанию DRF не поддерживает вложенные view. Данный декоратор решает эту проблему.

Вам нужны две или более модели с вложенными отношениями (многие-ко-многим или многие-к-одному) и два viewset’а. Декоратор вкладывает viewset’ы в родительский класс viewset’ов и генерирует пути в API.

Параметры:
  • name (str) – Имя вложенного пути. Также используется стандартное имя для связанных queryset’ов (см. manager_name).

  • arg (str) – Имя вложенного поля первичного ключа.

  • view (vstutils.api.base.ModelViewSet, vstutils.api.base.HistoryModelViewSet, vstutils.api.base.ReadOnlyModelViewSet) – Класс вложенного viewset’а.

  • allow_append (bool) – Флаг, разрешающий добавление существующих экземпляров.

  • manager_name (str,Callable) – Имя атрибута объекта модели, который содержит вложенный queryset.

  • methods (list) – Список разрешенных методов для endpoint’ов вложенных view.

  • subs (list,None) – Список разрешенных subviews или экшенов для endpoint’ов вложенных views.

  • queryset_filters – Список вызываемых объектов, которые возвращают отфильтрованный queryset.

Примечание

Некоторые методы view не будут вызваны из соображений производительности. Это также применяется к некоторым атрибутам класса, которые обычно инициализируются в методах. Например, .initial() никогда не будет вызван. Каждый viewset обернут вложенным классом с дополнительной логикой.

Пример:

from vstutils.api.decorators import nested_view
from vstutils.api.base import ModelViewSet
from . import serializers as sers


class StageViewSet(ModelViewSet):
    model = sers.models.Stage
    serializer_class = sers.StageSerializer


nested_view('stages', 'id', view=StageViewSet)
class TaskViewSet(ModelViewSet):
    model = sers.models.Task
    serializer_class = sers.TaskSerializer

Данный код генерирует пути api:

  • /tasks/ - GET, POST

  • /tasks/{id}/ - GET, PUT, PATCH, DELETE

  • /tasks/{id}/stages/ - GET, POST

  • /tasks/{id}/stages/{stages_id}/ - GET, PUT, PATCH, DELETE

vstutils.api.decorators.subaction(*args, **kwargs)[исходный код]

Декоратор, оборачивающий метод объекта в subaction viewset’а.

Параметры:
  • methods – Список разрешенных методов HTTP. По умолчанию ["post"].

  • detail – Флаг, указывающий, должен ли метод применяться к одному экземпляру.

  • serializer_class – Сериализатор для этого экшена.

  • permission_classes – Кортеж или список permission-классов.

  • url_path – Имя API-пути для этого экшена.

  • description – Описание этого экшена в OpenAPI.

  • multiaction – Разрешает использовать этот экшен в мультиэкшенах. Работает только с vstutils.api.serializers.EmptySerializer в response.

  • require_confirmation – Задает, должен ли экшен требовать подтверждения перед выполнением.

  • is_list – Отметить это действие как пагинируемый список со всеми правилами и параметрами.

  • title – Заменить заголовок действия.

  • icons – Настроить классы иконок действия.


ETag (Entity Tag) — это механизм, определенный протоколом HTTP для проверки кэша веба и эффективного управления версиями ресурсов. Он представляет собой уникальный идентификатор содержимого ресурса на определенный момент времени, позволяя клиенту и серверу определить, изменился ли ресурс без необходимости загружать весь контент. Этот механизм значительно сокращает использование полосы пропускания и улучшает производительность веба за счет использования условных запросов. Серверы отправляют ETags в ответах клиентам, которые могут кэшировать эти теги вместе с ресурсами. При последующих запросах клиенты отправляют кэшированный ETag обратно на сервер в заголовке If-None-Match. Если ресурс не изменился (ETag совпадает), сервер отвечает статусом 304 Not Modified, указывая, что кэшированная версия клиента актуальна.

Помимо GET-запросов, ETags также могут быть полезны в других методах HTTP, таких как PUT или DELETE, для обеспечения согласованности и предотвращения непреднамеренных перезаписей или удалений, известных как «избежание столкновений в воздухе». Включая ETag в заголовок If-Match не-GET запросов, клиенты сигнализируют, что операция должна продолжаться только в том случае, если текущее состояние ресурса соответствует указанному ETag, тем самым защищая от одновременных изменений разными клиентами. Это применение ETags повышает надежность и целостность веб-приложений, гарантируя выполнение операций с корректной версией ресурса.

Вот основные функции, предоставляемые для работы с механизмом ETag:

class vstutils.api.base.CachableHeadMixin(**kwargs)[исходный код]

Миксин, предназначенный для улучшения кэширования ответов на GET-запросы в представлениях Django REST framework, используя стандартный механизм кэширования HTTP. Он возвращает статус 304 Not Modified для чтения запросов, таких как GET или HEAD, когда ETag (Entity Tag) в запросе клиента совпадает с текущим состоянием ресурса, и статус 412 Precondition Failed для записывающих запросов, когда условие не выполняется. Этот подход снижает ненужный сетевой трафик и время загрузки для неизменных ресурсов, а также обеспечивает согласованность данных для операций записи.

Миксин использует функции get_etag_value() и check_request_etag() в контексте GenericViewSet для динамического создания и проверки ETag для состояний ресурсов. Сравнивая ETag, он определяет, изменилось ли содержимое с момента последнего запроса, позволяя клиентам повторно использовать кэшированные ответы, когда это применимо, и предотвращая одновременные операции записи от перезаписи друг друга без подтверждения обновленного состояния.

Предупреждение

Этот миксин разработан для работы с моделями, наследующими от vstutils.models.BModel. Использование с другими моделями может не обеспечить предполагаемое поведение кэширования и может привести к некорректному поведению приложения.

Примечание

Для эффективного использования убедитесь, что классы моделей совместимы с генерацией и проверкой ETag, реализовав метод get_etag_value() для пользовательского вычисления ETag. Кроме того, GenericViewSet, использующий этот миксин, должен правильно обрабатывать заголовки ETag в запросах клиентов для использования кэширования HTTP.

Дополнительной особенностью CachableHeadMixin является его автоматическое включение в сгенерированное представление из vstutils.models.BModel, если класс модели имеет атрибут класса _cache_responses, установленный в True. Это позволяет автоматизировать возможности кэширования для моделей, указывающих на готовность к кэшированию на основе HTTP, оптимизируя процесс сокращения времени ответа и снижения нагрузки на сервер для часто доступных ресурсов.

class vstutils.api.base.EtagDependency(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[исходный код]

Пользовательское перечисление, определяющее потенциальные зависимости для генерации ETag. Оно включает:

LANG = 4

Указывает на зависимость от языковых предпочтений пользователя.

SESSION = 2

Указывает на зависимость от сессии пользователя.

USER = 1

Указывает на зависимость от идентичности пользователя.

vstutils.api.base.check_request_etag(request, etag_value, header_name='If-None-Match', operation_handler=<slot wrapper '__eq__' of 'str' objects>)[исходный код]

Функция играет ключевую роль в контексте механизма ETag, предоставляя гибкий способ проверки ETags на стороне клиента по сравнению с версией на стороне сервера как для проверки кэша, так и для обеспечения согласованности данных в веб-приложениях. Она поддерживает условную обработку HTTP-запросов на основе совпадения или несовпадения значений ETag, адаптируясь к различным сценариям, таким как проверки свежести кэша и предотвращение одновременных изменений.

Параметры:
  • request (rest_framework.request.Request) – Объект HTTP-запроса, содержащий заголовки клиента, из которых извлекается ETag для сравнения.

  • etag_value (str) – ETag, сгенерированный сервером, представляет текущее состояние ресурса. Этот уникальный идентификатор пересчитывается при каждом изменении содержимого ресурса.

  • header_name (str) – Указывает HTTP-заголовок для поиска ETag клиента. По умолчанию используется «If-None-Match», обычно используемый в GET-запросах для проверки кэша. Для операций, требующих подтверждения того, что клиент действует с последней версией ресурса (например, PUT или DELETE), вместо этого следует использовать «If-Match».

  • operation_handler – Функция для сравнения ETags. По умолчанию установлено str.__eq__, которое проверяет точное совпадение ETags клиента и сервера, подходящее для проверки кэшей с If-None-Match. Для обработки сценариев If-Match, когда операция должна продолжаться только в случае, если ETags не совпадают, указывая на то, что ресурс был изменен, можно использовать str.__ne__ (не равно) в качестве обработчика операции. Эта гибкость позволяет точно контролировать, как и когда клиентам разрешено читать или записывать ресурсы на основе их версии.

Результат:

Возвращает кортеж, содержащий ETag сервера и булев флаг. Флаг равен True, если условие обработчика операции между ETag сервера и клиента выполнено, указывая на то, что запрос должен продолжаться на основе логики сопоставления, определенной обработчиком операции; в противном случае возвращает False.

vstutils.api.base.get_etag_value(view, model_class, request, pk=None)[исходный код]

Функция get_etag_value предназначена для вычисления уникального значения ETag на основе состояния модели, параметров запроса и дополнительных зависимостей, таких как язык пользователя, сессия и идентичность пользователя. Эта функция поддерживает как отдельные модели, так и коллекции моделей.

Параметры:
  • view (GenericViewSet) – Экземпляр GenericViewSet, отвечающий за операции просмотра.

  • model_class (django.db.models.Model, list, tuple, or set) – Класс модели, для которой генерируется значение ETag. Этот параметр может быть одним классом модели или коллекцией классов моделей (list, tuple или set). Каждый класс модели может необязательно реализовать метод класса с именем get_etag_value.

  • request (rest_framework.request.Request) – Объект запроса из Django REST framework, содержащий всю информацию HTTP-запроса.

  • pk – Первичный ключ экземпляра модели, для которого рассчитывается ETag. Это может быть конкретное значение (int или str) для использования в одной модели или словарь, сопоставляющий классы моделей с их соответствующими значениями первичных ключей для коллекций моделей.

Результат:

Вычисленное значение ETag в виде шестнадцатеричной строки.

Тип результата:

str

Функция работает по-разному в зависимости от предоставленного типа model_class:

  • Коллекция моделей: Когда model_class является коллекцией, функция вычисляет ETag, объединяя значения ETag отдельных моделей в коллекции, используя рекурсивный вызов для каждой модели. Значение ETag для каждой модели кодируется и хешируется с использованием алгоритма Blake2s.

  • Модель с методом ``get_etag_value``: Если класс модели имеет метод get_etag_value, функция вызывает этот метод, чтобы получить базовое значение ETag. Затем она добавляет информацию о языке, идентификаторе пользователя и ключе сессии, если они помечены как зависимости в атрибуте _cache_response_dependencies модели. Это базовое значение ETag может быть дополнительно обработано, включая полную строку версии приложения и хешировано, если включена информация о пользователе или сессии.

  • Модель без метода ``get_etag_value``: Для моделей без пользовательского метода get_etag_value функция генерирует ETag на основе имени класса модели и хеша полной строки версии приложения.

Actions (Действия)

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

Чтобы расширить набор действий, необходимо создать действие, которое будет работать с некоторым аспектом описанной модели. Для этих целей существует стандартный rest_framework.decorators.action(), который также можно расширить с помощью схемы. Но для большего удобства в vstutils есть набор декораторов, которые позволяют избежать написания

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

class vstutils.api.actions.Action(detail=True, methods=None, serializer_class=<class 'vstutils.api.serializers.DataSerializer'>, result_serializer_class=None, query_serializer=None, multi=False, title=None, icons=None, is_list=False, hidden=False, require_confirmation=False, **kwargs)[исходный код]

Базовый класс действий. Обладает минимально необходимой функциональностью для создания действия и позволяет написать только бизнес-логику. Этот декоратор подходит в случаях, когда невозможно реализовать логику с использованием SimpleAction или алгоритм значительно более сложный, чем стандартные операции CRUD.

Примеры:

...
from vstutils.api.fields import VSTCharField
from vstutils.api.serializers import BaseSerializer
from vstutils.api.base import ModelViewSet
from vstutils.api.actions import Action
...

class RequestSerializer(BaseSerializer):
    data_field1 = ...
    ...


class ResponseSerializer(BaseSerializer):
    detail = VSTCharField(read_only=True)


class AuthorViewSet(ModelViewSet):
    model = ...
    ...

    @Action(serializer_class=RequestSerializer, result_serializer_class=ResponseSerializer, ...)
    def profile(self, request, *args, **kwargs):
        ''' Got `serializer_class` body and response with `result_serializer_class`. '''
        serializer = self.get_serializer(self.get_object(), data=request.data)
        serializer.is_valid(raise_exception=True)
        return {"detail": "Executed!"}
Параметры:
  • detail – Флаг, указывающий, какой тип действия используется: на списке или на отдельной сущности. Влияет на то, где будет отображаться это действие - на детальной записи или на списке записей.

  • methods – Список доступных методов HTTP. По умолчанию ["post"].

  • serializer_class – Сериализатор для тела запроса. Используется также для формирования ответа по умолчанию.

  • result_serializer_class – Сериализатор для тела ответа. Необходим, когда запрос и ответ имеют различные наборы полей.

  • query_serializer – Сериализатор для данных запроса типа GET. Используется, когда необходимо получить корректные данные в строке запроса типа GET и привести их к нужному типу.

  • multi – Используется только с не-GET запросами и уведомляет GUI, что это действие должно быть применено к выбранным элементам списка.

  • title – Заголовок действия в пользовательском интерфейсе. Для действий, отличных от GET, заголовок генерируется на основе имени метода.

  • icons – Список иконок для кнопки пользовательского интерфейса.

  • is_list – Флаг, указывающий, является ли тип действия списком или отдельной сущностью. Обычно используется с действиями GET.

  • require_confirmation – Если истина, то в интерфейсе пользователь должен будет подтвердить действие перед выполнением.

  • kwargs – Набор именованных аргументов для rest_framework.decorators.action().

class vstutils.api.actions.EmptyAction(**kwargs)[исходный код]

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

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

Примеры:

...
from vstutils.api.fields import RedirectIntegerField
from vstutils.api.serializers import BaseSerializer
from vstutils.api.base import ModelViewSet
from vstutils.api.actions import EmptyAction
...

class ResponseSerializer(BaseSerializer):
    id = RedirectIntegerField(operation_name='sync_history')


class AuthorViewSet(ModelViewSet):
    model = ...
    ...

    @EmptyAction(result_serializer_class=ResponseSerializer, ...)
    def sync_data(self, request, *args, **kwargs):
        ''' Example of action which get object, sync data and redirect user to another view. '''
        sync_id = self.get_object().sync().id
        return {"id": sync_id}
...
from django.http.response import FileResponse
from vstutils.api.base import ModelViewSet
from vstutils.api.actions import EmptyAction
...

class AuthorViewSet(ModelViewSet):
    model = ...
    ...

    @EmptyAction(result_serializer_class=ResponseSerializer, ...)
    def resume(self, request, *args, **kwargs):
        ''' Example of action which response with generated resume in pdf. '''
        instance = self.get_object()

        return FileResponse(
            streaming_content=instance.get_pdf(),
            as_attachment=True,
            filename=f'{instance.last_name}_{instance.first_name}_resume.pdf'
        )
class vstutils.api.actions.SimpleAction(*args, **kwargs)[исходный код]

Идея этого декоратора заключается в том, чтобы получить полный CRUD для экземпляра с минимумом шагов. Экземпляр - это объект, который возвращается из декорируемого метода. Весь механизм очень похож на стандартный декоратор property, с описанием getter, setter, и deleter

Если вы собираетесь создать точку входа для работы с отдельным объектом, то вам не нужно определять методы. Наличие getter`a, setter`a, и deleter`a определит, какие методы будут доступны.

В официальной документации Django приведен пример с перемещением данных, которые не являются важными для авторизации, в модель Profile. Для работы с такими данными, находящимися вне основной модели, существует данный объект действия, который реализует основную логику в наиболеавтоматизированном виде.

Он охватывает большинство задач по работе с такими данными. По умолчанию у него есть метод GET вместо POST. Кроме того, для лучшей организации кода он позволяет изменить методы, которые будут вызываться при изменении или удалении данных.

При назначении действия на объект список методов также заполняется необходимыми методами.

Примеры:

...
from vstutils.api.fields import PhoneField
from vstutils.api.serializers import BaseSerializer
from vstutils.api.base import ModelViewSet
from vstutils.api.actions import Action
...

class ProfileSerializer(BaseSerializer):
    phone = PhoneField()


class AuthorViewSet(ModelViewSet):
    model = ...
    ...

    @SimpleAction(serializer_class=ProfileSerializer, ...)
    def profile(self, request, *args, **kwargs):
        ''' Get profile data to work. '''
        return self.get_object().profile

    @profile.setter
    def profile(self, instance, request, serializer, *args, **kwargs):
        instance.save(update_fields=['phone'])

    @profile.deleter
    def profile(self, instance, request, serializer, *args, **kwargs):
        instance.phone = ''
        instance.save(update_fields=['phone'])

Filterset’ы

Для большего удобства разработки, фреймворк предоставляет дополнительные классы и функции для фильтрации элементов на основе полей.

class vstutils.api.filters.DefaultIDFilter(data=None, queryset=None, *, request=None, prefix=None)[исходный код]

Базовый filterset для поиска по id. Предоставляет поиск по множеству значений, разделенных запятой. Использует extra_filter() в полях.

class vstutils.api.filters.DefaultNameFilter(data=None, queryset=None, *, request=None, prefix=None)[исходный код]

Базовый filterset для частичного поиска по названию. Использует условие LIKE в базе данных с помощью name_filter().

class vstutils.api.filters.FkFilterHandler(related_pk='id', related_name='name', pk_handler=<class 'int'>)[исходный код]

Простой handler для фильтрации по связанным полям.

Параметры:
  • related_pk (str) – Имя поля первичного ключа в связанной модели. По умолчанию „id“.

  • related_name (str) – Имя charfield-поля в связанной модели. По умолчанию „name“.

  • pk_handler (typing.Callable) – Изменяет handler для проверки значения перед поиском. Посылает «0», если handler падает. По умолчанию используется int().

Пример:
class CustomFilterSet(filters.FilterSet):
    author = CharFilter(method=vst_filters.FkFilterHandler(related_pk='pk', related_name='email'))

Где author - это ForeignKey на User, и вы хотите искать по первичному ключу и полю email.

vstutils.api.filters.extra_filter(queryset, field, value)[исходный код]

Метод, предназначенный для поиска значений в списке значений, разделенных запятой.

Параметры:
  • queryset (django.db.models.query.QuerySet) – queryset модели для фильтрации.

  • field (str) – имя поля в FilterSet’е. Также поддерживает суффикс __not.

  • value (str) – список искомых значений, разделенных запятыми.

Результат:

отфильтрованный queryset.

Тип результата:

django.db.models.query.QuerySet

vstutils.api.filters.name_filter(queryset, field, value)[исходный код]

Метод для частичного поиска по названию. Использует условие LIKE базы данных или выражение contains queryset’а.

Параметры:
  • queryset (django.db.models.query.QuerySet) – queryset модели для фильтрации.

  • field (str) – имя поля в FilterSet’е. Также поддерживает суффикс __not.

  • value (str) – часть названия для поиска.

Результат:

отфильтрованный queryset.

Тип результата:

django.db.models.query.QuerySet

Ответы (responses)

DRF предоставляет стандартный набор переменных, удобочитаемые названия которых соответствуют HTTP-кодам ответов. Для удобства мы динамически оборачиваем их в набор классов с соответствующими именами и дополнительно обеспечиваем следующие возможности:

  • Строковые ответы оборачиваются в json, например { "detail": "string response" }.

  • Тайминги атрибутов сохраняются для дальнейшей обработки в middleware.

  • Код состояния задается именем класса (например HTTP_200_OK или Response200 имеют код 200).

Все классы наследуются от:

class vstutils.api.responses.BaseResponseClass(*args, **kwargs)[исходный код]

Класс ответа API со стандартным кодом состояния.

Переменные:
  • status_code (int) – Код состояния HTTP.

  • timings (int,None) – Тайминги ответов.

Параметры:

timings – Тайминги ответов.

Middleware

По умолчанию Django предполагает, что разработчик создает класс Middleware вручную, однако зачастую это рутинная задача. Библиотека vstutils предлагает удобный класс request handler’а для изящной разработки в стиле ООП. Middleware используются для обработки входящих запросов и отправления ответов до того, как они достигнут получателя.

class vstutils.middleware.BaseMiddleware(get_response)[исходный код]

Базовый класс middleware для обработки:

Middleware должен быть добавлен в список MIDDLEWARE, находящийся в настройках.

Пример:
from vstutils.middleware import BaseMiddleware
from django.http import HttpResponse


class CustomMiddleware(BaseMiddleware):
    def request_handler(self, request):
        # Add header to request
        request.headers['User-Agent'] = 'Mozilla/5.0'
        return request

    def get_response_handler(self, request):
        if not request.user.is_stuff:
            # Return 403 HTTP status for non-stuff users.
            # This request never gets in any view.
            return HttpResponse(
                "Access denied!",
                content_type="text/plain",
                status_code=403
            )
        return super().get_response_handler(request)

    def handler(self, request, response):
        # Add header to response
        response['Custom-Header'] = 'Some value'
        return response
get_response_handler(request)[исходный код]

Точка входа для прерывания или продолжения обработки запроса. Эта функция должна возвращать объект django.http.HttpResponse или результат вызова родительского класса.

Начиная с релиза 5.3, было возможно написать этот метод асинхронным. Это должно использоваться в тех случаях, когда middleware делает запросы к базе данных или к кэшу. Однако такой компонент middleware должен быть исключен из bulk запросов.

Предупреждение

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

Установите async_capable в True и sync_capable в False для таких middleware.

Параметры:

request (django.http.HttpRequest) – Объект HTTP-запроса, созданный из клиентского запроса.

Тип результата:

django.http.HttpResponse

handler(request, response)[исходный код]

Handler ответа. Метод для обработки ответов.

Параметры:
Результат:

Обработанный объект ответа.

Тип результата:

django.http.HttpResponse

request_handler(request)[исходный код]

Handler запроса. Вызывается перед обработкой запроса view.

Параметры:

request (django.http.HttpRequest) – Объект HTTP-запроса, созданный из клиентского запроса.

Результат:

Обработанный объект запроса.

Тип результата:

django.http.HttpRequest

Filter Backend’ы

Filter Backend’ы используются для изменения queryset’а модели. Чтобы создать пользовательский filter backend (т.е. аннотировать queryset модели), следует наследоваться от vstutils.api.filter_backends.VSTFilterBackend и переопределить vstutils.api.filter_backends.VSTFilterBackend.filter_queryset(). В некоторых случаях также стоит переопределить vstutils.api.filter_backends.VSTFilterBackend.get_schema_fields().

class vstutils.api.filter_backends.DeepViewFilterBackend[исходный код]

Backend, фильтрующий queryset по колонке из свойства deep_parent_field модели. Значение для фильтрации должно быть передано в query-параметре __deep_parent.

Если параметр отсутствует, то никакие фильтры не применяются.

Если параметр - это пустое значение (/?__deep_parent=), то возвращаются объекты, не имеющие родителя (значение поля, чье имя хранится в свойстве модели deep_parent_field, равно None).

Этот filter backend и вложенное view автоматически добавляются в случае, если модель имеет свойство deep_parent_field.

Пример:
from django.db import models
from vstutils.models import BModel

class DeepNestedModel(BModel):
    name = models.CharField(max_length=10)
    parent = models.ForeignKey('self', null=True, default=None, on_delete=models.CASCADE)

    deep_parent_field = 'parent'
    deep_parent_allow_append = True

    class Meta:
        default_related_name = 'deepnested'

В примере выше если мы добавим эту модель под путь „deep“, следующие view будут созданы: /deep/ и /deep/{id}/deepnested/.

Filter backend, который может быть использован как /deep/?__deep_parent=1, и будет возвращать все объекты DeepNestedModel, чьи родительские первичные ключи равны 1.

Вы также можете использовать generic-view DRF. Для этого все еще нужно задать deep_parent_field вашей модели и вручную добавить DeepViewFilterBackend в список filter_backends.

class vstutils.api.filter_backends.HideHiddenFilterBackend[исходный код]

Filter Backend, убирающий из queryset все объекты, у которых задан атрибут hidden=True.

filter_queryset(request, queryset, view)[исходный код]

Очищает объекты со атрибутом hidden из queryset’а.

class vstutils.api.filter_backends.SelectRelatedFilterBackend[исходный код]

Filter Backend, автоматически вызывающий prefetch_related и select_related для всех отношений в queryset’е.

filter_queryset(request, queryset, view)[исходный код]

Выполняет select и prefetch в queryset’е.

class vstutils.api.filter_backends.VSTFilterBackend[исходный код]

Базовый класс filter backend’а, от которого следует наследоваться. Пример:

from django.utils import timezone
from django.db.models import Value, DateTimeField

from vstutils.api.filter_backends import VSTFilterBackend

class CurrentTimeFilterBackend(VSTFilterBackend):
    def filter_queryset(self, request, queryset, view):
        return queryset.annotate(current_time=Value(timezone.now(), output_field=DateTimeField()))

В данном примере Filter Backend аннотирует время в текущем часовом поясе в queryset’е используемой модели.

В некоторых случаях может быть необходимо передать параметр из query запроса. Чтобы определить этот параметр в схеме, вы должны перегрузить функцию get_schema_operation_parameters и указать список параметров, которые нужно использовать.

Пример:

from django.utils import timezone
from django.db.models import Value, DateTimeField

from vstutils.api.filter_backends import VSTFilterBackend

class ConstantCurrentTimeForQueryFilterBackend(VSTFilterBackend):
    query_param = 'constant'

    def filter_queryset(self, request, queryset, view):
        if self.query_param in request.query_params and request.query_params[self.query_param]:
            queryset = queryset.annotate(**{
                request.query_params[self.query_param]: Value(timezone.now(), output_field=DateTimeField())
            })
        return queryset

        def get_schema_operation_parameters(self, view):
            return [
                {
                    "name": self.query_param,
                    "required": False,
                    "in": openapi.IN_QUERY,
                    "description": "Annotate value to queryset",
                    "schema": {
                        "type": openapi.TYPE_STRING,
                    }
                },
            ]

В данном примере Filter Backend аннотирует время в текущем часовом поясе в queryset’е используемой модели именем поля из query constant.

get_schema_operation_parameters(view)[исходный код]

Вы также можете создать элементы управления фильтрами доступными для автогенерации схемы, предоставляемой REST-фреймворком, реализуя этот метод. Метод должен возвращать список OpenAPI сопоставлений схемы.

Celery

Celery - это распределенная очередь задач. Он используется для запуска задач асинхронно в отдельном worker’е. Чтобы узнать больше о Celery, смотрите официальную документацию. Для работы функций vstutils, связанных с Celery, необходимо указать секции [rpc] and [worker] в settings.ini. Также вам понадобится установить дополнительные [rpc] зависимости.

Tasks

class vstutils.tasks.TaskClass[исходный код]

Обертка для класса BaseTask из Celery. Использование такое же, как и стандартного класса, однако вы можете запустить задачу без необходимости создавать экземпляр с помощью метода TaskClass.do().

Пример:

from vstutils.environment import get_celery_app
from vstutils.tasks import TaskClass

app = get_celery_app()

class Foo(TaskClass):
    def run(*args, **kwargs):
        return 'Foo task has been executed'

app.register_task(Foo())
Теперь вы можете вызвать задачу несколькими методами:
  • вызвав Foo.do(*args, **kwargs)

  • получить зарегистрированный экземпляр задачи можно так: app.tasks[„full_path.to.task.class.Foo“]

Также вы можете сделать вашу зарегистрированную задачу периодической. Для этого нужно добавить ее CELERY_BEAT_SCHEDULE в settings.py:

CELERY_BEAT_SCHEDULE = {
    'foo-execute-every-month': {
        'task': 'full_path.to.task.class.Foo',
        'schedule': crontab(day_of_month=1),
    },
}
classmethod do(*args, **kwargs)[исходный код]

Метод, который посылает сигнал запуска удаленной задаче celery. Все аргументы будут переданы методу задачи TaskClass.run().

Тип результата:

celery.result.AsyncResult

property name

свойство для правильного выполнения Celery-задачи, нужно для работы метода TaskClass.do()

run(*args, **kwargs)

Тело задачи выполняется worker’ами.

Endpoint

Endpoint-view имеет две цели: выполнение bulk-запросов и предоставление схемы OpenAPI.

URL endpoint’а - /{API_URL}/endpoint/, например значение с настройками по умолчанию - /api/endpoint/.

API_URL может быть изменен в settings.py.

class vstutils.api.endpoint.EndpointViewSet(**kwargs)[исходный код]

Стандартный viewset API-endpoint’а.

get(request)[исходный код]

Возвращает ответ в виде Swagger UI или OpenAPI json-схему, если указан ?format=openapi

Параметры:

request (vstutils.api.endpoint.BulkRequestType) –

Тип результата:

django.http.response.HttpResponse

get_client(request)[исходный код]

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

Параметры:

request (vstutils.api.endpoint.BulkRequestType) –

Тип результата:

vstutils.api.endpoint.BulkClient

get_serializer(*args, **kwargs)[исходный код]

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

Тип результата:

vstutils.api.endpoint.OperationSerializer

get_serializer_context(context)[исходный код]

Дополнительный контекст, предоставляемый классу сериализатора.

Тип результата:

dict

operate(operation_data, context)[исходный код]

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

Параметры:
Тип результата:

typing.Tuple[typing.Dict, typing.SupportsFloat]

post(request)[исходный код]

Выполнить транзакционный bulk-запрос

Параметры:

request (vstutils.api.endpoint.BulkRequestType) –

Тип результата:

vstutils.api.responses.BaseResponseClass

put(request, allow_fail=True)[исходный код]

Выполнить нетранзакционный bulk-запрос

Параметры:

request (vstutils.api.endpoint.BulkRequestType) –

Тип результата:

vstutils.api.responses.BaseResponseClass

serializer_class

Класс сериализатора одной операции.

alias of OperationSerializer

versioning_class

alias of QueryParameterVersioning

Bulk-запросы

Bulk-запрос позволяет вам отсылать несколько запросов к api в одном. Он принимает json-список операций.

Метод

Транзакционный (все операции в одной транзакции)

Синхронный (операции выполняются одна за другой в указанном порядке)

PUT /{API_URL}/endpoint/

НЕТ

ДА

POST /{API_URL}/endpoint/

ДА

ДА

PATCH /{API_URL}/endpoint/

НЕТ

НЕТ

Параметры одной операции (обязательный параметр помечается *):

  • method* - http-метод запроса

  • path* - путь запроса, может быть типа str или list

  • data - данные для отправки

  • query - query-параметры типа str

  • let - строка с именем переменной (используется для доступа к результату ответа в шаблонах)

  • headers - словарь с заголовками, которые будут переданы в запрос (ключ - имя заголовка, значение - строка со значением заголовка.

  • version - str с указанной версией api, если не задано, то используется VST_API_VERSION

Предупреждение

В предыдущих версиях имена заголовков должны были соответствовать спецификации CGI (например, CONTENT_TYPE, GATEWAY_INTERFACE, HTTP_*).

Начиная с версии 5.3 и после миграции на Django 4 имена должны соответствовать HTTP спецификации вместо CGI.

В любой параметр запроса вы можете вставить результат значения предыдущей операции (<<{OPERATION_NUMBER or LET_VALUE}[path][to][value]>>), например:

[
    {"method": "post", "path": "user", "data": {"name": "User 1"}),
    {"method": "delete", "version": "v2", "path": ["user", "<<0[data][id]>>"]}
]

Результат bulk-запроса - это список json-объектов, описывающих операцию:

  • method - http-метод

  • path - путь запроса, всегда строка

  • data - данные, которые нужно отправить

  • status - код состояния ответа

Транзакционный bulk-запрос возвращает 502 BAG GATEWAY и делает откат к состоянию до запроса после первого неудачного запроса.

Предупреждение

Если вы отправили нетранзакционный bulk-запрос, вы получите код 200 и должны будете проверить статус каждого ответа операции отдельно.

Схема OpenAPI

Запрос на GET /{API_URL}/endpoint/ возвращает Swagger UI.

Запрос на GET /{API_URL}/endpoint/?format=openapi возвращает схему OpenAPI в формате json. Также вы можете указать нужную версию схемы, используя query-параметр version

Для изменения схемы после ее генерации и перед отправкой пользователю используйте хуки. Напишите одну или несколько функций, каждая из которых принимает 2 именованных аргумента:

  • request - объект запроса пользователя.

  • schema - ordered dict, содержащий схему OpenAPI.

Примечание

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

Пример хука:
def hook_add_username_to_guiname(request, schema):
    schema['info']['title'] = f"{request.username} - {schema['info']['title']}"

Чтобы присоединить хук(-и) к вашему приложению, добавьте строку импорта вашей функции в список OPENAPI_HOOKS в settings.py

OPENAPI_HOOKS = [
    '{{appName}}.openapi.hook_add_username_to_guiname',
]

Фреймворк для тестирования

Фреймворк VST Utils включает в себя хелпер в базовом тест-кейс классе и улучшает поддержку механизма отправки запросов. На практике это означает, что для отправления bulk-запроса на endpoint нет необходимости создавать и инициализировать test client, а можно сразу делать запрос.

endpoint_results = self.bulk([
    # list of endpoint requests
])

Создание тест-кейса

Модуль test.py содержит классы тест-кейсов, основанные на vstutils.tests.BaseTestCase. На текущий момент мы официально поддерживаем два подхода к написанию тестов: классический и с помощью оберток запросов с проверкой выполнения и runtime-оптимизацией bulk-запросов с ручной проверкой значений.

Простой пример с классическими тестами

Например, если у вас endpoint вида /api/v1/project/ и модель Project, вы можете написать такой тест:

from vstutils.tests import BaseTestCase


class ProjectTestCase(BaseTestCase):
    def setUp(self):
        super(ProjectTestCase, self).setUp()
        # init demo project
        self.initial_project = self.get_model_class('project.Test').objects.create(name="Test")

    def tearDown(self)
        super(ProjectTestCase, self).tearDown()
        # remove it after test
        self.initial_project.delete()

    def test_project_endpoint(self):
        # Test checks that api returns valid values
        self.list_test('/api/v1/project/', 1)
        self.details_test(
            ["project", self.initial_project.id],
            name=self.initial_project.name
        )
        # Try to create new projects and check list endpoint
        test_data = [
            {"name": f"TestProject{i}"}
            for i in range(2)
        ]
        id_list = self.mass_create("/api/v1/project/", test_data, 'name')
        self.list_test('/api/v1/project/', 1 + len(id_list))

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

Bulk-запросы в тестах

Система bulk-запросов хорошо подходит для тестирования и запуска валидных запросов. Предыдущий пример может быть переписан так:

from vstutils.tests import BaseTestCase


class ProjectTestCase(BaseTestCase):
    def setUp(self):
        super(ProjectTestCase, self).setUp()
        # init demo project
        self.initial_project = self.get_model_class('project.Test').objects.create(name="Test")

    def tearDown(self)
        super(ProjectTestCase, self).tearDown()
        # remove it after test
        self.initial_project.delete()

    def test_project_endpoint(self):
        test_data = [
            {"name": f"TestProject{i}"}
            for i in range(2)
        ]
        bulk_data = [
            {"method": "get", "path": ["project"]},
            {"method": "get", "path": ["project", self.initial_project.id]}
        ]
        bulk_data += [
            {"method": "post", "path": ["project"], "data": i}
            for i in test_data
        ]
        bulk_data.append(
            {"method": "get", "path": ["project"]}
        )
        results = self.bulk_transactional(bulk_data)

        self.assertEqual(results[0]['status'], 200)
        self.assertEqual(results[0]['data']['count'], 1)
        self.assertEqual(results[1]['status'], 200)
        self.assertEqual(results[1]['data']['name'], self.initial_project.name)

        for pos, result in enumerate(results[2:-1]):
            self.assertEqual(result['status'], 201)
            self.assertEqual(result['data']['name'], test_data[pos]['name'])

        self.assertEqual(results[-1]['status'], 200)
        self.assertEqual(results[-1]['data']['count'], 1 + len(test_data))

В этом случае хотя мы и получили больше кода, однако тесты стали ближе к процессу использования приложения в графическом интерфейсе, потому что проекты vstutils используют /api/endpoint/ для выполнения запросов. Так или иначе, bulk-запросы выполняются заметно быстрее благодаря оптимизации, которую они выполняют под капотом. Время выполнения теста, в котором используется bulk меньше по сравнению с тестом, использующим стандартный механизм.

API тест-кейса

class vstutils.tests.BaseTestCase(methodName='runTest')[исходный код]

Основной тест-кейс класс расширяет django.test.TestCase.

assertCheckDict(first, second, msg=None)[исходный код]

Падает, если два поля в словаре не равны по определению оператора „==“. Проверяет первое поле на пустоту и на равенство со вторым полем

Параметры:
assertCount(iterable, count, msg=None)[исходный код]

Вызывает len() через iterable и проверяет равенство с count.

Параметры:
  • iterable (typing.Sized) – любой итерируемый объект, который может быть отправлен в len().

  • count (int) – ожидаемый результат.

  • msg (typing.Any) – сообщение об ошибке

assertRCode(resp, code=200, *additional_info)[исходный код]

Падает, если коды ответа не совпадают. Сообщением явялется тело ответа.

Параметры:
bulk(data, code=200, **kwargs)[исходный код]

Делает нетранзакционный bulk-запрос и проверяет код состояния (200 по умолчанию)

Параметры:
Тип результата:

typing.Union[typing.List[typing.Dict[str, typing.Any]], str, bytes, bytearray, typing.Dict, typing.Sequence[typing.Union[typing.List[typing.Dict[str, typing.Any]], str, bytes, bytearray]]]

Результат:

bulk-ответ

bulk_transactional(data, code=200, **kwargs)[исходный код]

Делает транзакционный bulk-запрос и проверяет код состояния (200 по умолчанию)

Параметры:
Тип результата:

typing.Union[typing.List[typing.Dict[str, typing.Any]], str, bytes, bytearray, typing.Dict, typing.Sequence[typing.Union[typing.List[typing.Dict[str, typing.Any]], str, bytes, bytearray]]]

Результат:

bulk-ответ

call_registration(data, **kwargs)[исходный код]

Функция для вызова регистрации. Просто передайте данные формы вместе с заголовками.

Параметры:
  • data (dict) – Данные регистрации с формы.

  • kwargs – именованные аргументы вместе с заголовками запроса.

details_test(url, **kwargs)[исходный код]

Тест на получение детальной записи модели. При задании дополнительных именованных аргументов метод проверит их на равенство с полученными данными. Использует метод get_result().

Параметры:
  • url – url детальной записи. Например: /api/v1/project/1/ (где 1 - это уникальный идентификатор проекта). Вы можете использовать get_url() для построения url.

  • kwargs – параметры для проверки (ключ - имя поля, значение - значение поля).

endpoint_call(data=None, method='get', code=200, **kwargs)[исходный код]

Делает запрос на endpoint и проверяет код состояния ответа, если он задан (200 по умолчанию). Использует get_result().

Параметры:
Тип результата:

typing.Union[typing.List[typing.Dict[str, typing.Any]], str, bytes, bytearray, typing.Dict, typing.Sequence[typing.Union[typing.List[typing.Dict[str, typing.Any]], str, bytes, bytearray]]]

Результат:

bulk-ответ

endpoint_schema(**kwargs)[исходный код]

Делает запрос на схему. Возвращает словарь с данными swagger.

Параметры:

version – Версия API для парсера схемы.

get_count(model, **kwargs)[исходный код]

Простая обертка над get_model_filter(), возвращающая счетчик объектов.

Параметры:
Результат:

количество объектов в базе данных.

Тип результата:

int

get_model_class(model)[исходный код]

Получение класса модели по строке или получение аргумента модели.

Параметры:

model (str,django.db.models.Model) – строка, содержащая имя модели (если атрибут model установлен в класс тест-кейса), импорт модуля, app.ModelName или django.db.models.Model.

Результат:

Класс модели.

Тип результата:

django.db.models.Model

get_model_filter(model, **kwargs)[исходный код]

Простая обертка над get_model_class(), возвращающая фильтрованный queryset из модели.

Параметры:
Тип результата:

django.db.models.query.QuerySet

get_result(rtype, url, code=None, *args, **kwargs)[исходный код]

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

  • Тестирует авторизацию клиента (вместе с user, который создается в setUp()).

  • Выполняет запрос (отправляет аргументы и именованные аргументы в метод запроса).

  • Парсит результат (конвертирует строку json в объект python).

  • Проверяет http-код состояния с помощью assertRCode() (если вы его не указали, будет выбран соответствующий код для выполняемого метода из стандартного набора std_codes).

  • Деавторизация пользователя.

  • Возвращение распарсенного результата.

Параметры:
  • rtype – тип запроса (методы из Client cls): get, post и т.д.

  • url – запрошенный url в виде строки или кортежа для get_url(). Вы можете использовать get_url() для построения url или задать его полной строкой.

  • code (int) – ожидаемый код возврата из запроса.

  • relogin – выполнение авторизации и деавторизации перед каждым вызовом. По умолчанию True.

  • args – дополнительные аргументы для метода запроса класса Client.

  • kwargs – дополнительные именованные аргументы для метода запроса класса Client.

Тип результата:

typing.Union[typing.List[typing.Dict[str, typing.Any]], str, bytes, bytearray, typing.Dict, typing.Sequence[typing.Union[typing.List[typing.Dict[str, typing.Any]], str, bytes, bytearray]]]

Результат:

результат запроса.

get_url(*items)[исходный код]

Функция для создания пути url, основанного на настройках VST_API_URL и VST_API_VERSION. Без аргументов возвращает путь к версии api по умолчанию.

Тип результата:

str

Результат:

строка вида /api/v1/.../.../ где ... - аргументы функции.

list_test(url, count)[исходный код]

Тест на получение списка моделей. Проверяет только количество записей. Использует метод get_result().

Параметры:
  • url – url абстрактного слоя. Например: /api/v1/project/. Вы можете использовать get_url() для построения url.

  • count – количество объектов в базе данных.

models = None

Атрибут с модулем моделей проекта по умолчанию.

classmethod patch(*args, **kwargs)[исходный код]

Простая обертка над unittest.mock.patch().

Тип результата:

typing.ContextManager[unittest.mock.Mock]

classmethod patch_field_default(model, field_name, value)[исходный код]

Этот метод помогает найти значение по умолчанию в поле модели. Он очень полезен для полезен для полей DateTime, где по умолчанию установлено django.utils.timezone.now().

Параметры:
  • model (django.db.models.base.Model) –

  • field_name (str) –

  • value (typing.Any) –

Тип результата:

typing.ContextManager[unittest.mock.Mock]

random_name()[исходный код]

Простая функция, возвращающая строку uuid1.

Тип результата:

str

std_codes: typing.Dict[str, int] = {'delete': 204, 'get': 200, 'patch': 200, 'post': 201}

Стандартный http-код для различных http-методов. Использует get_result()

class user_as(testcase, user)[исходный код]

Контекст для выполнения bulk или чего-либо еще от некоторого пользователя. Контекстный менеджер переопределяет self.user в TestCase’е и возвращает изменения после выхода из него.

Параметры:

user (django.contrib.auth.models.AbstractUser) – новый объект пользователя, от которого будет выполнение.

Утилиты

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

class vstutils.utils.BaseEnum(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[исходный код]

BaseEnum расширяет класс Enum и используется для создания enum-подобных объектов, которые могут использоваться django-сериализаторами или django-моделями.

Пример:

from vstutils.models import BModel

class ItemCLasses(BaseEnum):
    FIRST = BaseEnum.SAME
    SECOND = BaseEnum.SAME
    THIRD = BaseEnum.SAME


class MyDjangoModel(BModel):
    item_class = models.CharField(max_length=ItemCLasses.max_len, choices=ItemCLasses.to_choices())

    @property
    def is_second(self):
        # Function check is item has second class of instance
        return ItemCLasses.SECOND.is_equal(self.item_class)

Примечание

вы можете установить значение как BaseEnum.LOWER` или ``BaseEnum.UPPER. Однако в обычных случаях рекомендуется использовать BaseEnum.SAME для оптимизации памяти.

class vstutils.utils.BaseVstObject[исходный код]

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

classmethod get_django_settings(name, default=None)[исходный код]

Получить параметры из настроек Django.

Параметры:
  • name (str) – название параметра

  • default (object) – значение параметра по умолчанию

Результат:

Параметр из настроек Django.

class vstutils.utils.Dict[исходный код]

Обертка над dict, возвращающая JSON при преобразовании в строку.

class vstutils.utils.Executor(stdout=-1, stderr=-2, **environ_variables)[исходный код]

Исполнитель команд с выводом и обработкой строк в реальном времени. По умолчанию и замыслу исполнитель инициализирует строковый атрибут output, который будет изменен оператором += с новыми строками с помощью метода Executor.write_output(). Переопределите метод, если нужно изменить поведение.

Класс исполнителя поддерживает периодеческий (0.01 сек) процесс обработки и выполняет некоторые проверки путем переопределения метода Executor.working_handler(). Если вы хотите отключить это поведение, переопределите метод значением None или используйте UnhandledExecutor.

Параметры:

environ_variables (str) –

exception CalledProcessError(returncode, cmd, output=None, stderr=None)

Выбрасывается, когда run() вызывается вместе с check=True и процесс возвращает код возврата отличный от нуля.

Атрибуты:

cmd, returncode, stdout, stderr, output

property stdout

Псевдоним для выходного атрибута, чтобы соответствовать stderr

async aexecute(cmd, cwd, env=None)[исходный код]

Выполняет команды и выводит их результат. Асинхронная реализация.

Параметры:
  • cmd – – список cmd-команд и аргументов

  • cwd – – рабочая директория

  • env – – дополнительные переменные окружения, которые перезаписывают переменные по умолчанию

Результат:

– строка, содержащая полный вывод

execute(cmd, cwd, env=None)[исходный код]

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

Параметры:
  • cmd – – список cmd-команд и аргументов

  • cwd – – рабочая директория

  • env – – дополнительные переменные окружения, которые перезаписывают переменные по умолчанию

Результат:

– строка, содержащая полный вывод

async post_execute(cmd, cwd, env, return_code)[исходный код]

Запускается после завершения выполнения.

Параметры:
  • cmd – – список cmd-команд и аргументов

  • cwd – – рабочая директория

  • env – – дополнительные переменные окружения, которые перезаписывают переменные по умолчанию

  • return_code – – код возврата выполненного процесса

async pre_execute(cmd, cwd, env)[исходный код]

Запускатеся перед началом выполнения.

Параметры:
  • cmd – – список cmd-команд и аргументов

  • cwd – – рабочая директория

  • env – – дополнительные переменные окружения, которые перезаписывают переменные по умолчанию

async working_handler(proc)[исходный код]

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

Параметры:

proc (asyncio.subprocess.Process) – запущенный процесс

write_output(line)[исходный код]
Параметры:

line (str) – – строка вывода команды

Результат:

None

Тип результата:

None

class vstutils.utils.KVExchanger(key, timeout=None)[исходный код]

Класс для передачи данных с использованием быстрого (кэш-подобного) хранилища между сервисами. Использует тот же самый кэш-бэкенд, что и Lock.

class vstutils.utils.Lock(id, payload=1, repeat=1, err_msg='', timeout=None)[исходный код]

Класс Lock предназначен для работы с несколькими задачами. Основан на KVExchanger. Lock позволяет только одному потоку войти в заблокированную и совместно используемую часть между приложениями, использующими один кэш блокировок (см. также [locks]).

Параметры:
  • id (int,str) – – уникальный id блокировки.

  • payload – – дополнительная информация о блокировке. Должна быть значением, равным True при приведении к булевому типу.

  • repeat (int) – – время ожидания lock.release. По умолчанию 1 секунда.

  • err_msg (str) – – сообщение для ошибки AcquireLockException.

Примечание

  • Использует django.core.cache и настройки в settings.py

  • Имеет Lock.SCHEDULER и Lock.GLOBAL id

Пример:
from vstutils.utils import Lock

with Lock("some_lock_identifier", repeat=30, err_msg="Locked by another proccess") as lock:
    # where
    # ``"some_lock_identifier"`` is unique id for lock and
    # ``30`` seconds lock is going wait until another process will release lock id.
    # After 30 sec waiting lock will raised with :class:`.Lock.AcquireLockException`
    # and ``err_msg`` value as text.
    some_code_execution()
    # ``lock`` object will has been automatically released after
    # exiting from context.
Другой пример без использования контекстного менеджера:
from vstutils.utils import Lock

# locked block after locked object created
lock = Lock("some_lock_identifier", repeat=30, err_msg="Locked by another proccess")
# deleting of object calls ``lock.release()`` which release and remove lock from id.
del lock
exception AcquireLockException[исходный код]

Исключение, которое будет выброшено в случае неосвобождения блокировки.

class vstutils.utils.ModelHandlers(type_name, err_message=None)[исходный код]

Обработчики для некоторых моделей, таких как „INTEGRATIONS“ или „REPO_BACKENDS“. Основан на ObjectHandlers, но больше сосредоточен на работе с моделями. Все handler-бэкенды получают объект модели по первому аргументу.

Атрибуты:

Параметры:
  • objects (dict) – – словарь объектов, например {<name>: <backend_class>}

  • keys (list) – – имена поддерживаемых бэкендов

  • values (list) – – поддерживаемые классы бэкендов

  • type_name – Имя для бэкенда, наподобие ключа в словаре.

get_object(name, obj)[исходный код]
Параметры:
  • name – – строковое имя бэкенда

  • name – str

  • obj (django.db.models.Model) – – объект модели

Результат:

объект бэкенда

Тип результата:

object

class vstutils.utils.ObjectHandlers(type_name, err_message=None)[исходный код]

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

Пример:
from vstutils.utils import ObjectHandlers

'''
In `settings.py` you should write some structure:

SOME_HANDLERS = {
    "one": {
        "BACKEND": "full.python.path.to.module.SomeClass"
    },
    "two": {
        "BACKEND": "full.python.path.to.module.SomeAnotherClass",
        "OPTIONS": {
            "some_named_arg": "value"
        }
    }
}
'''

handlers = ObjectHandlers('SOME_HANDLERS')

# Get class handler for 'one'
one_backend_class = handlers['one']
# Get object of backend 'two'
two_obj = handlers.get_object()
# Get object of backend 'two' with overriding constructor named arg
two_obj_overrided = handlers.get_object(some_named_arg='another_value')
Параметры:

type_name (str) – Имя для бэкенда, наподобие ключа в словаре.

backend(name)[исходный код]

Получить класс бэкенда

Параметры:

name (str) – – имя типа бэкенда

Результат:

класс бэкенда

Тип результата:

type,types.ModuleType,object

class vstutils.utils.Paginator(qs, chunk_size=None)[исходный код]

Класс для разбиения запроса на небольшие запросы.

class vstutils.utils.SecurePickling(secure_key=None)[исходный код]

Защищенная pickle-обертка с использованием шифра Виженера.

Предупреждение

В любом случае не используйте его с ненадежным средством передачи.

Пример:
from vstutils.utils import SecurePickling


serializer = SecurePickling('password')

# Init secret object
a = {"key": "value"}
# Serialize object with secret key
pickled = serializer.dumps(a)
# Deserialize object
unpickled = serializer.loads(pickled)

# Check, that object is correct
assert a == unpickled
class vstutils.utils.URLHandlers(type_name='URLS', *args, **kwargs)[исходный код]

Обработчик объекта для views в графическом интерфейсе. Использует GUI_VIEWS из settings.py. Основан на ObjectHandlers, но больше сосредоточен на urlpatterns.

Пример:
from vstutils.utils import URLHandlers


# By default gets from `GUI_VIEWS` in `settings.py`
urlpatterns = list(URLHandlers())
Параметры:

type_name – Имя для бэкенда, наподобие ключа в словаре.

get_object(name, *argv, **kwargs)[исходный код]

Получить объект кортежа url’ов для urls.py

Параметры:
  • name (str) – регулярное выражение url’а

  • argv – переопределенные аргументы

  • kwargs – переопределенные kwarg’и

Результат:

объект url’а

Тип результата:

django.urls.re_path

class vstutils.utils.UnhandledExecutor(stdout=-1, stderr=-2, **environ_variables)[исходный код]

Класс, основанный на Executor, но с выключенным working_handler.

Параметры:

environ_variables (str) –

class vstutils.utils.apply_decorators(*decorators)[исходный код]

Декоратор, оборачивающий метод или класс в список декораторов.

Пример:
from vstutils.utils import apply_decorators

def decorator_one(func):
    print(f"Decorated {func.__name__} by first decorator.")
    return func

def decorator_two(func):
    print(f"Decorated {func.__name__} by second decorator.")
    return func

@apply_decorators(decorator_one, decorator_two)
def decorated_function():
    # Function decorated by both decorators.
    print("Function call.")
class vstutils.utils.classproperty(fget, fset=None)[исходный код]

Декоратор, который из метода класса делает классовый property.

Пример:
from vstutils.utils import classproperty

class SomeClass(metaclass=classproperty.meta):
    # Metaclass is needed for set attrs in class
    # instead of and not only object.

    some_value = None

    @classproperty
    def value(cls):
        return cls.some_value

    @value.setter
    def value(cls, new_value):
        cls.some_value = new_value
Параметры:
  • fget – Функция для получения значения атрибута.

  • fset – Функция для установки значения атрибута.

vstutils.utils.create_view(model, **meta_options)[исходный код]

Простая функция для получения сгенерированного view стандартными средствами, но с перегруженными мета-параметрами. Этот метод позволяет полностью отказаться от создания прокси-моделей.

Пример:
from vstutils.utils import create_view

from .models import Host

# Host model has full :class:`vstutils.api.base.ModelViewSet` view.
# For overriding and create simple list view just setup this:
HostListViewSet = create_view(
    HostList,
    view_class='list_only'
)

Примечание

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

Предупреждение

Эта функция олдскульная и будет объявлена устаревшей в будущих версиях. Используйте встроенный вызов метода :method:`vstutils.models.BModel.get_view_class`.

Параметры:

model (Type[vstutils.models.BaseModel]) – Класс модели с методом .get_view_class. Этот метод также имеет vstutils.models.BModel.

Тип результата:

vstutils.api.base.GenericViewSet

vstutils.utils.decode(key, enc)[исходный код]

Декодировать строку из закодированной шифром Виженера.

Параметры:
  • key (str) – – секретный ключ для кодирования

  • enc (str) – – закодированная строка для декодирования

Результат:

– декодированная строка

Тип результата:

str

vstutils.utils.deprecated(func)[исходный код]

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

Параметры:

func – любой вызываемый объект, который будет обернут и выдаст предупреждение об устаревании при вызове.

vstutils.utils.encode(key, clear)[исходный код]

Закодировать строку шифром Виженера.

Параметры:
  • key (str) – – секретный ключ для кодирования

  • clear (str) – – чистое значение для кодирования

Результат:

– закодированная строка

Тип результата:

str

vstutils.utils.get_render(name, data, trans='en')[исходный код]

Рендеринг строки из шаблона.

Параметры:
  • name (str) – – полное название шаблона

  • data (dict) – – словарь переменных для рендеринга

  • trans (str) – – перевод для рендера. По умолчанию „en“.

Результат:

– отрендеренная строка

Тип результата:

str

vstutils.utils.lazy_translate(text)[исходный код]

Функция lazy_translate имеет то же поведение, что и translate(), но оборачивает его в lazy promise.

Это полезно, например, для перевода сообщений об ошибках в атрибутах класса, когда целевой язык еще неизвестен.

Параметры:

text – Текстовое сообщение, которое должно быть переведено.

vstutils.utils.list_to_choices(items_list, response_type=<class 'list'>)[исходный код]

Метод, предназначенный для создания django-модели choices из плоского списка значений.

Параметры:
  • items_list – плоский список значений.

  • response_type – тип приведения возвращаемого сопоставления

Результат:

список кортежей из значений items_list

class vstutils.utils.model_lock_decorator(**kwargs)[исходный код]

Декоратор для функций, где kwarg „pk“ существует для блокировки по id.

Предупреждение

  • В случае ошибки блокировки выбрасывает Lock.AcquireLockException

  • Метод должен иметь и быть вызван вместе с именованным аргументом pk.

class vstutils.utils.raise_context(*args, **kwargs)[исходный код]

Контекст для игнорирования исключений.

class vstutils.utils.raise_context_decorator_with_default(*args, **kwargs)[исходный код]

Контекст для предотвращения исключений и возврата значения по умолчанию.

Пример:
from yaml import load
from vstutils.utils import raise_context_decorator_with_default


@raise_context_decorator_with_default(default={})
def get_host_data(yaml_path, host):
    with open(yaml_path, 'r') as fd:
        data = load(fd.read(), Loader=Loader)
    return data[host]
    # This decorator used when you must return some value even on error
    # In log you also can see traceback for error if it occur

def clone_host_data(host):
    bs_data = get_host_data('inventories/aws/hosts.yml', 'build_server')
    ...
class vstutils.utils.redirect_stdany(new_stream=<_io.StringIO object>, streams=None)[исходный код]

Контекст для перенаправления любого вывода в свой поток.

Примечание

  • В контексте возвращает объект потока.

  • При выходе возвращает старые потоки.

vstutils.utils.send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None, html_message=None, **kwargs)[исходный код]

Обертка над django.core.mail.send_mail(), предоставляющая дополнительные именованные аргументы.

vstutils.utils.send_template_email(sync=False, **kwargs)[исходный код]

Функция, выполняющая синхронную или асинхронную отправку электронной почты в зависимости от аргумента sync и переменной настроек «RPC_ENABLED». Вы можете использовать эту функцию для отправки сообщений, она отправляет сообщение асинхронно или синхронно. Если вы не установили настройки для Celery или не установили Celery, она отправляет письмо синхронно. Если установлен и настроен Celery, и аргумент sync функции установлен на False, она отправляет электронное письмо асинхронно.

Параметры:
  • sync – аргумент для определения, как отправлять электронную почту, асинхронно или синхронно.

  • subject – тема письма.

  • email – список строк или отдельная строка с адресами электронной почты получателей.

  • template_name – относительный путь к шаблону в директории templates, должен включать расширение имени файла.

  • context_data – словарь с контекстом для отображения шаблона сообщения.

vstutils.utils.send_template_email_handler(subject, email_from, email, template_name, context_data=None, **kwargs)[исходный код]

Функция для отправки электронной почты. Функция преобразует получателя в список и устанавливает контекст перед отправкой, если это возможно.

Параметры:
  • subject – тема письма.

  • email_from – адрес отправителя, который будет указан в письме.

  • email – список строк или отдельная строка с адресами электронной почты получателей.

  • template_name – относительный путь к шаблону в директории templates, должен включать расширение имени файла.

  • context_data – словарь с контекстом для отображения шаблона сообщения.

  • kwargs – дополнительные именованные аргументы для send_mail.

Результат:

Количество отправленных электронных писем.

class vstutils.utils.tmp_file(data='', mode='w', bufsize=-1, **kwargs)[исходный код]

Временный файл с сгенерированным и автоматически именем и удаленный по закрытии

Атрибуты:

Параметры:
  • data (str) – – строка для записи во временный файл.

  • mode (str) – – режим открытия файла. По умолчанию w.

  • bufsize (int) – – размер буфера для tempfile.NamedTemporaryFile.

  • kwargs – – другие именованные аргументы для tempfile.NamedTemporaryFile.

write(wr_string)[исходный код]

Записать в файл и очистить буфер

Параметры:

wr_string (str) – – записываемая строка

Результат:

None

Тип результата:

None

class vstutils.utils.tmp_file_context(*args, **kwargs)[исходный код]

Объект контекста для работы с tmp_file. Автоматическое закрывается при выходе из контекста и удаляется файл, если он все еще существует.

Данный менеджер контекста работает с class:.tmp_file

vstutils.utils.translate(text)[исходный код]

Функция translate поддерживает динамический перевод сообщения с использованием стандартных механизмов i18n в vstutils.

Использует функцию django.utils.translation.get_language() для получения кода языка и пытается получить перевод из списка доступных.

Параметры:

text – Текстовое сообщение, которое должно быть переведено.

Интеграция Web Push-уведомлений

Web-уведомления - это эффективный способ взаимодействия с пользователями с помощью реального времени. Чтобы интегрировать web-уведомления в ваш проект VSTUtils, выполните следующие шаги:

  1. Конфигурация: Во-первых, включите модуль vstutils.webpush в разделе INSTALLED_APPS вашего файла settings.py. Это позволяет использовать функциональность web-уведомлений, предоставляемую VSTUtils. Кроме того, настройте необходимые параметры, как описано в разделе настроек web-уведомлений (см. здесь для подробностей).

  2. Создание уведомлений: Чтобы создать web-уведомление, вам нужно определить класс, который наследуется от vstutils.webpush.BaseWebPush или vstutils.webpush.BaseWebPushNotification. VSTUtils автоматически обнаруживает и использует классы web-уведомлений, определенные в модуле webpushes всех INSTALLED_APPS. Ниже приведен пример, иллюстрирующий, как реализовать пользовательские классы web-уведомлений:

     1from vstutils.api.models import Language
     2from vstutils.webpush.base import BaseWebPush, BaseWebPushNotification
     3from vstutils.webpush.models import WebPushDeviceSubscription, WebPushNotificationSubscription
     4
     5
     6class TestWebPush(BaseWebPush):
     7    """
     8    Webpush that is sent to all subscribed users
     9    """
    10
    11    def get_subscriptions(self):
    12        return WebPushDeviceSubscription.objects.filter(
    13            user_id__in=WebPushNotificationSubscription.objects.filter(
    14                type=self.get_key(),
    15                enabled=True,
    16            ).values('user_id'),
    17        )
    18
    19    def get_payload(self, lang: Language):
    20        return {"some": "data", "lang": lang.code}
    21
    22
    23class TestNotification(BaseWebPushNotification):
    24    """
    25    Webpush notification that is sent only to selected users
    26    """
    27
    28    def __init__(self, name: str, user_id: int):
    29        self.name = name
    30        self.user_id = user_id
    31        self.message = f"Hello {self.name}"
    32
    33    def get_users_ids(self):
    34        return (self.user_id,)
    35
    36    def get_notification(self, lang: Language):
    37        return {
    38            "title": self.message,
    39            "options": {
    40                "body": "Test notification body",
    41                "data": {"url": "/"},
    42            },
    43        }
    44
    45
    46class StaffOnlyNotification(BaseWebPushNotification):
    47    """
    48    Webpush notification that only staff user can subscribe to.
    49    """
    50
    51    @staticmethod
    52    def is_available(user):
    53        return user.is_staff
    

    Этот пример содержит три класса:

    • TestWebPush: Отправляет уведомления всем подписанным пользователям.

    • TestNotification: Направляет уведомления конкретным пользователям.

    • StaffOnlyNotification: Ограничивает уведомления только для сотрудников. Иногда вы можете хотеть разрешить подписку на конкретные уведомления только некоторым пользователям.

  3. Отправка уведомлений: Чтобы отправить web-уведомление, вызовите метод send или send_in_task на экземпляре вашего класса web-уведомления. Например, чтобы отправить уведомление с использованием TestNotification, вы можете сделать следующее:

    from test_proj.webpushes import TestNotification
    
    # Sending a notification immediately (synchronously)
    TestNotification(name='Some user', user_id=1).send()
    
    # Sending a notification as a background task (asynchronously)
    TestNotification.send_in_task(name='Some user', user_id=1)
    

Предупреждение

Асинхронная отправка web-уведомлений (с использованием методов, таких как send_in_task) требует настроенной конфигурации Celery в вашем проекте, поскольку она полагается на задачи Celery «под капотом». Убедитесь, что Celery правильно настроен и работает, чтобы использовать асинхронную отправку уведомлений.

Следуя этим шагам, вы быстро сможете интегрировать и использовать web-уведомления в проектах с VSTUtils.