Changes between Version 52 and Version 53 of GenshiTutorial
- Timestamp:
- Aug 31, 2007, 5:43:18 PM (17 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
GenshiTutorial
v52 v53 2 2 3 3 This tutorial is intended to give an introduction on how to use Genshi in your web application, and present common patterns and best practices. It is aimed at developers new to Genshi as well as those who've already used Genshi, but are looking for advice or inspiration on how to improve that usage. 4 5 4 6 5 7 == Introduction == … … 15 17 [[PageOutline(2-3, Content, inline)]] 16 18 19 20 17 21 == Getting Started == 22 18 23 19 24 === Prerequisites === … … 26 31 $ easy_install Genshi 27 32 }}} 33 28 34 29 35 === The !CherryPy Application === … … 89 95 90 96 Note that we've configured !CherryPy to serve static files from the `geddit/static` directory. !CherryPy will complain that that directory does not exist, so create it, but leave it empty for now. We'll add static resources later on in the tutorial. 97 91 98 92 99 === Basic Template Rendering === … … 175 182 }}} 176 183 184 177 185 === The Data Model === 178 186 … … 202 210 203 211 def add_comment(self, username, content): 204 self.comments.append(Comment(username, content)) 212 comment = Comment(username, content) 213 self.comments.append(comment) 214 return comment 205 215 206 216 … … 213 223 214 224 def __repr__(self): 215 return '<%s >' % (type(self).__name__)225 return '<%s by %r>' % (type(self).__name__, self.username) 216 226 }}} 217 227 … … 260 270 >>> link1 = Link(username='joe', url='http://example.org/', title='An example') 261 271 >>> link1.add_comment(username='jack', content='Bla bla bla') 272 <Comment by 'jack'> 262 273 >>> link1.add_comment(username='joe', content='Bla bla bla, bla bla.') 274 <Comment by 'joe'> 263 275 >>> link2 = Link(username='annie', url='http://reddit.com/', title='The real thing') 264 276 >>> import pickle … … 272 284 }}} 273 285 286 287 274 288 == Making the Application “Do Stuff” == 289 275 290 276 291 === Extending the Template === … … 303 318 </div> 304 319 305 <p><a class="action" href="/submit/">Submit new link</a></p>306 307 320 <ol py:if="links"> 308 321 <li py:for="link in reversed(links)"> … … 312 325 </ol> 313 326 327 <p><a class="action" href="/submit/">Submit new link</a></p> 328 314 329 <div id="footer"> 315 330 <hr /> … … 329 344 330 345 [[Image(tutorial01.png)]] 346 331 347 332 348 === Adding a Submission Form === … … 397 413 398 414 Please note though that we're not performing ''any'' kind of validation on the input, and that's of course a bad thing. So let's add validation next. 415 399 416 400 417 === Adding Form Validation === … … 513 530 Now, all entered values are preserved when validation errors occur. Note that the form is populated as the template is being generated, there is no reparsing and reserialization of the output. 514 531 532 533 515 534 == Improving the Application == 535 516 536 517 537 === Factoring out the Templating === … … 615 635 As you can see here, the code is now less repetitive: there's a simple decorator to define which template should be used, and the `render()` produces the template out stream which can then be further processed if necessary. 616 636 637 617 638 === Adding a Layout Template === 618 639 … … 742 763 [[Image(tutorial03.png)]] 743 764 765 744 766 === Implementing Comments === 745 767 … … 765 787 <body> 766 788 <h1>News</h1> 767 <p><a class="action" href="${url('/submit/')}">Submit new link</a></p>768 789 769 790 <ol py:if="links" class="links"> … … 778 799 </li> 779 800 </ol> 801 802 <p><a class="action" href="${url('/submit/')}">Submit new link</a></p> 780 803 </body> 781 804 </html> … … 816 839 posted by ${link.username} at ${link.time.strftime('%x %X')}<br /> 817 840 818 <p><a class="action" href="${url('/comment/%s/' % link.id)}">comment</a></p>819 820 841 <ul py:if="link.comments" class="comments"> 821 842 <li py:for="idx, comment in enumerate(link.comments)" id="comment$idx"> … … 824 845 </li> 825 846 </ul> 847 848 <p><a class="action" href="${url('/comment/%s/' % link.id)}">Add comment</a></p> 826 849 </body> 827 850 </html> … … 852 875 @cherrypy.expose 853 876 @template.output('comment.html') 854 def comment(self, code, cancel=False, **data):855 link = self.data.get( code)877 def comment(self, id, cancel=False, **data): 878 link = self.data.get(id) 856 879 if not link: 857 880 raise cherrypy.NotFound() … … 920 943 [[Image(tutorial04.png)]] 921 944 945 946 922 947 == Advanced Topics == 948 923 949 924 950 === Adding an Atom Feed === … … 1027 1053 [[Image(tutorial05.png)]] 1028 1054 1055 1056 === Ajaxified Commenting === 1057 1058 '''TODO''' 1059 1060 1029 1061 === Allowing Markup in Comments === 1030 1062 … … 1034 1066 * Using HTMLSanitizer 1035 1067 1036 === Ajaxified Commenting ===1037 1038 '''TODO'''1039 1068 1040 1069 === Protecting against Cross-Site Request Forgery === … … 1044 1073 * Check token against cookie before accepting POST requests 1045 1074 1075 1076 1046 1077 == Summary == 1047 1078