Replace part of template with contents of html file in Django - python

I have a problem with replacing part of website built in django with another content.
I have a code like
<section id='main_page'>
<div id="main_div">
<--! include kek.html content here -->
</div>
</section>
and I'd like to replace this comment with html placed in another html file.
I tried
def home(request):
return HttpResponse(render_to_string(
'index.html',{'bla':kek.html},
))
while in in index.html was
<section id='main_page'>
<div id="main_div">
{{ bla }}
</div>
</section>
but, it doesn't seem to work that way. I'm kinda new to django and python and I can't find any solution.

No, that wouldn't even run (kek.html is not defined in the view, so it's a NameError).
You can use the {% include %} tag in the template for this:
<section id='main_page'>
<div id="main_div">
{% include 'kek.html' %}
</div>
</section>
You should really do the Django tutorial, which explains how templates work (among other things).
Edit after comment
In that case you should treat the name of the include as a variable and pass it from the view:
{% include template_to_include %}
...
return render_to_response(
'index.html', {'template_to_include': 'kek.html'},
)
Note the quotes.

Related

How to call a function/method on Flask from the template

First of all, I'm quite new using flask, but this is something I haven't been able to find so far.
I'm working on my website with Flask and Jinja templates, using postgresql as a DB, I want to be able to call another function/method in my template.
Here I can get all my shares (posts)
#shares_app.route('/shares', methods=['GET'])
#login_required
def last_shares():
shares = fetch_last_shares()
form = ReusableForm(request.form)
return render_template('shares.html', form=form, shares=shares)
template
{% for share in shares %}
<li class="comment" style="border:1px solid black; padding:5px;" >
<a class="pull-left" href="#">
<img width="35" height="35" avatar="{{share[5]}}">
</a>
<div class="comment-body">
<div class="comment-heading">
<h4 class="user">{{share[5]}} ({{share[4]}}) </h4>
<h5 class="time">{{share[3]}} /</h5>
</div>
<p> <b>{{share[0]}} </b> / {{share[2]}}</p>
</div>
<!--comments here -->
Here I wanna be able to get all my comments related to shares, here its where I\'m no sure if I can call another function from my controller.
comments = fetch_last_comments(share[0])
{% for comment in comments %}
Show comments here
{% endfor %}
<!--comments here -->
{% endfor %}
Basically, I want to be calling this function
def fetch_comments_by_shares(share_id):
comments = db.query("""SELECT * FROM comments WHERE share_id = {} """.format(share_id)).getresult()
return comments
Thanks a lot.
Instead of making multiple DB queries for each and every share id you can get all the comments for all the shares in the backend and then pass comments while rendering the template.
like.
render_template('shares.html', form=form, shares=shares, comments=comments)
and if still, you want to call the python function from jinja template then you can follow this answer for the same.
Call a python function from jinja2

Calling Jinja block from included file

I am building a little web application in Python 3.5, using Flask 0.11.1 and Flask-Admin 1.4.2.
Instead of using Flask-Admin as an administrative interface (only used by administrators of the website), I want it to be used by all the users of the website (to take profit of its awesome CRUD generation with forms using Select2 JS lib, inline forms, list views with filtering, etc.).
With that in mind, I want to override the list view template to be more user-friendly. For that, I am doing the following.
First, in my view I override list_template:
from flask_admin.contrib.sqla import ModelView
class FriendView(ModelView):
list_template = 'friend/list.html'
...
Then, I write the friend/list.html file by extending admin/model/list.html and overriding the block model_list_table defined in it:
{% extends 'admin/model/list.html' %}
{% block model_list_table %}
{% for row in data %}
<div class="col-xs-6 col-sm-4 col-md-3">
{% include 'friend/panel.html' %}
</div>
{% endfor %}
{% endblock %}
The panel.html file represents a Bootstrap panel illustrating each Friend:
<div class="panel panel-success">
<div class="panel-heading">
This friend is named {{ row.name }}.
</div>
<div class="panel-body">
{% block list_row_actions_column scoped %}
{{ super() }}
{% endblock %}
</div>
<div class="panel-footer">
...
</div>
</div>
Here is the problem: as you can see, I use in panel.html the block list_row_actions_column, which is a Jinja block defined in admin/model/list.html.
Of course, this raises the following error:
jinja2.exceptions.UndefinedError: there is no parent block called 'list_row_actions_column'.
because the file panel.html is not extending admin/model/list.html.
I have tried to define panel as a Jinja macro and to import it in friend/list.html, this raises the same error...
I know that I could simply not separate the panel in another file, however my friend/list.html is pretty big, and I think it is a good thing to do it that way, for sake of readibility and decoupling.
Does someone have an idea about how I can proceed?
Thanks,
Edouard
just make an html file and write single block of code in html file then include that file into that particular location where you want to need that code. that is the best method without use of any #block or #micro and for every block of code use a new html file and use this file as a function by including it on that place.

How to use django base extension along with angularjs ng-include?

I'm using ng-include like this
HTML
<div ng-app="myapp" ng-controller="myctrl" ng-include="/static/html/main.html"></div>
main.html
{% extends "app\base.html" %}
{% block content %}
<div ng-controller="myctrl1">
some content
</div>
{% endblock %}
base.html
<div ng-controller="myapp2">some content </div>
but this is not working, it is showing an errorr "SyntaxError: Unexpected token % at Object.parse (native)"
Please suggest me a better way to implement this.
I don't quite know what you're trying to do here. Angular templates and Django ones are quite different, even if they superficially share the same {{ var }} syntax. You can't inherit an Angular template from a Django one, or vice versa.
But there's no reason to want to do that anyway. Angular is already loading the template as a partial, which means it will be inserted into the div in base.html. There's no need for inheritance here at all.

Displaying custom checkboxes with Django and ManyToManyField

I'm having trouble wiring my checkboxes together with the template to make a good user experience. I'm sending my form to the view which contains the following MyType which is described as:
models
class A(models.Model):
MyType = models.ManyToManyField(P)
forms
MyType = forms.ModelMultipleChoiceField(queryset=P.objects.all(), required=False, widget=forms.CheckboxSelectMultiple)
and the view is being sent as:
return render(request, "static/about.html", {'form': form})
and in the template, I have the following kind of structure
<li class="option table">
<div class="cell" id="center">
<div class="option-text">Option 1</div>
</div>
<div class="cell" id="right">
<div class="option-checkbox">
<div class="check"></div>
<input id="myid1" name="myname1" value="1" type="checkbox">
</div>
</div>
Now I can use answer: On a django form, how do I loop through individual options per field? to loop through, but this only gives the description. How do I recreate the actual HTML that deals with the options in the smartest way?
I've tried the shell to look at the objects, but I really don't see what I should be pulling in. i.e. in the template to recreate. What fields of each option should I pull in? or how do I get at the right info to build up my HTML such that the saving aspect of the form will work.
In a template I cannot do:
{% for field in form["MySmoking"] %}
{% endfor %}
so how could I modify the following:
{% for option in form.MyType.field.choices.queryset %}
{{ option.image }}
{{ option.title }}
{{ option.description }}
{% endfor %}
so, how would I spit out the HTML that builds the checkbox.
Thanks.

webapp2, Jinja2: how to cut large html file into multiple html files

When I blog, I like to separate each blog-post into its own .html file (is that ok?)
This prevents the file getting too big, and makes it easy to go back and edit a previously written blog post if need be.
Occasionally the blog post will contain css/js/ajax/template variables.
But on my website, I like all the blog posts on one page (so I can scroll through them all, instead of going to a separate page for each post)
Here is an html file that contains two blog posts:
{% extends "base.html" %}
{% block blog_posts %}
<!-- links/targest for the side menu to jump to a post -->
<li>Post2 - April 2012</li>
<li>Post1 - Feb 2012</li>
{% endblock %}
{% block content %}
<div id="post1">
spam1 blah blah
</div>
<div id="post2">
spam2
</div>
{% endblock %}
and in base.html I have something like:
<div id="content-container">
<div id="section-navigation">
<ul>
{% block blog_posts %}
{% endblock %}
</ul>
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</div>
What is the best way for me to split these blog posts out into separate files using webapp2 and jinja2?
e.g. blog1.html might look like:
{% block blog_posts %}
<!-- links/targest for the side menu to jump to a post -->
<li>Post1 - Feb 2012</li>
{% endblock %}
{% block content %}
<div id="post1">
spam1 blah blah
</div>
{% endblock %}
(And I would want the links and the blogposts to be displayed in the right order on the website)
I could think of a way of doing it where post2 extends post1.html, post3 extends post2.html etc, but I would prefer to fan out more
"Henry and Kafura introduced Software Structure Metrics Based on Information Flow in 1981[2] which measures complexity as a function of fan in and fan out."
Thanks
#robert king, your design has data embedded directly in the template. Templates should only contain the blueprint to a view, and they should be rendered with new data generated from your main code every time. I simulate this process here (Edited to illustrate the use of a loop to extract post titles, and the display of a single post.):
import jinja2
# NOTE: in this template there is no data relating to specific posts.
# There are only references to data structures passed in from your main code
page_template = jinja2.Template('''
<!-- this is a navigation block that should probably be in base.html -->
{% block blog_posts %}
<!-- links/targets for the side menu to jump to a post -->
{% for post in posts %}
<li><a href="{{ post.url }}">{{ post.title }}
- {{ post.date }}</a></li>
{% endfor %}
{% endblock %}
<!-- this is a content block that should probably be in page.html -->
{% block content %}
<div id="post">
<h1>{{ current.title }}</h1>
<h2>{{ current.date }}</h2>
<p>{{ current.content }}</p>
</div>
{% endblock %}
''')
# NOTE your main code would create a data structure such as this
# list of dictionaries ready to pass in to your template
list_of_posts = [
{ 'url' : '#post1',
'title' : 'My first post',
'date' : 'Feb 2012',
'content' : 'My first post is about Hello World.'},
{ 'url' : '#post2',
'title' : 'My second post',
'date' : 'Apr 2012',
'content' : 'My second post is about Foo Bar.'}
]
# Pass in a full list of posts and a variable containing the last
# post in the list, assumed to be the most recent.
print page_template.render(posts = list_of_posts,
current = list_of_posts[-1])
Hope this helps.
EDIT See also my answer to a question on "Site fragments - composite views"
I just found another option in the jinja2 tutorial. I think it makes more sense for my handler to pass my template a list of filenames of blog posts, and then to include the blog posts.
include - returns the rendered contents of that file into the current namespace:
{% include 'header.html' %}
<div ...
{% include 'footer.html' %}
Included templates have access to the variables of the active context by default. For more details about context behavior of imports and includes see Import Context Behavior.
From Jinja 2.2 onwards you can mark an include with ignore missing in which case Jinja will ignore the statement if the template to be ignored does not exist. When combined with with or without context it has to be placed before the context visibility statement. Here some valid examples:
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
New in version 2.2.
You can also provide a list of templates that are checked for existence before inclusion. The first template that exists will be included. If ignore missing is given, it will fall back to rendering nothing if none of the templates exist, otherwise it will raise an exception. Example:
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
When I read the raw html file (file.read()) and passed the data to my template, it escaped all the html.
instead of {{data}} i had to use {{data|safe}} which allowed raw html.
something like:
class HomeHandler(BaseHandler):
def get(self):
file_names = sorted(os.listdir('blog_posts'))
html = [open('blog_posts/%s' % fn).read() for fn in file_names]
templates = {'html': enumerate(html)}
self.render_template('home.html', **templates)
{% block content %}
{% for num,data in html %}
<div id="post{{num}}">
{{data|safe}}
</div>
<br />
<img src="http://www.sadmuffin.net/screamcute/graphics/graphics-page-divider/page-divider-007.gif" border=0>
<br />
{% endfor %}
{% endblock %}
(make sure the directory isn't a static directory)

Categories

Resources