diff --git a/setup.py b/setup.py index 19dddcef4..a799107c6 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ def build_media_pattern(base_folder, file_extension): setup( name = "django-wiki", - version = "0.0.5", + version = "0.0.6", author = "Benjamin Bach", author_email = "benjamin@overtag.dk", description = ("A wiki system written for the Django framework."), diff --git a/testproject/testproject/settings.py b/testproject/testproject/settings.py index 0ec4f1f9c..0cf198dbf 100644 --- a/testproject/testproject/settings.py +++ b/testproject/testproject/settings.py @@ -69,6 +69,7 @@ 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', + 'wiki.middleware.RequestCache', # Uncomment the next line for simple clickjacking protection: # 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) diff --git a/wiki/__init__.py b/wiki/__init__.py index e69de29bb..0077f6a10 100644 --- a/wiki/__init__.py +++ b/wiki/__init__.py @@ -0,0 +1 @@ +from middleware import get_current_request diff --git a/wiki/middleware.py b/wiki/middleware.py new file mode 100644 index 000000000..cc61539db --- /dev/null +++ b/wiki/middleware.py @@ -0,0 +1,62 @@ +import threading +import importlib + +from django.conf import settings + +if getattr(settings, "WIKI_REQUEST_CACHE_MIDDLEWARE_CLASS", None): + class_name = settings.WIKI_REQUEST_CACHE_MIDDLEWARE_CLASS.split(".")[-1] + module = ".".join(settings.WIKI_REQUEST_CACHE_MIDDLEWARE_CLASS.split('.')[:-1]) + RequestCache = getattr(importlib.import_module(module), class_name) +else: + class _RequestCache(threading.local): + """ + A thread-local for storing the per-request cache. + """ + def __init__(self): + super(_RequestCache, self).__init__() + self.data = {} + self.request = None + + + REQUEST_CACHE = _RequestCache() + + + class RequestCache(object): + @classmethod + def get_request_cache(cls, name=None): + """ + This method is deprecated. Please use :func:`request_cache.get_cache`. + """ + if name is None: + return REQUEST_CACHE + else: + return REQUEST_CACHE.data.setdefault(name, {}) + + @classmethod + def get_current_request(cls): + """ + This method is deprecated. Please use :func:`request_cache.get_request`. + """ + return REQUEST_CACHE.request + + @classmethod + def clear_request_cache(cls): + """ + Empty the request cache. + """ + REQUEST_CACHE.data = {} + REQUEST_CACHE.request = None + + def process_request(self, request): + self.clear_request_cache() + REQUEST_CACHE.request = request + return None + + def process_response(self, request, response): + self.clear_request_cache() + return response + + +def get_current_request(): + """Return the request associated with the current thread.""" + return RequestCache.get_current_request() diff --git a/wiki/models/urlpath.py b/wiki/models/urlpath.py index cbbc3f527..2b5d06ca6 100644 --- a/wiki/models/urlpath.py +++ b/wiki/models/urlpath.py @@ -4,6 +4,7 @@ from django.contrib.contenttypes import fields from django.contrib.contenttypes.models import ContentType from django.contrib.sites.models import Site +from django.contrib.sites.shortcuts import get_current_site from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse from django.db import models, transaction @@ -14,6 +15,7 @@ from mptt.models import MPTTModel from wiki import managers +from wiki import get_current_request from wiki.conf import settings from wiki.core.exceptions import NoRootURL, MultipleRootURLs from wiki.models.article import ArticleRevision, ArticleForObject, Article @@ -110,7 +112,7 @@ def delete_subtree(self): @classmethod def root(cls): - site = Site.objects.get_current() + site = get_current_site(get_current_request()) root_nodes = list( cls.objects.root_nodes().filter(site=site).select_related_common() ) @@ -192,7 +194,7 @@ def get_absolute_url(self): @classmethod def create_root(cls, site=None, title="Root", **kwargs): - if not site: site = Site.objects.get_current() + if not site: site = get_current_site(get_current_request()) root_nodes = cls.objects.root_nodes().filter(site=site) if not root_nodes: # (get_or_create does not work for MPTT models??) @@ -210,7 +212,7 @@ def create_root(cls, site=None, title="Root", **kwargs): def create_article(cls, parent, slug, site=None, title="Root", article_kwargs={}, **kwargs): """Utility function: Create a new urlpath with an article and a new revision for the article""" - if not site: site = Site.objects.get_current() + if not site: site = get_current_site(get_current_request()) article = Article(**article_kwargs) article.add_revision(ArticleRevision(title=title, **kwargs), save=True) @@ -241,8 +243,8 @@ def on_article_relation_save(instance, *args, **kwargs): def on_article_delete(instance, *args, **kwargs): # If an article is deleted, then throw out its URLPaths # But move all descendants to a lost-and-found node. - site = Site.objects.get_current() - + site = get_current_site(get_current_request()) + # Get the Lost-and-found path or create a new one try: lost_and_found = URLPath.objects.get(slug=settings.LOST_AND_FOUND_SLUG,