I know jinja2 is the default built-in template engine for Flask. My question is:
Is it possible to integreate Chameleon with Flask ?
If so, how can I do that ?
This is how I did. I wrap the response string in a method..
from chameleon import PageTemplate
def execute_page(template_str, page):
# Irrelevant
template = PageTemplate(template_str)
return template.render(page=page)
then consume the method and return the HTTPResponse. Hence, I completely skip render_template(template_file_name) approach.
My question is: Is it the proper (Pythonic, Flask) way to do?
Related
Currently I am using following way of views to determine if request is AJAX / XHR. Accordingly I am returning json data and rendering the template file in Flask. This working perfectly so for in my application.
from flask import request, render_template, jsonify
#cinemascope.route('/cinema')
def cinema():
if request.is_xhr:
cinema = Cinema.query.all()
return jsonify({'cinema_scope': cinema})
return render_template('cinema.html')
But I see this way little problematic as my application might many more #app.routes and every time I will have to repeat the code (if clause) so its loosing upon the maintainability aspect.
I am thinking about the two options here -
Option # 1 - Writing a simple function to wrap the if clause from above route.
Option # 2 - writing a decorator which will determine the request and accordingly it can be called from route - in a way decorator will handle the redundant part of code. I dont know too much about writing custom decorators so far though after reading little about it seems to be the best option.
Any further direction in adopting any of above approaches will be appreciated.
Basically I want to know the way - so I can avoid if clause part of code in each and every #app.route.
I refered - from http://justindonato.com/notebook/template-or-json-decorator-for-flask.html
This is what my decorator looks like
from functools import wraps
def xhr_request_check(template=None):
def decorator_request_parser(f):
#wraps(f)
def decorator_request(*args, **kwargs):
func_data = f(*args, **kwargs)
if request.is_xhr or not template:
return jsonify(func_data)
else:
return render_template(template, **func_data)
return decorator_request
return decorator_request_parser
In my view I have written
from flask import request, render_template, jsonify
#catalog.route('/cinema')
#xhr_request_check('cinema.html')
def cinema():
cinema = Cinema.query.all()
return {'cinema_scope': cinema}
Now I just needs to add #xhr_request_check('cinema.html') to each route and it is working perfectly.
Please let me know if any one would even better solution from code optimization perspective.
The way of doing this would be to create a decorator, which are essentially functions which take a function as an input and return a function as an output. They are not specific to flask, but python in general.
Here is an example for flask:
How to make a python decorator function in Flask with arguments (for authorization)
is_xhr is deprecated, but you could check on the Accepts header instead.
So I found this answer regarding setting session variables in a pyramid view file, and then later accessing it in a mako template. ( How to access session variable in Mako template and Pyramid? )
I wanted to know if you could do it the other way around. So instead of:
Pyramid view.py
def thisView(request):
session = request.session
session['selectedclientid'] = 'test' #selectedclient.id
session.save()
webpage.mako
${request.session['selectedclientid']}
Can I swap it so I can do this instead?
webpage.mako
${request.session['selectedclientid'] = '5'}
Pyramid view.py
def thisView(request):
someLogicOn(session['selectedclientid'])
So far I have been unsuccessful in making it work and I'm not sure if it's just due to a lack of understanding how to do it or if it's something that just can't be done. Any advice would be great!
In the typical rendering workflow, the view executes before the renderer. It's not clear how you are intending to correct for that. It's possible to do if you call render yourself within the view, I guess, so I'll show that.
webpage.mako:
<%
request.session['selectedClientId'] = '5'
%>
code:
def thisView(request):
response = render_to_response('webpage.mako', {}, request=request)
someLogicOn(request.session['selectedClientId'])
return response
This is logically a little backward though, so you might want to think twice about what you're doing.
I'm currently using the Pyramid web framework and I have it configured with Mako templates. I know that I can render a template as a string from within a view method (Pyramid - Is it possible to render my mako template as a string within my view callable?), however, I was wondering if it is possible to get the actual template object from within a view and not just a function to render the template.
Looking through the Pyramid source code, in mako_templating.py I see that the default TemplateLookup class is overridden with a lookup method for Pyramid. Is there anyway to access this lookup object primarily so I can use the get_template function that is part of it?
Thanks for any direction on this issue.
This level of introspection is not officially supported by Pyramid's rendering API. That being said, here's a way to do it. This is completely undocumented, unsupported, private, etc, etc. Meaning, don't come complaining when this stops working.
from pyramid.mako_templating import IMakoLookup
lookup = request.registry.queryUtility(IMakoLookup, name='mako.')
tmpl = lookup.get_template('myapp:templates/foo.mako')
opts = {} # rendering context
result = tmpl.render_unicode(**opts)
This works for me:
from pyramid.renderers import render
sRenderedStuff = render('path/to/template.mak',dContext)
An example use case would be something like this:
sEmailHtml = render("email/welcome_message_html.mak",dContext)
With the following line in your pyramid settings file:
mako.directories = your_app:templates
The template is fetched from your_app/templates/email/welcome_message.html. All inheritance and include tags work just as they would for templates rendered to a view response.
I am setting up an application using Flask based on a tutorial I found on the web. The problem I am having is so far it seems like I will have to write a lot of code for each view/route that I want to make so I am trying to devise a better system but I think I dug myself into a hole where I wrote too much code before really testing each step and since im not familiar with the framework im kindof lost.
so what I want is a base view class that will extract away some boilerplate stuff. Here is my attempt so far.
import jinja2
from jinja2 import Environment as Jinja2Environment
from webassets import Environment as AssetsEnvironment
from webassets.loaders import YAMLLoader
from webassets.ext.jinja2 import AssetsExtension
from flask import render_template
from app import app
class BaseView(object):
def __init__(self):
"init"
def get_jinja_env(self):
jinja_env = Jinja2Environment(loader=jinja2.FileSystemLoader('templates/'), extensions=[AssetsExtension])
return jinja_env
def get_asset_env(self):
asset_loader = webassets.YAMLLoader('conf/assets.yml')
asset_env = asset_loader.load_environment()
bundles = asset_loader.load_bundles()
[asset_env.register(name, bundle) for name, bundle in bundles.iteritems()]
return asset_env
def render_tmpl(self, tmpl_file, **context):
"Renders Jinja Template"
jinja_env = self.get_jinja_env
jinja_env.assets_environment = self.get_asset_env
template = jinja_env.get_template(tmpl_file)
return template.render(context)
Class that attempts to inherit from BaseView
from app.BaseView import BaseView
from app import app
class HelloView(BaseView):
#app.route('/')
def respond(self):
self.render_tmpl('hello.html')
My reasoning behind this is later I intend to extend some Jinja functionality such as caching and have some data be available for every view and template.
You will want to use the View classes included in flask already.
As they are very well explained there is not much I could explain here. Just read through the docs and I think you will see, what you will have to do (the flask docs are awesome.)
If you want to cache you also might want to have a look at Flask-Cache.
This doesn't quite answer your question entirely, but I thought it was worth mentioning anyway.
You can 'export' variables into the Jinja environment globals:
app.jinja_env.globals['data'] = ['One', 'Two', 'Three']
Once you've done this, all templates have access to the data variable and can operate on it as if it were passed in via kargs. You don't really need to go to the trouble of creating a whole new view class; you can just process it once and then make it available everywhere. It's handy for sidebars and login statuses and whatnot.
I'm getting an error:
GenerationException: url_for could not generate URL. Called with args: () {}
from this line of a mako template:
<p>Your url is ${h.url_for()}</p>
Over in my helpers.py, I do have:
from routes import url_for
Looking at the Routes-1.12.1-py2.6.egg/routes/util.py, I seem to go
wrong about line it calls _screenargs().
This is simple functionality from the Pylons book. What silly thing am I doing wrong? Was there a new url_current()? Where?
I didn't know url_for() (no arguments) was ever legal, but if it was and this is what you're referring to as "url_current", I believe the new approach is to use the url object, calling a method on it as url.current().