diff options
author | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2011-01-31 20:47:30 -0500 |
---|---|---|
committer | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2011-01-31 20:47:30 -0500 |
commit | cc38fb000063574555fe895f26b5ddf9b5ae23bb (patch) | |
tree | 04320cd10e71f6c39a961b6c76bb718708729220 | |
parent | fc2d51007e4a4d593a0d03dafc667759ebd64f6e (diff) | |
download | askbot-cc38fb000063574555fe895f26b5ddf9b5ae23bb.tar.gz askbot-cc38fb000063574555fe895f26b5ddf9b5ae23bb.tar.bz2 askbot-cc38fb000063574555fe895f26b5ddf9b5ae23bb.zip |
skins can now be switched on the go
-rw-r--r-- | askbot/conf/markup.py | 10 | ||||
-rwxr-xr-x | askbot/skins/README | 2 | ||||
-rwxr-xr-x | askbot/skins/common/media/README | 1 | ||||
-rw-r--r-- | askbot/skins/loaders.py | 42 | ||||
-rw-r--r-- | askbot/skins/utils.py | 11 | ||||
-rw-r--r-- | askbot/views/commands.py | 12 | ||||
-rw-r--r-- | askbot/views/meta.py | 31 | ||||
-rw-r--r-- | askbot/views/readers.py | 25 | ||||
-rw-r--r-- | askbot/views/users.py | 47 | ||||
-rw-r--r-- | askbot/views/writers.py | 23 |
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)) |