|
@@ -1,190 +0,0 @@
|
1
|
|
-<%inherit file="local:templates.master"/>
|
2
|
|
-
|
3
|
|
-<%def name="title()">
|
4
|
|
-Learning TurboGears 2.3: Quick guide to the Quickstart pages.
|
5
|
|
-</%def>
|
6
|
|
-
|
7
|
|
- <div class="row">
|
8
|
|
- <div class="span12">
|
9
|
|
- <div class="page-header">
|
10
|
|
- <h2>Architectural basics of a quickstart TG2 site.</h2>
|
11
|
|
- </div>
|
12
|
|
-
|
13
|
|
- <p>The TG2 quickstart command produces this basic TG site. Here's how it works.</p>
|
14
|
|
- </div>
|
15
|
|
-
|
16
|
|
- <div class="span4">
|
17
|
|
- <div class="well" style="padding: 8px 0;">
|
18
|
|
- <ul class="nav nav-list">
|
19
|
|
- <li class="nav-header">About Architecture</li>
|
20
|
|
- <li><a href="#data-model">Data Model</a></li>
|
21
|
|
- <li><a href="#url-structure">URL Structure</a></li>
|
22
|
|
- <li><a href="#template-reuse">Web page element's reuse</a></li>
|
23
|
|
- <li py:if="tg.auth_stack_enabled" class="nav-header">Authentication</li>
|
24
|
|
- <li py:if="tg.auth_stack_enabled"><a href="#authentication">Authorization and Authentication</a></li>
|
25
|
|
- </ul>
|
26
|
|
- </div>
|
27
|
|
-
|
28
|
|
- <div class="well" id="data-model">
|
29
|
|
- <h3>Code my data model</h3>
|
30
|
|
-
|
31
|
|
- <p>When you want a model for storing favorite links or wiki content, the
|
32
|
|
- <code>/model</code> folder in your site is ready to go.</p>
|
33
|
|
-
|
34
|
|
- <p>You can build a dynamic site without any data model at all. There still be a
|
35
|
|
- default data-model template for you if you didn't enable authentication and
|
36
|
|
- authorization in quickstart. If you have enabled authorization, the auth
|
37
|
|
- data-model is ready-made.</p>
|
38
|
|
- </div>
|
39
|
|
-
|
40
|
|
- <div class="well" id="url-structure">
|
41
|
|
- <h3>Design my URL structure</h3>
|
42
|
|
-
|
43
|
|
- <p>The "<code>root.py</code>" file under the <code>/controllers</code> folder has
|
44
|
|
- your URLs. When you called this url (<code><a href=
|
45
|
|
- "${tg.url('/about')}">about</a></code>), the command went through the
|
46
|
|
- RootController class to the <code>about()</code> method.</p>
|
47
|
|
-
|
48
|
|
- <p>Those Python methods are responsible to create the dictionary of variables
|
49
|
|
- that will be used in your web views (template).</p>
|
50
|
|
- </div>
|
51
|
|
- </div>
|
52
|
|
-
|
53
|
|
- <div class="span8"><img src=
|
54
|
|
- "http://www.turbogears.org/2.1/docs/_images/tg2_files.jpg" alt=
|
55
|
|
- "TurboGears2 quickstarted project" /></div>
|
56
|
|
- </div>
|
57
|
|
-
|
58
|
|
- <div class="row">
|
59
|
|
- <div class="span12" id="template-reuse">
|
60
|
|
- <h3>Reuse the web page elements</h3>
|
61
|
|
-
|
62
|
|
- <p>A web page viewed by user could be constructed by single or several reusable
|
63
|
|
- templates under <code>/templates</code>. Take 'about' page for example, each
|
64
|
|
- reusable templates generating a part of the page. We'll cover them in the order of
|
65
|
|
- where they are found, listed near the top of the about.html template</p>
|
66
|
|
-
|
67
|
|
- <div class="row">
|
68
|
|
- <div class="span6">
|
69
|
|
- <p><strong><span class="label label-info">header.html</span></strong> - The
|
70
|
|
- "header.html" template contains the HTML code to display the 'header': The div,
|
71
|
|
- the h1 tag, and the subtitle are there, and the the blue gradient, TG2 logo,
|
72
|
|
- are placed by way of the .css file (from style.css) are all at the top of every
|
73
|
|
- page it is included on. When the "about.html" template is called, it includes
|
74
|
|
- this "header.html" template (and the others) with a <code><xi:include
|
75
|
|
- /></code> tag, part of the Genshi templating system. The "header.html"
|
76
|
|
- template is not a completely static HTML -- it also includes (via
|
77
|
|
- <code><xi:include/></code> tag) "master.html", which dynamically displays
|
78
|
|
- the current page name with a Genshi template method called "replace" with the
|
79
|
|
- code: <code><span py:replace="page"/></code>. It means replace this
|
80
|
|
- <code><span /></code> region with the contents found in the variable
|
81
|
|
- 'page' that has been sent in the dictionary to this "about.html" template, and
|
82
|
|
- is available through that namespace for use by this "header.html" template.
|
83
|
|
- That's how it changes in the header depending on what page you are
|
84
|
|
- visiting.</p>
|
85
|
|
-
|
86
|
|
- <p><strong><span class="label label-info">sidebars.html</span></strong> - The
|
87
|
|
- sidebars (navigation areas on the right side of the page) are generated as two
|
88
|
|
- separate <code>py:def</code> blocks in the "sidebars.html" template. The
|
89
|
|
- <code>py:def</code> construct is best thought of as a "macro" code... a simple
|
90
|
|
- way to separate and reuse common code snippets. All it takes to include these
|
91
|
|
- on the "about.html" page template is to write</p>
|
92
|
|
- <pre><span>$</span>{sidebar_top()}
|
93
|
|
-<span>$</span>{sidebar_bottom()}
|
94
|
|
- </pre>in the page where they are wanted. CSS styling (in "/public/css/style.css") floats
|
95
|
|
- them off to the right side. You can remove a sidebar or add more of them, and the CSS
|
96
|
|
- will place them one atop the other.
|
97
|
|
-
|
98
|
|
- <p>This is, of course, also exactly how the header and footer templates are
|
99
|
|
- also displayed in their proper places, but we'll cover that in the
|
100
|
|
- "master.html" template below.</p>
|
101
|
|
-
|
102
|
|
- <p>Oh, and in sidebar_top we've added a dynamic menu that shows the link to
|
103
|
|
- this page at the top when you're at the "index" page, and shows a link to the
|
104
|
|
- Home (index) page when you're here. Study the "sidebars.html" template to see
|
105
|
|
- how we used <code>py:choose</code> for that.</p>
|
106
|
|
- </div>
|
107
|
|
-
|
108
|
|
- <div class="span6">
|
109
|
|
- <p><strong><span class="label label-info">footer.html</span></strong> - The
|
110
|
|
- "footer.html" block is simple, but also utilizes a special "replace" method to
|
111
|
|
- set the current YEAR in the footer copyright message. The code is:</p>
|
112
|
|
- <pre>
|
113
|
|
- <span py:replace="now.strftime('%Y')">
|
114
|
|
- </pre>and it uses the variable "now" that was passed in with the dictionary of variables.
|
115
|
|
- But because "now" is a datetime object, we can use the Python <code>"strftime()"</code>
|
116
|
|
- method with the "replace" call to say "Just Display The Year Here". Simple, elegant; we
|
117
|
|
- format the date display in the template (the View in the Model/View/Controller
|
118
|
|
- architecture) rather than formatting it in the Controller method and sending it to the
|
119
|
|
- template as a string variable.
|
120
|
|
-
|
121
|
|
- <p><strong><span class="label label-info">master.html</span></strong> - The
|
122
|
|
- "master.html" template is called last, by design. The "master.html" template
|
123
|
|
- controls the overall design of the page we're looking at, calling first the
|
124
|
|
- "header" py:def macro, then the putting everything from this "about.html"
|
125
|
|
- template into the "main_content" div, and then calling the "footer" macro at
|
126
|
|
- the end. Thus the "master.html" template provides the overall architecture for
|
127
|
|
- each page in this site.</p>
|
128
|
|
-
|
129
|
|
- <p>But why then shouldn't we call it first? Isn't it the most important?
|
130
|
|
- Perhaps, but that's precisely why we call it LAST. The "master.html" template
|
131
|
|
- needs to know where to find everything else, everything that it will use in
|
132
|
|
- py:def macros to build the page. So that means we call the other templates
|
133
|
|
- first, and then call "master.html".</p>
|
134
|
|
-
|
135
|
|
- <p>There's more to the "master.html" template... study it to see how the
|
136
|
|
- <title> tags and static JS and CSS files are brought into the page.
|
137
|
|
- Templating with Genshi is a powerful tool and we've only scratched the surface.
|
138
|
|
- There are also a few little CSS tricks hidden in these pages, like the use of a
|
139
|
|
- "clearingdiv" to make sure that your footer stays below the sidebars and always
|
140
|
|
- looks right. That's not TG2 at work, just CSS. You'll need all your skills to
|
141
|
|
- build a fine web app, but TG2 will make the hard parts easier so that you can
|
142
|
|
- concentrate more on good design and content rather than struggling with
|
143
|
|
- mechanics.</p>
|
144
|
|
- </div>
|
145
|
|
-
|
146
|
|
- <div class="span12" id="authentication" py:if="tg.auth_stack_enabled">
|
147
|
|
- <h3>Authentication & Authorization in a TG2 site.</h3>
|
148
|
|
-
|
149
|
|
- <p>If you have access to this page, this means you have enabled authentication
|
150
|
|
- and authorization in the quickstart to create your project.</p>
|
151
|
|
-
|
152
|
|
- <p>The paster command will have created a few specific controllers for you. But
|
153
|
|
- before you go to play with those controllers you'll need to make sure your
|
154
|
|
- application has been properly bootstapped. This is dead easy, here is how to do
|
155
|
|
- this:</p>
|
156
|
|
- <pre>paster setup-app development.ini</pre>
|
157
|
|
-
|
158
|
|
- <p>inside your application's folder and you'll get a database setup (using the
|
159
|
|
- preferences you have set in your development.ini file). This database will also
|
160
|
|
- have been prepopulated with some default logins/passwords so that you can test
|
161
|
|
- the secured controllers and methods.</p>
|
162
|
|
-
|
163
|
|
- <p>To change the comportement of this setup-app command you just need to edit
|
164
|
|
- the <code>websetup.py</code> file.</p>
|
165
|
|
-
|
166
|
|
- <p>Now try to visiting the <a href=
|
167
|
|
- "${tg.url('/manage_permission_only')}">manage_permission_only</a> URL. You will
|
168
|
|
- be challenged with a login/password form.</p>
|
169
|
|
-
|
170
|
|
- <p>Only managers are authorized to visit this method. You will need to log-in
|
171
|
|
- using:</p>
|
172
|
|
- <pre>login: manager
|
173
|
|
-password: managepass</pre>
|
174
|
|
-
|
175
|
|
- <p>Another protected resource is <a href=
|
176
|
|
- "${tg.url('/editor_user_only')}">editor_user_only</a>. This one is protected by
|
177
|
|
- a different set of permissions. You will need to be <code>editor</code> with a
|
178
|
|
- password of <code>editpass</code> to be able to access it.</p>
|
179
|
|
-
|
180
|
|
- <p>The last kind of protected resource in this quickstarted app is a full so
|
181
|
|
- called <a href="${tg.url('/secc')}">secure controller</a>. This controller is
|
182
|
|
- protected globally. Instead of having a @require decorator on each method, we
|
183
|
|
- have set an allow_only attribute at the class level. All the methods in this
|
184
|
|
- controller will require the same level of access. You need to be manager to
|
185
|
|
- access <a href="${tg.url('/secc')}">secc</a> or <a href=
|
186
|
|
- "${tg.url('/secc/some_where')}">secc/some_where</a>.</p>
|
187
|
|
- </div>
|
188
|
|
- </div>
|
189
|
|
- </div>
|
190
|
|
- </div>
|