Add initial version of Python files
Getty Ritter
4 years ago
1 | #!/usr/bin/python2 | |
2 | ||
3 | import flask | |
4 | import web | |
5 | import markdown | |
6 | import storage | |
7 | import sys | |
8 | ||
9 | web.template.ALLOWED_AST_NODES.append('Constant') | |
10 | ||
11 | ||
12 | def slugify(string): | |
13 | def process(char): | |
14 | if char in '- \n\t\f': | |
15 | return '-' | |
16 | elif char.isalpha(): | |
17 | return char.lower() | |
18 | else: | |
19 | return '' | |
20 | return ''.join(process(c) for c in string)[:40] | |
21 | ||
22 | ||
23 | def thumb(url): | |
24 | if url: | |
25 | return url[:-4] + '_thumb' + url[-4:] | |
26 | ||
27 | ||
28 | def five(n): | |
29 | return '{0:05}'.format(n) | |
30 | ||
31 | ||
32 | db = storage.DB() | |
33 | render = web.template.render('templates/', | |
34 | globals=dict(markdown=markdown.markdown, | |
35 | slugify=slugify, | |
36 | all_categories=db.all_categories, | |
37 | thumb=thumb, | |
38 | five=five)) | |
39 | ||
40 | concat = '\n'.join | |
41 | ||
42 | ||
43 | def snip(text): | |
44 | if len(text) < 256: | |
45 | return text | |
46 | else: | |
47 | return text[:256] + '...' | |
48 | ||
49 | ||
50 | def main(func): | |
51 | def new_func(*args, **kwargs): | |
52 | web.header('Content-Type', 'application/xhtml+xml') | |
53 | return render.main(*func(*args, **kwargs)) | |
54 | new_func.__name__ = func.__name__ | |
55 | return new_func | |
56 | ||
57 | ||
58 | class index: | |
59 | @main | |
60 | def GET(self): | |
61 | try: | |
62 | pg = db.get_page('main') | |
63 | return ('Frony Ritter Designs', | |
64 | markdown.markdown(pg.text)) | |
65 | except: | |
66 | raise web.notfound() | |
67 | ||
68 | ||
69 | class contact: | |
70 | ||
71 | @main | |
72 | def GET(self): | |
73 | return 'Contact Information', 'Send me an email at my email address.' | |
74 | ||
75 | ||
76 | class design: | |
77 | ||
78 | @main | |
79 | def GET(self, id, slug=None): | |
80 | try: | |
81 | id = int(id) | |
82 | design = db.get_design(id) | |
83 | return 'Designs', render.design_page(*design) | |
84 | except: | |
85 | raise web.notfound() | |
86 | ||
87 | def POST(self, id, slug='electric-boogaloo'): | |
88 | try: | |
89 | id = int(id) | |
90 | except: | |
91 | raise web.redirect('/') | |
92 | input = dict(web.input()) | |
93 | if ('title' in input and | |
94 | 'description' in input and | |
95 | 'category' in input and | |
96 | 'tags' in input): | |
97 | db.put_design(id, | |
98 | input['title'], | |
99 | input['description'], | |
100 | input['category']) | |
101 | db.process_tag_list(id, input['tags']) | |
102 | if not slug: | |
103 | slug = slugify(input['title']) | |
104 | raise web.redirect('/edit/design/{0:05}/slug/'.format(id, slug)) | |
105 | ||
106 | ||
107 | class all_designs: | |
108 | ||
109 | @main | |
110 | def GET(self): | |
111 | winput = web.input(page=0) | |
112 | page = int(winput['page']) | |
113 | min, max = db.max_page_ranges() | |
114 | data = db.get_all(offset=page) | |
115 | return ('Designs', | |
116 | render.design_list( | |
117 | (render.design_tile(name, pics, snip(desc), id) | |
118 | for name, pics, desc, cat, id in data), | |
119 | page, | |
120 | max, | |
121 | page > min, | |
122 | page < max)) | |
123 | ||
124 | ||
125 | class category: | |
126 | ||
127 | @main | |
128 | def GET(self, cat): | |
129 | winput = web.input(page=0) | |
130 | page = int(winput['page']) | |
131 | data = db.get_designs_by_category(cat, page) | |
132 | min, max = db.max_page_range_for_category(cat) | |
133 | return (cat.capitalize(), | |
134 | render.by_category_list( | |
135 | cat, | |
136 | (render.design_tile(name, pics, 0, id) | |
137 | for name, pics, desc, cat, id in data), | |
138 | page, | |
139 | page > min, | |
140 | page < (max - 1))) | |
141 | ||
142 | ||
143 | class category_tag: | |
144 | ||
145 | @main | |
146 | def GET(self, cat, tag): | |
147 | winput = web.input(page=0) | |
148 | page = int(winput['page']) | |
149 | data = db.get_designs_by_category_and_tag(cat, tag, page) | |
150 | min, max = db.max_page_range_for_category(cat) | |
151 | return (cat.capitalize(), | |
152 | render.by_category_list( | |
153 | cat, | |
154 | (render.design_tile(name, pics, 0, id) | |
155 | for name, pics, desc, cat, id in data), | |
156 | page, | |
157 | page > min, | |
158 | page < (max - 1))) | |
159 | ||
160 | ||
161 | class tag: | |
162 | ||
163 | @main | |
164 | def GET(self, tag): | |
165 | winput = web.input(page=0) | |
166 | page = int(winput['page']) | |
167 | data = db.get_designs_by_tag(tag, page) | |
168 | min, max = db.max_page_range_for_tag(tag) | |
169 | pretty_tag = ' '.join(w.capitalize() | |
170 | for w in tag.split('_')) | |
171 | return (pretty_tag, | |
172 | render.by_tag_list( | |
173 | tag, | |
174 | (render.design_tile(name, pics, 0, id) | |
175 | for name, pics, desc, cat, id in data), | |
176 | page, | |
177 | page > min, | |
178 | page < max)) | |
179 | ||
180 | ||
181 | class all_categories: | |
182 | ||
183 | @main | |
184 | def GET(self): | |
185 | categories = db.all_categories() | |
186 | return 'Category', render.select_category(categories) | |
187 | ||
188 | ||
189 | class all_tags: | |
190 | ||
191 | @main | |
192 | def GET(self): | |
193 | pretty = lambda t: ' '.join(w.capitalize() | |
194 | for w in t.split('_')) | |
195 | tags = ( | |
196 | (t, pretty(t), db.num_for_tag(t)) | |
197 | for t in sorted(db.get_all_tags())) | |
198 | return 'All Tags', render.select_tag(tags) | |
199 | ||
200 | ||
201 | class page: | |
202 | ||
203 | @main | |
204 | def GET(self, name): | |
205 | try: | |
206 | pg = db.get_page(name) | |
207 | return (pg.title, | |
208 | markdown.markdown(pg.text)) | |
209 | except: | |
210 | raise web.notfound() | |
211 | ||
212 | ||
213 | class admin: | |
214 | ||
215 | class edit_all_designs: | |
216 | ||
217 | ||
218 | @main | |
219 | def GET(self): | |
220 | winput = web.input(page=0) | |
221 | page = int(winput['page']) | |
222 | min, max = db.max_page_ranges() | |
223 | data = db.get_all(offset=page) | |
224 | return ('Edit Mode', | |
225 | render.edit_design_list( | |
226 | ((name, pics, id) for name, pics, _, _, id in data), | |
227 | page, | |
228 | page > min, | |
229 | page < max)) | |
230 | ||
231 | def POST(self): | |
232 | id = db.new_design() | |
233 | raise web.redirect('/edit/design/{0:05}/'.format( | |
234 | id)) | |
235 | ||
236 | class edit_design: | |
237 | ||
238 | ||
239 | @main | |
240 | def GET(self, id, slug=None): | |
241 | try: | |
242 | id = int(id) | |
243 | design = db.get_design(id) | |
244 | tags = ' '.join(db.get_tags_for_design(id)) | |
245 | (name, images, | |
246 | description, | |
247 | cat, id) = design | |
248 | return name, render.edit_design( | |
249 | name, images, description, cat, id, tags) | |
250 | except: | |
251 | raise web.notfound() | |
252 | ||
253 | class delete_design: | |
254 | ||
255 | ||
256 | @main | |
257 | def GET(self, id): | |
258 | try: | |
259 | id = int(id) | |
260 | except: | |
261 | raise web.notfound() | |
262 | design = db.get_design(id) | |
263 | return ('Delete', | |
264 | render.delete_design(*design)) | |
265 | ||
266 | ||
267 | def POST(self, id): | |
268 | try: | |
269 | id = int(id) | |
270 | except: | |
271 | raise web.notfound() | |
272 | db.delete_design(id) | |
273 | raise web.redirect('/edit/design/') | |
274 | ||
275 | class add_photo: | |
276 | ||
277 | ||
278 | @main | |
279 | def GET(self): | |
280 | input = web.input() | |
281 | if 'id' in input: | |
282 | return ('Add Photo For Design {0}'.format(input.id), | |
283 | render.photo_upload(input.id)) | |
284 | else: | |
285 | return ('Add Generic Photo', render.photo_upload(-1)) | |
286 | ||
287 | ||
288 | def POST(self): | |
289 | input = web.input(file={}) | |
290 | try: | |
291 | id = int(input['id']) | |
292 | except: | |
293 | raise web.redirect('/design/') | |
294 | if 'file' in input: | |
295 | photo_id = db.add_photo(input['file'], id) | |
296 | if id == -1: | |
297 | raise web.redirect('/edit/view-photo/{0:09}/'.format(photo_id)) | |
298 | else: | |
299 | raise web.redirect('/edit/design/{0:05}/'.format(id)) | |
300 | ||
301 | class all_files: | |
302 | ||
303 | ||
304 | @main | |
305 | def GET(self): | |
306 | files = db.all_files() | |
307 | return ('All Uploaded Files', render.all_files(files)) | |
308 | ||
309 | class add_file: | |
310 | ||
311 | ||
312 | @main | |
313 | def GET(self): | |
314 | return ('Add File', render.file_upload()) | |
315 | ||
316 | ||
317 | def POST(self): | |
318 | input = web.input(file={}) | |
319 | if 'file' in input: | |
320 | file_id = db.add_photo(input['file']) | |
321 | raise web.redirect('/edit/file-list/') | |
322 | ||
323 | class modify_photo: | |
324 | ||
325 | ||
326 | @main | |
327 | def GET(self, id): | |
328 | design_id = web.input().design_id | |
329 | return ('Delete Photo', | |
330 | render.photo_delete(id, design_id)) | |
331 | ||
332 | ||
333 | def POST(self, id): | |
334 | input = web.input() | |
335 | design_id = int(input['design_id']) | |
336 | db.delete_photo(id) | |
337 | raise web.redirect('/edit/design/{0:05}/'.format( | |
338 | design_id)) | |
339 | ||
340 | class view_all_photos: | |
341 | ||
342 | ||
343 | @main | |
344 | def GET(self): | |
345 | winput = web.input(page=0) | |
346 | page = int(winput['page']) | |
347 | min, max = db.max_photo_page_ranges() | |
348 | data = db.get_all_photos(offset=page) | |
349 | return ('Photos', | |
350 | render.photo_list((render.photo_tile(p) for p in data), | |
351 | page, max, page > min, page < max)) | |
352 | ||
353 | class view_photo: | |
354 | ||
355 | ||
356 | @main | |
357 | def GET(self, id): | |
358 | photo = db.get_photo_by_id(id) | |
359 | if photo: | |
360 | return ('Viewing Photo {0}'.format(id), | |
361 | render.view_photo(id, photo)) | |
362 | else: | |
363 | raise web.notfound() | |
364 | ||
365 | class edit_page_list: | |
366 | ||
367 | ||
368 | @main | |
369 | def GET(self): | |
370 | return ('Edit Page List', | |
371 | render.edit_pages(db.get_page_list())) | |
372 | ||
373 | class edit_page: | |
374 | ||
375 | ||
376 | @main | |
377 | def GET(self, name): | |
378 | return ( | |
379 | 'Edit Page {0}'.format(name), | |
380 | render.edit_page(name, db.get_page(name))) | |
381 | ||
382 | ||
383 | def POST(self, name): | |
384 | input = web.input() | |
385 | text = input.get('text', '') | |
386 | title = input.get('title', name.capitalize()) | |
387 | db.set_page(name, title, text) | |
388 | raise web.redirect('/edit/pages/{0}/'.format(name)) | |
389 | ||
390 | class edit_about: | |
391 | ||
392 | ||
393 | @main | |
394 | def GET(self): | |
395 | return ( | |
396 | 'Edit About', | |
397 | render.edit_about(db.get_about_text())) | |
398 | ||
399 | ||
400 | def POST(self): | |
401 | input = web.input() | |
402 | text = input.get('text', '') | |
403 | db.set_about_text(text) | |
404 | raise web.redirect('/edit/about/') | |
405 | ||
406 | ||
407 | urls = ( | |
408 | ||
409 | # viewing urls | |
410 | '/', index, | |
411 | '/design/?', all_designs, | |
412 | '/design/([^/]*)/([^/]*)/?$', design, | |
413 | '/design/([^/]*)/?$', design, | |
414 | '/category/?', all_categories, | |
415 | '/category/([^/]*)/?', category, | |
416 | '/category/([^/]*)/tag/([^/]*)/?', category_tag, | |
417 | '/tag/?', all_tags, | |
418 | '/tag/([^/]*)/?', tag, | |
419 | ||
420 | # editing urls | |
421 | '/edit/design/?', admin.edit_all_designs, | |
422 | '/edit/design/([^/]*)/?', admin.edit_design, | |
423 | '/edit/design/([^/]*)/([^/]*)/?', admin.edit_design, | |
424 | '/edit/delete/([^/]*)/?', admin.delete_design, | |
425 | '/edit/photo/?', admin.add_photo, | |
426 | '/edit/photo/([^/]*)/?', admin.modify_photo, | |
427 | '/edit/view-photo/?', admin.view_all_photos, | |
428 | '/edit/view-photo/([^/]*)/?', admin.view_photo, | |
429 | '/edit/file-list/?', admin.all_files, | |
430 | '/edit/file/?', admin.add_file, | |
431 | '/edit/pages/?', admin.edit_page_list, | |
432 | '/edit/pages/([^/]*)/?', admin.edit_page, | |
433 | '/edit/about/?', admin.edit_about, | |
434 | ||
435 | # catch-all for other pages | |
436 | '/([^/]*)/?', page | |
437 | ||
438 | ) | |
439 | ||
440 | # app = web.application(urls, globals()) | |
441 | # # web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr) | |
442 | ||
443 | # if __name__ == '__main__': | |
444 | # app.run() |
1 | import os | |
2 | import web | |
3 | from PIL import Image | |
4 | ||
5 | THUMB_SIZE = (100, 100) | |
6 | ||
7 | ||
8 | class DB: | |
9 | ||
10 | def __init__(self, per_page=16): | |
11 | self._db = web.database(dbn='sqlite', | |
12 | db='frony.db') | |
13 | self.per_page = per_page | |
14 | self.categories = {} | |
15 | self.photo_num = self.get_max_photo_num() + 1 | |
16 | ||
17 | def get_max_photo_num(self): | |
18 | n = 0 | |
19 | for file in os.listdir(os.path.join('static', 'photos')): | |
20 | try: | |
21 | n = max(int(file[:5]), n) | |
22 | except: | |
23 | pass | |
24 | return n | |
25 | ||
26 | def get_category_id(self, nm): | |
27 | id = list(self._db.where('categories', name=nm)) | |
28 | return id and id[0].id | |
29 | ||
30 | def all_categories(self): | |
31 | categories = self._db.select('categories') | |
32 | return [(c.name, c.id, c.nicename) for c in categories] | |
33 | ||
34 | def get_category_name(self, id): | |
35 | if id in self.categories: | |
36 | return self.categories[id] | |
37 | else: | |
38 | nm = list(self._db.where('categories', id=id)) | |
39 | if nm: | |
40 | self.categories[id] = nm[0].name | |
41 | return nm and nm[0].name or 'unknown' | |
42 | ||
43 | def get_design(self, id): | |
44 | d = list(self._db.where('designs', id=id)) | |
45 | if not d: | |
46 | return None | |
47 | else: | |
48 | d = d[0] | |
49 | return (d.title, | |
50 | self.get_all_photos_for_design(d.id), | |
51 | d.description, | |
52 | self.get_category_name(d.category), | |
53 | d.id) | |
54 | ||
55 | def put_design(self, id, title, description, category): | |
56 | description = description.replace('\r\n', '\n') | |
57 | self._db.update( | |
58 | 'designs', | |
59 | where='id = $id', | |
60 | vars=dict(id=id), | |
61 | title=title, | |
62 | description=description, | |
63 | category=category | |
64 | ) | |
65 | ||
66 | def get_photo_by_id(self, id): | |
67 | try: | |
68 | return self._db.where('photos', id=id)[0].filename | |
69 | except: | |
70 | return None | |
71 | ||
72 | def get_picture(self, id): | |
73 | try: | |
74 | return (self._db.where('photos', design_id=id, | |
75 | limit=1))[0].filename | |
76 | except: | |
77 | return None | |
78 | ||
79 | def get_all_photos(self, offset=0, pp=None): | |
80 | if not pp: | |
81 | pp = self.per_page | |
82 | ps = list(self._db.select('photos', | |
83 | offset=offset * pp, | |
84 | limit=pp, | |
85 | order='id DESC')) | |
86 | return ps | |
87 | ||
88 | def get_all_photos_for_design(self, id): | |
89 | return list(d.filename for d in self._db.where('photos', | |
90 | design_id=id)) | |
91 | ||
92 | def get_all(self, offset=0, pp=None): | |
93 | if not pp: | |
94 | pp = self.per_page | |
95 | ds = list(self._db.select('designs', | |
96 | offset=offset * self.per_page, | |
97 | limit=pp, | |
98 | order='id DESC')) | |
99 | return ((d.title, | |
100 | self.get_picture(d.id), | |
101 | d.description, | |
102 | self.get_category_name(d.category), | |
103 | d.id) for d in ds) | |
104 | ||
105 | def get_new_charts(self, pp): | |
106 | ds = list(self._db.select('designs', | |
107 | where='category = 8', | |
108 | limit=pp, | |
109 | order='id DESC')) | |
110 | return ((d.title, | |
111 | self.get_picture(d.id), | |
112 | d.description, | |
113 | self.get_category_name(d.category), | |
114 | d.id) for d in ds) | |
115 | ||
116 | def get_designs_by_category(self, cat, offset=0): | |
117 | cat = self.get_category_id(cat) | |
118 | ds = self._db.where('designs', | |
119 | category=cat, | |
120 | offset=offset * self.per_page, | |
121 | limit=self.per_page, | |
122 | order='id DESC') | |
123 | return ((d.title, | |
124 | self.get_picture(d.id), | |
125 | d.description, | |
126 | cat, | |
127 | d.id) for d in ds) | |
128 | ||
129 | def get_designs_by_category_and_tag(self, cat, tag, offset=0): | |
130 | cid = self.get_category_id(cat) | |
131 | ds = self._db.query( | |
132 | '''select * from designs, tags | |
133 | where tags.tag_name = $tag | |
134 | and category=$cat | |
135 | and designs.id = tags.design_id | |
136 | order by designs.id desc | |
137 | limit $per_page offset $offset''', | |
138 | vars=dict(tag=tag, | |
139 | cat=cid, | |
140 | offset=offset * self.per_page, | |
141 | per_page=self.per_page)) | |
142 | ||
143 | return ((d.title, | |
144 | self.get_picture(d.design_id), | |
145 | d.description, | |
146 | cat, | |
147 | d.design_id) for d in ds) | |
148 | ||
149 | def new_design(self): | |
150 | new_id = self._db.query( | |
151 | 'select max(id) as n from designs')[0].n + 1 | |
152 | self._db.insert( | |
153 | 'designs', | |
154 | id=new_id, | |
155 | title='New Design', | |
156 | description='', | |
157 | category=0) | |
158 | return new_id | |
159 | ||
160 | def delete_design(self, id): | |
161 | self._db.delete( | |
162 | 'designs', | |
163 | where='id = $id', | |
164 | vars=dict(id=id)) | |
165 | ||
166 | def add_file(self, file): | |
167 | new_id = (self._db.query('select max(id) as n from files')[0].n + 1) | |
168 | extn = file.filename.split()[-1] | |
169 | name = '{0:05}.{1}'.format(new_id, extn) | |
170 | path = '/' + os.path.join('srv', 'http', 'frd', | |
171 | 'static', 'files', name) | |
172 | self.file_num = self.get_max_file_num() + 1 | |
173 | with open(path, 'rb') as f: | |
174 | f.write(file.file) | |
175 | return new_id | |
176 | ||
177 | def all_files(self): | |
178 | return list(self._db.where('')) | |
179 | ||
180 | def add_photo(self, file, d_id): | |
181 | self.photo_num = self.get_max_photo_num() + 1 | |
182 | new_id = (self._db.query( | |
183 | 'select max(id) as n from photos')[0].n + 1) | |
184 | new_num = self.photo_num | |
185 | self.photo_num += 1 | |
186 | extension = file.filename[-3:] | |
187 | name = '{0:05}.{1}'.format(new_num, extension) | |
188 | thumb = '{0:05}_thumb.{1}'.format(new_num, extension) | |
189 | img = Image.open(file.file) | |
190 | img.thumbnail((400, 400), Image.ANTIALIAS) | |
191 | img.save('/' + os.path.join('srv', 'http', | |
192 | 'frd', 'static', 'photos', name)) | |
193 | img.thumbnail(THUMB_SIZE, Image.ANTIALIAS) | |
194 | img.save(os.path.join('static', 'photos', thumb)) | |
195 | self._db.insert( | |
196 | 'photos', | |
197 | id=new_id, | |
198 | filename=name, | |
199 | design_id=d_id) | |
200 | return new_id | |
201 | ||
202 | def delete_photo(self, photo_name): | |
203 | self._db.delete( | |
204 | 'photos', | |
205 | where='filename = $filename', | |
206 | vars=dict(filename=photo_name)) | |
207 | ||
208 | def max_photo_page_ranges(self): | |
209 | num_designs = self._db.query( | |
210 | 'select count(*) as n from photos')[0].n | |
211 | return (0, (num_designs // self.per_page)) | |
212 | ||
213 | def max_page_ranges(self): | |
214 | num_designs = self._db.query( | |
215 | 'select count(*) as n from designs')[0].n | |
216 | return (0, (num_designs // self.per_page)) | |
217 | ||
218 | def max_page_range_for_category(self, cat): | |
219 | cat_id = self.get_category_id(cat) | |
220 | num_designs = self._db.query( | |
221 | 'select count(*) as n from designs where category = $cat', | |
222 | vars=dict(cat=cat_id))[0].n | |
223 | return (0, 1 + (num_designs // self.per_page)) | |
224 | ||
225 | def get_all_tags(self): | |
226 | all_tags = [ | |
227 | t.tag_name for t in | |
228 | self._db.query( | |
229 | 'select distinct tag_name from tags')] | |
230 | return all_tags | |
231 | ||
232 | def get_designs_by_tag(self, tag, offset=0): | |
233 | ds = self._db.query( | |
234 | '''select * from designs, tags | |
235 | where tags.tag_name = $tag | |
236 | and designs.id = tags.design_id | |
237 | order by designs.id desc | |
238 | limit $per_page offset $offset''', | |
239 | vars=dict(tag=tag, | |
240 | offset=offset * self.per_page, | |
241 | per_page=self.per_page)) | |
242 | ||
243 | return ((d.title, | |
244 | self.get_picture(d.design_id), | |
245 | d.description, | |
246 | self.get_category_name(d.category), | |
247 | d.design_id) for d in ds) | |
248 | ||
249 | def get_tags_for_design(self, design_id): | |
250 | return [ | |
251 | t.tag_name for t in | |
252 | self._db.select( | |
253 | 'tags', | |
254 | what='tag_name', | |
255 | where='design_id = $d_id', | |
256 | vars=dict(d_id=design_id))] | |
257 | ||
258 | def process_tag_list(self, design_id, tag_string): | |
259 | new_tag_id = ( | |
260 | lambda: (self._db.query( | |
261 | 'select max(id) as n from tags')[0].n or 0) + 1) | |
262 | tag_list = tag_string.lower().split() | |
263 | self._db.delete( | |
264 | 'tags', where='design_id = $d_id', | |
265 | vars=dict(d_id=design_id)) | |
266 | for t in tag_list: | |
267 | self._db.insert( | |
268 | 'tags', | |
269 | id=new_tag_id(), | |
270 | tag_name=t, | |
271 | design_id=design_id) | |
272 | ||
273 | def max_page_range_for_tag(self, tag): | |
274 | num_designs = self._db.query( | |
275 | 'select count(*) as n from tags where tag_name = $t', | |
276 | vars=dict(t=tag))[0].n | |
277 | return (0, (num_designs // self.per_page)) | |
278 | ||
279 | def num_for_tag(self, tag): | |
280 | return self._db.query( | |
281 | 'select count(*) as n from tags where tag_name = $t', | |
282 | vars={'t': tag})[0].n | |
283 | ||
284 | def get_about_text(self): | |
285 | return self._db.where('pages', name='about')[0].text | |
286 | ||
287 | def set_about_text(self, text): | |
288 | self._db.update('pages', where='name = \'about\'', | |
289 | text=text) | |
290 | ||
291 | def get_page_list(self): | |
292 | return self._db.query('select * from pages') | |
293 | ||
294 | def add_page(self, name, title): | |
295 | self._db.insert('pages', name=name, title=title, text='') | |
296 | ||
297 | def get_page(self, name): | |
298 | pg = list(self._db.where('pages', name=name)) | |
299 | if pg: | |
300 | return pg[0] | |
301 | else: | |
302 | raise Exception('No page named {0}'.format(name)) | |
303 | ||
304 | def set_page(self, name, title, text): | |
305 | self._db.update('pages', | |
306 | where='name = $name', | |
307 | title=title, | |
308 | text=text, | |
309 | vars={'name': name}) | |
310 | ||
311 | def get_clacker(self, new_visitor=None): | |
312 | if new_visitor is not None: | |
313 | exists = self._db.query( | |
314 | 'select count(*) as n from visits where visitor = $v', | |
315 | vars={'v': new_visitor})[0].n | |
316 | else: | |
317 | exists = 1 | |
318 | total = self._db.query('select count(*) as n from visits')[0].n | |
319 | if exists == 0 and new_visitor: | |
320 | self._db.insert('visits', | |
321 | visitor=new_visitor) | |
322 | return total + 1 | |
323 | else: | |
324 | return total |