Python and Django utilities shared between different OpenWISP modules.
Table of Contents:
- Customized admin theme for OpenWISP modules
- Multitenant admin interface and testing mixins
- TimeStamped models and mixins which add self-updating
created
andmodified
fields. - DependencyLoader: template loader which looks in the templates dir of all django-apps
listed in
EXTENDED_APPS
- DependencyFinder: finds static files of django-apps listed in
EXTENDED_APPS
- Minimize code duplication among OpenWISP modules
Install from pypi:
pip install openwisp-utils
# install optional dependencies for openwisp-users too
pip install openwisp-utils[users]
Install tarball:
pip install https://github.com/openwisp/openwisp-utils/tarball/master
Alternatively you can install via pip using git:
pip install -e git+git://github.com/openwisp/openwisp-utils#egg=openwisp-utils
If you want to contribute, install your cloned fork:
git clone [email protected]:<your_fork>/openwisp-utils.git
cd openwisp-utils
python setup.py develop
INSTALLED_APPS
in settings.py
should look like the following if you want to use all the utilities
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# customized admin theme
'openwisp_utils.admin_theme',
# all-auth
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'django_extensions',
# openwisp2 modules
'openwisp_users',
# admin
'django.contrib.admin',
]
For using the customized admin theme,
- Make sure you've added
openwisp_utils.admin_theme
toINSTALLED_APPS
insettings.py
- Add the following into your
urls.py
file which containsadmin
urls.
from django.conf.urls import include, url
from openwisp_utils.admin_theme.admin import admin, openwisp_admin
openwisp_admin()
urlpatterns = [
# other url patterns
url(r'^admin/', include(admin.site.urls)),
]
These are mixins which make a ModelAdmin class multitenant: users will see only the objects related to the organizations they are associated with.
- MultitenantAdminMixin: adding this mixin to a
ModelAdmin
class will make it multitenant. Setmultitenant_shared_relations
to the list of parameters you wish to have only organization specific options. - MultitenantOrgFilter: admin filter that shows only organizations the current user is associated with in its available choices.
- MultitenantRelatedOrgFilter: similar
MultitenantOrgFilter
but shows only objects which have a relation with one of the organizations the current user is associated with. - TimeReadonlyAdminMixin: Admin mixin which adds two readonly fields
created
andmodified
. This is an admin mixin for models inheritingTimeStampedEditableModel
which adds the fieldscreated
andmodified
to the database.
Example usage:
from django.contrib import admin
from openwisp_utils.admin import (MultitenantAdminMixin,
MultitenantObjectFilter,
MultitenantOrgFilter,
TimeReadonlyAdminMixin)
from .models import Book, Shelf
class BaseAdmin(MultitenantAdminMixin, TimeReadonlyAdminMixin, admin.ModelAdmin):
pass
class ShelfAdmin(BaseAdmin):
list_display = ['name', 'organization']
list_filter = [('organization', MultitenantOrgFilter)]
fields = ['name', 'organization', 'created', 'modified']
class BookAdmin(BaseAdmin):
list_display = ['name', 'author', 'organization', 'shelf']
list_filter = [('organization', MultitenantOrgFilter),
('shelf', MultitenantObjectFilter)]
fields = ['name', 'author', 'organization', 'shelf', 'created', 'modified']
multitenant_shared_relations = ['shelf']
Add the list of all packages extended to EXTENDED_APPS
in settings.py
.
If you've extended django_netjsonconfig
and django_x509
:
EXTENDED_APPS = ['django_netjsonconfig', 'django_x509']
Add openwisp_utils.staticfiles.DependencyFinder
to STATICFILES_FINDERS
in settings.py
.
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'openwisp_utils.staticfiles.DependencyFinder',
]
Add openwisp_utils.staticfiles.DependencyFinder
to TEMPLATES_LOADERS
in settings.py
or as shown below.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'OPTIONS': {
'loaders': [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'openwisp_utils.loaders.DependencyLoader',
],
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Install sqlite:
sudo apt-get install sqlite3 libsqlite3-dev
Install your forked repo:
git clone git://github.com/<your_fork>/openwisp-utils
cd openwisp-utils/
python setup.py develop
Install test requirements:
pip install -r requirements-test.txt
Create database:
cd tests/
./manage.py migrate
./manage.py createsuperuser
Set EMAIL_PORT
in settings.py
to a port number (eg: 1025
):
EMAIL_PORT = '1025'
Launch development server and SMTP deubgging server:
./manage.py runserver
# open another session and run
python -m smtpd -n -c DebuggingServer localhost:1025
You can access the admin interface of the test project at http://127.0.0.1:8000/admin/.
Run tests with:
./runtests.py
- Announce your intentions in the OpenWISP Mailing List and open relavant issues using the issue tracker
- Fork this repo and install the project following the instructions
- Follow PEP8, Style Guide for Python Code
- Write code and corresponding tests
- Ensure that all tests pass and the test coverage does not decrease
- Document your changes
- Send a pull request
See CHANGES.
See LICENSE.