Быстрый старт
Создать новый проект, основанный на фреймворке VST Utils, довольно просто. Мы рекомендуем создавать виртуальное окружение отдельно для каждого из ваших проектов, чтобы избежать конфликтов в системе.
Давайте учиться на примерах. Все что вам нужно сделать это запустить несколько команд. Этот мануал состоит из двух частей:
Описание процесса создания нового приложения и основных команд для запуска и развертывания.
Описание процесса создания новых сущностей в приложении.
Создание нового приложения
В этом руководстве мы создадим базовое приложение.
Установка VST Utils
pip install vstutils
В данном случае мы устанавливаем пакет с минимальным набором зависимостей для создания новых проектов. Однако, внутри проекта используется специальный аргумент prod который дополнительно устанавливает все пакеты, необходимые для работы в окружении для развертывания. Также имеется набор зависимостей для тестирования, в котором содержится все, что нужно для тестирования и анализа покрытия кода.
Также стоит отметить дополнительно зависимости, такие как:
rpc - установка зависимостей для выполнения асинхронных задач
ldap - набор зависимостей для поддержки авторизации ldap
doc - все, что нужно для построения документации и осуществления доставки документации на запущенный сервер
pil - библиотека для корректной работы валидации изображений
boto3 - дополнительный набор зависимостей для работы с S3 хранилищем вне AWS
sqs - набор зависимостей для соединения асинхронных задач с SQS очередями (может использоваться вместо rpc).
Вы можете комбинировать разные зависимости одновременно, чтобы собрать ваш функциональный набор в проекте. Например, для работы приложения с асинхронными задачами и медиахранилищем в MinIO вам потребуется следующая команда:
pip install vstutils[prod,rpc,boto3]
Чтобы установить наиболее полный набор зависимостей, вы можете использовать обычный параметр all.
pip install vstutils[all]
Создание нового проекта, основанного на VST Utils
Если вы впервые используете vstutils, вам нужно позаботиться о начальной настройке. А именно: вам необходимо будет автоматически сгенерировать код, создающий приложение vstutils, включая конфигурацию базы данных, специфичные опции для Django и vstutils, а также настройки, специфичные для приложения. Для создания нового проекта выполните следующую команду:
python -m vstutils newproject --name {{app_name}}
Эта команда предложит указать такие параметры нового приложения, как:
project name - имя вашего нового приложения;
project guiname - имя вашего нового приложения, которое будет использоваться в GUI(веб-интерфейсе);
project directory - путь к директории, в которой будет создан проект.
Или вы можете выполнить следующую команду, которая содержит всю необходимую информацию для создания нового проекта.
python -m vstutils newproject --name {{app_name}} --dir {{app_dir}} --guiname {{app_guiname}} --noinput
Эта команда создает новый проект без подтверждения какой-либо информации.
Эти команды создают несколько файлов в
project directory
:/{{app_dir}}/{{app_name}} ├── frontend_src │ ├── app │ │ └── index │ ├── .editorconfig │ ├── .eslintrc.js │ └── .prettierrc ├── MANIFEST.in ├── package.json ├── README.rst ├── requirements-test.txt ├── requirements.txt ├── pyproject.toml ├── setup.py ├── {{app_name}} │ ├── __init__.py │ ├── __main__.py │ ├── models │ │ └── __init__.py │ ├── settings.ini │ ├── settings.py │ ├── web.ini │ └── wsgi.py ├── test.py ├── tox.ini └── webpack.config.jsdefault
где
frontend_src - директория, содержащая все исходные файлы для фронтенда;
MANIFEST.in - этот файл используется для создания установочного пакета;
{{app_name}} - директория с файлами вашего приложения;
package.json - этот файл содержит список зависимостей фронтенда и команд для сборки;
README.rst - стандартный README файл для вашего приложения (этот файл включает базовые команды для запуска/остановки вашего приложения);
requirements-test.txt - файл со списком зависимостей для тестирования вашего окружения;
requirements.txt - файл со списком зависимостей вашего приложения;
pyproject.toml - файл, используемый для сборки установочного пакета;
setup.py - файл, используемый для сборки установочного пакета;
test.py - этот файл используется для создания тестов;
tox.ini - этот файл используется для выполнения тестов;
webpack.config.js.default - этот файл содержит минимальный скрипт для webpack (замените „.default“, если пишите что-то в „app.js“).
Вам нужно выполнять приведенные ниже команды из директории
/{{app_dir}}/{{app_name}}/
. Хорошей практикой будет использование tox (должен быть установлен перед использованием) для создания отладочной среды для вашего приложения. Для этих целей рекомендуется использоватьtox -e contrib
в директории проекта, что автоматически создаст новое окружение с необходимыми зависимостями.Применение миграций
Давайте проверим, работает ли новый проект vstutils. Перейдите во внешний каталог
/{{app_dir}}/{{app_name}}
, если вы еще этого не сделали, и выполните следующую команду:python -m {{app_name}} migrate
Эта команда создаст базу данных SQLite (по умолчанию) с SQL схемой по умолчанию. VSTUTILS поддерживает все базы данных которые поддерживает Django.
Создание суперпользователя
python -m {{app_name}} createsuperuser
Запуск приложения
python -m {{app_name}} web
Веб-интерфейс вашего приложения будет запущен на порту 8080. Вы запустили сервер vstutils для продакшена на основе uWSGI.
Предупреждение
Сейчас хорошее время отметить: если вы хотите запустить веб-сервер с отладчиком, то вам следует запустить стандартный сервер разработки Django <https://docs.djangoproject.com/en/3.2/intro/tutorial01/#the-development-server>`_
Если вам нужно остановить сервер, используйте следующую команду:
python -m {{app_name}} web stop=/tmp/{{app_name}}_web.pid
Вы создали простейшее приложение, основанное на фреймворке VST Utils. Это приложение содержит только модель пользователя. Если вы хотите создать свои собственные модели, обратитесь к разделу ниже.
Добавление новых моделей в приложение
Если вы хотите добавить новые сущности в ваше приложение, вам необходимо выполнить следующие действия на серверной стороне:
Создайте модель;
Создайте сериализатор (опционально);
Создайте view (опционально);
Добавьте созданную модель или view в API;
Создайте миграции;
Примените миграции;
Перезапустите ваше приложение.
Давайте посмотрим, как это можно сделать на примере приложения AppExample которое содержит 2 пользовательские модели:
Task (абстракция для некоторых задач/активностей, которые пользователь должен выполнить);
Stage (абстракция для некоторых этапов, которые пользователь должен пройти для выполнения задачи. Эта модель вложена в модель Task).
Создание моделей
Сначала вам необходимо создать файл {{model_name}}.py
в директории /{{app_dir}}/{{app_name}}/{{app_name}}/models
.
Давайте рассмотрим пример с моделью BModel:
- class vstutils.models.BModel(*args, **kwargs)[исходный код]
Класс модели по умолчанию, который генерирует viewset, отдельные сериализаторы для list() и retrieve(), фильтры, эндпоинты API и вложенные 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
по адресу/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
с model_nameСписок мета-атрибутов для создания view:
_view_class
- список дополнительных классов view для наследования, класс или строка для импорта с базовым классом viewSet. Также поддерживаются константы:read_only
- для создания view только для просмотра;list_only
- для создания view только со списком;history
- для создания view только для просмотра и удаления записей
CRUD-view применяется по умолчанию.
_serializer_class
- класс сериализатора API; используйте этот атрибут, чтобы указать родительский класс для автоматически создаваемых сериализаторов. По умолчанию используетсяvstutils.api.serializers.VSTSerializer
. Может принимать строку для импорта, класс сериализатора илиdjango.utils.functional.SimpleLazyObject
._serializer_class_name
- имя модели для определений OpenAPI. Это будет имя модели в сгенерированном интерфейсе администратора. По умолчанию используется имя класса модели._list_fields
или_detail_fields
- список полей, которые будут перечислены списке сущностей или детальном view соответственно. То же самое, что и мета-атрибут «fields» сериализаторов DRF._override_list_fields
или_override_detail_fields
- отображение с именами и типами полей, которые будут переопределены в атрибутах сериализатора (рассматривайте это как объявление полей в сериализаторе DRF ModelSerializer)._properties_groups
- словарь с ключом в виде имени группы и значением в виде списка полей (строк). Позволяет группировать поля в разделы на фронтенде._view_field_name
- имя поля, которое фронтенд показывает в качестве основного имени view._non_bulk_methods
- список методов, которые не должны использоваться через пакетные запросы._extra_serializer_classes
- отображение с дополнительными сериализаторами в viewset. Например, пользовательский сериализатор, который будет вычислять что-то в действии (имя отображения). Значение может быть строкой для импорта. Важное замечание: установка атрибута модели в None позволяет использовать стандартный механизм создания сериализатора и получать поля из сериализатора списка или детальной записи (установите __inject_from__ мета-атрибут сериализатора в list или detail соответственно). В некоторых случаях требуется передать модель в сериализатор. Для этого можно использовать константу LAZY_MODEL в качестве мета-атрибута. Каждый раз при использовании сериализатора будет установлена точная модель, в которой был объявлен этот сериализатор._filterset_fields
- список/словарь имен фильтров для фильтрации API. По умолчанию это список полей в view списке. При обработке списка полей проверяется наличие специальных имен полей и наследуются дополнительные родительские классы. Если список содержитid
, класс будет наследоваться отvstutils.api.filters.DefaultIDFilter
. Если список содержитname
, класс будет наследоваться отvstutils.api.filters.DefaultNameFilter
. Если присутствуют оба условия, наследование будет происходить от всех вышеперечисленных классов. Возможные значения включают список (list) полей для фильтрации или словарь (dict), где ключ - это имя поля, а значение - класс Filter. Словарь расширяет функциональность атрибута и позволяет переопределять класс поля фильтра (значение None отключает переопределение)._search_fields
- кортеж или список полей, используемых для поисковых запросов. По умолчанию (или None) получаются все поля, по которым можно фильтровать в детальном view._copy_attrs
- список атрибутов экземпляра модели, указывающих, что объект можно скопировать с этими атрибутами._nested
- сопоставление ключ-значение вложенных view (ключ - имя вложенного view, kwargs для декоратораvstutils.api.decorators.nested_view
, но поддерживает атрибутmodel
в качестве вложенного).model
может быть строкой для импорта. Используйте параметрoverride_params
в тех случаях, когда необходимо перегрузить параметры генерируемого представления в качестве вложенного (работает только когда заданmodel
как вложенное представление)._extra_view_attributes
- отображение ключ-значение с дополнительными атрибутами view, но имеет меньший приоритет перед сгенерированными атрибутами.
Также вы также можете добавлять пользовательские атрибуты для переопределения или расширения списка обрабатываемых классов по умолчанию. Поддерживаемые атрибуты view:
filter_backends
,permission_classes
,authentication_classes
,throttle_classes
,renderer_classes
иparser_classes
. Список мета-атрибутов для настроек view выглядит следующим образом:_pre_{attribute}
- список классов, включаемых перед значениями по умолчанию._{attribute}
- список классов, включаемых после значений по умолчанию._override_{attribute}
- флаг-булево значение, указывающее, переопределяет ли атрибут view по умолчанию (в противном случае добавляется). По умолчанию False.
Примечание
Возможно, вам понадобится создать action в сгенерированном view. Используйте декоратор
vstutils.models.decorators.register_view_action
с аргументомdetail
, чтобы определить применимость к списку или детальной записи. В этом случае декорированный метод будет принимать объект view в качестве атрибутаself
.Примечание
В некоторых случаях при наследовании моделей может потребоваться наследовать класс Meta от базовой модели. Если Meta явно объявлена в базовом классе, вы можете получить ее через атрибут OriginalMeta и использовать для наследования.
Примечание
Docstring модели будет использоваться для описания 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) }, }, }, )
Разработчики могут использовать этот метод для изменения различных аспектов получаемого представления, таких как классы сериализаторов, конфигурацию полей, фильтры,классы разрешений и т.п. Этот метод использует такие же атрибуты, которые были объявлены в мета-атрибутах, но позволяет перегружать отдельные части.
Более подробную информацию о моделях вы можете найти в документации Django Models.
Если вам не нужно создавать пользовательские сериализаторы или view sets, вы можете перейти к этому этапу.
Создание сериализаторов
Примечание - Если вам не нужен пользовательский сериализатор, вы можете пропустить этот раздел.
В первую очередь вам необходимо создать файл serializers.py
в директории /{{app_dir}}/{{app_name}}/{{app_name}}/
.
Затем вам нужно добавить некоторый код, подобный следующему, в файл serializers.py
:
from datetime import datetime
from vstutils.api import serializers as vst_serializers
from . import models as models
class StageSerializer(models.Stage.generated_view.serializer_class):
class Meta:
model = models.Stage
fields = ('id',
'name',
'order',)
def update(self, instance, validated_data):
# Put custom logic to serializer update
instance.last_update = datetime.utcnow()
super().update(instance, validated_data)
Более подробную информацию о сериализаторах вы можете найти в документации Django REST Framework по сериализаторам.
Создание views
Примечание - Если вам не нужен пользовательский view set, вы можете пропустить этот раздел.
В первую очередь вам необходимо создать файл views.py
в директории /{{app_dir}}/{{app_name}}/{{app_name}}/
.
Затем вам нужно добавить некоторый код, подобный следующему, в файл views.py
:
from vstutils.api import decorators as deco
from vstutils.api.base import ModelViewSet
from . import serializers as sers
from .models import Stage, Task
class StageViewSet(Stage.generated_view):
serializer_class_one = sers.StageSerializer
'''
Decorator, that allows to put one view into another
* 'tasks' - suburl for nested view
* 'methods=["get"]' - allowed methods for this view
* 'manager_name='hosts' - Name of related QuerySet to the child model instances (we set it in HostGroup model as "hosts = models.ManyToManyField(Host)")
* 'view=Task.generated_view' - Nested view, that will be child view for decorated view
'''
@nested_view('stage', view=StageViewSet)
class TaskViewSet(Task.generated_view):
'''
Task operations.
'''
Больше информации о view и viewset вы можете найти в документации Django REST Framework для view.
Добавление моделей в API
Для добавления моделей в APi вам нужно написать код, подобный этому в в конце файла settings.py
:
'''
Some code generated by VST Utils
'''
'''
Add Task view set to the API
Only 'root' (parent) views should be added there.
Nested views added automatically, that's why there is only Task view.
Stage view is added altogether with Task as nested view.
'''
API[VST_API_VERSION][r'task'] = {
'view': 'newapp2.views.TaskViewSet'
}
'''
You can add model too.
All model generate base ViewSet with data that they have, if you don't create custom ViewSet or Serializer
'''
API[VST_API_VERSION][r'task'] = dict(
model='newapp2.models.Task'
)
# Adds link to the task view to the GUI menu
PROJECT_GUI_MENU.insert(0, {
'name': 'Task',
# CSS class of font-awesome icon
'span_class': 'fa fa-list-alt',
'url': '/task'
})
Создание миграций
Для создания миграций откройте директорию /{{app_dir}}/{{app_name}}/
и выполните следующую команду:
python -m {{app_name}} makemigrations {{app_name}}
Более подробную информацию о миграциях вы можете найти в документации Django Migrations.
Применение миграций
Для применения миграций вам необходимо открыть директорию /{{app_dir}}/{{app_name}}/
и выполнить следующую команду:
python -m {{app_name}} migrate
Перезапуск приложения
Для перезапуска вашего приложения вам сначала нужно остановить его (если оно было запущено ранее):
python -m {{app_name}} web stop=/tmp/{{app_name}}_web.pid
Затем запустите его снова:
python -m {{app_name}} web
После перезагрузки кэша вы увидите следующую страницу:
Как вы можете видеть, ссылка на новое Task view добавлена в боковое меню. Давайте нажмем на нее.
В вашем приложении нет экземпляра задачи. Добавьте его, используя кнопку „new“.
После создания новой задачи вы увидите следующую страницу:
Как видите, есть кнопка „stages“, которая открывает страницу со списком этапов этой задачи. Давайте на нее нажмем.
В вашем приложении нет экземпляров этапов. Давайте создадим 2 новых этапа.
После создания этапов страница со списком этапов будет выглядеть так:
Сортировка по полю order работает, как мы указали в нашем файле models.py
для модели Stage.
Дополнительную информацию о Django и Django REST Framework вы можете найти в документации Django и документации Django REST Framework.