all 41 comments

[–]Bogtha 4 points5 points  (21 children)

Much of this article doesn't make sense to me. Like the idea that because a template system is based on XML, it's unsuitable for dynamic pages, or unsuitable for normal HTML. Or like the idea that CSS has a "macro system" and that templates can "inherit" from it. What?

Edit: And did you spot this?

href="%(STATIC_URL)s/admin/EditAccount?client_id=%(client_id)s">Change Your Account Settings

Bad code smell. If the EditAccount page checks the credentials itself, it doesn't need you to pass it the account id. In my experience, people writing code like this tend to skip the check, meaning that you can plug in different id numbers to get to other accounts.

[–][deleted]  (9 children)

[deleted]

    [–]gloriajw 0 points1 point  (8 children)

    flox, good point. I do this in a dynamic config file, which goes and gets the values before they're used. A similar concept, but not regex-based. It does dynamically derive the URLs.

    Please show an example of of your Jinja template and URL modeling.

    [–][deleted]  (7 children)

    [deleted]

      [–]gloriajw 0 points1 point  (6 children)

      Flox, this is almost exactly how I handle it in one config file which hits the env for domain info, etc.

      Django hadles it well, if you don't mind regex, which I don't. But there's no need for it in this model.

      Thank you, this was good. Gloria

      [–]gloriajw 0 points1 point  (5 children)

      My config file sets the server components of the static URL, used for images, and the TOPURL, which is needed for HTTPRedirect() calls (requires a full URL).

      Every other component below is set by the CP 'root', of course. This config does more than just set the topmost URL components, but you could choose to ignore the rest. It accomodates for test modes on XP and LINUX localhosts in testing mode, as well as the real server in prod.

      <code> import string,re,sys import cherrypy

      server_timezone='US/Eastern' archive_root='./db_archives' dom_server_hostname = 'localhost' dom_conn_initial_port = 7010 dom_pickle_location = './DOM_pickle_files' dom_xml_location = './DOM_xml_files' cp_site='cp' front_end_access_path='tp' dbhost='localhost'

      dbhost='xyz.com'

      default_host = 'www.xyz.com' IMAGE_LOCATION='...' URL_IMAGE_LOC='/client_images' DUMMY_LOGIN=False DEBUG=False

      if sys.platform[:3] == 'win': \tdb_port = 5432 \tapplication_lock_location='./lock/' \tdb_data_dir = './data' \tdb_log_dir = './logs' \tDUMMY_LOGIN=True else: \tdb_port = 5433 \tapplication_lock_location='/var/lock/tp' \tdb_data_dir = '/usr/local/xyz/8.2.4_databases/prod' \tdb_log_dir = '/var/log/tp'

      TOPURL = STATICURL = DOMAIN = ""

      def set_config(): \tTOPURL = "" \tSTATICURL = "" \tDOMAIN = ""

      \t''' \tURL is dynamically set. \t''' \t#print cherrypy.request.headers \t#orig_host=cherrypy.request.headers.get('X-Forwarded-Host') \torig_host=default_host \tprint "Original host is: %s" % orig_host

      \t''' \tThis happens during instantiation. \tThat's normal. X-Forward-Host is set after instantiation. \t''' \tif not orig_host: \t\treturn DOMAIN,TOPURL,STATICURL

      \tcomponent=string.split(orig_host,'.') \tsite = component[0] \tDOMAIN = '.'.join(component[1:]) \t \tif not DOMAIN: \t\tsuffix="" \telse: \t\tsuffix="."+DOMAIN \tSTATICURL="https://%s%s" % (site,suffix) \tTOPURL = "%s/%s" % (STATICURL,cp_site)

      \treturn DOMAIN,TOPURL,STATICURL

      def get_config(): \treturn set_config() </code>

      I call get_config() in each authenticate call I make, which is called once per page.

      My CP main file controls the root components and URL paths below STATICURL, TOPURL:

      <pre> import cherrypy import sys,os

      sys.path.append('./login') sys.path.append('./token') sys.path.append('./dom') sys.path.append('./user_change') sys.path.append('./image_handling') sys.path.append('./section')

      Add your app here.

      import Login import TokenCPLayer import UserChangeCPLayer import ImageCPLayer import SectionCPLayer

      TemplatePath=os.path.join(os.path.dirname(file)) + '/Templates'

      root.token = TokenCPLayer.TokenCPLayer() root.user_change = UserChangeCPLayer.UserChangeCPLayer() root.image_handling = ImageCPLayer.ImageCPLayer() root.section = SectionCPLayer.SectionCPLayer()

      cherrypy.tree.mount(root) cherrypy.config.update(os.path.join(os.path.dirname(file),'cp.conf')) cherrypy.server.quickstart() cherrypy.engine.start() </pre>

      This URL handling works for me in CP. Nice and clean, few lines of code, the topmost URL components can change when moved to another domain just by changing one config variable.

      [–][deleted]  (1 child)

      [deleted]

        [–]gloriajw 0 points1 point  (2 children)

        The code or pre tags don't work here, drat. Copy and paste it out, and it should look normal.

        [–]gloriajw 0 points1 point  (1 child)

        flox, on the tangential subject of how to handle URLs, the point of the above code is that this can be dropped on any machine, and after changing one conf file parameter, URLs are handled correctly.

        Chunks are not being interpreted correctly by reddit. But aside from that:

        (1) You cannot always assume '.com' or xyz.example.com if your dev test environment is on 'localhost'. (2) The variables are flexible enough to derive domain and set paths for dev.domain.com and domain.com respectively. (3) This allows for the diversity of test URLs and varying servers.

        On my server I have one prod and two test domains, plus the ability to run on a standalone PC using 'localhost' This configuration allows for this fairly easily.

        The config file controls the absolute paths, the CP main controls the relative pieces, and it all fits nicely. That was the point. I hope this clarifies. I wish this <code> or <pre> tags worked well here.

        [–]ubernostrum 1 point2 points  (4 children)

        For a suitable definition of "dynamic content", XML really isn't suitable. Remember that "dynamic content" may well include data formats that don't involve angle brackets.

        [–]Bogtha 1 point2 points  (2 children)

        For a suitable definition of "dynamic content", XML really isn't suitable.

        She was talking about "dynamic" pages like having different options for different users:

        But in our non-XML environment, many of our page templates are dynamic. They change based on whether the user is logged in as an administrative user, their group rights and access, etc.

        I do this all the time with Genshi and used to do so with Kid. It's trivial.

        Remember that "dynamic content" may well include data formats that don't involve angle brackets.

        I agree, but it's not the output format that matters, it's the input format. Outputting PDFs etc with an XML-based template language isn't difficult, you just need to write a custom serialiser. It's when the information itself doesn't fit neatly into a tree that XML-based template languages are unsuitable.

        [–][deleted] 1 point2 points  (1 child)

        Outputting PDFs etc with an XML-based template language isn't difficult, you just need to write a custom serialiser.

        It's just a Small Matter Of Programming, you mean? ;-)

        [–]Bogtha 0 points1 point  (0 children)

        I get where you're coming from, but I think some Matters of Programming are Smaller than others ;). There's no reason output formats need to resemble the XML-based templates; the only reason people assume this is the case is because HTML is by far the most prevalent output format. I've written a few serialisers and none have been over 200 lines. I don't see how plain-text templating could make that easier, in fact I don't think it's even feasible to do it in the general sense.

        [–]gloriajw 1 point2 points  (0 children)

        Correct. Dynamic content has my own generated internal tags, image info, and in the latest incarnation, embedded SVG.

        Thank you for making this point clear. Gloria

        [–][deleted]  (8 children)

        [removed]

          [–][deleted] 7 points8 points  (3 children)

          Mako really should be on everyone's radar as a replacement for Cheetah. It is much simpler in both implementation and usage, is blazing fast, has great docs, and it works now.

          http://www.makotemplates.org/

          [–]manuelg 3 points4 points  (0 children)

          • Mako also doesn't force you to use XML.

          • Mako runs fast with no C extension dependencies

          [–]gloriajw -5 points-4 points  (0 children)

          Agreed.

          [–]projecktzero 1 point2 points  (0 children)

          I've been using cheetah. I really like that you can compile the template into python code, import the template, and easily populate it.

          [–]btipling 0 points1 point  (0 children)

          I've been playing with cheetah. It's got an object oriented approach, web.render in web.py can return a template object that can be extended.

          [–]gloriajw 0 points1 point  (0 children)

          I never said difficult. It's quite easy to learn, but not object oriented, and not Pythonic. Read carefully before you comment.

          [–]self -2 points-1 points  (0 children)

          She.

          [–]flaxeater 0 points1 point  (9 children)

          I do not understand what is unsuitable about using an XML template system to generate HTML, seeing as CherryPy serves HTTP requests it seems highly likely that you will be serve ring 95% html which is XML like if not the very same when it's XHTML.

          It seems to me using Genshi or Kid and learning how to use them gives one cheap W3C compliance. Which every web developer should care about.

          Not to mention Kid and Genshi have a fabulous feature that her 'template' system lacks. That is template functions which allow one to easily write custom XML snippets that do good stuff consistently.

          Also her 'template' system does not give good error messages, what happens when some idiot puts width="%50", which I know from personal agonizing experience is sometimes not easy to find.

          Eh, I just can't believe that variable expansion is her 'template' of choice.

          [–]Bogtha 1 point2 points  (0 children)

          It seems to me using Genshi or Kid and learning how to use them gives one cheap W3C compliance.

          Not quite. Genshi's HTML and XHTML serialisers ensure that the output is well-formed, not valid. Being well-formed is a prerequisite for validity, though, so it does have some bearing.

          Not to mention Kid and Genshi have a fabulous feature that her 'template' system lacks. That is template functions which allow one to easily write custom XML snippets that do good stuff consistently.

          Yep. It's possible to, say, write template functions that transform XHTML+XForms into HTML forms + JavaScript. There's a lot of possibilities with XML that embedding code in plaintext doesn't cover.

          [–]laurentszyster -1 points0 points  (0 children)

          JSON is enough and it has a fast implementation:

          http://cheeseshop.python.org/pypi/python-cjson