Here is something I would like to be able to do in a template:
{% placeholder right as rightmenu with TextInput %}
[and later on]
{% get_page rightmenu as some_page %}
{% pages_submenu some_page %}
So far:
{% get_page variable_id ... %}
fails because variable_id is interpreted as a literal string, not a variable.
{% get_page "my_page_slug" ... %}
fails because quotes surrounding the string argument are not stripped. Thus a page with the slug '"my_page_slug"', not 'my_page_slug' is looked for. This is what your last commit fixes (5eb6fe3)
But {% get_page 9999 ... %} where 9999 is a page ID, works fine.
Tried to fix this by myself and I think what you did in you last commit is not completely right. Each case: "string", variable_id, 9999 must be handled seperatly in the do_get_page() function.
For example I managed to fixed the same issue as you, just by stripping the quotes as suggested in django manual. What I don't understant is why you use FilterExpression objects instead of Variable ones, which as far as I understand, are intended for that purpose. I tried to use Variable instance for the page argument in do_get_page() in the case where that argument is neither a quoted string or a int. Yet I did not manage to get the resolve() method on my Variabnle instance to actually resolve the variable. As a matter of fact something goes wrong in the PlaceholderNode instanciation: the call to get_content_from_context(context) at the first line of the render method returns nothing. Here follows the code:
def do_get_page(parser, token):
"""Retrieve a page and insert into the template's context.
Example::
{% get_page "news" as news_page %}
:param page: the page object, slug or id
:param name: name of the context variable to store the page in
"""
bits = token.split_contents()
if 4 != len(bits):
raise TemplateSyntaxError('%r expects 4 arguments' % bits[0])
if bits[-2] != 'as':
raise TemplateSyntaxError(
'%r expects "as" as the second argument' % bits[0])
if bits[1][0] == bits[1][-1] and bits[1][0] in ("'", '"'):
page = bits[1][1:-1]
elif bits[1].isdigit():
page = bits[1]
else:
page = template.Variable(bits[1])
varname = bits[-1]
return GetPageNode(page, varname)
do_get_page = register.tag('get_page', do_get_page)
Which also requires to add support for variables in get_page_from_string_or_id():
def get_page_from_string_or_id(page_string, context, lang=None):
"""Return a Page object from a slug or an id."""
if type(page_string) == int:
return Page.objects.get(pk=int(page_string))
# if we have a string coming from some templates templates
elif ( isinstance(page_string, SafeUnicode) or
isinstance(page_string, unicode) ):
if page_string.isdigit():
return Page.objects.get(pk=int(page_string))
else:
return Page.objects.from_path(page_string, lang)
elif isinstance(page_string, template.Variable):
return page_string.resolve(context) ## This fails
else:
# in any other case we return the input becasue it's probably
# a Page object.
return page_string
Still digging...
Also wanted to add the following test cases (in test_unit.py), but I cannot manage to run them ! How should I proceed ?
def test_get_page_template_tag_with_page_arg_as_id(self):
"""Test get_page template tag with page argument given as a page id"""
context = Context({})
pl1 = """{% load pages_tags %}{% get_page 1 as toto %}{{ toto }}"""
template = get_template_from_string(pl1)
self.assertEqual(template.render(context), u'None')
page = self.new_page({'id': 1, 'slug': 'get-page-slug'})
self.assertEqual(template.render(context), u'get-page-slug')
def test_get_page_template_tag_with_page_arg_as_variable_containing_page_id(self):
"""Test get_page template tag with page argument given as a page id"""
context = Context({})
pl1 = """{% load pages_tags %}{% placeholder areftosomepage as somepage %}{% get_page somepage as toto %}{{ toto }}"""
template = get_template_from_string(pl1)
self.assertEqual(template.render(context), u'None')
page = self.new_page( { 'id': 1, 'slug': 'get-page-slug'},
contents={ 'areftosomepage': '1',
'title': 'test-page' } )
self.assertEqual(template.render(context), u'get-page-slug')
def test_get_page_template_tag_with_page_arg_as_variable_containing_page_slug(self):
"""Test get_page template tag with page argument given as a page id"""
context = Context({})
pl1 = """{% load pages_tags %}{% placeholder areftosomepage as somepage %}{% get_page somepage as toto %}{{ toto }}"""
template = get_template_from_string(pl1)
self.assertEqual(template.render(context), u'None')
page = self.new_page( {'id': 1, 'slug': 'get-page-slug'},
contents={ 'title': 'test-title',
'areftosomepage': "get-page-slug" } )
self.assertEqual(template.render(context), u'get-page-slug')
Thanks,
Nicolas.
Edit: Fixed test cases so they are more likely to run but still haven't managed to actually run them. Tryed:
./manage test (just runs django tests)
./manage pages
Got lots of output but the result was: ran 0 tests.
./manage pages.tests.test_unit.UnitTestCase
Got a ValueError: label shoud be of the form app.TestCase or app.TestCase.test_method. Tryed such form, no more luck.