]> git.ipfire.org Git - ipfire.org.git/blame - src/backend/blog.py
blog: Add history pages
[ipfire.org.git] / src / backend / blog.py
CommitLineData
0a6875dc
MT
1#!/usr/bin/python
2
7e64f6a3
MT
3import textile
4
0a6875dc
MT
5from . import misc
6
7class Blog(misc.Object):
8 def _get_post(self, query, *args):
9 res = self.db.get(query, *args)
10
11 if res:
12 return Post(self.backend, res.id, data=res)
13
14 def _get_posts(self, query, *args):
15 res = self.db.query(query, *args)
16
17 for row in res:
18 yield Post(self.backend, row.id, data=row)
19
487417ad
MT
20 def get_by_id(self, id):
21 return self._get_post("SELECT * FROM blog \
22 WHERE id = %s", id)
23
0a6875dc
MT
24 def get_by_slug(self, slug):
25 return self._get_post("SELECT * FROM blog \
26 WHERE slug = %s AND published_at <= NOW()", slug)
27
28 def get_newest(self, limit=None):
29 return self._get_posts("SELECT * FROM blog \
30 WHERE published_at IS NOT NULL \
31 AND published_at <= NOW() \
32 ORDER BY published_at DESC LIMIT %s", limit)
33
34 def get_by_tag(self, tag, limit=None):
35 return self._get_posts("SELECT * FROM blog \
36 WHERE published_at IS NOT NULL \
37 AND published_at <= NOW() \
38 AND %s = ANY(tags) \
4bde7f18 39 ORDER BY published_at DESC LIMIT %s", tag, limit)
0a6875dc
MT
40
41 def get_by_author(self, uid, limit=None):
42 return self._get_posts("SELECT * FROM blog \
43 WHERE author_uid = %s \
44 AND published_at IS NOT NULL \
45 AND published_at <= NOW() \
46 ORDER BY published_at DESC LIMIT %s", uid, limit)
47
7e64f6a3
MT
48 def get_by_year(self, year):
49 return self._get_posts("SELECT * FROM blog \
50 WHERE EXTRACT(year FROM published_at) = %s \
51 AND published_at IS NOT NULL \
52 AND published_at <= NOW() \
53 ORDER BY published_at DESC", year)
54
0a6875dc
MT
55 def search(self, query, limit=None):
56 return self._get_posts("SELECT blog.* FROM blog \
57 LEFT JOIN blog_search_index search_index ON blog.id = search_index.post_id \
58 WHERE search_index.document @@ to_tsquery('english', %s) \
59 ORDER BY ts_rank(search_index.document, to_tsquery('english', %s)) DESC \
60 LIMIT %s", query, query, limit)
61
62 def refresh(self):
63 """
64 Needs to be called after a post has been changed
65 and updates the search index.
66 """
67 self.db.execute("REFRESH MATERIALIZED VIEW blog_search_index")
68
7e64f6a3
MT
69 @property
70 def years(self):
71 res = self.db.query("SELECT DISTINCT EXTRACT(year FROM published_at)::integer AS year \
72 FROM blog WHERE published_at IS NOT NULL AND published_at <= NOW() \
73 ORDER BY year DESC")
74
75 for row in res:
76 yield row.year
77
0a6875dc
MT
78
79class Post(misc.Object):
80 def init(self, id, data=None):
81 self.id = id
82 self.data = data
83
84 @property
85 def title(self):
86 return self.data.title
87
88 @property
89 def slug(self):
90 return self.data.slug
91
92 # XXX needs caching
93 @property
94 def author(self):
95 if self.data.author_uid:
96 return self.backend.accounts.get_by_uid(self.data.author_uid)
97
98 @property
99 def created_at(self):
100 return self.data.created_at
101
102 @property
103 def published_at(self):
104 return self.data.published_at
105
7e64f6a3
MT
106 @property
107 def markdown(self):
108 return self.data.markdown
109
0a6875dc
MT
110 @property
111 def html(self):
112 """
113 Returns this post as rendered HTML
114 """
7e64f6a3 115 return self.data.html or textile.textile(self.markdown.decode("utf-8"))
8ebc98d4
MT
116
117 @property
118 def tags(self):
119 return self.data.tags
1e76fec4
MT
120
121 @property
122 def link(self):
123 return self.data.link