1 | """Proof of concept for on-the-fly, standalone DJango filter code.
|
---|
2 |
|
---|
3 | Problem: in some of my work I use the nifty DJango template code
|
---|
4 | for documentation generation in standalone code - i.e. I generate
|
---|
5 | documentation of some form without using any web app/infrastructure
|
---|
6 | at all.
|
---|
7 |
|
---|
8 | DJango can works fine sans-web so long as you set it up correctly
|
---|
9 | and you don't use custom filters or tags.
|
---|
10 |
|
---|
11 | Actually, thats not 100% true. You *can* use custom filters and tags,
|
---|
12 | but it takes a bit of magic that I didn't think should be necessary.
|
---|
13 |
|
---|
14 | The challenge was to submit a patch to the DJango code, but to do
|
---|
15 | that I need a small demo app that proves the new work..
|
---|
16 |
|
---|
17 |
|
---|
18 | Objective: Render a template, completely standalone, using custom filters
|
---|
19 | and tags, in a "Django-compliant" way with minimal code changes to DJango.
|
---|
20 |
|
---|
21 | Specifically, this demo renders some restructured text using filters
|
---|
22 | to generate underlines and header formatting.
|
---|
23 |
|
---|
24 | Remember: the changes to DJango mustn't break any existing behavior!
|
---|
25 |
|
---|
26 | A. Roark, June 2007
|
---|
27 | """
|
---|
28 | import sys, re, os, os.path
|
---|
29 |
|
---|
30 | try: import django
|
---|
31 | except ImportError, e:
|
---|
32 | sys.stderr.write("DJango not installed\n")
|
---|
33 | sys.exit(1)
|
---|
34 |
|
---|
35 | template_content="""{{ title|rst_format_title:"=" }}
|
---|
36 |
|
---|
37 | {{author|rst_format_author}}
|
---|
38 | {% rst_doc_date %}
|
---|
39 |
|
---|
40 | {{subtitle|rst_format_h1}}
|
---|
41 |
|
---|
42 | {{para}}
|
---|
43 | """
|
---|
44 |
|
---|
45 | def do_filter_demo():
|
---|
46 | """Render a template from a string using our local filter.
|
---|
47 |
|
---|
48 | This will render something like:
|
---|
49 | >>>
|
---|
50 | ===============
|
---|
51 | Filtered Demo
|
---|
52 | ===============
|
---|
53 |
|
---|
54 | :Author: A. Roark
|
---|
55 | :Date: 2007-06-30 21:45:40.205000
|
---|
56 |
|
---|
57 | Simple restructured text demo
|
---|
58 | -----------------------------
|
---|
59 |
|
---|
60 | This uses builtin filters for formatting text
|
---|
61 | <<<
|
---|
62 | """
|
---|
63 |
|
---|
64 | # Render the template here - note that no special imports/code needed.
|
---|
65 | t=Template(template_content)
|
---|
66 | context=Context({
|
---|
67 | 'title': 'Filtered Demo',
|
---|
68 | 'author': 'A. Roark',
|
---|
69 | 'subtitle': 'Simple restructured text demo',
|
---|
70 | 'para': 'This uses builtin filters for formatting text',
|
---|
71 | })
|
---|
72 | out=t.render(context)
|
---|
73 | print "\nDjango Custom Filter Demo:\n>>>\n%s\n<<<\n" % out
|
---|
74 |
|
---|
75 |
|
---|
76 | #
|
---|
77 | # --- Define some filters here ---
|
---|
78 | #
|
---|
79 |
|
---|
80 | def filter_rst_h1(value, arg='-'):
|
---|
81 | "Write a single underline under the text"
|
---|
82 | line=arg * len(value)
|
---|
83 | return "%s\n%s" % (value, line)
|
---|
84 |
|
---|
85 | def filter_rst_title(value, arg='-'):
|
---|
86 | "Add a line before and after the text"
|
---|
87 | line=arg * (2+len(value))
|
---|
88 | return "%s\n %s \n%s" % (line, value, line)
|
---|
89 |
|
---|
90 | def filter_rst_author(value, arg=None):
|
---|
91 | return ":Author: %s" %value
|
---|
92 |
|
---|
93 | #
|
---|
94 | # --- A simple tag ---
|
---|
95 | #
|
---|
96 | def tag_rst_doc_date(parser, token):
|
---|
97 | # A "real" tag should be much more than this -
|
---|
98 | # I'm amazed this works as-is, but its ok for a demo.
|
---|
99 | # For real details, see:
|
---|
100 | # http://www.djangoproject.com/documentation/templates_python/#writing-the-compilation-function
|
---|
101 | import datetime
|
---|
102 | return ":Date: %s" % datetime.datetime.now()
|
---|
103 |
|
---|
104 | #
|
---|
105 | # --- Main code ---
|
---|
106 | #
|
---|
107 | if __name__ == "__main__":
|
---|
108 |
|
---|
109 | # In a standalone app, do this first, before other imports
|
---|
110 | from django.conf import settings
|
---|
111 | settings.configure(
|
---|
112 | # for debug:
|
---|
113 | # DEBUG=True, TEMPLATE_DEBUG=True,
|
---|
114 | # for template files, something like...
|
---|
115 | # TEMPLATE_DIRS=(root_dir, os.path.join(root_dir, 'ref'))
|
---|
116 | )
|
---|
117 |
|
---|
118 | from django.template import Template, Context, BuiltinLibrary
|
---|
119 |
|
---|
120 | # set up extra library of routines for later use...
|
---|
121 | custom_library = BuiltinLibrary()
|
---|
122 | custom_library.filter('rst_format_title', filter_rst_title)
|
---|
123 | custom_library.filter('rst_format_h1', filter_rst_h1)
|
---|
124 | custom_library.filter('rst_format_author', filter_rst_author)
|
---|
125 | custom_library.tag( 'rst_doc_date', tag_rst_doc_date)
|
---|
126 |
|
---|
127 | do_filter_demo()
|
---|
128 |
|
---|