Дисклеймер!
Статья предназначена для людей, которые достаточно хорошо разбираются в веб разработке на python. Это моя первая статья, поэтому прошу сильно не ругаться :)
Привет, Хабр!
Создавая небольшой сайтик на Django появилась мысль сделать из него web приложение(Опыт в создании веб приложение был, правда только на Flask). И в итоге начались поиски, которые так и не привели к наиболее приятному способы создания PWA приложения на Django, к моему удивлению даже на хабре не нашлось статьи на это тему (. Спустя 3 дня упорных поисков , я совершенно случайно наткнулся на gitlab, где задача была реализована достаточно понятно, и без старонних библиотек. Если вы достаточно хорошо понимаете django и сам принцип создание веб сайтов, данный gitlab можно посмотреть и скачать здесь.
Если хотите разобраться вместе со мной, тогда вперёд!
Установка Django и создание проекта
Ну сперва-наперво нужно установить сам Django.
pip install django
Ну или, если у вас линукс или что-то такое:
sudo pip install django
На всякий случай оставлю ссылку на pip библиотеку здесь.
Теперь пора создавать сам проект
Переходим в папку, где будет размещаться проект, и пишем:
django-admin startproject имя вышего проекта
У меня проект будет называться django-pwa-test
Заходим в папку проекта. Там должны быть: папка с именем вашего проекта, файл manage.py и файл db.sqlite3.
Переходим в папку с именем вашего проекта, и создаем там папки: static(здесь будут храниться некоторые статические файлы) и templates(здесь будут храниться frontend файлы). По желанию так-же стоит создать папку apps, в ней будут храниться приложения(я создам, а вы - как хотите).
Дальше. Переходим в папку apps и создаём приложение(у меня оно будет называться 'Pwa')
django-admin startapp Pwa
Создание манифеста и сервис воркера
И так. Для тех, кто не знает: манифест и сервис воркер - это основные файлы, которые и буду отвечать за работу PWA.
Service worker обеспечивают возможность работы offline, также он — посредник между клиентом и сервером, пропускающий через себя все запросы к серверу.
В манифесте будет храниться информация: о названии приложения, его описание, стартовый url, его иконки и тд.
Для создание манифеста:переходим в папку static и создаём файл manifest.json. В файле пишем:
{ "name": "Django PWA", "short_name": "djangopwa", "start_url": "/", "scope": ".", "display": "standalone", "background_color": "#FFF", "theme_color": "#493174", "description": "Test app for Django and PWA", "dir": "ltr", "lang": "en-US", "orientation": "portrait-primary", "icons": [{ "src": "/static/icons/aurss.96x96.png", "type": "image/png", "sizes": "96x96" }, { "src": "/static/icons/aurss.512x512.png", "type": "image/png", "sizes": "512x512" }] }
Где: name и shortname - имена приложения, starturl - ulr, который будет открываться при запуске PWA приложения, scope - уровни, на которых может работать сервис воркер, icons - путь к иконкам для приложения(мы создадим их немного позже). Подробнее можно почитать здесь.
Создание сервис воркера
Переходим в папку templates и создаём файл sw.js. Пишем в нём:
console.log('Hello from sw.js'); importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.2.0/workbox-sw.js'); if (workbox) { console.log(`Yay! Workbox is loaded 🎉`); workbox.precaching.precacheAndRoute([ { "url": "/", "revision": "1" } ]); workbox.routing.registerRoute( /\.(?:js|css)$/, workbox.strategies.staleWhileRevalidate({ cacheName: 'static-resources', }), ); workbox.routing.registerRoute( /\.(?:png|gif|jpg|jpeg|svg)$/, workbox.strategies.cacheFirst({ cacheName: 'images', plugins: [ new workbox.expiration.Plugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days }), ], }), ); workbox.routing.registerRoute( new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'), workbox.strategies.cacheFirst({ cacheName: 'googleapis', plugins: [ new workbox.expiration.Plugin({ maxEntries: 30, }), ], }), ); } else { console.log(`Boo! Workbox didn't load 😬`); }
Если хотите больше узнать о том, как работает сервис воркер, то смотрите здесь.
Подключение PWA к html файлу
Переходим в папку templates и создаем html файл с любым именем (у меня будет home.html). В html файле прописываем:
<!DOCTYPE html> <html> <head> {% load static %} <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="manifest" href="{% static 'manifest.json' %}"> <title>hello world</title> </head> <body> <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('{% url "sw.js" %}', { scope: '/' }).then(function(reg) { // registration worked console.log('Registration succeeded. Scope is ' + reg.scope); }).catch(function(error) { // registration failed console.log('Registration failed with ' + error); }); } </script> </body> </html>
Пробежимся по основному
{% load static %} дает нам доступ к папке staticЧерез тег link в 8 строке мы подключаем файл манифеста.
С помощью небольшого js скрипта, мы подключаем сервис воркер.
Иконки для манифеста
Если вспомнить код манифеста, а точнее часть с параметрами иконок:
"icons": [{ "src": "/static/icons/aurss.96x96.png", "type": "image/png", "sizes": "96x96" }, { "src": "/static/icons/aurss.512x512.png", "type": "image/png", "sizes": "512x512" }]
Можно заметить, что иконки берутся из /static/icons, поэтому мы переходим в папку static и создаём там папку с именем icons. В этой папке будут храниться иконки разного размера, для вашего приложения. В данном случае, в папку icons нужно сохранить изображения с размерами: 96x96 512x512. С именем, которое указано в манифесте(При желании его можно изменить)
На этом создание дополнительных файлов подходит к концу)
И так, если вы всё сделали правильно, то ваш проект будет выглядеть как-то так :
django-pwa-test manage.py db.sqlite3 django-pwa-test apps Pwa python файлы static manifest.json icons ваши иконки для приложения templates home.html sw.js
Настройка параметров в settings.py
Теперь пора немного изменить настройки приложения)
Переходим в основную папку проекта, находим settings.py и дополняем.
Для начала нужно импортировать модуль os:
import os
Теперь ищем переменную TEMPLATES, в ней ищем массив с именем DIRS, и добавляем в него:
os.path.join(BASE_DIR, 'имя вашего приложения/templates')
Должно получиться что-то такое:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ os.path.join(BASE_DIR, 'имя вашего приложения/templates'), ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
Далее ищем переменную BASE_DIR(она будет в самом начале), и после неё пишем:
STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'имя вышего приложения/static/'), ] STATIC_ROOT = BASE_DIR / 'static'
На этом изменения в настройках закончены.
Рендер страницы и доступ к sw.js
Для того, чтобы наша страница могла получить доступ к файлу sw.js на нужно написать класс, который будет в этом участвовать.
Идём в папку с приложением(именно приложением, не проектом. Если не забыли, у меня приложение называется Pwa) и записываем в файл views.py:
from django.shortcuts import render from django.views.generic import TemplateView # Create your views here. def home(request): return render(request, 'home.html') class ServiceWorkerView(TemplateView): template_name = 'sw.js' content_type = 'application/javascript' name = 'sw.js'
Быстрый разбор:
Если вы хотя бы немного знаете Django, то функция home должна быть вам понятна(Если вы не знаете, как она работает, то советую сначала поучить Django, и потом уже приходить сюда. Без обид)
через urls.py методом .as_view() мы получим доступ к классу ServiceWorkerView (а также и его значениям), и достанем из него значение переменно
name(она будет использована для получения доступа к файлу).
Добавление адресов в urls.py
Здесь мы пропишем адреса для отображения основной страницы и sw.js
Идем в основную папку проекта, открываем файл urls.py и пишем.
Для начала из созданного приложения (У меня это Pwa) нужно импортировать файл
В случае, если вы, как и я сохранили приложение в папке apps:
from .apps.Pwa import views
Если же вы самостоятельная личность, и сохранили без папки apps, то:
from .Pwa import views
Напоминаю: я импорти��ую из папки Pwa потому, что так называется моё приложение(у вас оно может быть другим, но тогда вам надо проверить все файлы и сменить их путь на свой)!!!
Теперь в массив urlpatterns нужно добавить следующие значения: path("", views.home), path('sw.js',views.ServiceWorkerView.as_view(), name=views.ServiceWorkerView.name,)
Теперь ваш urls.py должен выглядеть как-то так:
from django.contrib import admin from django.urls import path from .apps.Pwa import views urlpatterns = [ path('admin/', admin.site.urls), path("", views.home), path('sw.js', views.ServiceWorkerView.as_view(), name=views.ServiceWorkerView.name, ), ]
Разбор:
path('', views.home)прорисует основную страницу вызвав функцию home() из файла view.py в нашем приложенииpath('sw.js',views.ServiceWorkerView.as_view(),name=views.ServiceWorkerView.name) позволяет получить доступ к файлу sw.js
На этом пока всё. Если хотите протестировать, то переходите в папку с файлом manage.py, и выполняйте команду python3 manage.py runserver
Открывайте браузер по указанной ссылке(она в терминале), и если ваш браузер поддерживает pwa, то на панели поиска(справа, вверху) появится предложение установить приложение. Если у вас FireFox, то скорее всего не появится.
Ели вы в поддерживающем pwa браузере, но предложение установить приложение, или иконка установки так и не появились, то нажимайте F12, и посмотрите в консоли ошибки, если ошибок нет, то нажимайте F12 переходите на вкладку 'Приложения', и проверьте манифест и сервис воркер. Если ничего не помогло, тогда гугл в помощь!
P.S. Открыт для критики, буду рад, если укажите на ошибки и недочёты :)
