view README.html @ 60:682cd33e564c draft

Documentation (incomplete).
author David Barts <n5jrn@me.com>
date Sat, 08 Jun 2019 07:43:15 -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>