i am unable to set the environment variables from jinja2
<body>
<h1>hi {{session['user']}}<h1>
{{session['user']='Mad'}}
</body>
<body>
<h1>
hi {{session['user']}}
<h1>
{{session['user']='Mad'}}
</body>
I have already declared session['user'] in python code in flask but i am unable to set it in jinja2 that is the with the following html code
As described above, you need to define your variables within your backend and pass them to your template. For example:
run.py
from flask import Flask, render_template, session
app = Flask(__name__)
app.secret_key = 'your-secret-key'
#app.route("/<user>")
def user_page(user):
session['user'] = user
return render_template("user_page.html", user=session['user'])
if __name__ == '__main__':
app.run()
user_page.html
<body>
<h1>hi {{ user }}<h1>
</body>
Doing this doesn't make sense. Jinja2 is an HTML templating system, used server-side to render a page; it is not meant to update global variable. The logic should be implemented in your python code, before calling the template. The repsonsibility is thus:
python method: does server-side logic and prepare the variables needed by Jinja2 to render the response page;
jinja2 template: simply render the page using the variables prepared in 1.
Hence, editing session content should never appear in Jinja2 (it wouldn't make any sense anyway), so move your line to the python code. If you need two different names, simply save the old session value to a new variable that you pass to jinja2 alongside the updated session.
Related
I am having bigger Flask app and I want to utilize blueprints for cleaner design. Current code looks like this:
main_app.py:
app = Flask(__name__)
# ... some config passing to app ...
app.register_blueprint(user_management, url_prefix="/user")
and user_management.py
user_management = Blueprint("user_management", __name__, static_folder="static", template_folder="templates")
#user_management.route("/register")
def register_user():
register_form = UserRegistrationForm()
return render_template('user_registration.html', title="...", form=register_form)
The problem I am currently trying to solve is that I have base Jinja template layout.html, which is used in blueprints Jinja template user_registration.html like this:
{# user_registration.html #}
{% extends "layout.html" %}
But the layout.html is using some global variables of Flask app via flask.g and also config of app. When I try to load page with user_registration.html template (/user/register), it prints out error:
jinja2.exceptions.UndefinedError: 'ac' is undefined
The ac variable is defined inside of another route in main_app.py like g.ac = "...". I managed to solve this by adding parameter to template rendering inside of register_user() method as render_template(..., ac=g.ac), but it is not really elegant way of solving this issue, because there are also some other variables like config of app (also used in layout.html), which brings another error:
jinja2.exceptions.UndefinedError: 'flask.config.Config object' has no attribute 'login'
There must be some better way of handling this issue and passing base app attributes and global variables from flask.g inside of blueprint Jinja template. I've read multiple threads but cannot find similar issue.
I am familiar with flask, and trying hands on bottle module. I wanted to have a single base.tpl file which can have an editable body and the other tpl files could extend this base file and edit in its body to change the content. Like in flask, using jinja, we could use {% block bodyContent %}{% endblock %} and insert the html body content later when needed. How can we achieve the same with bottle module?
Bottle comes with jinja2 support, out of the box. Here's a toy example, just to illustrate. Note that you may prefer to use Bottle's jinja2_view rather than return a template directly.
from bottle import jinja2_template
app = Bottle()
home_template = '''
{{greeting}} - Thanks for stopping by.
'''
app.route('/')
def home():
return jinja2_template(home_template, greeting='Hello!')
You can find examples of more advanced usage here.
Actually bottle comes with this solution built into it's own template engine.
https://bottlepy.org/docs/dev/stpl.html#template-functions
include(sub_template, **variables)
Render a sub-template with the specified variables and insert the resulting text into the current template. The function returns a dictionary containing the local variables passed to or defined within the sub-template:
% include('header.tpl', title='Page Title')
Page Content
% include('footer.tpl')
rebase(name, **variables)
Mark the current template to be later included into a different template. After the current template is rendered, its resulting text is stored in a variable named base and passed to the base-template, which is then rendered. This can be used to wrap a template with surrounding text, or simulate the inheritance feature found in other template engines:
% rebase('base.tpl', title='Page Title')
<p>Page Content ...</p>
This can be combined with the following base.tpl:
<html>
<head>
<title>{{title or 'No title'}}</title>
</head>
<body>
{{!base}}
</body>
</html>
Be forewarned of a triple-newbie threat - new to python, new to python anywhere, new to flask.
[pythonanywhere-root]/mysite/test01.py
# A very simple Flask Hello World app for you to get started with...
from flask import Flask
from flask import render_template # for templating
#from flask import request # for handling requests eg form post, etc
app = Flask(__name__)
app.debug = True #bshark: turn on debugging, hopefully?
#app.route('/')
#def hello_world():
# return 'Hello from Flask! wheee!!'
def buildOrg():
orgname = 'ACME Inc'
return render_template('index.html', orgname)
And then in [pythonanywhere-root]/templates/index.html
<!doctype html>
<head><title>Test01 App</title></head>
<body>
{% if orgname %}
<h1>Welcome to {{ orgname }} Projects!</h1>
{% else %}
<p>Aw, the orgname wasn't passed in successfully :-(</p>
{% endif %}
</body>
</html>
When I hit up the site, I get 'Unhandled Exception' :-(
How do I get the debugger to at least spit out where I should start looking for the problem?
The problem is render_template only expects one positional argument, and rest of the arguments are passed as keyword only arguments.So, you need to change your code to:
def buildOrg():
orgname = 'ACME Inc'
return render_template('index.html', name=orgname)
For the first part, you can find the error logs under the Web tab on pythonanywhere.com.
You need to also pass your name of orgname variable that is used in your template to render_template.
flask.render_template:
flask.render_template(template_name_or_list, **context)
Renders a template from the template folder with the given context.
Parameters:
template_name_or_list – the name of the template to be rendered,
or an iterable with template names the first one existing will be rendered
context – the variables that should be available in the context of the template.
So, change this line:
return render_template('index.html', orgname)
To:
return render_template('index.html', orgname=orgname)
How can I create a widget on the site, such as login forms, dynamic menu (items taken from the database), site statistics?
I know that you can render a template that will extend out of a base template. And in the base template you can create these widgets.
But I do not know how to move the logic from the base template to my code. For example, the selection data for the block. Such actions certainly can be done in the template, but it would be a poor method in my opinion.
Sorry for my bad English. If you can not understand, I'll try to rephrase.
You would use a python library called WTForms. It helps you write code for creating forms and other widgets backed by database which you can render using jinja2 templates.
class YourForm(Form):
your_field1 = TextField()
....
your_fieldn = SubmitField()
#app.route('/')
def view():
form=YourForm()
return render_template('your.html', form=form)
In your.html
<form >
{{ form.your_field1 }}
....
{{ form.your_fieldn }}
</form>
Check out this flask pattern for form validation and rendering to know more about it.
Edit: To create global variables available to all templates,there are two ways:
You can use global dict of jinja environment.
This is the code:
app.jinja_env.globals.update({'variable':1})
You can use ContextProcessor. Code:
#app.context_processor
def inject_variable():
return dict(variable=1)
Now you can access variable in any template of your app.
I have an HTML file that has a web page design with a single form, for a user to enter his name. I want to create an six entry array for every submission (to later be filled with information on another page)
Is Django the proper utility to use for this? I would like to have the html design file and the python back end processing as separate files. If so, can anyone point me towards a good place to read about integrating HTML and underlying python codes that process HTML submission forms?
Django may be overkill for this. If all you want is a way to link a form to some backend Python code, a micro framework like Flask might be a better choice.
Here is how you do a simple form with Flask:
Create a directory project and inside it, a directory templates
Your template is simple:
{% if name %}
Hello {{ name }}
{% endif %}
<form method="POST">
<input type="text" name="name" value="Enter your name">
<input type="submit">
</form>
Save that as index.html in the templates subdirectory.
Create a file called go.py in the project directory, and in it copy and paste this:
from flask import Flask
from flask import render_template
from flask import request
app = Flask(__name__)
#app.route('/',methods=['POST','GET'])
def process_form():
if request.method == 'POST':
form_input = request.form['name']
return render_template('index.html',name=form_input)
else:
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
Finally from the project directory, type:
python go.py
Open your browser and go to http://localhost:5000/
You can create html form in Django, though you may have to convert the form to a template.
In case this you first time to use django, you may go though the official Django book
Django provides a template system (in which the presentation files are separate from the business logic and the entire system is highly decoupled). The template language is simple (but very powerful) text substitution on top of an existing text file. You can use the Django templates in HTML (full or partial), text, XML, JSON, or nearly any other text-based format.
Django also allows you to hook into another template system, but I don't know a lot about how that works.
Look at the Django template documentation for more information.