Дисклеймер!
Статья предназначена для людей, которые достаточно хорошо разбираются в веб разработке на 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. Открыт для критики, буду рад, если укажите на ошибки и недочёты :)