Commit 85c58dc5 by benjaoming

Merge branch 'master' of github.com:benjaoming/django-wiki

parents 3edd2867 2d7c9870
...@@ -45,15 +45,7 @@ def get_article(func=None, can_read=True, can_write=False, deleted_contents=Fals ...@@ -45,15 +45,7 @@ def get_article(func=None, can_read=True, can_write=False, deleted_contents=Fals
path = kwargs.pop('path', None) path = kwargs.pop('path', None)
article_id = kwargs.pop('article_id', None) article_id = kwargs.pop('article_id', None)
articles = models.Article.objects
# TODO: Is this the way to do it?
# https://docs.djangoproject.com/en/1.4/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related
# This is not the way to go... optimize below statements to behave
# according to normal prefetching.
articles = articles.prefetch_related()
urlpath = None urlpath = None
# fetch by urlpath.path # fetch by urlpath.path
...@@ -72,7 +64,8 @@ def get_article(func=None, can_read=True, can_write=False, deleted_contents=Fals ...@@ -72,7 +64,8 @@ def get_article(func=None, can_read=True, can_write=False, deleted_contents=Fals
# TODO: Make a nice page # TODO: Make a nice page
return HttpResponseNotFound("This article was not found, and neither was the parent. This page should look nicer.") return HttpResponseNotFound("This article was not found, and neither was the parent. This page should look nicer.")
if urlpath.article: if urlpath.article:
article = get_object_or_404(articles, id=urlpath.article.id) # urlpath is already smart about prefetching items on article (like current_revision), so we don't have to
article = urlpath.article
else: else:
# Be robust: Somehow article is gone but urlpath exists... clean up # Be robust: Somehow article is gone but urlpath exists... clean up
return_url = reverse('wiki:get', kwargs={'path': urlpath.parent.path}) return_url = reverse('wiki:get', kwargs={'path': urlpath.parent.path})
...@@ -82,6 +75,9 @@ def get_article(func=None, can_read=True, can_write=False, deleted_contents=Fals ...@@ -82,6 +75,9 @@ def get_article(func=None, can_read=True, can_write=False, deleted_contents=Fals
# fetch by article.id # fetch by article.id
elif article_id: elif article_id:
#TODO We should try to grab the article form URLPath so the caching is good, and fall back to grabbing it from Article.objects if not
articles = models.Article.objects
article = get_object_or_404(articles, id=article_id) article = get_object_or_404(articles, id=article_id)
try: try:
urlpath = models.URLPath.objects.get(articles__article=article) urlpath = models.URLPath.objects.get(articles__article=article)
......
...@@ -15,6 +15,8 @@ from wiki.core.exceptions import NoRootURL, MultipleRootURLs ...@@ -15,6 +15,8 @@ from wiki.core.exceptions import NoRootURL, MultipleRootURLs
from wiki.models.article import ArticleRevision, ArticleForObject, Article from wiki.models.article import ArticleRevision, ArticleForObject, Article
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
URLPATH_PREFECTED_PROPERTIES = ["parent", "article__current_revision", "article__owner"]
class URLPath(MPTTModel): class URLPath(MPTTModel):
""" """
Strategy: Very few fields go here, as most has to be managed through an Strategy: Very few fields go here, as most has to be managed through an
...@@ -36,16 +38,29 @@ class URLPath(MPTTModel): ...@@ -36,16 +38,29 @@ class URLPath(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='children') parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
@property @property
def cached_ancestors(self):
if not hasattr(self, "_cached_ancestors"):
self._cached_ancestors = list(self.get_ancestors().select_related(*URLPATH_PREFECTED_PROPERTIES) )
return self._cached_ancestors
@cached_ancestors.setter
def cached_ancestors(self, ancestors):
self._cached_ancestors = ancestors
@property
def path(self): def path(self):
if not self.parent: return "" if not self.parent: return ""
if not hasattr(self, '_cachedpath'):
self._cachedpath = "/".join([obj.slug if obj.slug else "" for obj in self.get_ancestors(include_self=True).exclude(parent=None)]) + "/" ancestors = filter(lambda ancestor: ancestor.parent is not None, self.cached_ancestors)
return self._cachedpath slugs = [obj.slug if obj.slug else "" for obj in ancestors + [self] ]
return "/".join(slugs) + "/"
@classmethod @classmethod
def root(cls): def root(cls):
site = Site.objects.get_current() site = Site.objects.get_current()
root_nodes = list(cls.objects.root_nodes().filter(site=site)) root_nodes = list(cls.objects.root_nodes().filter(site=site).select_related(*URLPATH_PREFECTED_PROPERTIES))
# We fetch the nodes as a list and use len(), not count() because we need # We fetch the nodes as a list and use len(), not count() because we need
# to get the result out anyway. This only takes one sql query # to get the result out anyway. This only takes one sql query
no_paths = len(root_nodes) no_paths = len(root_nodes)
...@@ -108,9 +123,13 @@ class URLPath(MPTTModel): ...@@ -108,9 +123,13 @@ class URLPath(MPTTModel):
parent = cls.root() parent = cls.root()
for slug in slugs: for slug in slugs:
if settings.URL_CASE_SENSITIVE: if settings.URL_CASE_SENSITIVE:
parent = parent.get_children().get(slug=slug) child = parent.get_children().select_related(*URLPATH_PREFECTED_PROPERTIES).get(slug=slug)
child.cached_ancestors = parent.cached_ancestors + [parent]
parent = child
else: else:
parent = parent.get_children().get(slug__iexact=slug) child = parent.get_children().select_related(*URLPATH_PREFECTED_PROPERTIES).get(slug__iexact=slug)
child.cached_ancestors = parent.cached_ancestors + [parent]
parent = child
level += 1 level += 1
return parent return parent
......
{% load i18n %}{% load url from future %} {% load i18n %}{% load url from future %}
{% if urlpath %} {% if urlpath %}
<ul class="breadcrumb pull-left" class=""> <ul class="breadcrumb pull-left" class="">
{% for ancestor in urlpath.get_ancestors.all %} {% for ancestor in urlpath.cached_ancestors %}
<span class="divider">/</span> <span class="divider">/</span>
<li><a href="{% url 'wiki:get' path=ancestor.path %}">{{ ancestor.article.current_revision.title }}</a></li> <li><a href="{% url 'wiki:get' path=ancestor.path %}">{{ ancestor.article.current_revision.title }}</a></li>
{% endfor %} {% endfor %}
......
...@@ -12,9 +12,10 @@ class ArticleMixin(TemplateResponseMixin): ...@@ -12,9 +12,10 @@ class ArticleMixin(TemplateResponseMixin):
self.urlpath = kwargs.pop('urlpath', None) self.urlpath = kwargs.pop('urlpath', None)
self.article = article self.article = article
self.children_slice = [] self.children_slice = []
for child in self.article.get_children(max_num=settings.SHOW_MAX_CHILDREN+1, if settings.SHOW_MAX_CHILDREN > 0:
articles__article__current_revision__deleted=False): for child in self.article.get_children(max_num=settings.SHOW_MAX_CHILDREN+1,
self.children_slice.append(child) articles__article__current_revision__deleted=False):
self.children_slice.append(child)
return super(ArticleMixin, self).dispatch(request, *args, **kwargs) return super(ArticleMixin, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment