| | 804 | Passing template variables to the tag |
|---|
| | 805 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| | 806 | |
|---|
| | 807 | Although you can pass any number of arguments to a template tag using |
|---|
| | 808 | ``token.split_contents()``, the arguments are all unpacked as |
|---|
| | 809 | string literals. A little more work is required in order to dynamic content (a |
|---|
| | 810 | template variable) to a template tag as an argument. |
|---|
| | 811 | |
|---|
| | 812 | While the previous examples have formatted the current time into a string and |
|---|
| | 813 | returned the string, suppose you wanted to pass in a ``DateTimeField`` from an |
|---|
| | 814 | object and have the template tag format that date-time:: |
|---|
| | 815 | |
|---|
| | 816 | <p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p> |
|---|
| | 817 | |
|---|
| | 818 | Initially, ``token.split_contents()`` will return three values: |
|---|
| | 819 | |
|---|
| | 820 | 1. The tag name ``format_time``. |
|---|
| | 821 | 2. The string "blog_entry.date_updated" (without the surrounding quotes). |
|---|
| | 822 | 3. The formatting string "%Y-%m-%d %I:%M %p". The return value from |
|---|
| | 823 | ``split_contents()`` will include the leading and trailing quotes for |
|---|
| | 824 | string literals like this. |
|---|
| | 825 | |
|---|
| | 826 | Now your tag should begin to look like this:: |
|---|
| | 827 | |
|---|
| | 828 | from django import template |
|---|
| | 829 | def do_format_time(parser, token): |
|---|
| | 830 | try: |
|---|
| | 831 | # split_contents() knows not to split quoted strings. |
|---|
| | 832 | tag_name, date_to_format, format_string = token.split_contents() |
|---|
| | 833 | except ValueError: |
|---|
| | 834 | raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents[0] |
|---|
| | 835 | if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): |
|---|
| | 836 | raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name |
|---|
| | 837 | return FormatTimeNode(date_to_format, format_string[1:-1]) |
|---|
| | 838 | |
|---|
| | 839 | You also have to change the renderer to retrieve the actual contents of the |
|---|
| | 840 | ``date_updated`` property of the ``blog_entry`` object. This can be |
|---|
| | 841 | accomplished by using the ``resolve_variable()`` function in |
|---|
| | 842 | ``django.template``. You pass ``resolve_variable()`` the variable name and the |
|---|
| | 843 | current context, available in the ``render`` method:: |
|---|
| | 844 | |
|---|
| | 845 | from django import template |
|---|
| | 846 | from django.template import resolve_variable |
|---|
| | 847 | import datetime |
|---|
| | 848 | class FormatTimeNode(template.Node): |
|---|
| | 849 | def __init__(self, date_to_format, format_string): |
|---|
| | 850 | self.date_to_format = date_to_format |
|---|
| | 851 | self.format_string = format_string |
|---|
| | 852 | |
|---|
| | 853 | def render(self, context): |
|---|
| | 854 | try: |
|---|
| | 855 | actual_date = resolve_variable(self.date_to_format, context) |
|---|
| | 856 | return actual_date.strftime(self.format_string) |
|---|
| | 857 | except VariableDoesNotExist: |
|---|
| | 858 | return '' |
|---|
| | 859 | |
|---|
| | 860 | ``resolve_variable`` will try to resolve ``blog_entry.date_updated`` and then |
|---|
| | 861 | format it accordingly. |
|---|
| | 862 | |
|---|
| | 863 | .. note:: |
|---|
| | 864 | The ``resolve_variable()`` function will throw a ``VariableDoesNotExist`` |
|---|
| | 865 | exception if it cannot resolve the string passed to it in the current |
|---|
| | 866 | context of the page. |
|---|
| | 867 | |
|---|