I am using Tornado and I have the following code:
class UserHandler(RequestHandler):
def get(self):
user = self.get_argument("username")
self.set_cookie("user", user)
out = tableize(user)
self.render('chat.html',table=out)
now, chatter.html looks like this:
<iframe src="{{ static_url('mess.html') }}" width="500" height="400"></iframe>
where mess.html is:
<div id="chat">
{% for x in table %}
<b> x </b>
{% end %}
</div>
My question is, how do I pass the 'table' argument to mess.html? I can't figure out how to make it display properly.
Have a look at {% include %} in the Tornado docs, it might do what you are trying to achieve. Instead of using an iframe, directly do {% include "mess.html" %}.
If you want to keep the independent frame so you can refresh individually, you have to consider the iframe being a separate request. As such, you also have to provide its own RequestHandler where you get your cookie and then generate the table for your user. You then set the iframe src to be the URL you chose for this RequestHandler.
Related
I have a form I'm working with in Django.
I have a built in error message I'm trying to get to render on the form.
My first step is to get the error message to render on the form and then I will go into the function and tweak when it shows up.
My problem emerges when it comes to doing it in python.
Normally, my preferred way would be to JQuery for the footer and use JavaScript to append/prepend the HTML. Then set it to show/hide based on conditionals.
However, for this I am wanting to do it in Python to make it easier for the people working w/ me.
Here's an example of the error message HTML I would like to use for appending to something else in JS.
error_field.append('<em for="name" class="form-error-message text-danger">');
Here is an example of the Django Code Block I would like to add it within
{% block form-footer %}
{{ block.super }}
{% endblock %}
What is the easiest way to accomplish this within Python/Django? To be clear, I can figure out the conditional stuff myself. Just the rendering of the specific HTML/CSS error class I have already created. I should be able to do the conditional/function part of this myself.
I can just show you an example, this is a part of my project
views.py
try:
user=User.objects.get(username=username)
except:
messages.info(request,'username does not exist')
return redirect('login')
return render(request,'users/login-register.html')
html
{% if messages %}
{% for i in messages %}
<div class="alert alert--{{i.tags}}">
<p class="alert__message">{{i}}</p>
<button class="alert__close">x</button>
</div>
{% endfor %}
{% endif %}
You can use this anywhere in your html page. This is a common page, and everything in here is extended. And of course this is an example similar to your problem. Check it out if you want
I'm trying to figure out if there is a way to extend a partial view into a view that already extends base.html.
Here is an example of what I'm trying to do:
my-template.html
{% extends 'base.html '%}
<div class="row">
<div class="col-xs-12">
<ul class="nav nav-tabs">
<li role="presentation" class="active">Tab1</li>
<li role="presentation">Tab2</li>
</ul>
</div>
</div>
<div>
{% block tab_content %}
{% endblock %}
</div>
partial1.html
{% extends 'my-template.html' %}
{% block tab_content %}
<h1>I'm partial 1</h1>
{% endblock %}
The my-template.html view has a url that is constructed like so:
url(r'^my-template/(?P<id>[0-9]+)/$', views.my_template_view, name='my-template')
in addition a context dict is passed into the my_template_view providing the id for the url.
I would like the for the user to click on a tab and for its corresponding partial to be rendered with a url like so:
url(r'^my-template/(?P<id>[0-9]+)/tab1/$', views.tab1_view, name='tab1-view')
but right now I'm getting a NoReverseMatch at /my-template/97/tab1/ which I'm assuming means that my tab1_view doesn't have access to the same context as the my_template_view and thus can't get the id to build the reverse of my url.
In template /partial1.html, error at line 0
Reverse for 'tab1_view' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['/my-template/(?P<id>[0-9]+)/tab1/$']
So, is there a way for me, at the very least, to pass along the context or the id so this works, or am i going about this in the entirely wrong way?
The typical way to solve this is by using the include template tag, not by extending with a new template.
Here is the Django doc describing this.
You can even use a variable to define a dynamic template name that will be included based on logic in your view.
Little more clarification here:
You can also have the URL route direct to the same view and have the "tab" optionally passed in as a second parameter as so:
url(r'^my-template/(?P<id>[0-9]+)/(?P<tab_name>\w+)/$', views.my_template_view, name='my-template')
url(r'^my-template/(?P<id>[0-9]+)/$', views.my_template_view, name='my-template')
And your view would look something like:
def my_template_view(request, id, tab_name=None):
if not tab_name:
tab_name = "tab1"
if tab_name == "tab1":
partial = "tab1.django.html"
elif tab_name == "tab2":
partial = "tab2.django.html"
return render("my-template.html", { 'partial': partial })
And on your template you would have:
{% include partial %}
Because the included template will have the same context, you will have access to any variables that were available in the original context as well.
EDIT 2020/09/04: As noted in a comment below, the above page no longer exists. I've updated the above link to the latest in the 1.11 branch, but for the latest version of Django (3.1 as of this edit) you can refer to the same doc here.
How would I return text with template markup from an expression and have the tags rendered by Jinja? It looks like Jinja only makes one pass, and just escapes and dumps the text in without further processing it as part of the template (which would be the right thing 99% of the time). Is there a way to make two passes with the renderer, or render the result of my expression first and pass it to the template?
Simplified Problem
I have included further details below in case there is more to this than I think, but this should be all the information needed for the problem.
If do_render() returns <p>Hello there {{ current_user.name }}</p>, how could I do the following in a template, so that I obtain the value of name?
<div>
{{ do_render() }}
</div>
This renders as <div><p>Hello there {{ current_user.name }}</p></div>, when I want <div><p>Hello there Sam</p></div>.
Complete Problem
I'm using Flask, Flask-Bootstrap, and Flask-Nav with Python 2.7. I could just create the navigation bar myself and none of this would matter, but "autogenerated" sounded so much simpler...
Flask-Bootstrap provides a Flask-Nav compatible renderer; I have subclassed it to modify my navigation bar. I'm trying to add a logon form in the navigation bar, right-aligned. Because the BootstrapRenderer generates the complete navbar, I have to inject my form into it prior to the closing tags (alternatively, I could skip super() and do it all myself).
class MyRenderer(BootstrapRenderer):
def visit_Navbar(self, node):
""" Returns the html for a Bootstrap navigation bar. """
root = super(MyRenderer, self).visit_Navbar(node)
# Replace the navbar style with my custom css
root['class'] = 'navbar navbar-mystyle'
# Here I try injecting a login form. This is the correct position,
# and it inserts properly; it just treats {{, }}, {%, %}
# as nothing special.
elem = root[0][1] # div class="navbar navbar-collapse"
elem.add(
dominate.util.include(
os.path.join(
config.app_path_root, app.template_folder, 'inc/login_form.jinja')))
# I have also tried
# elem.add('{% block nav_right %}{% endblock %}')
# thinking I would use inheritance later (still my preference).
return root
I then register the renderer with Flask-Nav, and render it by inserting {{ nav.main_nav.render() }} into my base template, which my .html files inherit from. All of this works.
My problem is that I only want the login form when the person is not logged in.
The login_form is:
{% if not current_user.is_authenticated() %}
<form class="navbar-form navbar-right" role="search" action="login" method="post">
<div class="form-group"><input type="text" name="username" /></div>
<div class="form-group"><input type="password" name="password" /></div>
</form>
{% else %}
<div class="navbar-right">
Welcome {{ current_user.name }} | Logout
</div>
{% endif %}
My HTML output is identical to the template; neither statements, expressions, nor comments are treated as such.
Other attempts: I have generated the navbar first, then passed it to the template via render_template('index.html', navbar=navbar) but I have the same problem. I have also tried macros. I'm about ready to write my navigation menu in the base template myself and be done with it, but now it feels like that would be giving up.
Other than {% include ... %} and {% extends ... %}, you're not going to be able to have the template system automatically render something that's added to a template during runtime without a bit of customization.
The beautiful part about Jinja 2 is that its API is very powerful and you can do many things without having to feel like your "hacking" the system. To do what your first example is implying, you just need to have the function render the included template snippet snd return a rendered string. If you're expecting the template to be rendered with the context of the parent template, that's not gonna happen automatically, but that's not a problem since you can pass in whatever you need directly in your function call in the template.
I'm a beginner to flask and I'm making a small web scraper app. What I've done so far has created a dropdown with a list of elements. Now I want to be able to render another page when the user selects a value from the list and I want to pass that value to the next page as well.
{% extends "base.html" %}
{% block content %}
<select id = "foo" onchange="">
{% for item in Citydata %}
<option value = {{ item.link }}> {{ item.name }} </option>
{% endfor %}
</select>
{% endblock %}
This makes the list and adds in all the links and values. I know that what should happen is that when an option is selected a new route is selected/used and a new template file is loaded. But I don't know how to do it.
If you are trying to do a form submission, follow colidyre's suggestion.
It seems to me, however, that you're looking to add a variable in your path, so you will need to use Flask's Variable Rules
It is unclear what item.link is, however if you have formatted that to be associated with an item's id such as /item/1, you could create an <a> tag like so:
{% for item in Citydata %}
{{ item.name }}
{% endfor %}
That would handle populating the href properly on the front-end, next you will need to set up the proper route on the server to handle the path:
#app.route('/item/<int:item_id>')
def item_route(item_id):
# do some stuff
NOTE: you don't have to create <a> tags, but it is a bit more straight forward than <option>. To stick with <option> you would just need to add some JavaScript client-side to call the back-end service based on the selected <option>'s value attribute instead.
I have a python dictionary called "asides". The values of this dict are html snippets loaded from my database and I want to inject them into a jinja template.
The below is the jinja snippet:
<div class="small-3 large-3 columns">
{% for k in asides.keys() %}
<div id={{k}} class="aside">{{asides[k]|safe}}</div>
{% endfor %}
</div>
This creates nested divs. Say my dict has ids 1 and 2, this will do the following:
<div class="small-3 large-3 columns">
<div id=1 class="aside">some html here
<div id=2 class="aside">some html here
</div>
</div>
</div>
</div>
If I remove the safe filter, it behaves normally creating non nested divs.
I would like to know why the safe filter does this and how to avoid it (as I don't want nested divs).
All right, following the suggestion in the comments I realized where the issue was. I am going to document it here as it's a funny business in my opinion.
So, in app.py (using Flask):
from flask import Flask, render_template
app = Flask(__name__)
app.debug = True
#app.route('/')
def index():
d = {'1':'<p>Test 1</p', '2':'<p>Test 2</p>'}
return render_template('index.html', d=d)
if __name__=='__main__':
app.run()
Note how the html of the first element in d is not correct. The closing p tag is missing a ">".
Then in the template
<html>
<body>
<div>
{% for k in d %}
<div class={{k}}>{{d[k]|safe}}</div>
{% endfor %}
</div>
</body>
</html>
This will nest the second div inside the first div.
I think the question is still open as it would be interesting to know why this happens.
Your template has an error
d = {'1':'<p>Test 1</p', '2':'<p>Test 2</p>'}
the first para tag is not properly closed, it should be
'1':'<p>Test 1</p>'
I had the same issue, with incomplete HTML tags in my input data.
I'm not sure if this is a Jinja bug or not, maybe it could handle it better, or create an error