Edgewall Software

Changes between Version 52 and Version 53 of GenshiTutorial


Ignore:
Timestamp:
Aug 31, 2007, 5:43:18 PM (17 years ago)
Author:
cmlenz
Comment:

Some cleanup in preparation for next step (AJAX)

Legend:

Unmodified
Added
Removed
Modified
  • GenshiTutorial

    v52 v53  
    22
    33This 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
    46
    57== Introduction ==
     
    1517[[PageOutline(2-3, Content, inline)]]
    1618
     19
     20
    1721== Getting Started ==
     22
    1823
    1924=== Prerequisites ===
     
    2631$ easy_install Genshi
    2732}}}
     33
    2834
    2935=== The !CherryPy Application ===
     
    8995
    9096Note 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
    9198
    9299=== Basic Template Rendering ===
     
    175182}}}
    176183
     184
    177185=== The Data Model ===
    178186
     
    202210
    203211    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
    205215
    206216
     
    213223
    214224    def __repr__(self):
    215         return '<%s>' % (type(self).__name__)
     225        return '<%s by %r>' % (type(self).__name__, self.username)
    216226}}}
    217227
     
    260270>>> link1 = Link(username='joe', url='http://example.org/', title='An example')
    261271>>> link1.add_comment(username='jack', content='Bla bla bla')
     272<Comment by 'jack'>
    262273>>> link1.add_comment(username='joe', content='Bla bla bla, bla bla.')
     274<Comment by 'joe'>
    263275>>> link2 = Link(username='annie', url='http://reddit.com/', title='The real thing')
    264276>>> import pickle
     
    272284}}}
    273285
     286
     287
    274288== Making the Application “Do Stuff” ==
     289
    275290
    276291=== Extending the Template ===
     
    303318    </div>
    304319
    305     <p><a class="action" href="/submit/">Submit new link</a></p>
    306 
    307320    <ol py:if="links">
    308321      <li py:for="link in reversed(links)">
     
    312325    </ol>
    313326
     327    <p><a class="action" href="/submit/">Submit new link</a></p>
     328
    314329    <div id="footer">
    315330      <hr />
     
    329344
    330345[[Image(tutorial01.png)]]
     346
    331347
    332348=== Adding a Submission Form ===
     
    397413
    398414Please 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
    399416
    400417=== Adding Form Validation ===
     
    513530Now, 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.
    514531
     532
     533
    515534== Improving the Application ==
     535
    516536
    517537=== Factoring out the Templating ===
     
    615635As 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.
    616636
     637
    617638=== Adding a Layout Template ===
    618639
     
    742763[[Image(tutorial03.png)]]
    743764
     765
    744766=== Implementing Comments ===
    745767
     
    765787  <body>
    766788    <h1>News</h1>
    767     <p><a class="action" href="${url('/submit/')}">Submit new link</a></p>
    768789
    769790    <ol py:if="links" class="links">
     
    778799      </li>
    779800    </ol>
     801
     802    <p><a class="action" href="${url('/submit/')}">Submit new link</a></p>
    780803  </body>
    781804</html>
     
    816839    posted by ${link.username} at ${link.time.strftime('%x %X')}<br />
    817840
    818     <p><a class="action" href="${url('/comment/%s/' % link.id)}">comment</a></p>
    819 
    820841    <ul py:if="link.comments" class="comments">
    821842      <li py:for="idx, comment in enumerate(link.comments)" id="comment$idx">
     
    824845      </li>
    825846    </ul>
     847
     848    <p><a class="action" href="${url('/comment/%s/' % link.id)}">Add comment</a></p>
    826849  </body>
    827850</html>
     
    852875    @cherrypy.expose
    853876    @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)
    856879        if not link:
    857880            raise cherrypy.NotFound()
     
    920943[[Image(tutorial04.png)]]
    921944
     945
     946
    922947== Advanced Topics ==
     948
    923949
    924950=== Adding an Atom Feed ===
     
    10271053[[Image(tutorial05.png)]]
    10281054
     1055
     1056=== Ajaxified Commenting ===
     1057
     1058'''TODO'''
     1059
     1060
    10291061=== Allowing Markup in Comments ===
    10301062
     
    10341066 * Using HTMLSanitizer
    10351067
    1036 === Ajaxified Commenting ===
    1037 
    1038 '''TODO'''
    10391068
    10401069=== Protecting against Cross-Site Request Forgery ===
     
    10441073 * Check token against cookie before accepting POST requests
    10451074
     1075
     1076
    10461077== Summary ==
    10471078