summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2011-01-31 20:47:30 -0500
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2011-01-31 20:47:30 -0500
commitcc38fb000063574555fe895f26b5ddf9b5ae23bb (patch)
tree04320cd10e71f6c39a961b6c76bb718708729220
parentfc2d51007e4a4d593a0d03dafc667759ebd64f6e (diff)
downloadaskbot-cc38fb000063574555fe895f26b5ddf9b5ae23bb.tar.gz
askbot-cc38fb000063574555fe895f26b5ddf9b5ae23bb.tar.bz2
askbot-cc38fb000063574555fe895f26b5ddf9b5ae23bb.zip
skins can now be switched on the go
-rw-r--r--askbot/conf/markup.py10
-rwxr-xr-xaskbot/skins/README2
-rwxr-xr-xaskbot/skins/common/media/README1
-rw-r--r--askbot/skins/loaders.py42
-rw-r--r--askbot/skins/utils.py11
-rw-r--r--askbot/views/commands.py12
-rw-r--r--askbot/views/meta.py31
-rw-r--r--askbot/views/readers.py25
-rw-r--r--askbot/views/users.py47
-rw-r--r--askbot/views/writers.py23
10 files changed, 85 insertions, 119 deletions
diff --git a/askbot/conf/markup.py b/askbot/conf/markup.py
index 23a2dc67..026c5536 100644
--- a/askbot/conf/markup.py
+++ b/askbot/conf/markup.py
@@ -15,13 +15,6 @@ MARKUP = ConfigurationGroup(
_('Markup formatting')
)
-mathjax_dir = os.path.join(
- askbot.get_install_directory(),
- 'skins',
- 'common',
- 'media'
- )
-
settings.register(
BooleanValue(
MARKUP,
@@ -47,10 +40,9 @@ settings.register(
help_text=_(
'If you enable this feature, '
'<a href="%(url)s">mathjax</a> must be '
- 'installed in directory %(dir)s'
+ 'installed on your server in its own directory.'
) % {
'url': const.DEPENDENCY_URLS['mathjax'],
- 'dir': mathjax_dir,
},
default = False
)
diff --git a/askbot/skins/README b/askbot/skins/README
index 01ef0a9d..42a6ea25 100755
--- a/askbot/skins/README
+++ b/askbot/skins/README
@@ -1,7 +1,6 @@
this directory contains available skins
1) default - default skin with templates
-2) common - this directory is to media directory common to all or many templates
to create a new skin just create another directory under skins/
and start populating it with the directory structure as in
@@ -16,7 +15,6 @@ templates are resolved in the following way:
media is resolved with one extra option
* settings.ASKBOT_DEFAULT_SKIN
* 'default'
-* 'common'
media does not have to be composed of files named the same way as in default skin
whatever media you link to from your templates - will be in operation
diff --git a/askbot/skins/common/media/README b/askbot/skins/common/media/README
deleted file mode 100755
index 3376e754..00000000
--- a/askbot/skins/common/media/README
+++ /dev/null
@@ -1 +0,0 @@
-directory for media common to all or many templates
diff --git a/askbot/skins/loaders.py b/askbot/skins/loaders.py
index 47367715..c9a1a059 100644
--- a/askbot/skins/loaders.py
+++ b/askbot/skins/loaders.py
@@ -1,5 +1,7 @@
import os.path
from django.template.loaders import filesystem
+from django.template import RequestContext
+from django.http import HttpResponse
from django.utils import translation
from askbot.conf import settings as askbot_settings
from django.conf import settings as django_settings
@@ -65,14 +67,20 @@ class SkinEnvironment(CoffinEnvironment):
that loads templates from askbot skins
"""
+ def __init__(self, *args, **kwargs):
+ """save the skin path and initialize the
+ Coffin Environment
+ """
+ self.skin = kwargs.pop('skin')
+ super(SkinEnvironment, self).__init__(*args, **kwargs)
+
def _get_loaders(self):
"""this method is not used
over-ridden function _get_loaders that creates
the loader for the skin templates
"""
loaders = list()
- skin_name = askbot_settings.ASKBOT_DEFAULT_SKIN
- skin_dirs = utils.get_available_skins(selected = skin_name).values()
+ skin_dirs = utils.get_available_skins(selected = self.skin).values()
template_dirs = [os.path.join(skin_dir, 'templates') for skin_dir in skin_dirs]
loaders.append(jinja_loaders.FileSystemLoader(template_dirs))
@@ -86,10 +94,38 @@ class SkinEnvironment(CoffinEnvironment):
trans = translation.trans_real.translation(language_code)
self.install_gettext_translations(trans)
-
ENV = SkinEnvironment(
autoescape=False,
extensions=['jinja2.ext.i18n'],
+ skin = 'default'
#loader = SkinLoader()
)
ENV.set_language(django_settings.LANGUAGE_CODE)
+
+def load_skins():
+ skins = dict()
+ for skin_name in utils.get_available_skins():
+ skins[skin_name] = SkinEnvironment(skin = skin_name)
+ skins[skin_name].set_language(django_settings.LANGUAGE_CODE)
+ return skins
+
+SKINS = load_skins()
+
+def get_template(template, request):
+ """retreives template for the skin
+ request variable will be used in the future to set
+ template according to the user preference or admins preference
+
+ at this point request variable is not used though
+ """
+ skin = SKINS[askbot_settings.ASKBOT_DEFAULT_SKIN]
+ return skin.get_template(template)
+
+def render_into_skin(template, data, request, mimetype = 'text/html'):
+ """in the future this function will be able to
+ switch skin depending on the site administrator/user selection
+ right now only admins can switch
+ """
+ context = RequestContext(request, data)
+ template = get_template(template, request)
+ return HttpResponse(template.render(context), mimetype = mimetype)
diff --git a/askbot/skins/utils.py b/askbot/skins/utils.py
index b244da00..a80c85ed 100644
--- a/askbot/skins/utils.py
+++ b/askbot/skins/utils.py
@@ -3,7 +3,6 @@
the lookup resolution process for templates and media works as follows:
* look up item in selected skin
* if not found look in 'default'
-* the look in 'common'
* raise an exception
"""
import os
@@ -29,11 +28,10 @@ def get_skins_from_dir(directory):
def get_available_skins(selected=None):
"""selected is a name of preferred skin
if it's None, then information about all skins will be returned
- otherwise, only data about selected, default and common skins
+ otherwise, only data about selected and default skins
will be returned
selected skin is guaranteed to be the first item in the dictionary
-
"""
skins = SortedDict()
if hasattr(django_settings, 'ASKBOT_EXTRA_SKINS_DIR'):
@@ -42,7 +40,6 @@ def get_available_skins(selected=None):
stock_dir = os.path.normpath(os.path.dirname(__file__))
stock_skins = get_skins_from_dir(stock_dir)
default_dir = stock_skins.pop('default')
- common_dir = stock_skins.pop('common')
skins.update(stock_skins)
@@ -55,9 +52,8 @@ def get_available_skins(selected=None):
assert(selected == 'default')
skins = SortedDict()
- #re-insert default and common as last two items
+ #re-insert default as a last item
skins['default'] = default_dir
- skins['common'] = common_dir
return skins
@@ -75,11 +71,10 @@ def get_skin_choices():
"""returns a tuple for use as a set of
choices in the form"""
skin_names = list(reversed(get_available_skins().keys()))
- skin_names.remove('common')
return zip(skin_names, skin_names)
def resolve_skin_for_media(media=None, preferred_skin = None):
- #see if file exists, if not, try skins 'default', then 'common'
+ #see if file exists, if not, try skin 'default'
available_skins = get_available_skins(selected = preferred_skin).items()
for skin_name, skin_dir in available_skins:
if os.path.isfile(os.path.join(skin_dir, 'media', media)):
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index 4fdc18b2..e760080b 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -11,13 +11,12 @@ from django.core import exceptions
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
-from django.template import RequestContext
from askbot import models
from askbot.forms import CloseForm
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from askbot.utils.decorators import ajax_only, ajax_login_required
-from askbot.skins.loaders import ENV
+from askbot.skins.loaders import render_into_skin
from askbot import const
import logging
@@ -397,10 +396,7 @@ def close(request, id):#close question
else:
request.user.assert_can_close_question(question)
form = CloseForm()
- template = ENV.get_template('close.html')
- data = {'form': form, 'question': question}
- context = RequestContext(request, data)
- return HttpResponse(template.render(context))
+ return render_into_skin('close.html', data, request)
except exceptions.PermissionDenied, e:
request.user.message_set.create(message = unicode(e))
return HttpResponseRedirect(question.get_absolute_url())
@@ -428,9 +424,7 @@ def reopen(request, id):#re-open question
'closed_by_profile_url': closed_by_profile_url,
'closed_by_username': closed_by_username,
}
- context = RequestContext(request, data)
- template = ENV.get_template('reopen.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('reopen.html', data, request)
except exceptions.PermissionDenied, e:
request.user.message_set.create(message = unicode(e))
diff --git a/askbot/views/meta.py b/askbot/views/meta.py
index 7bd72ee6..7cc536ed 100644
--- a/askbot/views/meta.py
+++ b/askbot/views/meta.py
@@ -16,14 +16,13 @@ from askbot.utils.forms import get_next_url
from askbot.utils.mail import mail_moderators
from askbot.models import BadgeData, Award, User
from askbot.models import badges as badge_data
-from askbot.skins.loaders import ENV
+from askbot.skins.loaders import render_into_skin
from askbot.conf import settings as askbot_settings
from askbot import skins
def generic_view(request, template = None, page_class = None):
- template = ENV.get_template(template)
- context = RequestContext(request, {'page_class': page_class})
- return HttpResponse(template.render(context))
+ """this may be not necessary, since it is just a rewrite of render_into_skin"""
+ return render_into_skin(template, {'page_class': page_class}, request)
def config_variable(request, variable_name = None, mimetype = None):
"""Print value from the configuration settings
@@ -42,15 +41,13 @@ def server_error(request, template='500.html'):
return generic_view(request, template)
def faq(request):
- template = ENV.get_template('faq.html')
data = {
'gravatar_faq_url': reverse('faq') + '#gravatar',
#'send_email_key_url': reverse('send_email_key'),
'ask_question_url': reverse('ask'),
'page_class': 'meta',
}
- context = RequestContext(request, data)
- return HttpResponse(template.render(context))
+ return render_into_skin('faq.html', data, request)
def feedback(request):
data = {'page_class': 'meta'}
@@ -71,15 +68,11 @@ def feedback(request):
form = FeedbackForm(initial={'next':get_next_url(request)})
data['form'] = form
- context = RequestContext(request, data)
- template = ENV.get_template('feedback.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('feedback.html', data, request)
feedback.CANCEL_MESSAGE=_('We look forward to hearing your feedback! Please, give it next time :)')
def privacy(request):
- context = RequestContext(request, {'page_class': 'meta'})
- template = ENV.get_template('privacy.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('privacy.html', {'page_class': 'meta'}, request)
def logout(request):#refactor/change behavior?
#currently you click logout and you get
@@ -93,9 +86,7 @@ def logout(request):#refactor/change behavior?
'next' : get_next_url(request),
'page_class': 'meta',
}
- context = RequestContext(request, data)
- template = ENV.get_template('logout.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('logout.html', data, request)
def badges(request):#user status/reputation system
#todo: supplement database data with the stuff from badges.py
@@ -110,7 +101,6 @@ def badges(request):#user status/reputation system
).distinct()
#my_badges.query.group_by = ['badge_id']
- template = ENV.get_template('badges.html')
data = {
'active_tab': 'badges',
'badges' : badges,
@@ -118,8 +108,7 @@ def badges(request):#user status/reputation system
'mybadges' : my_badges,
'feedback_faq_url' : reverse('feedback'),
}
- context = RequestContext(request, data)
- return HttpResponse(template.render(context))
+ return render_into_skin('badges.html', data, request)
def badge(request, id):
#todo: supplement database data with the stuff from badges.py
@@ -133,15 +122,13 @@ def badge(request, id):
'-last_awarded_at'
)
- template = ENV.get_template('badge.html')
data = {
'active_tab': 'badges',
'badge_recipients' : badge_recipients,
'badge' : badge,
'page_class': 'meta',
}
- context = RequestContext(request, data)
- return HttpResponse(template.render(context))
+ return render_into_skin('badge.html', data, request)
def media(request, skin, resource):
"""view that serves static media from any skin
diff --git a/askbot/views/readers.py b/askbot/views/readers.py
index 27fbfe78..236a7485 100644
--- a/askbot/views/readers.py
+++ b/askbot/views/readers.py
@@ -12,7 +12,7 @@ import urllib
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.core.paginator import Paginator, EmptyPage, InvalidPage
-from django.template import RequestContext, Context
+from django.template import Context
from django.utils.http import urlencode
from django.utils import simplejson
from django.utils.translation import ugettext as _
@@ -35,7 +35,7 @@ from askbot.search.state_manager import SearchState
from askbot.templatetags import extra_tags
from askbot.templatetags import extra_filters
import askbot.conf
-from askbot.skins.loaders import ENV #jinja2 template loading enviroment
+from askbot.skins.loaders import render_into_skin, get_template#jinja2 template loading enviroment
# used in index page
#todo: - take these out of const or settings
@@ -144,7 +144,7 @@ def questions(request):
}
if q_count > search_state.page_size:
- paginator_tpl = ENV.get_template('blocks/paginator.html')
+ paginator_tpl = get_template('blocks/paginator.html', request)
#todo: remove this patch on context after all templates are moved to jinja
paginator_context['base_url'] = request.path + '?sort=%s&' % search_state.sort
data = {
@@ -275,7 +275,7 @@ def questions(request):
if meta_data.get('author_name',None):
reset_method_count += 1
- template_context = RequestContext(request, {
+ template_data = {
'language_code': translation.get_language(),
'reset_method_count': reset_method_count,
'page_class': 'main-page',
@@ -296,14 +296,13 @@ def questions(request):
'show_sort_by_relevance': askbot.conf.should_show_sort_by_relevance(),
'scope': search_state.scope,
'context' : paginator_context,
- })
+ }
assert(request.is_ajax() == False)
#ajax request is handled in a separate branch above
#before = datetime.datetime.now()
- template = ENV.get_template('questions.html')
- response = HttpResponse(template.render(template_context))
+ response = render_into_skin('questions.html', template_data, request)
#after = datetime.datetime.now()
#print after - before
return response
@@ -360,9 +359,7 @@ def tags(request):#view showing a listing of available tags - plain list
'keywords' : stag,
'paginator_context' : paginator_context
}
- context = RequestContext(request, data)
- template = ENV.get_template('tags.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('tags.html', data, request)
def question(request, id):#refactor - long subroutine. display question body, answers and comments
"""view that displays body of the question and
@@ -559,9 +556,7 @@ def question(request, id):#refactor - long subroutine. display question body, an
}
if request.user.is_authenticated():
data['tags_autocomplete'] = _get_tags_cache_json()
- context = RequestContext(request, data)
- template = ENV.get_template('question.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('question.html', data, request)
def revisions(request, id, object_name=None):
assert(object_name in ('Question', 'Answer'))
@@ -581,9 +576,7 @@ def revisions(request, id, object_name=None):
'post': post,
'revisions': revisions,
}
- context = RequestContext(request, data)
- template = ENV.get_template('revisions.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('revisions.html', data, request)
@ajax_only
@anonymous_forbidden
diff --git a/askbot/views/users.py b/askbot/views/users.py
index e68d1446..524ea33c 100644
--- a/askbot/views/users.py
+++ b/askbot/views/users.py
@@ -16,7 +16,6 @@ from django.core.paginator import Paginator, EmptyPage, InvalidPage
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404
-from django.template import RequestContext
from django.http import HttpResponse
from django.http import HttpResponseRedirect, Http404
from django.utils.translation import ugettext as _
@@ -30,7 +29,7 @@ from askbot.conf import settings as askbot_settings
from askbot import models
from askbot import exceptions
from askbot.models.badges import award_badges_signal
-from askbot.skins.loaders import ENV
+from askbot.skins.loaders import render_into_skin
from askbot.templatetags import extra_tags
question_type = ContentType.objects.get_for_model(models.Question)
@@ -127,9 +126,7 @@ def users(request):
'tab_id' : sortby,
'paginator_context' : paginator_context
}
- template = ENV.get_template('users.html')
- context = RequestContext(request, data)
- return HttpResponse(template.render(context))
+ return render_into_skin('users.html', data, request)
def user_moderate(request, subject):
"""user subview for moderation
@@ -222,9 +219,7 @@ def user_moderate(request, subject):
'user_rep_changed': user_rep_changed,
'user_status_changed': user_status_changed
}
- context = RequestContext(request, data)
- template = ENV.get_template('user_profile/user_moderate.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('user_profile/user_moderate.html', data, request)
#non-view function
def set_new_email(user, new_email, nomessage=False):
@@ -275,9 +270,7 @@ def edit_user(request, id):
'form' : form,
'gravatar_faq_url' : reverse('faq') + '#gravatar',
}
- context = RequestContext(request, data)
- template = ENV.get_template('user_profile/user_edit.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('user_profile/user_edit.html', data, request)
def user_stats(request, user):
@@ -390,9 +383,7 @@ def user_stats(request, user):
'awarded_badge_counts': dict(awarded_badge_counts),
'total_awards' : total_awards,
}
- context = RequestContext(request, data)
- template = ENV.get_template('user_profile/user_stats.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('user_profile/user_stats.html', data, request)
def user_recent(request, user):
@@ -664,9 +655,7 @@ def user_recent(request, user):
'view_user' : user,
'activities' : activities[:const.USER_VIEW_DATA_SIZE]
}
- context = RequestContext(request, data)
- template = ENV.get_template('user_profile/user_recent.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('user_profile/user_recent.html', data, request)
@owner_or_moderator_required
def user_responses(request, user):
@@ -733,9 +722,7 @@ def user_responses(request, user):
'view_user' : user,
'responses' : response_list,
}
- context = RequestContext(request, data)
- template = ENV.get_template('user_profile/user_inbox.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('user_profile/user_inbox.html', data, request)
@owner_or_moderator_required
def user_votes(request, user):
@@ -799,9 +786,7 @@ def user_votes(request, user):
'view_user' : user,
'votes' : votes[:const.USER_VIEW_DATA_SIZE]
}
- context = RequestContext(request, data)
- template = ENV.get_template('user_profile/user_votes.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('user_profile/user_votes.html', data, request)
def user_reputation(request, user):
reputes = models.Repute.objects.filter(user=user).order_by('-reputed_at')
@@ -838,9 +823,7 @@ def user_reputation(request, user):
'reputation': reputes,
'reps': reps
}
- context = RequestContext(request, data)
- template = ENV.get_template('user_profile/user_reputation.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('user_profile/user_reputation.html', data, request)
def user_favorites(request, user):
favorited_q_id_list= models.FavoriteQuestion.objects.filter(
@@ -868,9 +851,7 @@ def user_favorites(request, user):
'favorited_myself': favorited_q_id_list,
'view_user' : user
}
- context = RequestContext(request, data)
- template = ENV.get_template('user_profile/user_favorites.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('user_profile/user_favorites.html', data, request)
@owner_or_moderator_required
def user_email_subscriptions(request, user):
@@ -901,7 +882,6 @@ def user_email_subscriptions(request, user):
tag_filter_form = forms.TagFilterSelectionForm(instance=user)
action_status = None
- template = ENV.get_template('user_profile/user_email_subscriptions.html')
data = {
'active_tab': 'users',
'page_class': 'user-profile-page',
@@ -913,8 +893,11 @@ def user_email_subscriptions(request, user):
'tag_filter_selection_form': tag_filter_form,
'action_status': action_status,
}
- context = RequestContext(request, data)
- return HttpResponse(template.render(context))
+ return render_into_skin(
+ 'user_profile/user_email_subscriptions.html',
+ data,
+ request
+ )
user_view_call_table = {
'stats': user_stats,
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 2dc3f2c8..2bc4d3a3 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -16,7 +16,6 @@ from django.core.files.storage import FileSystemStorage
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
-from django.template import RequestContext
from django.utils import simplejson
from django.utils.html import strip_tags
from django.utils.translation import ugettext as _
@@ -27,7 +26,7 @@ from django.conf import settings
from askbot.views.readers import _get_tags_cache_json
from askbot import forms
from askbot import models
-from askbot.skins.loaders import ENV
+from askbot.skins.loaders import render_into_skin
from askbot.utils.decorators import ajax_only
from askbot.utils.functions import diff_date
from askbot.templatetags import extra_filters_jinja as template_filters
@@ -180,13 +179,11 @@ def import_data(request):
else:
form = forms.DumpUploadForm()
- template = ENV.get_template('import_data.html')
data = {
'dump_upload_form': form,
'need_configuration': (not stackexchange.is_ready())
}
- context = RequestContext(request, data)
- return HttpResponse(template.render(context))
+ return render_into_skin('import_data.html', data, request)
#@login_required #actually you can post anonymously, but then must register
def ask(request):#view used to ask a new question
@@ -255,15 +252,13 @@ def ask(request):#view used to ask a new question
form.initial['title'] = query
tags = _get_tags_cache_json()
- template = ENV.get_template('ask.html')
data = {
'active_tab': 'ask',
'form' : form,
'tags' : tags,
'email_validation_faq_url':reverse('faq') + '#validate',
}
- context = RequestContext(request, data)
- return HttpResponse(template.render(context))
+ return render_into_skin('ask.html', data, request)
@login_required
def retag_question(request, id):
@@ -306,9 +301,7 @@ def retag_question(request, id):
'form' : form,
'tags' : _get_tags_cache_json(),
}
- context = RequestContext(request, data)
- template = ENV.get_template('question_retag.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('question_retag.html', data, request)
except exceptions.PermissionDenied, e:
if request.is_ajax():
response_data = {
@@ -366,9 +359,7 @@ def edit_question(request, id):
'form' : form,
'tags' : _get_tags_cache_json()
}
- context = RequestContext(request, data)
- template = ENV.get_template('question_edit.html')
- return HttpResponse(template.render(context))
+ return render_into_skin('question_edit.html', data, request)
except exceptions.PermissionDenied, e:
request.user.message_set.create(message = unicode(e))
@@ -417,15 +408,13 @@ def edit_answer(request, id):
else:
revision_form = forms.RevisionForm(answer, latest_revision)
form = forms.EditAnswerForm(answer, latest_revision)
- template = ENV.get_template('answer_edit.html')
data = {
'active_tab': 'questions',
'answer': answer,
'revision_form': revision_form,
'form': form,
}
- context = RequestContext(request, data)
- return HttpResponse(template.render(context))
+ return render_into_skin('answer_edit.html', data, request)
except exceptions.PermissionDenied, e:
request.user.message_set.create(message = unicode(e))