Mercurial > cgi-bin > hgweb.cgi > tincan
view README.html @ 46:997d0c8c174f draft
Default for the launch callable should be not to log.
author | David Barts <n5jrn@me.com> |
---|---|
date | Thu, 30 May 2019 16:36:43 -0700 |
parents | e726fafcffac |
children |
line wrap: on
line source
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Introducing TinCan</title> <style type="text/css"> .kbd { font-family: monospace; } </style> </head> <body> <h1>Introducing TinCan, a “Code-Behind” MVC Framework for Bottle</h1> <h2>Introduction</h2> <p>TinCan is a Python 3 code-behind web framework implemented in the Bottle microframework. As with Bottle, all the code is in one module, and there is no direct dependency on anything that is not part of the standard Python library (except of course for Bottle itself).</p> <p>The default templating engine for TinCan is <a href="https://chameleon.readthedocs.io/en/latest/">Chameleon</a>. TinCan adds Chameleon as a fully-supported templating engine for Bottle. Any template engine supported by Bottle can be used to render TinCan Pages.</p> <h2>Why Do This?</h2> <p>In short, there is too much repeating oneself in most all Python web frameworks (and this includes Bottle). One is always saying “this is controller <span class="kbd">foo</span>, whose view is in the template <span class="kbd">foo.pt</span>, at route <span class="kbd">/foo</span>.”</p> <p>That’s a lot more busywork than just writing <span class="kbd">foo.php</span> or <span class="kbd">foo.cgi</span>, so many simple webapps end up being implemented via the latter means. That’s unfortunate, as CGI isn’t very resource-efficient, and there’s much nicer languages to code in than PHP (such as Python :-) ). Worst of all, you now have logic and presentation all scrambled together, never a good idea.</p> <p>What if, instead, you could write <span class="kbd">foo.pspx</span> and <span class="kbd">foo.py</span>, and a framework would automatically create the <span class="kbd">/foo.pspx</span> route for you, much like ASP.NET or JSP would for a <span class="kbd">.aspx</span> or <span class="kbd">.jsp</span> file? The matching code-behind in the <span class="kbd">.py</span> file would be easily detected (same name, different extension) and automatically associated with the template, of course. You could focus on writing pages instead of repeating yourself saying the obvious over and over again. </p> <p>This is what TinCan lets you do.</p> <h2>Hang On, Code-Behind Isn’t MVC!</h2> <p>Why <em>isn’t</em> it? The model, as always, is the data and containing core business logic. The template file defines the view presented to the user, and the code-behind is the intermediary between the two. A controller by any other name…</p> <h2>How Can There Be Multiple Views for One Controller?</h2> <p>Easily. Take a look at the <code>#python</code> header directive. </p> <h2>Multiple Controllers for One View?</h2> <p>Personally, I don’t think this is the best of ideas. Just because two controllers might be able to share a view <em>now</em> does not mean they will continue to in the future. Then you change one (controller, view) pair and another controller someplace else breaks!</p> <p>However, if you insist, check out the <code>#template</code> and <code>#hidden</code> header directives. </p> <h2>But This Causes Less SEO-Friendly Routes!</h2> <p>First, this is not always important. Sometimes, all you want to do is get a small, simple, special-purpose, site up and running with a minimum of busywork. Why should you be forced to do more work just because that extra work benefits someone <em>else</em>?</p> <p>Second, when it is, you can always use <code>RewriteRule</code> (Apache) <code>rewrite</code> (nginx), or the equivalent in your favorite Web server, and code your templates to use the SEO-friendly version of your URL’s. With TinCan sitting behind a good, production-grade web server, you get the best of both worlds: fast, simple deployment when you want it, and SEO-friendly URL’s when you want it. </p> <h2>But What about Routing Things Based on Both Path and Method?</h2> <p>That’s easy enough to do, as TinCan is implemented on top of Bottle. You can add your Bottle routes, using the <code>@route</code> decorator on your controller methods, same as always. Just stick them in the same start-up script you use to launch your TinCan files.</p> <p>If for some reason you don’t want to mess with manually creating routes and associating them with controllers in Bottle (even in cases like this where it arguably makes sense), and want to do <em>everything</em> the TinCan way, you can create a set of hidden (using the <code>#hidden</code> directive) pages and a main dummy page whose code-behind forwards (<code>page.request.app.forward</code>) to the appropriate hidden page depending on request method. </p> <h2>What about Launching Multiple TinCan Webapps?</h2> <p>It works just as well (and just as poorly) as launching multiple Bottle webapps. Note that the big limitation here is Python’s module subsystem; there is only one. Thus, all webapps share the same module path. There is no way to have one webapp using an older version of a given module served by the same server as another using a newer version, save renaming one of the modules. This is a Python issue, not a Bottle issue or a TinCan issue.</p> <p>Note that TinCan bypasses the Python module cache and manages its own importing of code-behind files, so there is no problem if you have multiple webapps using the same relative URL paths. TinCan will keep all those code-behind files straight; it will not confuse one webapp’s <span class="kbd">/index.py</span> with another’s.</p> <h2>What about Bottle Plugins?</h2> <p>I am working on adding support for these.</p> </body> </html>