Edgewall Software

source: trunk/examples/tutorial/geddit/controller.py

Last change on this file was 780, checked in by cmlenz, 16 years ago

Fix compatibility of tutorial code with CherryPy 3.1. Closes #159.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 4.3 KB
Line 
1#!/usr/bin/env python
2
3import operator, os, pickle, sys
4
5import cherrypy
6from formencode import Invalid
7from genshi.input import HTML
8from genshi.filters import HTMLFormFiller, HTMLSanitizer
9
10from geddit.form import LinkForm, CommentForm
11from geddit.lib import ajax, template
12from geddit.model import Link, Comment
13
14
15class Root(object):
16
17    def __init__(self, data):
18        self.data = data
19
20    @cherrypy.expose
21    @template.output('index.html')
22    def index(self):
23        links = sorted(self.data.values(), key=operator.attrgetter('time'))
24        return template.render(links=links)
25
26    @cherrypy.expose
27    @template.output('submit.html')
28    def submit(self, cancel=False, **data):
29        if cherrypy.request.method == 'POST':
30            if cancel:
31                raise cherrypy.HTTPRedirect('/')
32            form = LinkForm()
33            try:
34                data = form.to_python(data)
35                link = Link(**data)
36                self.data[link.id] = link
37                raise cherrypy.HTTPRedirect('/')
38            except Invalid, e:
39                errors = e.unpack_errors()
40        else:
41            errors = {}
42
43        return template.render(errors=errors) | HTMLFormFiller(data=data)
44
45    @cherrypy.expose
46    @template.output('info.html')
47    def info(self, id):
48        link = self.data.get(id)
49        if not link:
50            raise cherrypy.NotFound()
51        return template.render(link=link)
52
53    @cherrypy.expose
54    @template.output('comment.html')
55    def comment(self, id, cancel=False, **data):
56        link = self.data.get(id)
57        if not link:
58            raise cherrypy.NotFound()
59        if cherrypy.request.method == 'POST':
60            if cancel:
61                raise cherrypy.HTTPRedirect('/info/%s' % link.id)
62            form = CommentForm()
63            try:
64                data = form.to_python(data)
65                markup = HTML(data['content']) | HTMLSanitizer()
66                data['content'] = markup.render('xhtml')
67                comment = link.add_comment(**data)
68                if not ajax.is_xhr():
69                    raise cherrypy.HTTPRedirect('/info/%s' % link.id)
70                return template.render('_comment.html', comment=comment,
71                                       num=len(link.comments))
72            except Invalid, e:
73                errors = e.unpack_errors()
74        else:
75            errors = {}
76
77        if ajax.is_xhr():
78            stream = template.render('_form.html', link=link, errors=errors)
79        else:
80            stream = template.render(link=link, comment=None, errors=errors)
81        return stream | HTMLFormFiller(data=data)
82
83    @cherrypy.expose
84    @template.output('index.xml', method='xml')
85    def feed(self, id=None):
86        if id:
87            link = self.data.get(id)
88            if not link:
89                raise cherrypy.NotFound()
90            return template.render('info.xml', link=link)
91        else:
92            links = sorted(self.data.values(), key=operator.attrgetter('time'))
93            return template.render(links=links)
94
95
96def main(filename):
97    # load data from the pickle file, or initialize it to an empty list
98    if os.path.exists(filename):
99        fileobj = open(filename, 'rb')
100        try:
101            data = pickle.load(fileobj)
102        finally:
103            fileobj.close()
104    else:
105        data = {}
106
107    def _save_data():
108        # save data back to the pickle file
109        fileobj = open(filename, 'wb')
110        try:
111            pickle.dump(data, fileobj)
112        finally:
113            fileobj.close()
114    if hasattr(cherrypy.engine, 'subscribe'): # CherryPy >= 3.1
115        cherrypy.engine.subscribe('stop', _save_data)
116    else:
117        cherrypy.engine.on_stop_engine_list.append(_save_data)
118
119    # Some global configuration; note that this could be moved into a
120    # configuration file
121    cherrypy.config.update({
122        'tools.encode.on': True, 'tools.encode.encoding': 'utf-8',
123        'tools.decode.on': True,
124        'tools.trailing_slash.on': True,
125        'tools.staticdir.root': os.path.abspath(os.path.dirname(__file__)),
126    })
127
128    cherrypy.quickstart(Root(data), '/', {
129        '/media': {
130            'tools.staticdir.on': True,
131            'tools.staticdir.dir': 'static'
132        }
133    })
134
135if __name__ == '__main__':
136    import formencode
137    formencode.api.set_stdtranslation(languages=['en'])
138    main(sys.argv[1])
Note: See TracBrowser for help on using the repository browser.