How to include template generated in runtime and stored in variable? - python

Business:
Practical background for all that is design of web-app, where web-page constructed from prototype objects, gadgets, which individually defined each in its own view function (its own code, not necessarily django-view function). And to build a 'production' web-page they can be placed in regular view, related to this page, and produce web-page elements according to given source-data and other parameters.
For example I have a chart-gadget, and it receives source data, parameters, about chart-type, beauty/colors etc, and draws a chart. How can it be stored in separate from specific ap, loose-coupled code? Which design-approach is better?
What Ive tried:
Ive tried 'dumb' way:
For example I have a simple view:
from django.shortcuts import render_to_response
from django.template import Template, Context
from string import letters
def home(request):
t = Template("""<ul>
{% for key, value in d.items %}
<li>{{ key }}: {{ value }}</li>
{% endfor %}
</ul>""")
d = {k: v for v, k in enumerate(letters)}
return render_to_response('home.html', {'t': t, 'd':d})
And template:
<html>
<head>
<title>Django tests</title>
</head>
<body>
{% include t with d=d %}
</body>
</html>
With such setup I get: TemplateDoesNotExist
Expectations about answer:
Im searching any reasonable scheme for storing chunk of web-page, which designed to kinda live by its own life, less-or-more separately from other elements of web-page, in a similarly separate chunk of code in web-app program backend.
As example I can provide such projects as:
iGoogle
Netvibes
Thank you!
ps
Extracts from django-docs:
Extends:
{% extends variable %} uses the value of variable. If the variable
evaluates to a string, Django will use that string as the name of the
parent template. If the variable evaluates to a Template object,
Django will use that object as the parent template.
So It means, that with {% extends %} tag, operation what Im talking in question is definitely possible.
Include:
This example includes the contents of the template whose name is
contained in the variable template_name:
{% include template_name %}
So it probably means, that variable passed to {% include %} can bu just a string with name of file. And if its true, it is clear answer on my question - template defined in variable cannot be included in regular template.
It still slightly ambiguous for me, because in Python word name might be used as synonym of variable.

As someone already mentioned in a comment, you need to just render your template to a string and pass it in to the second template, marking it as a safe string so it isn't auto-escaped. So, your example would be:
from django.shortcuts import render_to_response
from django.template import Template, Context
from django.utils.safestring import mark_safe
from string import letters
def home(request):
t = Template("""<ul>
{% for key, value in d.items %}
<li>{{ key }}: {{ value }}</li>
{% endfor %}
</ul>""")
c = Context({'d': {k: v for v, k in enumerate(letters)}})
return render_to_response('home.html', {'t': mark_safe(t.render(c))})
Then, in home.html, render with {{ t }}

You should put your include template in it's own file
include.html:
<ul>
{% for key, value in d.items %}
<li>{{ key }}: {{ value }}</li>
{% endfor %}
</ul>
home.html:
<html>
<head>
<title>Django tests</title>
</head>
<body>
{% include 'include.html' with d=d %}
</body>
</html>
Then your view becomes:
def home(request):
d = {k: v for v, k in enumerate(letters)}
return render_to_response('home.html', {'d':d})

You should render your sub-template, then place it in the context of your home.html template (as t in this case). This is what I've used before for recursive templates.
home.html
<html>
<head>
<title>Django tests</title>
</head>
<body>
{{ t }}
</body>
</html>
views.py
from django.shortcuts import render_to_response
from django.template import Template, Context
from string import letters
def home(request):
t = Template("""<ul>
{% for key, value in d.items %}
<li>{{ key }}: {{ value }}</li>
{% endfor %}
</ul>""")
d = {k: v for v, k in enumerate(letters)}
t_rendered = t.render(Context({'d': d}))
return render_to_response('home.html',
{'t': t_rendered})
Note that you can cache your sub-template by creating it outside of the view so it doesn't get created on every request. You can use loader to keep your sub-template in a template file. However, changes will not reflect until you restart the server.
from django.shortcuts import render_to_response
from django.template import Template, Context, loader
from string import letters
t = loader.get_template('subtemplate.html')
def home(request):
d = {k: v for v, k in enumerate(letters)}
t_rendered = t.render(Context({'d': d}))
return render_to_response('home.html',
{'t': t_rendered})

i believe render_to_response is a shortcut operation. I don't think it takes a template as 2nd param but a context instead
return render_to_response('home.html', {'d': d,})
<html>
<head>
<title>Django tests</title>
</head>
<body>
<ul>
{% for key, value in d.items %}
<li>{{ key }}: {{ value }}
{% endfor %}
</ul>
</body>
</html>
Yo ucould create a list template in your template dir and include it in your template
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#include
It looks like include just takes a template name and not a dynamic template

Related

Displaying python list of dictionaries on front-end using django [duplicate]

I'm passing a dictionary from my view to a template. So {"key1":"value1","key2":"value2"} is passed in and looping through key,value pairs is fine, however I've not found an elegant solution from access directly in the view from a specific key, say "key1" for example bu json.items["key1"]. I could use some if/then statements, but I'd rather do directly is there a way?
Here is looping code in the html template:
{% for key, value in json.items %}
<li>{{key}} - {{value}}</li>
{% endfor %}
The Django template language supports looking up dictionary keys as follows:
{{ json.key1 }}
See the template docs on variables and lookups.
The template language does not provide a way to display json[key], where key is a variable. You can write a template filter to do this, as suggested in the answers to this Stack Overflow question.
As #Alasdair suggests, you can use a template filter.
In your templatetags directory, create the following file dict_key.py:
from django.template.defaultfilters import register
#register.filter(name='dict_key')
def dict_key(d, k):
'''Returns the given key from a dictionary.'''
return d[k]
Then, in your HTML, you can write:
{% for k in json.items %}
<li>{{ k }} - {{ json.items|dict_key:k }}</li>
{% endfor %}
For example, to send the below dictionary
dict = {'name':'myname','number':'mynumber'}
views :
return render(request, self.template_name, {'dict': dict})
To render the value in html template:
<p>{{ dict.name }}</p>
It prints 'myname'
To overcome this problem you could try something like this:
def get_context_data(self, **kwargs):
context['cart'] = []
cart = Cart()
cart.name = book.name
cart.author = book.author.name
cart.publisher = book.publisher.name
cart.price = 123
cart.discount = 12
cart.total = 100
context['cart'].append(cart)
return context
class Cart(object):
"""
Cart Template class
This is a magic class, having attributes
name, author, publisher, price, discount, total, image
You can add other attributes on the fly
"""
pass
By this way you can access your cart something like this:
{% for item in cart %}
<div class="jumbotron">
<div>
<img src="{{item.image}}" />
<div class="book_name"> <b>{{item.name}}</b></div>
<div class="book_by"><i>{{item.author}}</i></div>
<span>Rs. {{item.price}}</span> <i>{{item.discount}}% OFF </i>
<b>Rs. {{item.total}}</b>
{% endfor %}

In django templates, how to dynamically update header section depending on a customized tag parameters in body section

I am building a Django listing app. to use it, a template should looks like this :
{% load django_listing %}
<html>
<head>
...
{% include "django_listing/header.html" %}
...
</head>
<body>
...
{% render_listing data some_parameters %}
...
{% include "django_listing/footer.html" %}
</body>
</html>
This template is directly used in a TemplateView. It is important to know that the user can define all parameters in the template, the listing is created on-the-fly in the custom render_listing tag thus some_parameters is only known in template side (not known at TemplateView side). The user only gives the data in the TemplateView context.
I want to dynamically declare some CSS and JS depending on the some_parameters values. I succeded to do that for JS in {% include "django_listing/footer.html" %}, but not for CSS because when rendering {% include "django_listing/header.html" %} the listing object has not been created yet.
Do you have an idea how to dynamically declare some CSS depending on the some_parameters ?
May be there is a way to postpone {% include "django_listing/header.html" %} rendering ?
Finally, the solution was to create a template tag for the header that renders the remaining before itself :
class ListingHeaderNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
remaining_output = self.nodelist.render(context)
tpl = template.loader.get_template('django_listing/header.html')
tpl_output = tpl.render(context.flatten())
return f'{tpl_output}\n{remaining_output}'
#register.tag(name="render_listing_header")
def do_listing_header(parser, token):
nodelist = parser.parse()
return ListingHeaderNode(nodelist)
Then I can use it instead of the include :
{% load django_listing %}
<html>
<head>
...
{% render_listing_header %}
...
</head>
<body>
...
{% render_listing data some_parameters %}
...
{% render_listing_footer %}
</body>
</html>

Why is Django not taking the integer in the DB and displaying it in the HTML template?

I have the following basic code, which is meant to get number X, add a simple value "+1" just as proof of concept, then save that number back into the database.
Also, I require a Django based, jinja template to pull that number and render it onto a website.
My question is, why is the number failing to show up? I only get a blank space where the number is supposed to be rendered and if I remove the [:1] filter, the div is generated 3x; this tells me that the issue might be somewhere in that line but I am at a loss. The code is:
/views.py:
from django.shortcuts import render
from django.http import HttpResponse
from django.template import Context, loader
from home.models import DeathNum
def index(request):
counter = DeathNum.objects.get(pk=1)
fj = counter.deaths
t = loader.get_template('home/basenum.html')
c = {'number_post': str(fj)[:1]}
return HttpResponse(t.render(c))
def increment(request):
counter1 = DeathNum.objects.get(pk=1)
counter1.deaths += 1
counter1.save()
t = loader.get_template('home/basenum.html')
c = {'number_post': str(counter1)[:1]}
return HttpResponse(t.render(c))
/models.py:
from django.db import models
class DeathNum(models.Model):
deaths = models.IntegerField()
def __str__(self):
return "{0}/{1}\n".format(self.id, self.deaths)
/basenum.html:
{% extends "home/index.html" %}
{% block content %}
<br />
<div class="banner">
<div class="bannerNum">
<p div class="numberOf">
Number of deaths in Blank since 1999:
</p>
{% for post in number_post %}
<br /><br /><br />
<p class="death1">
{{ post.deaths }}
</p>
{% endfor %}
</div>
</div>
{% endblock %}
Answer to your question.
number_post is string. Why for loop to display the str ? Please remove the for loop from your template and just add this...
{{ number_post }}
Or
Another solution to your question
I believe you want to show all the deaths. Please consider below approach?
death_nums = DeathNum.objects.all()
return render(request, 'deaths.html', {'death_nums': death_nums})
And in HTML
{% for death_num in death_nums %}
{{ death_num.deaths }}
{% endfor %}

Couldn't iterate over a dictionary context variable in template, despite having all in place, as far as I know?

I'm trying to iterate over the keys of a dictionary passed as context variable in template. But it's just not happening.
And when I put {{ key }} in template I get the value corresponding to that key but just couldn't iterate over.
logic.py
global table
table = {}
for i in range(9):
for j in range(9):
key = 'i'
key = key + str(i) + str(j)
table[key] = 1
view.py
from django.shortcuts import render
from .formss import SudokuForm, RealSudoku
from .logic import table
# Create your views here.
def sudokuf(request):
title = "Sudoku Puzzle"
if request.method == 'POST' :
print(request.POST)
return render (request,"sudoku.html",table)
sudoku.html
<form method="POST" action=""> {% csrf_token %}
{% for key,value in table.items %}
{{ key }}:{{ values }}
{% endfor %}
{{ i04 }} # If I do this I get the value table['i04'] but not in the above for loop
<input type="submit" align="centre" value="Solve">
The third argument to render is a "context", a dictionary whose keys will be available to your HTML as names. You're passing your table object as the context, so its keys (like i04) are available as variables... but there is no key named table in your table, so the name table isn't available to your HTML.
Change this line in view.py:
return render (request,"sudoku.html",table)
to:
return render(request, "sudoku.html", {"table": table})
And you'll have the name table available in your HTML. (But not the name i04).
You could also do something like:
import logic
render(request, "sudoku.html", logic)
And that would make all the names defined in your logic module available to your HTML.
If there's anything that's not clear about this answer, leave a comment and let me know, and I'll try to explain further.
It's probably that you have {{ values }} where you should have {{ value }}.
So instead of
{% for key,value in table.items %}
{{ key }}:{{ values }}
{% endfor %}
try...
{% for key,value in table.items %}
{{ key }}:{{ value }}
{% endfor %}

Is there a simple way to display mysql data in Django template without creating an app?

I have a table in my MySQL database named mysite_categories, there are 4 columns but for my purposes I just need two (name, base_url).
I currently have a template '*base_categories.html*' that I use to load the categories manually.
base_categories.html (trimmed down)
{% block content %}
<div class="section" style="float: right;">
<h4 class="gradient">Category List</h4>
<ul>
<li>Art</li>
<li>Biography</li>
<li>Science</li>
</ul>
</div>
{% endblock %}
What I'd like to do is pull the data from the db and use it in a for loop. Something like:
{% block content %}
<div class="section" style="float: right;">
<h4 class="gradient">Category List</h4>
<ul>
{% for category in mysite_categories %}
<li>{{ category.name }}</li>
{% endfor %}
</ul>
</div>
{% endblock %}
This is probably a newbie question but is it possible to something like this without creating an app?
*EDIT 1*
These are my app files, I'll admit this is probably junk, I have tried so many edits from so many different posts I'm sure I've broke it somewhere :P. I was going to remove it and start fresh but I figure I might as well post it to see where I might have gone wrong?
views.py
from django.shortcuts import render_to_response
from categories.models import categoryList
def index(request):
categories = categoryList.objects.all()
extra_context = {"categories": categories}
return render_to_response("myapp/index.html", extra_context)
models.py
from django.db import models
class categoryList(models.Model):
#id = models.IntegerField(unique=True, db_column='ID') # Field name made lowercase.
name = models.CharField(max_length=255L, unique=True)
base_url = models.CharField(max_length=255L, unique=True)
thumb = models.CharField(max_length=1L, unique=True, blank=True)
class Meta:
db_table = 'mysite_categories'
index.html
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<div class="section" style="float: right;">
<h4 class="gradient">Category List</h4>
<ul>
{% for category in categories %}
<li>{{ category.title }}</li>
{% endfor %}
</ul>
</div>
As mentioned, it's probably junk at this point, if any of you can help me straighten this out it would be appreciated!
*EDIT 2*
base_right_panel.html
{% block content %}
<div style="float: right;">
<div id="base_categories" style="margin: 10px; padding-bottom: 10px;">
{% block base_categories %}
{% include "base_categories.html" %}
{% endblock %}
</div>
</div>
{% endblock %}
*Edit 3*
base_categories.html
{% block content %}
<div class="section" style="float: right;">
<h4 class="gradient">Category List</h4>
<ul>
{% if categories %}
{% for category in categories %}
<li>{{ category.title }}</li>
{% endfor %}
{% else %}
<p>no data! {{ categories|length }}</p>
{% endif %}
</ul>
</div>
{% endblock %}
*EDIT 4*
(Application name was changed to CategoryList)
CategoryList/views.py
from django.views.generic import TemplateView
from CategoryList.models import CategorylistCategorylist #<-- Changed to match inspectdb result
class IndexView(TemplateView):
template_name="categorylist.html" #<-- Changed name from index.html for clarity
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context["categories"] = CategorylistCategorylist.objects.all()
return context
CategoryList/models.py
from django.db import models
class CategorylistCategorylist(models.Model): #<-- Changed to match inspectdb
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=255L, unique=True)
base_url = models.CharField(max_length=255L, unique=True)
thumb = models.ImageField(upload_to="dummy", blank=True) #<-- Ignored inspectdb's suggestion for CharField
def __unicode__(self):
return self.name
# Re-added Meta to match inspectdb
class Meta:
db_table = 'categorylist_categorylist'
CategoryList/urls.py
from django.conf.urls.defaults import patterns, url, include
from django.contrib import admin
from django.conf import settings
from CategoryList import views
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', views.IndexView.as_view(), name='categorylist'),
)
if settings.DEBUG:
urlpatterns = patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
url(r'', include('django.contrib.staticfiles.urls')),
) + urlpatterns
MySite/urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
from home import views as home_view
from CategoryList import views as index_view
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', home_view.HomeView.as_view(), name="home"),
url(r'^categories/$', index_view.IndexView.as_view(), name='categorylist'),#include('CategoryList.urls')),
url(r'^admin/', include(admin.site.urls)),
#url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
)
if settings.DEBUG:
urlpatterns = patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
url(r'', include('django.contrib.staticfiles.urls')),
) + urlpatterns
So far I can load the url "localhost:8000/categories" and I will see the list of category names appear on the right side of the screen as expected, but there is no template formatting applied. Inside my "*base_right_panel.html*" file I've tried "{% include "categorylist.html %}" to link directly to the application, which displays the correct template formatting, but displays the "{% else %}" response from "{% if categories %}" instead of the categories? I have tried changing the include to point to "categories/", which works in the browser, but it tells me it cannot find the template?
I'm sooo stumped right now..?
This answer is not meant to disagree with Alasdair's - it's just to add some more information on working with templates.
The core handler of an HTTP request to a Django application is the view. The view receives the HTTP request, as well as any arguments captured from the URL, and is responsible for returning an HttpResponse instance (or an instance of one of its subclasses) which will be returned to the browser.
The view is not bound to use any particular method to create the HttpResponse. Rendering a template to include information derived from the database and from request information or URL arguments is sufficiently common that there's code to support it, like the render shortcut or its mostly obsolete antecedent render_to_response, but this is by no means required. It's perfectly legitimate to have a view directly construct the HttpResponse:
def index(request):
return HttpResponse('This is an index page.')
Or, for very simple HTML:
def index(request):
return HttpResponse('<html><head><title>example</title></head><body>This is an index page.</body></html>')
In practice, I have often created HttpResponse instances directly to return json data or a dynamically created PDF or Excel file.
A simple way to slot information retrieved from the database into your response would be to use Python's built-in string interpolation:
def index(request):
return HttpResponse('Hello, %s' % request.user.email)
Or you could use the advanced string formatting options:
def index(request):
user_names = {}
user_names['first_name'] = request.user.first_name
user_names['last_name'] = request.user.last_name
return HttpResponse('Hello, %(first_name)s %(last_name)s' % user_names)
All this is building up to the point that it doesn't matter how you generate the text contents of your HttpResponse. All that matters is that you return one.
The template system is a powerful and extensible tool for generating text content, but that's all it does. If you look at the template docs about rendering a template, you'll see some examples that are almost exactly the same as the the string interpolation above.
render_to_response was a shortcut that would accept a template and a context and return an HttpResponse with the rendered contents of that template and context. Skipping over its context_instance and content_type parameters for the sake of demonstration, these two code blocks are identical in effect:
def index(request):
t = Template('Hello, {{ first_name }} {{ last_name }}')
c = Context({'first_name': request.user.first_name, 'last_name': request.user.last_name})
response_text = t.render(c)
return HttpResponse(response_text)
Assume a template index.txt exists as defined below, at the top level of an entry in the setting's TEMPLATE_DIRS tuple.
index.txt
Hello, {{ first_name}} {{ last_name}}
Then the view above could be replaced with:
def index(request):
t = get_template('index.html')
c = Context({'first_name': request.user.first_name, 'last_name': request.user.last_name})
response_text = t.render(c)
return HttpResponse(response_text)
Alternatively, you can skip the explicit creation of the context object and rendering of the template into a string thus:
def index(request):
return render_to_response('index.html', {'first_name': request.user.first_name, 'last_name': request.user.last_name})
On more recent versions of Django you should generally use the render shortcut rather than render_to_response - the details are a bit too much to go into if you're still struggling with getting context into your templates.
def index(request):
return render('index.html', {'first_name': request.user.first_name, 'last_name': request.user.last_name})
Of course, part of what makes templates useful is that the rendering engine can perform certain kinds of logic and lookup. I don't actually need to explictly keep looking up first_name and last_name - I can just pass in request as part of my context and look up its attributes in the templates:
index_showing_context.html
Hello, {{ request.user.first_name }} {{ request.user.last_name }}
def index_showing_context(request):
return render('index_showing_context.html', {'request': request})
Even passing in request isn't strictly necessary in that example, because one of the differences between render and render_to_response that I alluded to above is that request is always part of the context for render. But, again, that's an advanced subject.
So for your particular problem, it really doesn't matter where in your templates you render the data you want, as long as you have provided it to your view's context and are rendering the correct template. The template is in effect just a file name used to find and build a string, into which your context will be interpolated.
The {% include %} template tag is one way to mix template fragments into other templates. If I wanted to, I could set mine up like this:
header.html:
<head>
<title>This is a sample title.</title>
</head>
index.html:
<html>
{% include "header.html" %}
<body><p>This is my template body, {{ request.user.first_name }} {{ request.user.last_name }}.</p></body>
</html>
detail.html:
<html>
{% include "header.html" %}
<body><p>This is a detail page, probably for something selected in the context and given the context key 'object'.</p>
<p>{{ object }}</p>
</body>
</html>
That works fine, but it's not the only option. From your question, I see that you're using blocks and template inheritance. A common idiom is to define a base template that all or almost all other templates will inherit from:
base.html
<html>
<head>
<title>{% block title %}Default title{% endblock %}</title>
{% block extra_head_elements %}{% endblock %}
</title>
<body>
{% block body_header %}Standard page header here {% endblock %}
{% block body_content %}{% endblock %}
{% block body_footer %}Standard page footer here {% endblock %}
</body>
</html>
index.html
{% extends "base.html" %}
{% block title %}index {% endblock %}
{% block body_content %}<p>This is my template body, {{ request.user.first_name }} {{ request.user.last_name }}.</p>{% endblock %}
detail.html
{% extends "base.html" %}
{% block title %}detail{% endblock %}
{% block body_content %}<p>This is a detail page, probably for something selected in the context and given the context key 'object'.</p>
<p>{{ object }}</p>
{% endblock %}
So ultimately, I am not quite sure how you should best stitch together your right panel concept because it depends on the way you want your pages to work. If it's going to be present everywhere or almost everywhere, I would recommend putting it into a base template that the rest of your templates will extend. If you want it on exactly one page, just literally include it in that template. If you want it on some but not all pages, a template fragment that you can {% include %} is probably best.
The main thing is to understand how the template engine will compose your {% include %} and {% extends %} tags, and to provide the necessary data to the template's context in your view.
Edit:
If I wanted to have a view and template pair that just retrieved the categories, this is a simple way to lay it out using your example model code and rendering. There are other options.
index.html
<html>
<head><title>Simple category listing</title></head>
<body><p>The categories are:</p>
<ul>
{% for category in categories %}
<li>{{ category.name }}</li>
{% endfor %}
</ul>
</body>
</html>
view:
def index(request):
categories = categoryList.objects.all()
extra_context = {"categories": categories}
return render_to_response("index.html", extra_context)
If I wanted to reuse the category listing on multiple pages, that gets back into the include vs. extends discussion above. Either way, the template will always require your view to pass in categories as a context variable.
You could execute custom SQL directly to fetch categories in your view, and loop through the output in your template. This would not require an app.
If you create a model, you will be able to use the Django queryset api, which is very convenient, e.g.
mysite_categories = Category.objects.all()
This does require you to create an app. However, creating an app is really easy, just use the startapp command.
python manage.py startapp myapp
Once you've created your app, you can use the inspectdb command to inspect your database, and create a model for your mysite_categories table.

Categories

Resources