The purpose of django-userskins is to facilitate Django apps to allow users to select from a variety of provided skins to customize how a site looks for them. Essentially, to provide the functionality exposed in Twitter's recent update where users can choose from a handful of different appearances for how Twitter appears when they visit the site.
Django-userskins' implementation is designed to minimize additional hits on the database, but to allow the skin preference to persist across cleanings of the cookie cache.
The implementation is split into a template processing context, a template tag, and a middleware.
The behavior of the custom template processing context is:
-
Check if the user has a cookie named
userskins
. If so, use its value to select the skin. -
Otherwise use the default skin.
The behavior of the middleware is to examine all HttpResponse objects and:
-
If the HttpResponse object has a cookie named
userskins
, do nothing. -
If the response does not have a cookie named
userskins
, then if the user is anonymous give it auserskins
cookie for the default skin.If the user is authenticated, then attempt to retrieve a
userskins.SkinPreference
object with the logged in user as the value of itsuser
foreign key.(Note that this is the only hit on the database that the userskins app will cause. Meaning, it will only hit the database for logged in users who don't already have a userskins cookie. When it does hit the database, it will set a cookie for the user, so it should only be necessary to hit the database once each time a user cleans their cookie cache. Also note, that you may use the
USERSKINS_NEVER_ACCESS_DATABASE
setting value to disable the middleware, and thus remove all database accesses, although skin preferences will no longer persist across cookie cleanings.)Set the value of the
userskins
cookie to the value stored in theSkinPreference
object if one exists, otherwise set it to the default skin.
The userskins
template tag library contains one template
tag, userskin
, which takes no arguments and handles outputing
the correct CSS include or (if you have the correct settings enabled)
django-compress group.
-
Add
django-userskins.userskins
to your Python path. -
Add
userskins
to your applicationsINSTALLED_APPS
setting in settings.py. -
Add the
userskins.context.userskins
template context processor insettings.py
(note that this will be a new setting in your settings.py file, by default it is not shown):TEMPLATE_CONTEXT_PROCESSORS = ( "django.core.context_processors.auth", "django.core.context_processors.debug", "django.core.context_processors.i18n", "django.core.context_processors.media", "userskins.context.userskins", )
-
Add the
userskins.middleware.UserskinsMiddleware
middleware to your project's middleware.MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'userskins.middleware.UserskinsMiddleware', )
The position of the
UserskinsMiddleware
shouldn't be signifigant. -
Establish values for the
USERSKINS_DEFAULT
,USERSKINS_DETAILS
andUSERSKINS_USE_COMPRESS_GROUPS_INSTEAD
values in your settings.py file.USERSKINS_DEFAULT = "light" USERSKINS_DETAILS = { 'light':'light.css', 'dark':'dark.css', } USERSKINS_USE_COMPRESS_GROUPS = False # optional USERSKINS_NEVER_ACCESS_DATABASE = False # optional
USERSKINS_USE_COMPRESS_GROUPS
is to support integration with the django-compress project. In that case, the values of keys inUSERSKINS_DETAILS
are ignored, and the keys themselves are passed to the django-compress template tags as names of compressed css groups. The default value ofUSERSKINS_USER_COMPRESS_GROUP
is False.It is highly recommended to use django-userskins along with django-compress, as it will allow you to provide users with selectable skins without increasing the median bandwith per request or the median number of http requests per page.
There is also the
USERSKINS_NEVER_ACCESS_DATABASE
option, which is what you should use if you want skin preferences to be entirely cookie based (and never check the database if the user has an associated SkinPreference object). The default value ofUSERSKINS_NEVER_ACCESS_DATABASE
is False. -
Sync your database to create the relevant models. Note that this is not necessary if you use
USERSKINS_NEVER_ACCESS_DATABASE = True
.python manage.py syncdb
-
Now modify your base template (or wherever you want to use skins) to resemble this code:
{% load userskins %} <html><head> <title> Some title </title> {% userskin %} </head> <body> {% block content %}{% endblock %} </body> </html>
-
The last stage of setup is to setup a mechanism for allowing users to select skins. Depending on your needs, this may be as simple as a view that sets an appropriate cookie and redirects to the page they came from, or it may be part of a user preferences panel.
More details coming soon, for the time being look at the userskins.models.SkinPreference model and the dev_userskins.urls file for some ideas.