Django: Use a variable from a view in a template - python

I want to use the content of a variable with the name "files" in my template in django. My views.py looks like this:
from django.shortcuts import render
import os
def index(request):
os.chdir("/home/ubuntu/newproject/static")
for files in os.listdir("."):
return render(request, 'sslcert/index.html','files')
And my template with the name "index.html" looks like this:
<head>
{% block title %}
<h3>
Following directories are in this folder:
</h3>
{% endblock %}
</head>
<body>
<<(HERE SHOULD BE THE OUTCOME OF THE VARIABLE LIST)>>
</body>
Help would be really cool and explanation too :/ I am a real beginner in django and I wish to know how this template and views stuff is connected :) please do not hate on me if this question is really stupid :(

You can pass variable to template like this:
from django.shortcuts import render_to_response
def index(request):
os.chdir("/home/ubuntu/newproject/static")
for file in os.listdir("."):
files.append(file)
return render_to_response('sslcert/index.html', {'files':files})
And in template you can use it like:
{{files}}
if you want to use whole field or you can loop through them
{% for file in files %}
# do something with file here
{% endfor %}

Do something like:
from django.shortcuts import render
import os
def index(request):
os.chdir("/home/ubuntu/newproject/static")
files = []
for file in os.listdir("."):
files.append(file)
context = {'files':files}
return render(request, 'sslcert/index.html', context)
and then the template:
<head>
{% block title %}
<h3>
Following directories are in this folder:
</h3>
{% endblock %}
</head>
<body>
{{ files }}
</body>

render function You are using in Your example got dictionary argument which can extend context passed into template
render(request, template_name[, dictionary][, context_instance][, content_type][, status][, current_app][, dirs])
dictionary
A dictionary of values to add to the template context. By default, this is an empty dictionary. If a value in the dictionary is callable, the view will call it just before rendering the template.
so you can pass any data into template as dictionary which keys will be available in template as variable
from django.shortcuts import render
def index(request):
dir = "/home/ubuntu/newproject/static"
return render('sslcert/index.html', {'files': os.listdir(dir)})

Related

Is there a way to add actual HTML to a template from strings containing HTML markup in Django?

So, I want to convert a string I have containing HTML tags converted from a Markdown file into actual HTML. Then inserting the HTML afterwards into a template via Django (this is my first time ever using Django).
What my current output looks like:
Instead of getting plain text, I want the HTML shown in the screenshot to be executed like normal HTML.
Code from my views.py file:
from django.http.response import HttpResponse
from django.shortcuts import render
from markdown2 import Markdown, markdown
import random
from . import util
import html.parser
# index output
def index(request):
return render(request, "encyclopedia/index.html", {
"entries": util.list_entries()
})
# function to render wiki entries
def page_render(request, title):
entry = util.get_entry(title)
if entry != None:
markdowner = Markdown()
content = markdowner.convert(entry)
return render(request, "encyclopedia/display.html", {
"title": title,
"content": content
})
else:
return render(request, "encyclopedia/error.html")
Code from my HTML template:
{% extends "encyclopedia/layout.html" %}
{% block title %}
{{ title }}
{% endblock %}
{% block body %}
{{ content }}
{% endblock %}
Thanks in advance for the help!
Kind Regards
PrimeBeat
You can use the safe tag.
Insert content like this : {{ content|safe }}
If you don't want the HTML to be escaped, look at the safe filter and the autoescape tag:
safe:
{{ myhtml |safe }}
autoescape:
{% autoescape off %}
{{ myhtml }}
{% endautoescape %}

Why am i getting the TypeError:context must be a dict rather than Context. Django

Trying to setup a webpage to list the tags for startups (following along in Django unleashed). The book uses Django 1.8, and Im using 3.0. There are spots where ive seen deprecated functions in the book and was able to find what the updated replacement was, but i cant figure out why django is giving me this error when loading the homepage. Still kinda new at Python and Django. I do have tags created, when executing Tag.objects.all() and one startup has been saved to the database which has its related tag.
Views.py
from django.shortcuts import render
from django.http.response import HttpResponse
from .models import Tag
from django.template import Template, Context, loader
def homepage(request):
tag_list = Tag.objects.all()
template = loader.get_template('organizer/tag_list.html')
context = Context({'tag_list':tag_list})
output = template.render(context)
return HttpResponse(output)
Tag_list.html
{% extends parent_template|default:"organizer/base_organizer.html" %} #An alternative reference to "base.html"
{% block title %}
{{ block.super }} - Tag List
{% endblock %}
{% block content%}
<h2>Tag List</h2>
<ul>
{% for tag in tag_list %}
<li>
<a href="">
{{ tag.name|title }}</a>
</li>
{% empty %}
<p><em>There are currently no Tags available.</em></p>
{% endfor %}
</ul>
{% endblock %}
TypeError at /
context must be a dict rather than Context.
Request Method: GET
Request URL: http://127.0.0.1:8000/
Django Version: 3.0
Exception Type: TypeError
Exception Value:
context must be a dict rather than Context.
Exception Location: C:\Users\Antho\Desktop\suorganizer\su_env\lib\site-packages\django\template\context.py in make_context, line 270
Python Executable: C:\Users\Antho\Desktop\suorganizer\su_env\Scripts\python.exe
Python Version: 3.7.5
Python Path:
You should pass context variables as dict objects to the template as below,
def homepage(request):
tag_list = Tag.objects.all()
template = loader.get_template('organizer/tag_list.html')
context = {'tag_list': tag_list} # update this line
output = template.render(context)
return HttpResponse(output)
Also, you could rewrite the view by using render() function
def homepage(request):
tag_list = Tag.objects.all()
context = {'tag_list': tag_list}
return render(request, 'organizer/tag_list.html', context)

Django template tags forloop

I have created a template tag and trying to loop through the results from the template tag
but I don't get any results
tags.py
from django import template
from loadprograms import dbcontext
register = template.Library()
#register.simple_tag
def get_category():
x = dbcontext.DBContext()
results = x.executequery("Select name from Categories")
categories = [each[0] for each in results]
return categories
template code
{% load category_tags %}
{% get_category %}
{% for each in get_category %}
{{ each }}
{% endfor %}
The {% get_category %} prints all the categories without any issues but the for loop stmt
that loop through the results does not work
What could be the problem?
To make this change in your tag, you'll have to set a variable in the context, but if your objective is to have a list of categories available in templates, just like you would have passed it in from the view - then you need to write a template context processor, which will allow all views to have this variable in their context.
A template context processor is just a method that adds to the request context, by returning a dictionary. Think of it like a view function, that just returns a context.
from .models import Categories
def cat_names(request):
return {'category_names': Category.objects.values_list('name', flat=True)}
To activate this context processor, you have to do a few things:
Add the above code to a file called template_processors.py in the same place as your models.py and views.py.
In your settings.py, add the fully-qualified name of the method to the TEMPLATE_CONTEXT_PROCESSORS setting, making sure you don't override the defaults. To do this easily, import the default settings first, then add to it:
from django.conf.default_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP
TEMPLATE_CONTEXT_PROCESSORS = TCP + ('yourapp.template_processors.cat_names',)
Use the render shortcut, which will make sure the context is correctly passed.
In your views, you can now just do this:
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
In your home.html, you can now do:
{% for name in category_names %}
{{ name }}
{% endfor %}

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

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

Include a view in a template

In django I have a view that fills in a template html file but inside the html template I want to include another view that uses a different html template like so:
{% block content %}
Hey {{stuff}} {{stuff2}}!
{{ view.that_other_function }}
{% endblock content %}
Is this possible?
Yes, you need to use a template tag to do that. If all you need to do is render another template, you can use an inclusion tag, or possibly just the built in {% include 'path/to/template.html' %}
Template tags can do anything you can do in Python.
https://docs.djangoproject.com/en/3.0/howto/custom-template-tags/
[Followup]
You can use the render_to_string method:
from django.template.loader import render_to_string
content = render_to_string(template_name, dictionary, context_instance)
You'll either need to resolve the request object from the context, or hand it in as an argument to your template tag if you need to leverage the context_instance.
Followup Answer: Inclusion tag example
Django expects template tags to live in a folder called 'templatetags' that is in an app module that is in your installed apps...
/my_project/
/my_app/
__init__.py
/templatetags/
__init__.py
my_tags.py
#my_tags.py
from django import template
register = template.Library()
#register.inclusion_tag('other_template.html')
def say_hello(takes_context=True):
return {'name' : 'John'}
#other_template.html
{% if request.user.is_anonymous %}
{# Our inclusion tag accepts a context, which gives us access to the request #}
<p>Hello, Guest.</p>
{% else %}
<p>Hello, {{ name }}.</p>
{% endif %}
#main_template.html
{% load my_tags %}
<p>Blah, blah, blah {% say_hello %}</p>
The inclusion tag renders another template, like you need, but without having to call a view function. Hope that gets you going. The docs on inclusion tags are at: https://docs.djangoproject.com/en/3.0/howto/custom-template-tags/#inclusion-tags
Using your example and your answer to Brandon's response, this should work for you then:
template.html
{% block content %}
Hey {{stuff}} {{stuff2}}!
{{ other_content }}
{% endblock content %}
views.py
from django.http import HttpResponse
from django.template import Context, loader
from django.template.loader import render_to_string
def somepage(request):
other_content = render_to_string("templates/template1.html", {"name":"John Doe"})
t = loader.get_template('templates/template.html')
c = Context({
'stuff': 'you',
'stuff2': 'the rocksteady crew',
'other_content': other_content,
})
return HttpResponse(t.render(c))
Someone created a template tag that loads a view. I've tried it, and it works. The advantage of using that template tag is that you don't have to rewrite your existing views.

Categories

Resources