Введение
Мне часто по жизни доводится работать с проектами, где есть SPA на Vue и какой-то бэк на Django + DRF. Раскидывать их по разных контейнерам в докере и рулить маршрутами на стороне nginx, конечно, круто, но а что если нужно передать какой-то параметр (например, токен) в Vue и мы не можем авторизовать пользователя просто так?
Кейс
Есть такая штука, как битрикс (да, я знаю, питону не место там, но всё же он там может быть). У него есть возможность установки внешних приложений из маркетплейса. И работает оно просто — открывается iframe и посылается POST запрос на URI обработчика приложения. В этом запросе битрикс передаёт токены для доступа, id пользователя, домен портала и прочую полезную инфу (место вызова приложения, тариф и прочее). Кстати, в битриксе это называют приложением второго типа (Первый тип без бэка вообще. А третий без фронта xD).
Подкручиваем бэк
Для начала стоит создать приложение, которое будет сёрвить фронт (можно и не создавать, но мне кажется, что пилить проект по кускам, когда одно приложение отвечает за пользователей, другое за фронт, третье за посты/товары/корзины и многое другое и так далее). Сделаем с нуля проект django, вкинем туда venv и приступим
django-admin startproject vue_django_test_app cd vue_django_test_app python3 -m venv venv source venv/bin/activate pip install django pip freeze > requirements.txt python3 ./manage.py startapp app
Вот проект и создан, мы в виртуальном окружении. Побалуемся 🙂
Во-первых, нам нужно подредачить settings.py и добавить приложение app в INSTALLED_APPS, прописать STATIC_ROOT и указать путь к шаблонам
INSTALLED_APPS = [ ... 'app' ] ... TEMPLATES = [ { ... 'DIRS': [BASE_DIR / 'templates'], ... } ] ... STATIC_ROOT = BASE_DIR / 'static/'
Для любителей Heroku
Если вы хотите дружить и с Heroku, то вам желательно установить и настроить пакет whitenoise
Как это сделать, можно почитать туть:
https://whitenoise.evans.io/en/stable/django.html
Напрямую сервить статику django через staticfiles_urlpatterns() не желательно
Теперь займёмся настройкой маршрутизации. По пути vue_django_test_app/urls.py нужно подключить вьюху, которая отправит шаблон (чуть позже напишем). Также на деве будем обслуживать статику через встроенный механизм django
from django.urls import path from django.contrib.staticfiles.urls import staticfiles_urlpatterns from app.views import FrontendTemplateView urlpatterns = [ path('', FrontendTemplateView.as_view()) ] urlpatterns += staticfiles_urlpatterns
Пишем представление Django
Как мы помним, нам нужно передать токены и GET параметры на фронт. Для этого нужно написать своё представление. Напишем его в app/views.py
from django.shortcuts import render from django.views import View import json class FrontendTemaplteView(View): def post(self, request): # Собираем все параметры запроса в контекст context = { 'post_data': request.body, 'get_data': json.dumps(request.GET) # Сериализуем в JSON } # Отправляем клиенту отрендеренный с контекстом шаблон return render(request, 'index.html', context)
Абсолютно простая вьюшка. Думаю, легко понять, что осталось сделать, чтобы пробросить данные)
Создание и настройка сборки vue приложения
Допустим, какой-то бэк на django у нас уже есть. Заходим в корень проекта и создаём проект vue.js (пусть будет frontend)
vue create frontend
Там vue поспрашивает за конфигурацию приложения. Выбирать можно что угодно, но нужно, чтобы конфиг хранился в раздельных .js файлах.
Про vue router
Vue router желательно не использовать в history mode, так как на каждый url фронта, нужно будет докидывать маршрут и в django
Затем нам нужно подредачить vue.config.js, чтобы webpack автоматом клал шаблон и статику в директории django
// Путь к приложению в котором храниться статика django const static_dir = '../app/static' // Путь, относительно static_dir // В него webpack положит шаблон Vue приложения const template_path = '../../templates/index.html' module.exports = { // Paths // Рабочая директория сборки // Я обычно указываю директорию приложения django, которое отвеает за фронт outputDir: process.env.NODE_ENV === 'production' ? static_dir : 'dist/', // Куда пойдёт шаблон проекта indexPath: process.env.NODE_ENV === 'production' ? template_path : 'index.html', // Куда пойдут ассеты (относительно outputDir) assetsDir: '', // ассеты храним там же, где и JS/CSS // Путь по которому можно достать статику // Нужно указать тот, который прописан в STATIC_URL настроек django publicPath: process.env.NODE_ENV === 'production' ? 'static' : '/', }
Проверка на NODE_ENV нужна для того, что дев сервер webpack мог нормально отработать при запуске npm/yarn run serve (ну мало ли нужно будет)
Модификация шаблона webpack
Осталось лишь дать понять django куда пихать контекст. И нам в этом поможет файл public/index.html — из него webpack соберёт окончательный html файл и положит его в папку templates. Добавим в этот файл маленький скрипт в котором создадим переменную глобального скоупа и положим туда наши JSON-чики
<head> ... <script> window.data = { post: {{post_data | safe}}, get: {{get_data | safe}}, } </script> ... </head>
Фильтр safe отключает экранирование символов, чтобы JSON остался валидным.
Финиш
Вот и всё готово! Осталось лишь собрать проект!
Из корня проекта:
cd frontend; npm run build; cd ../ python3 ./manage.py collectstatic --noinput python3 ./manage.py makemigrations; python3 ./manage.py migrate pip install gunicorn gunicorn vue_django_test_app.wsgi
ссылка на оригинал статьи https://habr.com/ru/post/568666/
Добавить комментарий