]> git.ipfire.org Git - ipfire.org.git/blob - src/web/blog.py
blog: Use upstream cache to cache generated feed
[ipfire.org.git] / src / web / blog.py
1 #!/usr/bin/python
2
3 import datetime
4 import email.utils
5 import tornado.web
6
7 from . import handlers_base as base
8
9 from . import ui_modules
10
11 class IndexHandler(base.BaseHandler):
12 def get(self):
13 posts = self.backend.blog.get_newest(limit=3)
14
15 self.render("blog/index.html", posts=posts)
16
17
18 class AuthorHandler(base.BaseHandler):
19 def get(self, uid):
20 author = self.accounts.get_by_uid(uid)
21 if not author:
22 raise tornado.web.HTTPError(404, "User is unknown")
23
24 # Get all posts from this author
25 posts = self.backend.blog.get_by_author(author)
26 if not posts:
27 raise tornado.web.HTTPError(404, "User has no posts")
28
29 self.render("blog/author.html", author=author, posts=posts)
30
31
32 class FeedHandler(base.BaseHandler):
33 def get(self):
34 posts = self.backend.blog.get_newest(limit=50)
35
36 # Render the feed
37 feed = self.render_string("blog/feed.xml", posts=posts,
38 now=email.utils.formatdate())
39
40 # Allow this to be cached for 5 minutes
41 self.set_expires(300)
42
43 # Set correct content type
44 self.set_header("Content-Type", "application/rss+xml")
45
46 # Deliver content
47 self.finish(feed)
48
49
50 class PostHandler(base.BaseHandler):
51 def get(self, slug):
52 post = self.backend.blog.get_by_slug(slug, published=not self.current_user)
53 if not post:
54 raise tornado.web.HTTPError(404)
55
56 self.render("blog/post.html", post=post)
57
58
59 class PublishHandler(base.BaseHandler):
60 @tornado.web.authenticated
61 def post(self, slug):
62 post = self.backend.blog.get_by_slug(slug, published=not self.current_user)
63 if not post:
64 raise tornado.web.HTTPError(404)
65
66 # Is the post already published?
67 if post.is_published():
68 raise tornado.web.HTTPError(400, "Post is already published")
69
70 # XXX Check that we are only publishing our own posts
71
72 # Publish the post
73 with self.db.transaction():
74 post.publish()
75
76 self.redirect("/post/%s" % post.slug)
77
78
79 class DraftsHandler(base.BaseHandler):
80 @tornado.web.authenticated
81 def get(self):
82 drafts = self.backend.blog.get_drafts(author=self.current_user)
83
84 self.render("blog/drafts.html", drafts=drafts)
85
86
87 class SearchHandler(base.BaseHandler):
88 def get(self):
89 q = self.get_argument("q")
90
91 posts = self.backend.blog.search(q, limit=50)
92 if not posts:
93 raise tornado.web.HTTPError(404, "Nothing found")
94
95 self.render("blog/search-results.html", q=q, posts=posts)
96
97
98 class TagHandler(base.BaseHandler):
99 def get(self, tag):
100 posts = self.backend.blog.get_by_tag(tag)
101 if not posts:
102 raise tornado.web.HTTPError(404, "There are no posts with tag: %s" % tag)
103
104 self.render("blog/tag.html", posts=list(posts), tag=tag)
105
106
107 class YearHandler(base.BaseHandler):
108 def get(self, year):
109 posts = self.backend.blog.get_by_year(year)
110 if not posts:
111 raise tornado.web.HTTPError(404, "There are no posts in %s" % year)
112
113 self.render("blog/year.html", posts=posts, year=year)
114
115
116 class ComposeHandler(base.BaseHandler):
117 @tornado.web.authenticated
118 def get(self):
119 self.render("blog/compose.html", post=None)
120
121 @tornado.web.authenticated
122 def post(self):
123 title = self.get_argument("title")
124 text = self.get_argument("text")
125 tags = self.get_argument("tags", None)
126
127 with self.db.transaction():
128 post = self.backend.blog.create_post(title, text,
129 author=self.current_user, tags=tags)
130
131 self.redirect("/drafts")
132
133
134 class EditHandler(base.BaseHandler):
135 @tornado.web.authenticated
136 def get(self, slug):
137 post = self.backend.blog.get_by_slug(slug, published=False)
138 if not post:
139 raise tornado.web.HTTPError(404)
140
141 # Check if post is editable
142 if not post.is_editable(self.current_user):
143 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
144
145 self.render("blog/compose.html", post=post)
146
147 @tornado.web.authenticated
148 def post(self, slug):
149 post = self.backend.blog.get_by_slug(slug, published=False)
150 if not post:
151 raise tornado.web.HTTPError(404)
152
153 # Check if post is editable
154 if not post.is_editable(self.current_user):
155 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
156
157 # Save updated content
158 with self.db.transaction():
159 post.update(
160 title = self.get_argument("title"),
161 text = self.get_argument("text"),
162 tags = self.get_argument("tags").split(),
163 )
164
165 # Return to blog if the post is already published
166 if post.is_published():
167 self.redirect("/post/%s" % post.slug)
168 return
169
170 # Otherwise return to drafts
171 self.redirect("/drafts")
172
173
174 class HistoryNavigationModule(ui_modules.UIModule):
175 def render(self):
176 return self.render_string("blog/modules/history-navigation.html",
177 years=self.backend.blog.years)
178
179
180 class ListModule(ui_modules.UIModule):
181 def render(self, posts):
182 return self.render_string("blog/modules/list.html", posts=posts)
183
184
185 class PostModule(ui_modules.UIModule):
186 def render(self, post):
187 return self.render_string("blog/modules/post.html", post=post)
188
189
190 class PostsModule(ui_modules.UIModule):
191 def render(self, posts):
192 return self.render_string("blog/modules/posts.html", posts=list(posts))