Как подружить django и vue.js

от автора

Введение

Мне часто по жизни доводится работать с проектами, где есть 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *