Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,26 @@ It should create a folder ``themes`` at the project with the following structure
| | -- images/
| -- templatefiles and folders


Installable Themes

To install a theme add it to ``INSTALLED_APPS``, then define ``THEMING_APPS`` dict with the theme slug as
the key and the app label as the value e.g. ::

THEMING_ROOT = 'themes'
THEMING_APPS = {
'default': 'my_default_theme_app', # could be the project app or an installed theme.
'mytheme': 'my_theme',
'slug': 'app_label', # example format
}




Contributing
============

Development of **django-template-theming** happens at github and any idea and contribution is wellcome.
Development of **django-template-theming** happens at github and any idea and contribution is welcome.
https://github.com/wtayyeb/django-template-theming

Credits
Expand Down
4 changes: 1 addition & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

from setuptools import setup, find_packages

import theming


BASE = path.abspath(path.dirname(__file__))

Expand All @@ -14,7 +12,7 @@

setup(
name='django-template-theming',
version=theming.__version__,
version='0.8.2',
url='https://github.com/wtayyeb/django-template-theming',
author='w.Tayyeb',
author_email='tayyeb@tsaze.com',
Expand Down
32 changes: 19 additions & 13 deletions theming/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

class App(AppConfig):
name = 'theming'
label = 'template_theming'
verbose_name = "Template Theming"

class Defaults:
THEMING_DEFAULT_THEME = 'default'
Expand All @@ -40,20 +42,24 @@ def configure(self):

def patch_settings_staticfiles_dirs(self):
staticfiles_dirs = []
for theme_slug in os.listdir(settings.THEMING_ROOT):
if theme_slug.startswith('~'):
continue
from .models import Theme
root_list = Theme.get_theming_root()
# make root a list
for root in root_list:
for theme_slug in os.listdir(root):
if theme_slug.startswith('~'):
continue

real_path = os.path.join(settings.THEMING_ROOT, theme_slug, 'static').replace('\\', '/')
if os.path.isdir(real_path):
# here we need its path under static so using THEMING_URL
key = os.path.join(settings.THEMING_URL, theme_slug).replace('\\', '/')
row = (key, real_path)
if os.name == 'nt': # fix for windows
row = [r.replace('/', '\\') for r in row]
staticfiles_dirs.append(row)
else:
logger.debug('theme `%s` not found.' % theme_slug)
real_path = os.path.join(settings.THEMING_ROOT, theme_slug, 'static').replace('\\', '/')
if os.path.isdir(real_path):
# here we need its path under static so using THEMING_URL
key = os.path.join(settings.THEMING_URL, theme_slug).replace('\\', '/')
row = (key, real_path)
if os.name == 'nt': # fix for windows
row = [r.replace('/', '\\') for r in row]
staticfiles_dirs.append(row)
else:
logger.debug('theme `%s` not found.' % theme_slug)

PRE_STATICFILES_DIRS = getattr(settings, 'PRE_STATICFILES_DIRS', None)
if PRE_STATICFILES_DIRS is None:
Expand Down
13 changes: 12 additions & 1 deletion theming/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ class ThemingMiddleware(object):
)

'''
def __init__(self, get_response=None):
self.get_response = get_response

def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response

def process_request(self, request):
try:
Expand All @@ -38,4 +50,3 @@ def process_request(self, request):
sitetheme = None

set_thread_variable('sitetheme', sitetheme)

2 changes: 1 addition & 1 deletion theming/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('theme_slug', models.CharField(max_length=100, choices=thememanager.get_themes_choice())),
('site', models.OneToOneField(to='sites.Site')),
('site', models.OneToOneField(to='sites.Site',on_delete=models.CASCADE)),
],
),
]
2 changes: 1 addition & 1 deletion theming/migrations/0002_auto_20170508_0505.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class Migration(migrations.Migration):

dependencies = [
('theming', '0001_initial'),
('template_theming', '0001_initial'),
]

operations = [
Expand Down
53 changes: 45 additions & 8 deletions theming/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,41 @@ def __init__(self, slug, *args, **kwargs):
self._metadata = {}
self.metadata_ready = None

@classmethod
def get_theming_root(cls, theme_slug=None):
root = settings.THEMING_ROOT if hasattr(settings, 'THEMING_ROOT') else 'themes'
if theme_slug:
if hasattr(settings, 'THEMING_APPS') and settings.THEMING_APPS is not None:
theme_app = settings.THEMING_APPS[theme_slug] if \
hasattr(settings, 'THEMING_APPS') else 'themes'
theme_app = __import__(theme_app)
root = os.path.join(theme_app.__file__).replace(
'__init__.py', settings.THEMING_ROOT
)
else:
if hasattr(settings, 'THEMING_APPS') and settings.THEMING_APPS is not None:
root_list = []
for theme, app in settings.THEMING_APPS.items():
theme_app = __import__(app)

# Get the THEMING_ROOT for a loaded theme app.
# Theme apps should use the same construction i.e.
# the THEMING_ROOT and folder layout should be standardised.
root = os.path.join(theme_app.__file__).replace(
'__init__.py', settings.THEMING_ROOT
)
root_list.append(root)
return root_list
return [root]
# used by read_metadata or by passing a theme_slug to return a
# a single root rather than a list.
return root

def read_metadata(self):
filename = os.path.join(settings.THEMING_ROOT, self.slug, self._metadata_filename)
filename = os.path.join(
Theme.get_theming_root(thememanager.get_current_theme().slug),
self.slug, self._metadata_filename
)
try:
with open(filename, 'r') as f:
self._metadata = json.load(f)
Expand Down Expand Up @@ -70,10 +103,11 @@ def __init__(self, *args, **kwargs):
def find_themes(self, force=False):
if self._themes is None or force:
self._themes = {}
root = settings.THEMING_ROOT
for dirname in os.listdir(root):
if not dirname.startswith('~'):
self._themes[dirname] = Theme(dirname)
root_list = Theme.get_theming_root()
for root in root_list:
for dirname in os.listdir(root):
if not dirname.startswith('~'):
self._themes[dirname] = Theme(dirname)
return self._themes

def get_themes_choice(self):
Expand All @@ -88,10 +122,13 @@ def get_current_theme(self):
if sitetheme:
theme = sitetheme.theme
else:
theme = self.get_theme(settings.THEMING_DEFAULT_THEME)
if not hasattr(settings, 'THEMING_DEFAULT_THEME'):
theme = self.get_theme('default')
else:
theme = self.get_theme(settings.THEMING_DEFAULT_THEME)
return theme

def get_theme(self, theme_slug):
def get_theme(self, theme_slug='default'):
self.find_themes()
return self._themes[theme_slug]

Expand All @@ -101,7 +138,7 @@ def get_theme(self, theme_slug):

@python_2_unicode_compatible
class SiteTheme(models.Model):
site = models.OneToOneField(Site)
site = models.OneToOneField(Site, on_delete=models.CASCADE)
theme_slug = models.CharField(max_length=100, choices=thememanager.get_themes_choice())
site_title = models.CharField(max_length=255, default='', blank=True)
site_description = models.CharField(max_length=255, default='', blank=True)
Expand Down
3 changes: 2 additions & 1 deletion theming/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ def get_template_sources(self, template_name, template_dirs=None):
theme = thememanager.get_current_theme()

if not template_dirs:
template_dirs = [safe_join(settings.THEMING_ROOT, theme.slug), ]
from .models import Theme
template_dirs = [safe_join(Theme.get_theming_root(theme.slug), theme.slug), ]

for template_dir in template_dirs:
try:
Expand Down
9 changes: 6 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ minversion = 1.8
skip_missing_interpreters=True

envlist =
py27-dj{1.8,1.9,.dev},
py34-dj{1.8,1.9,.dev},
py35-dj{1.9,.dev},
py27-dj{1.8,1.9,1.10,1.11},
py34-dj{1.8,1.9,1.10,1.11},
py35-dj{1.9,1.10,1.11,2.0,.dev},
py36-dj{1.9,1.10,1.11,2.0,.dev},

docs,

Expand All @@ -17,6 +18,8 @@ deps =
dj1.8: Django >= 1.8, < 1.9
dj1.9: Django >= 1.9a1, < 1.10
dj1.10: Django >= 1.10, < 1.11
dj1.11: Django >= 1.11, < 2.0
dj2.0: Django >= 2.0, < 2.1
dj.dev: https://github.com/django/django/tarball/master

coverage
Expand Down