Start to switch to Mustache templates
    
    
      
        Getty Ritter
        5 years ago
      
    
    
  
  
  | 3 | 3 | import flask | 
| 4 | 4 | import web | 
| 5 | 5 | import markdown | 
| 6 | import pystache | |
| 6 | 7 | import storage | 
| 7 | 8 | import sys | 
| 8 | 9 | |
| 9 | 10 | web.template.ALLOWED_AST_NODES.append('Constant') | 
| 10 | 11 | |
| 12 | class Templates: | |
| 13 | renderer = pystache.Renderer() | |
| 14 | ||
| 15 | def load_template(name): | |
| 16 | with open(f"templates/{name}.mustache") as f: | |
| 17 | parsed = pystache.parse(f.read()) | |
| 18 | return lambda stuff: Templates.renderer.render(parsed, stuff) | |
| 19 | ||
| 20 | main = load_template('main') | |
| 21 | design_page = load_template('design_page') | |
| 11 | 22 | |
| 12 | 23 | def slugify(string): | 
| 13 | 24 | def process(char): | 
| 30 | 41 | |
| 31 | 42 | |
| 32 | 43 | db = storage.DB() | 
| 33 | render = web.template.render(' | |
| 44 | render = web.template.render('old_templates/', | |
| 34 | 45 | globals=dict(markdown=markdown.markdown, | 
| 35 | 46 | slugify=slugify, | 
| 36 | 47 | all_categories=db.all_categories, | 
| 49 | 60 | |
| 50 | 61 | def main(func): | 
| 51 | 62 | def new_func(*args, **kwargs): | 
| 52 | web.header('Content-Type', 'application/xhtml+xml') | |
| 53 | return render.main(*func(*args, **kwargs)) | |
| 63 | title, content = func(*args, **kwargs) | |
| 64 | return Templates.main({'title': title, 'content': content}) | |
| 54 | 65 | new_func.__name__ = func.__name__ | 
| 55 | 66 | return new_func | 
| 56 | 67 | |
| 60 | 71 | def GET(self): | 
| 61 | 72 | try: | 
| 62 | 73 | pg = db.get_page('main') | 
| 63 | return ('Frony Ritter Designs', | |
| 64 | markdown.markdown(pg.text)) | |
| 74 | return 'Frony Ritter Designs', markdown.markdown(pg.text) | |
| 65 | 75 | except: | 
| 66 | 76 | raise web.notfound() | 
| 67 | 77 | |
| 68 | 78 | |
| 69 | 79 | class contact: | 
| 70 | ||
| 71 | 80 | @main | 
| 72 | 81 | def GET(self): | 
| 73 | 82 | return 'Contact Information', 'Send me an email at my email address.' | 
| 74 | 83 | |
| 75 | 84 | |
| 76 | 85 | class design: | 
| 77 | ||
| 78 | 86 | @main | 
| 79 | 87 | 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() | |
| 88 | id = int(id) | |
| 89 | design = db.get_design(id) | |
| 90 | print(design) | |
| 91 | return 'Designs', Templates.design_page(design) | |
| 86 | 92 | |
| 87 | 93 | def POST(self, id, slug='electric-boogaloo'): | 
| 88 | 94 | try: | 
| 437 | 443 | |
| 438 | 444 | ) | 
| 439 | 445 | |
| 440 |  | |
| 446 | app = web.application(urls, globals()) | |
| 441 | 447 | # # web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr) | 
| 442 | 448 | |
| 443 | # if __name__ == '__main__': | |
| 444 | # app.run() | |
| 449 | if __name__ == '__main__': | |
| 450 | app.run() | |
| 1 | import markdown | |
| 1 | 2 | import os | 
| 2 | 3 | import web | 
| 3 | 4 | from PIL import Image | 
| 4 | 5 | |
| 6 | import typing | |
| 7 | ||
| 8 | class Image(typing.NamedTuple): | |
| 9 | image: str | |
| 10 | ||
| 11 | class PageContent: | |
| 12 | def __init__(self, source): | |
| 13 | self.source = source | |
| 14 | self.rendered = markdown.markdown(source) | |
| 15 | ||
| 16 | class Design(typing.NamedTuple): | |
| 17 | title: str | |
| 18 | images: typing.List[Image] | |
| 19 | description: PageContent | |
| 20 | category: str | |
| 21 | id: int | |
| 22 | ||
| 5 | 23 | THUMB_SIZE = (100, 100) | 
| 6 | ||
| 7 | 24 | |
| 8 | 25 | class DB: | 
| 9 | 26 | |
| 46 | 63 | return None | 
| 47 | 64 | else: | 
| 48 | 65 | 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 |  | |
| 66 | return Design(title=d.title, | |
| 67 | images=self.get_all_photos_for_design(d.id), | |
| 68 | description=PageContent(d.description), | |
| 69 | category=self.get_category_name(d.category), | |
| 70 | id=d.id) | |
| 54 | 71 | |
| 55 | 72 | def put_design(self, id, title, description, category): | 
| 56 | 73 | description = description.replace('\r\n', '\n') | 
| 79 | 96 | def get_all_photos(self, offset=0, pp=None): | 
| 80 | 97 | if not pp: | 
| 81 | 98 | pp = self.per_page | 
| 82 | ps = list(self._db.select('photos', | |
| 83 | offset=offset * pp, | |
| 84 | limit=pp, | |
| 85 | order='id DESC')) | |
| 86 | return | |
| 99 | return [ | |
| 100 | Image(l) for l | |
| 101 | in self._db.select('photos', | |
| 102 | offset=offset * pp, | |
| 103 | limit=pp, | |
| 104 | order='id DESC') | |
| 105 | ] | |
| 87 | 106 | |
| 88 | 107 | def get_all_photos_for_design(self, id): | 
| 89 | return list(d.filename for d in self._db.where('photos', | |
| 90 | design_id=id)) | |
| 108 | return list(Image(d.filename) for d in self._db.where('photos', | |
| 109 | design_id=id)) | |
| 91 | 110 | |
| 92 | 111 | def get_all(self, offset=0, pp=None): | 
| 93 | 112 | if not pp: | 
| 1 | <div id="photo"> | |
| 2 | <img src="/static/frony.png" /> | |
| 3 | </div> | |
| 4 | <div id="about-block"> | |
| 5 | {{{text}}} | |
| 6 | </div> | 
| 1 | <div class="design"> | |
| 2 | <div class="title">{{title}}</div> | |
| 3 | <div class="images"> | |
| 4 | {{#images}} | |
| 5 | <img src="/static/photos/{{image}}" /> | |
| 6 | {{/images}} | |
| 7 | </div> | |
| 8 | <div class="description">{{#description}}{{{ rendered }}}{{/description}}</div> | |
| 9 | <div class="related"> | |
| 10 | <a href="/category/{{category}}/">{{category}}</a> | |
| 11 | </div> | |
| 12 | </div> | 
| 1 | <!DOCTYPE html> | |
| 2 | <html> | |
| 3 | <head> | |
| 4 | <script> | |
| 5 | /* Google Analytics malarkey */ | |
| 6 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ | |
| 7 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), | |
| 8 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) | |
| 9 | })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); | |
| 10 | ||
| 11 | ga('create', 'UA-43663896-1', 'fronyritterdesigns.com'); | |
| 12 | ga('send', 'pageview'); | |
| 13 | </script> | |
| 14 | <meta http-equiv="Content-Type" contents="application/xhtml+xml; charset=utf-8;" /> | |
| 15 | <meta name="description" content="Cross-Stitch Patterns and Other Crafts from Frony Ritter Designs" /> | |
| 16 | <link rel="stylesheet" type="text/css" href="/static/standard.css" /> | |
| 17 | <title>Frony Ritter Designs – $title</title> | |
| 18 | </head> | |
| 19 | <body> | |
| 20 | <div id="page"> | |
| 21 | <div id="header"> | |
| 22 | <p> | |
| 23 | <a href="/"><img src="/static/frd_logo.png"/></a> | |
| 24 | </p> | |
| 25 | <p>{{ title }}</p> | |
| 26 | </div> | |
| 27 | <div id="sidebyside"> | |
| 28 | <div class="topnav"> | |
| 29 | <ul> | |
| 30 | <a href="/"><li class="topitem">Home</li></a> | |
| 31 | <a href="http://blog.fronyritterdesigns.com/"><li class="topitem">Blog</li></a> | |
| 32 | ||
| 33 | <a href="/category/charts"><li class="topitem">Cross-Stitch Charts</li></a> | |
| 34 | ||
| 35 | <ul> | |
| 36 | <a href="/category/charts/tag/celtic"><li class="topitem">Celtic Series</li></a> | |
| 37 | <a href="/category/charts/tag/spring"><li class="topitem">Spring Series</li></a> | |
| 38 | <a href="/category/charts/tag/summer"><li class="topitem">Summer Series</li></a> | |
| 39 | <a href="/category/charts/tag/fall"><li class="topitem">Fall Series</li></a> | |
| 40 | <a href="/category/charts/tag/winter"><li class="topitem">Winter Series</li></a> | |
| 41 | <a href="/category/charts/tag/flags"><li class="topitem">Flags</li></a> | |
| 42 | <a href="/category/charts/tag/booklets"><li class="topitem">Booklets</li></a> | |
| 43 | <a href="/category/charts/tag/kits"><li class="topitem">Kits</li></a> | |
| 44 | <a href="/category/charts/tag/minis"><li class="topitem">Minis</li></a> | |
| 45 | <a href="/category/charts/tag/large"><li class="topitem">Large Charts</li></a> | |
| 46 | <a href="/category/charts/tag/recipe"><li class="topitem">Small-Batch Recipe</li></a> | |
| 47 | </ul> | |
| 48 | ||
| 49 | <a href="/category/papercrafting" ><li class="topitem" >Papercraft Ideas</li></a> | |
| 50 | <ul> | |
| 51 | <a href="/tag/cards"><li class="topitem">Cards</li></a> | |
| 52 | <a href="/tag/tags"><li class="topitem">Tags</li></a> | |
| 53 | <a href="/tag/placecards"><li class="topitem">Placecards</li></a> | |
| 54 | <a href="/tag/boxes"><li class="topitem">Boxes</li></a> | |
| 55 | <a href="/tag/bags"><li class="topitem">Bags</li></a> | |
| 56 | </ul> | |
| 57 | ||
| 58 | <a href="/category/beading" ><li class="topitem" >Beading</li></a> | |
| 59 | ||
| 60 | <a href="/category/paintings"><li class="topitem">Painting</li></a> | |
| 61 | ||
| 62 | <a href="/tag/free"><li class="topitem">Free Patterns</li></a> | |
| 63 | <ul> | |
| 64 | <a href="/category/charts/tag/free"><li class="topitem">Cross-Stitch</li></a> | |
| 65 | <a href="/category/paintings/tag/free"><li class="topitem">Painting</li></a> | |
| 66 | <a href="/category/beading/tag/free"><li class="topitem">Beading</li></a> | |
| 67 | </ul> | |
| 68 | ||
| 69 | <a href="/category/gallery"><li class="topitem">Stitchers' Gallery</li></a> | |
| 70 | ||
| 71 | <a href="/wheretobuy"><li class="topitem">Where To Buy</li></a> | |
| 72 | <a href="/retailinfo"><li class="topitem">Info For Retailers</li></a> | |
| 73 | <a href="/corrections/"><li class="topitem">Corrections</li></a> | |
| 74 | <a href="/about/"><li class="topitem">About</li></a> | |
| 75 | ||
| 76 | </ul> | |
| 77 | </div> | |
| 78 | <div id="contents"> | |
| 79 | {{{ content }}} | |
| 80 | </div> | |
| 81 | <div style="clear: both;"></div> | |
| 82 | </div> | |
| 83 | <div id="footer"> | |
| 84 | ©2020 | <a href="/about/">About</a> | <a href="/contact/">Contact</a> | |
| 85 | </div> | |
| 86 | </div> | |
| 87 | </body> | |
| 88 | </html> |