Initial revision.

This commit is contained in:
Scott
2017-02-04 22:20:40 -07:00
commit a66325af7b
19 changed files with 284 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.py[cod]
.idea/
*.orig

5
CHANGELOG.md Normal file
View File

@@ -0,0 +1,5 @@
# Changelog
## 0.1.0
- Initial release

21
LICENSE.md Normal file
View File

@@ -0,0 +1,21 @@
MIT License (MIT)
Copyright (c) 2014 Scott Vitale
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
MANIFEST.in Normal file
View File

@@ -0,0 +1,2 @@
include *.md
recursive-include pwa/templates *

91
README.md Normal file
View File

@@ -0,0 +1,91 @@
django-progressive-web-app
=====
This Django app turns your project into a [progressive web app](https://developers.google.com/web/progressive-web-apps/). Navigating to your site on an Android phone will prompt you to add the app to your home screen.
![Prompt for install](images/screenshot1.png)
Launching the app from your home screen will display your app [without browser chrome](images/screenshot2.png). As such, it's critical that your application provides all navigation within the HTML (no reliance on the browser back or forward button).
Requirements
=====
Progressive Web Apps require HTTPS unless being served from localhost. If you're not already using HTTPS on your site, check out [Let's Encrypt](https://letsencrypt.org/) and [ZeroSSL](https://zerossl.com/).
Installation
=====
Install from PyPI:
```
pip install django-progressive-web-app
```
Configuration
=====
Add `pwa` to your list of `INSTALLED_APPS` in settings.py:
```python
INSTALLED_APPS = [
...
'pwa',
...
]
```
Configure your app name, description, and icons in settings.py:
```python
PWA_APP_NAME = 'My Kickass App'
PWA_APP_DESCRIPTION = "Do kickass things all day long without that pesky browser chrome"
PWA_APP_THEME_COLOR = '#0A0302'
PWA_APP_ICONS = [
{
'src': '/static/images/my_app_icon.png',
'sizes': '160x160'
}
]
```
Add the progressive web app URLs to urls.py:
```python
from django.conf.urls import url, include
urlpatterns = [
...
url('', include('pwa.urls')), # You MUST use an empty string as the URL prefix
...
]
```
Inject the required meta tags in your base.html (or wherever your HTML <head> is defined):
```html
{% load pwa %}
<head>
...
{% progressive_web_app_meta %}
...
</head>
```
Troubleshooting
=====
While running the Django test server:
1. Verify that `/manifest.json` is being served
1. Verify that `/serviceworker.js` is being served
1. Use the Application tab in the Chrome Developer Tools to verify the progressive web app is configured correctly.
1. Use the "Add to homescreen" link on the Application Tab to verify you can add the app successfully.
Adding Your Own Service Worker
=====
By default, the service worker implemented by this app is empty. To add service worker functionality, you'll want to create a `serviceworker.js` or similarly named file, and then point at it using the PWA_SERVICE_WORKER_PATH variable.
```python
PWA_SERVICE_WORKER_PATH = os.path.join(BASE_DIR, 'my_app', 'serviceworker.js')
```
Feedback
=====
I welcome your feedback and pull requests. Enjoy!
License
=====
All files in this repository are distributed under the MIT license.

BIN
images/screenshot1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
images/screenshot2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

0
pwa/__init__.py Normal file
View File

21
pwa/app_settings.py Normal file
View File

@@ -0,0 +1,21 @@
""" Settings required by django-progressive-web-app. """
from django.conf import settings
import os
# Path to the service worker implementation. Default implementation is empty.
PWA_SERVICE_WORKER_PATH = getattr(settings, 'PWA_SERVICE_WORKER_PATH',
os.path.join(os.path.abspath(os.path.dirname(__file__)), 'templates', 'serviceworker.js'))
# App parameters to include in manifest.json and appropriate meta tags
PWA_APP_NAME = getattr(settings, 'PWA_APP_NAME', 'MyApp')
PWA_APP_DESCRIPTION = getattr(settings, 'PWA_APP_DESCRIPTION', 'My Progressive Web App')
PWA_APP_ROOT_URL = getattr(settings, 'PWA_APP_ROOT_URL', '/')
PWA_APP_THEME_COLOR = getattr(settings, 'PWA_APP_THEME_COLOR', '#000')
PWA_APP_ICONS = getattr(settings, 'PWA_APP_ICONS', [
{
'src': '/',
'sizes': '160x160'
}
])

5
pwa/apps.py Normal file
View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class PwaConfig(AppConfig):
name = 'pwa'

View File

@@ -0,0 +1,11 @@
{% load pwa %}
{
"name": {{ PWA_APP_NAME|js }},
"short_name": {{ PWA_APP_NAME|js }},
"description": {{ PWA_APP_DESCRIPTION|js }},
"start_url": "/",
"display": "standalone",
"background_color": "#fff",
"theme_color": {{ PWA_APP_THEME_COLOR|js }},
"icons": {{ PWA_APP_ICONS|js }}
}

27
pwa/templates/pwa.html Normal file
View File

@@ -0,0 +1,27 @@
<!-- Path to manifest.json -->
<link rel="manifest" href="/manifest.json">
<!-- Icons for Apple Devices -->
{% for icon in PWA_APP_ICONS %}
<link rel="apple-touch-icon" href="{{ icon.src }}" sizes="{{ icon.sizes }}">
{% endfor %}
<meta name="theme-color" content="{{ PWA_APP_THEME_COLOR }}">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="{{ PWA_APP_NAME }}">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<script type="text/javascript">
// Initialize the service worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/serviceworker.js').then(function (registration) {
// Registration was successful
console.log('django-progressive-web-app: ServiceWorker registration successful with scope: ', registration.scope);
}).catch(function (err) {
// registration failed :(
console.log('django-progressive-web-app: ServiceWorker registration failed: ', err);
});
});
}
</script>

View File

@@ -0,0 +1,2 @@
// Empty Service Worker implementation. To use your own Service Worker, set the PWA_SERVICE_WORKER_PATH variable in
// settings.py

View File

25
pwa/templatetags/pwa.py Normal file
View File

@@ -0,0 +1,25 @@
import json
from django import template
from django.core.serializers.json import DjangoJSONEncoder
from django.utils.safestring import mark_safe
from .. import app_settings
register = template.Library()
@register.filter(is_safe=True)
def js(obj):
""" Transform a python object so it can be safely used in javascript/JSON. """
return mark_safe(json.dumps(obj, cls=DjangoJSONEncoder))
@register.inclusion_tag('pwa.html', takes_context=True)
def progressive_web_app_meta(context):
# Pass all PWA_* settings into the template
return {
setting_name: getattr(app_settings, setting_name)
for setting_name in dir(app_settings)
if setting_name.startswith('PWA_')
}

8
pwa/urls.py Normal file
View File

@@ -0,0 +1,8 @@
from django.conf.urls import url
from .views import manifest, service_worker
# Serve up serviceworker.js and manifest.json at the root
urlpatterns = [
url('^serviceworker.js$', service_worker),
url('^manifest.json$', manifest)
]

17
pwa/views.py Normal file
View File

@@ -0,0 +1,17 @@
from django.http import HttpResponse
from django.shortcuts import render
from . import app_settings
def service_worker(request):
response = HttpResponse(open(app_settings.PWA_SERVICE_WORKER_PATH).read(), content_type='application/javascript')
return response
def manifest(request):
return render(request, 'manifest.json', {
setting_name: getattr(app_settings, setting_name)
for setting_name in dir(app_settings)
if setting_name.startswith('PWA_')
})

1
requirements-dev.txt Normal file
View File

@@ -0,0 +1 @@
pypandoc==1.3.3

45
setup.py Normal file
View File

@@ -0,0 +1,45 @@
import os
from setuptools import find_packages, setup
short_description = 'A Django app to include a manifest.json and Service Worker instance to enable progressive web ' \
'app behavior '
# noinspection PyBroadException
try:
# noinspection PyPackageRequirements
import pypandoc
long_description = pypandoc.convert('README.md', 'rst')
except:
long_description = short_description
# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
setup(
name='django-progressive-web-app',
version='0.1',
packages=find_packages(),
include_package_data=True,
license='MIT License',
description=short_description,
long_description=long_description,
url='http://github.com/svvitale/django-progressive-web-app',
author='Scott Vitale',
author_email='svvitale@gmail.com',
classifiers=[
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 1.10',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
)