X-Git-Url: https://git.mdrn.pl/django-ssify.git/blobdiff_plain/3d2c8ba4dfb4774daff367dae1656099eb2b562c..49bb850ee3f5c4fbd32643c6019b8e1c8ccf619a:/ssify/decorators.py diff --git a/ssify/decorators.py b/ssify/decorators.py index 9b67c25..1e2d62a 100644 --- a/ssify/decorators.py +++ b/ssify/decorators.py @@ -1,14 +1,31 @@ +# -*- coding: utf-8 -*- +# This file is part of django-ssify, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See README.md for more information. +# +""" +Defines decorators for use in ssify-enabled projects. +""" +from __future__ import unicode_literals import functools from inspect import getargspec import warnings -from django.template.base import parse_bits +from django.conf import settings +from django.http import Http404 +try: + # Django 1.9 + from django.template.library import parse_bits +except ImportError: + from django.template.base import parse_bits + from django.utils.translation import get_language, activate -from .store import cache_include +from .cache import cache_include, DEFAULT_TIMEOUT from . import exceptions from .variables import SsiVariable -def ssi_included(view=None, use_lang=True, get_ssi_vars=None): +def ssi_included(view=None, use_lang=True, + timeout=DEFAULT_TIMEOUT, version=None, + get_ssi_vars=None, patch_response=None): """ Marks a view to be used as a snippet to be included with SSI. @@ -29,20 +46,26 @@ def ssi_included(view=None, use_lang=True, get_ssi_vars=None): lang = kwargs.pop('lang') except KeyError: raise exceptions.NoLangFieldError(request) + if lang not in [language[0] for language in settings.LANGUAGES]: + raise Http404 current_lang = get_language() activate(lang) + request.LANGUAGE_CODE = lang response = view(request, *args, **kwargs) if use_lang: activate(current_lang) if response.status_code == 200: + # We don't want this view to be cached in + # UpdateCacheMiddleware. We'll just cache the contents + # ourselves, and point the webserver to use this cache. request._cache_update_cache = False def _check_included_vars(response): - used_vars = request.ssi_vars_needed + used_vars = getattr(request, 'ssi_vars_needed', {}) if get_ssi_vars: # Remove the ssi vars that should be provided # by the including view. - pass_vars = set(get_ssi_vars(*args, **kwargs)) + pass_vars = get_ssi_vars(*args, **kwargs) for var in pass_vars: if not isinstance(var, SsiVariable): @@ -60,7 +83,8 @@ def ssi_included(view=None, use_lang=True, get_ssi_vars=None): # Don't use default django response caching for this view, # just save the contents instead. - cache_include(request.path, response.content) + cache_include(request.path, response.content, + timeout=timeout, version=version) if hasattr(response, 'render') and callable(response.render): response.add_post_render_callback(_check_included_vars) @@ -72,13 +96,23 @@ def ssi_included(view=None, use_lang=True, get_ssi_vars=None): # Remember get_ssi_vars so that in can be computed from args/kwargs # by including view. new_view.get_ssi_vars = get_ssi_vars + new_view.ssi_patch_response = patch_response return new_view return dec(view) if view else dec -def ssi_variable(register, vary=None, name=None): +def ssi_variable(register, name=None, patch_response=None): + """ + Creates a template tag representing an SSI variable from a function. + + The function must take 'request' as its first argument. + It may take other arguments, which should be provided when using + the template tag. + + """ # Cache control? def dec(func): + # Find own path. function_name = (name or getattr(func, '_decorated_function', func).__name__) @@ -121,7 +155,7 @@ def ssi_variable(register, vary=None, name=None): ['context'] + params[1:], varargs, varkw, defaults, takes_context=True, name=function_name) - return SsiVariableNode(tagpath, args, kwargs, vary, asvar) + return SsiVariableNode(tagpath, args, kwargs, patch_response, asvar) _ssi_var_tag.get_value = func #return _ssi_var_tag return func