RequestContext and Context Processors
instance of django.template.Context, but Django also comes with a special subclass, django.template.RequestContext, that acts slightly differently. RequestContextadds a bunch of variables to your template context by default – things like the HttpRequest object or information about the currently logged-in user.
Use RequestContext when you don’t want to have to specify the same set of variables in a series of templates.
Avoid repeating the same values in the context dictionary
Point: a context with many similar elements
DO NOT REPEAT YOURSELF
MOST LOW-LEVEL
context processor: it takes an HttpRequest object and returns a dictionary of variables to use in the template context
# naming convention: processorName_proc
processors argument, which is a list or tuple of context processor functions to use.
render_to_reponse() + RequestContext
END MOST LOW-LEVEL
GLOBAL CONTEXT-LEVEL (Not really understood)
global context processors
This setting is a tuple of callables that use the same interface as our custom_proc function above – functions that take a request object as their argument and return a dictionary of items to be merged into the context.
Auto escape
Django has two ways to load templates:
django.template.loaders.filesystem.load_template_source: This loader loads templates from the filesystem, according to TEMPLATE_DIRS. It is enabled by default.
django.template.loaders.app_directories.load_template_source: This loader loads templates from Django applications on the filesystem. For each application in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django looks for templates there.
This means you can store templates with your individual applications, making it easy to distribute Django applications with default templates. For example, if INSTALLED_APPS contains('myproject.polls', 'myproject.music'), then get_template('foo.html') will look for templates in this order:
/path/to/myproject/polls/templates/foo.html
/path/to/myproject/music/templates/foo.html
Note that the loader performs an optimization when it is first imported: it caches a list of which INSTALLED_APPS packages have a templates subdirectory.
This loader is enabled by default.
django.template.loaders.eggs.load_template_source: This loader is just like app_directories, except it loads templates from Python eggs rather than from the filesystem. This loader is disabled by default; you’ll need to enable it if you’re using eggs to distribute your application. (Python eggs are a way of compressing Python code into a single file.)
Django uses the template loaders in order according to the TEMPLATE_LOADERS setting. It uses each loader until a loader finds a match.
Three steps of creating template library
Later:
When Django compiles a template, it splits the raw template text into nodes. Each node is an instance of django.template.Node and has a render() method. Thus, a compiled template is simply a list of Node objects. For example, consider this template:
Thus, to define a custom template tag, you specify how the raw template tag is converted into a Node (the compilation function) and what the node’s render() method does.
{% xxx %} parser
User-defined {% current_time %} #actually available: {% now %}
token.contents is a string of the raw contents of the tag. In our example, it’s'current_time "%Y-%m-%d %I:%M %p"'.
parser is the template parser object. We don’t use it in this example. token is the token currently being parsed by the parser.
As with filter registration, it is also possible to use register.tag as a decorator in Python 2.4 and above:
parser.parse() takes a tuple of names of template tags to parse until. It returns an instance ofdjango.template.NodeList, which is a list of all Node objects that the parser encountered before it encountered any of the tags named in the tuple.
So in the preceding example, nodelist is a list of all nodes between {% comment %} and {% endcomment %}, not counting {% comment %} and {% endcomment %} themselves.
After parser.parse() is called, the parser (not nodeList from parser.parse) hasn’t yet “consumed” the {% endcomment %} tag, so the code needs to explicitly call parser.delete_first_token() to prevent that tag from being processed twice.
take a single argument, and return a string -> shortcut for it
Another common template tag is the type that displays some data by rendering ANOTHER template
result in
1. function
2. Template
3. Register
shortcut:
to be continued...
http://www.djangobook.com/en/2.0/chapter09.html
done
use the inclusion tag:
processors argument, which is a list or tuple of context processor functions to use.
END MOST LOW-LEVEL
GLOBAL CONTEXT-LEVEL (Not really understood)
global context processors
This removes the need to specify processors each time you use RequestContext
For that reason, Django provides support for global context processors. The TEMPLATE_CONTEXT_PROCESSORSsetting (in your settings.py) designates which context processors should always be applied to RequestContext.
For that reason, Django provides support for global context processors. The TEMPLATE_CONTEXT_PROCESSORSsetting (in your settings.py) designates which context processors should always be applied to RequestContext.
django.core.context_processors.auth
- user
- messages
- perms
django.core.context_processors.debug
- debug
- sql_queries
django.core.context_processors.i18n
- LANGUAGES
- LANGUAGE_CODE
Auto escape
(template variable, variable from view functions)
...rather than
This doesn’t affect what happens to data coming from the variable itself.
Generally, template authors don’t need to worry about auto-escaping very much. Developers on the Python side (people writing views and custom filters) need to think about the cases in which data shouldn’t be escaped, and mark data appropriately, so things work in the template.Inside Template Loading
Generally, you’ll store templates in files on your filesystem, but you can use custom template loaders to load templates from other sources.Django has two ways to load templates:
- django.template.loader.get_template(template_name)
- django.template.loader.select_template(template_name_list)
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'template').replace('\\','/'),
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
os.path.join(os.path.dirname(__file__), 'template').replace('\\','/'),
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
django.template.loaders.filesystem.load_template_source: This loader loads templates from the filesystem, according to TEMPLATE_DIRS. It is enabled by default.
django.template.loaders.app_directories.load_template_source: This loader loads templates from Django applications on the filesystem. For each application in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django looks for templates there.
This means you can store templates with your individual applications, making it easy to distribute Django applications with default templates. For example, if INSTALLED_APPS contains('myproject.polls', 'myproject.music'), then get_template('foo.html') will look for templates in this order:
/path/to/myproject/polls/templates/foo.html
/path/to/myproject/music/templates/foo.html
Note that the loader performs an optimization when it is first imported: it caches a list of which INSTALLED_APPS packages have a templates subdirectory.
This loader is enabled by default.
django.template.loaders.eggs.load_template_source: This loader is just like app_directories, except it loads templates from Python eggs rather than from the filesystem. This loader is disabled by default; you’ll need to enable it if you’re using eggs to distribute your application. (Python eggs are a way of compressing Python code into a single file.)
Django uses the template loaders in order according to the TEMPLATE_LOADERS setting. It uses each loader until a loader finds a match.
Extending the Template System
custom template tags and/or filters
Creating a Template Library
to create a template library – a small bit of infrastructure Django can hook into.
- First, create another app solely for the template library. because your filters might be useful to you in future projects, add the app to your INSTALLED_APPS setting
- Second, create a templatetags directory in the appropriate Django application’s package. It should be on the same level as models.py, views.py, and so forth. For example:
- __init__.py and then your custom tag/filter defintions
correspond to the poll_extras.py # your custom defined tag/filter
The {% load %} tag looks at your INSTALLED_APPS setting (new app for template library must be added in setting)and only allows the loading of template libraries within installed Django applications. This is a security feature; it allows you to host Python code for many template libraries on a single computer without enabling access to all of them for every Django installation.
first thing in poll_extras.py is registration:
Writing Custom Template Filters
- __init__.py inside app folder, and inside templatetags folder (under yourApp folder)
- app name in the INSTALLED_APPS section from settings.py
- to use: {% load customizedfilter %}s
Custom filters are just Python functions that take one or two arguments:
- The value of the variable (input)
- The value of the argument, which can have a default value or be left out altogether
Rule for filter functions:
. They shouldn’t raise exceptions, and they should fail silently. If there’s an error, they should return either the original input or an empty string
using decorator
doneWriting Custom Template Tags
When Django compiles a template, it splits the raw template text into nodes. Each node is an instance of django.template.Node and has a render() method. Thus, a compiled template is simply a list of Node objects. For example, consider this template:
In compiled template form, this template is represented as this list of nodes:
- Text node: "Hello, "
- Variable node: person.name
- Text node: ".\n\n"
- IfEqual node: name.birthday and today
Thus, to define a custom template tag, you specify how the raw template tag is converted into a Node (the compilation function) and what the node’s render() method does.
1 Writing the Compilation Function
For each template tag the parser encounters, it calls a Python function with the tag contents and the parser object itself. This function is responsible for returning a Node instance based on the contents of the tag.{% xxx %} parser
User-defined {% current_time %} #actually available: {% now %}
token.contents is a string of the raw contents of the tag. In our example, it’s'current_time "%Y-%m-%d %I:%M %p"'.
parser is the template parser object. We don’t use it in this example. token is the token currently being parsed by the parser.
- Don’t hard-code the tag’s name in your error messages, because that couples the tag’s name to your function. token.split_contents()[0] will always be the name of your tag – even when the tag has no arguments.
- The function returns a CurrentTimeNode (which we’ll create shortly) containing everything the node needs to know about this tag. In this case, it just passes the argument "%Y-%m-%d %I:%M %p". The leading and trailing quotes from the template tag are removed with format_string[1:-1].
- Template tag compilation functions must return a Node subclass; any other return value is an error.
2 Writing the Template Node
3 Registering the Tag
------------------------------------------------------------------------------------------------
Setting a Variable in the Context
The previous section’s example simply returned a value. Often it’s useful to set template variables instead of returning values.
return a value vs. set a value
dictionary assignment
Note that render() returns an empty string. render() should always return a string, so if all the template tag does is set a variable, render() should return an empty string.
New version: setting template variable through context dictionary
(hard-coded)
(non hard-coded)
Template tags can work as blocks containing other tags (like {% if %}, {% for %}, etc.). To create a template tag like this, use parser.parse() in your compilation function.To do so:
Re: Regular expression operations
Parsing Until Another Template Tag
Comment Tag:
parser.parse() takes a tuple of names of template tags to parse until. It returns an instance ofdjango.template.NodeList, which is a list of all Node objects that the parser encountered before it encountered any of the tags named in the tuple.
So in the preceding example, nodelist is a list of all nodes between {% comment %} and {% endcomment %}, not counting {% comment %} and {% endcomment %} themselves.
After parser.parse() is called, the parser (not nodeList from parser.parse) hasn’t yet “consumed” the {% endcomment %} tag, so the code needs to explicitly call parser.delete_first_token() to prevent that tag from being processed twice.
Parsing Until Another Template Tag and Saving Contents {% endXXXX %}
The only new concept here is self.nodelist.render(context) in UpperNode.render(). This simply calls render() on eachNode in the node list.
The only new concept here is self.nodelist.render(context) in UpperNode.render(). This simply calls render() on eachNode in the node list.
Shortcut for Simple Tags
- Single: Only the (single) argument is passed into our function.
- Error Checking: Checking for the required number of arguments has already been done by the time our function is called, so we don’t need to do that.
- Strip: The quotes around the argument (if any) have already been stripped away, so we receive a plain Unicode string.
Inclusion Tags
effect:
result in
1. function
2. Template
3. Register
shortcut:
>>>
takes_context: Sometimes, your inclusion tags need access to values from the parent template’s context
link.html template:
Writing Custom Template Loaders
special loading logic. For example, you could load templates from a database, or directly from a Subversion repository using Subversion’s Python bindings, or (as shown shortly) from a ZIP archive.to be continued...
http://www.djangobook.com/en/2.0/chapter09.html
done
No comments:
Post a Comment