Commit 2edd8d37 by Bridger Maxwell

Added simple child list page. Doesn't have any styling yet.

parent 2d7c9870
...@@ -15,8 +15,6 @@ from wiki.core.exceptions import NoRootURL, MultipleRootURLs ...@@ -15,8 +15,6 @@ 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
...@@ -39,15 +37,24 @@ class URLPath(MPTTModel): ...@@ -39,15 +37,24 @@ class URLPath(MPTTModel):
@property @property
def cached_ancestors(self): def cached_ancestors(self):
"""
This returns the ancestors of this urlpath. These ancestors are hopefully
cached from the article path lookup. Accessing a foreign key included in
add_selecte_related on one of these ancestors will not occur an additional
sql query, as they were retrieved with a select_related.
If the cached ancestors were not set explicitly, they will be retrieved from
the database.
"""
if not hasattr(self, "_cached_ancestors"): if not hasattr(self, "_cached_ancestors"):
self._cached_ancestors = list(self.get_ancestors().select_related(*URLPATH_PREFECTED_PROPERTIES) ) self._cached_ancestors = list(self.__class__.add_select_related(self.get_ancestors()) )
return self._cached_ancestors return self._cached_ancestors
@cached_ancestors.setter @cached_ancestors.setter
def cached_ancestors(self, ancestors): def cached_ancestors(self, ancestors):
self._cached_ancestors = ancestors self._cached_ancestors = ancestors
@property @property
def path(self): def path(self):
if not self.parent: return "" if not self.parent: return ""
...@@ -58,9 +65,17 @@ class URLPath(MPTTModel): ...@@ -58,9 +65,17 @@ class URLPath(MPTTModel):
return "/".join(slugs) + "/" return "/".join(slugs) + "/"
@classmethod @classmethod
def add_select_related(cls, urlpath_queryset):
"""
Before using a queryset that retrieves urlpaths, run it through this first. It
adds a select_related with a list of foreign keys often retrieved from a urlpath.
"""
return urlpath_queryset.select_related("parent", "article__current_revision", "article__owner")
@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).select_related(*URLPATH_PREFECTED_PROPERTIES)) root_nodes = list( cls.add_select_related(cls.objects.root_nodes().filter(site=site)) )
# 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)
...@@ -123,11 +138,11 @@ class URLPath(MPTTModel): ...@@ -123,11 +138,11 @@ 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:
child = parent.get_children().select_related(*URLPATH_PREFECTED_PROPERTIES).get(slug=slug) child = cls.add_select_related(parent.get_children()).get(slug=slug)
child.cached_ancestors = parent.cached_ancestors + [parent] child.cached_ancestors = parent.cached_ancestors + [parent]
parent = child parent = child
else: else:
child = parent.get_children().select_related(*URLPATH_PREFECTED_PROPERTIES).get(slug__iexact=slug) child = cls.add_select_related(parent.get_children()).get(slug__iexact=slug)
child.cached_ancestors = parent.cached_ancestors + [parent] child.cached_ancestors = parent.cached_ancestors + [parent]
parent = child parent = child
level += 1 level += 1
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
{% endif %} {% endif %}
<li class="divider"></li> <li class="divider"></li>
<li> <li>
<a href="" onclick="alert('TODO')">{% trans "List sub-pages" %} &raquo;</a> <a href="{% url 'wiki:list' path=urlpath.path %}">{% trans "List sub-pages" %} &raquo;</a>
</li> </li>
</ul> </ul>
</div> </div>
......
...@@ -55,6 +55,7 @@ urlpatterns += patterns('', ...@@ -55,6 +55,7 @@ urlpatterns += patterns('',
url('^(?P<path>.+/|)_edit/$', article.Edit.as_view(), name='edit'), url('^(?P<path>.+/|)_edit/$', article.Edit.as_view(), name='edit'),
url('^(?P<path>.+/|)_preview/$', 'wiki.views.article.preview', name='preview'), url('^(?P<path>.+/|)_preview/$', 'wiki.views.article.preview', name='preview'),
url('^(?P<path>.+/|)_history/$', article.History.as_view(), name='history'), url('^(?P<path>.+/|)_history/$', article.History.as_view(), name='history'),
url('^(?P<path>.+/|)_list/$', article.List.as_view(), name='list'),
url('^(?P<path>.+/|)_settings/$', article.Settings.as_view(), name='settings'), url('^(?P<path>.+/|)_settings/$', article.Settings.as_view(), name='settings'),
url('^(?P<path>.+/|)_revision/change/(?P<revision_id>\d+)/$', 'wiki.views.article.change_revision', name='change_revision'), url('^(?P<path>.+/|)_revision/change/(?P<revision_id>\d+)/$', 'wiki.views.article.change_revision', name='change_revision'),
url('^(?P<path>.+/|)_revision/merge/(?P<revision_id>\d+)/$', 'wiki.views.article.merge', name='merge_revision'), url('^(?P<path>.+/|)_revision/merge/(?P<revision_id>\d+)/$', 'wiki.views.article.merge', name='merge_revision'),
......
...@@ -385,6 +385,38 @@ class History(ListView, ArticleMixin): ...@@ -385,6 +385,38 @@ class History(ListView, ArticleMixin):
return super(History, self).dispatch(request, article, *args, **kwargs) return super(History, self).dispatch(request, article, *args, **kwargs)
class List(ListView, ArticleMixin):
template_name="wiki/list.html"
allow_empty = True
context_object_name = 'children'
paginate_by = 50
def get_queryset(self):
return models.URLPath.add_select_related(self.urlpath.get_children().order_by('slug'))
def get_context_data(self, **kwargs):
# Is this a bit of a hack? Use better inheritance?
kwargs_article = ArticleMixin.get_context_data(self, **kwargs)
kwargs_listview = ListView.get_context_data(self, **kwargs)
kwargs.update(kwargs_article)
kwargs.update(kwargs_listview)
# We take this opportunity to add a bit of caching to each child.
# Otherwise, 1 query every time we get a child's path
updated_children = kwargs[self.context_object_name]
new_ancestors = self.urlpath.cached_ancestors + [self.urlpath]
for child in updated_children:
child.cached_ancestors = new_ancestors
kwargs['object_list'] = kwargs[self.context_object_name] = updated_children
return kwargs
@method_decorator(get_article(can_read=True))
def dispatch(self, request, article, *args, **kwargs):
return super(List, self).dispatch(request, article, *args, **kwargs)
class Plugin(View): class Plugin(View):
def dispatch(self, request, path=None, slug=None, **kwargs): def dispatch(self, request, path=None, slug=None, **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