Get the value in queryset in Django template - django

I have used Django to develop a web app.
In the View function, I have rendered a queryset list to frontend.
In my case, title table is book information, and Material is the detailed info of this book is attached to which course and if this attached relation is "discard". is_discard is in Material table, and not the book discard or not. In Material table several books attached to a course, and discard status is not by book but by book-course pair, as some books may discard in one course but active in other courses
view.py:
def render_2(request):
books = Title.objects.filter(name=title).values()
query_results_book_is_discard =
Material.objects.filter(id=book_id).values('is_discard')
return render(request, 'main.html',
context=
{'query_results_book_is_discard':query_results_book_is_discard,
'book', books})
In the frontend, the query_results_book_is_discard variable shows the following format :
<QuerySet [{'is_discard': True}, {'is_discard': False}, {'is_discard': False}, {'is_discard': False}, {'is_discard': True}, {'is_discard': True}, {'is_discard': False}]>
The query_results_book_is_discard variable is in a loop in frontend Django template,
I want to use the forloop counter to get the value(True or False) to use if condition to check.
I haved tried in main.html:
{% for book in books %}
{% if query_results_book_is_discard.counter0 != False %}
...
and
{% if query_results_book_is_discard.counter0.is_discard != False %}
and
{% if query_results_book_is_discard.is_discard.counter0 != False %}
All failed.
How could I get the True or False value in query_results_book_is_discard to use if condition?

I would recommend you to create a custom template tag that allows you to access a specific index of a list in the template, as follows.
Your app file tree structure should have something like this:
your_app/
__init__.py
models.py
templatetags/
__init__.py
your_app_extras.py
views.py
Then, in your custom template tag file.
your_app_extras.py
from django import template
register = template.Library()
#register.filter
def index(indexable, i):
return indexable[i]
Then, in your template, load your custom template tags:
{% load your_app_extras %}
Then, in your for-loop, you use the following:
{% for book in books %}
{% with query_results_book=query_results_book_is_discard|index:forloop.counter0 %}
{% if query_results_book.is_discard %}
{% endwith %}
{% endfor %}

Related

How to use Jinja in Django framework?

I want to access the elements of a list using Jinja.
Here in the below code both "id" and images are list.
image_name is the field that stores the image
{% for blog in id%}
<h3>{{blog.news_title}}</h3><br/>
<img src="images[loop.index0].image_name"/><br/>
<time>{{blog.news_date}}</time><br/>
click here<br/>
{% endfor%}</li>
Views.py
def BlogViews(request,blog_type):
"""
The blogs are displayed according to the latest, current-month and last-month classification
"""
blog_type=blog_type.replace('-','_')
response_blog=requests.get("API" % (settings.BASE_URL,blog_type),headers=headers,verify=False)
if(response_blog.status_code==200):
data_blog=response_blog.json()
if(data_blog['ErrorCode']==0 and data_blog['SubErrorCode']==0):
blog=BlogYearViews()
blog_images=BlogImages(request,data_blog)
return render(request,"CombinedBlog.html",{"id":data_blog['Data'],"years":blog,"images":blog_images})
else:
return render(request,"Page404.html")
def BlogImages(request,data_blog):
"""
Returns a list of all the images
"""
data_image_list=[]
for i in range(0,len(data_blog['Data'])):
images=data_blog['Data'][i]['image_id']
response_image=requests.get("API"%(settings.BASE_URL),headers=headers,verify=False)
data_image=(response_image.json())
data_image_list=data_image_list+data_image['Data']
return (data_image_list)
You need to zip the two lists together in your view and iterate through them in the template.
blog_images = BlogImages(request, data_blog)
blogs_and_images = zip(data_blog['Data'], blog_images)
return render(request, "CombinedBlog.html", {"blogs_and_images": blogs_and_images, "years":blog})
...
{% for blog, image in blogs_and_images %}
<h3>{{ blog.news_title }}</h3><br/>
<img src="{{ image.image_name }}"/><br/>
<time>{{ blog.news_date }}</time><br/>
click here<br/>
{% endfor %}</li>
Note, you really should be using the {% url %} tag to create the hrefs rather than building it manually like that. Also note, your BlogImages function doesn't need to take the request, since it never uses it, and is anyway extremely un-Pythonic. It should look like this:
def blog_images(data_blog):
data_image_list = []
for blog in data_blog['Data']:
image_id = blog['image_id']
response_image = requests.get("API" % settings.BASE_URL, headers=headers, verify=False)
data_image = response_image.json()
data_image_list.append(data_image['Data'])
return
data_image_list
To access images list using index you can use forloop.counter.
You can use either:
{{ forloop.counter }} # index starts at 1
{{ forloop.counter0 }} # index starts at 0.
In template, you can do:
<img src="{{images[forloop.counter0].image_name.url}}"/>
Advice:
You should consider renaming blog lists as blogs or blog_list inplace of id.

How to get a model by modelname in django template

I have model LandingSnippet that contains attribute ...model = CharField()..., and it is related to context keyword (for example cars in context below)
I have next code in my view
def GeneratedLanding(request):
snippets = LandingSnippet.objects.all().filter(view_on=True).order_by('order')
context = {
'snippets':snippets,
...
'cars':Car.objects.all(), # this is cars
...
return render(request,'qlanding/generateindex.html',{'context':context})
how i can get querySet cars that is in context by keyword cars as a string
for example
{{context}}
prints
{'snippets': <QuerySet [<LandingSnippet: Snippet1Title>, <LandingSnippet: 2 - about - Лучшая служба развозки детей>]>, 'services': <QuerySet []>, 'cars': <QuerySet []>, 'faqs': <QuerySet []>}
and
{{snippet.model}}
prints
cars
QUESTION:
How can i get the {{ context.cars }} ? I think something like context[snippet.model] where snippet.model='cars'
i want push it inside another template when include
{% if snippet.module %}
{% with "qlanding/snippets/module/"|add:snippet.module|add:".html" as path %}
{% include path with model=context[snippet.model] %} # But this is incorect while rendering
{% endwith %}
{% endif %}
you can write a simple template tag like this:
first in your app directory create a directory named templatetags this directory must contains an empty file named __init__.py
create a file with any name in this directory. for example load_from_context
write these code on this file
from django import template
register = template.Library()
#register.tag(name="GetFromContext")
def get_from_context(parser, token):
bits = token.split_contents()
node_list = parser.parse(('endGetFromContext',))
variable = bits[1]
return GetFromContextNode(node_list, variable)
class GetFromContextNode(template.Node):
def __init__(self, node_list, variable):
self.node_list = node_list
self.variable = variable
def render(self, context):
variable_value = template.Variable(self.variable).resolve(context)
with context.push():
context['model'] = context.get(variable_value)
return self.node_list.render(context)
then in your template you can use it like this
{% load load_from_context %}
{# any code in your template #}
{% GetFromContext snippet.model %}
{% include path %}
{% endGetFromContext %}
#vorujack , I get the same error still. but based on your solution I got next.
from Django import template
register = template.Library()
#register.simple_tag
def get_model_from_context(context,model_name):
return context[model_name]
and how I used in view
{% get_model_from_context context=context model_name=snippet.model as model %}
{% include "qlanding/snippets/module/"|add:snippet.module|add:".html" with model=model %}
many thanks for #vorujack

Django: context of modified query list

I have a database with blog style documents, i.e., author's name, publication date, body text, etc.
I have built a django framework to output entries from the database as a result of a search term. That part is ok. The problem is that I want to show sections of the body text with the matched search terms highlighted (equivalent to a google search result). This means that I can't create a template tag with the body_text attribute only, because that text is not highlighted. I already did a function that receives as input the query and the body text and outputs the same text with the found search terms in bold.
My problem now is how do I pass this result to the html template?
Using the tutorial from Django documentation suppose you have the following views.py:
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
and the correspondent template:
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
Now suppose you have the function in views.py:
def signal_tokens(text,query_q):
...
return new_text
What should be the best way to replace the {{ question.question_text } with the output from signal_tokens? My solution was to replicate the context variable with a list of dictionaries, where each dictionary is a copy of each entry, except for the 'question_text' key, where I used signal_tokens result:
def index(request):
query_q = 'test'
latest_question_list = Question.objects.order_by('-pub_date')[:5]
new_context = []
for entry in latest_question_list:
temp_d = {}
temp_d['id'] = entry.id
temp_d['question_text'] = signal_tokens(entry.question_text,query_q)
new_context.append(temp_d)
context = {'latest_question_list': new_context}
return render(request, 'polls/index.html', context)
But the problem is that I need to copy all entries. Is there a more elegant way to solve this problem?
This is an ideal use case for a template filter. Move your highlight code to a file in the templatetags directory, register it as a filter, then you can call it from the template:
{{ question.question_text|highlight:query_q }}
Obviously you will need to pass query_q to the template context as well.

How to print model items in a template file?

I would like to show in the template file how many users I have and how many from them chose a language exam in English
How to display this information in an admin template file? (base.html) I tried something like this:
{{users.count()}}
I added an application "Userprofile" which is the form that user can choose an exam's language
class UserProfile(models.Model):
JEZYK = (
('DE', 'niemiecki'),
('FR', 'francuski'),
('EN', 'angielski'),
)
jezyk_egzaminu = models.CharField(max_length=6, choices=JEZYK, verbose_name='jezyk')
How can I show in a template file how many users chose 'EN', 'angielski' option ?
Thanks Catavaran I tried this solution but I do something wrong :(
I saved a file in a main project app "aplikacja" (aplikacja/aplikacja)
I added in base.html
{% load mytags %}
<div>Total users: {% user_count %}</div>
<div>English users: {% user_count 'EN' %}</div>
I get an error as return /admin/ site
Exception Type: TemplateSyntaxError
Exception Value:
'mytags' is not a valid tag library: Template library mytags not
found, tried
django.templatetags.mytags,django.contrib.admin.templatetags.mytags,django.contrib.staticfiles.templatetags.mytags
Pass the following context to the template:
{'users': UserProfile.objects.all(),
'en_users': UserProfile.objects.filter(jezyk_egzaminu='EN')}
And then call count() method:
<div>Total users: {{ users.count }}</div>
<div>English users: {{ en_users.count }}</div>
If you want to get user count in the admin's base.html then you have to create custom template tag:
from django import template
from myapp.models import UserProfile
register = template.Library()
#register.simple_tag
def user_count(lang=None):
users = UserProfile.objects.all()
if lang:
users = users.filter(jezyk_egzaminu=lang)
return users.count()
This code should be in the profil/templatetags/mytags.py file. And don't forget to create empty profil/templatetags/__init__.py file. See the docs for code layout.
Usage of this template tag in the base.html:
{% load mytags %}
<div>Total users: {% user_count %}</div>
<div>English users: {% user_count 'EN' %}</div>

Displaying complex dictionaries in Django Templates

I'm using Django 1.4 with Python 2.7 on Ubuntu 12.04.
I have a template that I want to fill with information regarding developers working on a project.
Each developer will have the following information to display:
type
title
first_name
last_name
skills
The trouble I'm running into is that each developer has many skills associated with them.
I've created the model like this:
class DevSkills(models.Model):
dev = models.ForeignKey(User)
skill = models.CharField(max_length = 200)
I'm trying to create a view that will populate the dictionary so that I can loop through each developer, display their info, then loop through each skill (to display them one at a time).
Here is the view:
def developers(request):
"""
.. function:: developers()
Provide the page that shows the developer credentials
:param request: Django Request object
"""
devs = User.objects.filter(is_staff = True)
dev_info = {}
for dev in devs:
dev_info.update(createDevDisplayDict(dev))
data = { 'user' : request.user }
data.update({ 'devs' : dev_info })
return render_to_response("developers.html", data)
I've designated the is_staff field from User to indicate the user is a developer.
I've created a simple utility that helps me populate the embedded dictionaries so I can loop through them:
def createDevDisplayDict(user):
"""
.. function:: createDevDisplayDict()
Create a dictionary for showcasing the developer
:param user: developer who we are working with
"""
userProfile = UserProfile.objects.get(user = user)
devSkills = DevSkills.objects.filter(dev = user)
dev_dict = {}
user_dict = { 'dev_type' : userProfile.dev_type,
'title' : userProfile.title,
'first_name' : user.first_name,
'last_name' : user.last_name,
}
dev_dict.update(user_dict)
skill_dict = {}
for skill in devSkills:
skill_dict.upate({ 'skill' : skill.skill })
dev_dict.update(skill_dict)
return dev_dict
My intention is to loop through each developer, create a "super" dictionary to contain each of their user_dict dictionaries (which are based on their User info) and add to that a dictionary for each of their skills. Then, back in the template I want to loop through the "super" dictionary in such a way that it will present them something like the following:
James Taylor
Project Lead
Software Developer
• Django
• Python
• JavaScript
• JQuery
Elizabeth Norton
Design Lead
Graphic Designer
• Edge
• Adobe Photoshop
• Adobe Illustrator
• CSS
Here is the template I'm trying to work with:
{% extends "base.html" %}
{% block content %}
<div>
<p>Our Developers</p>
</div>
{% for dev in devs %}
{{ dev.user_dict.first_name }} {{ dev.user_dict.last_name }}
{{ dev.user_dict.title }}
{{ dev.user_dict.dev_type }}
<ul>
{% for skill in dev.skill_dict %}
<li>skill.skill</li>
{% endfor %}
</ul>
{% endfor %}
{% endblock %}
When I see the page now it looks like this:
Our Developers
Yeah...nothing is getting populated. Any suggestions?
UPDATE 1:
I've modified my utility per iMom0's suggestion. I'm now using a list to contain each skill. Like so:
def createDevDisplayDict(user):
"""
.. function:: createDevDisplayDict()
Create a dictionary for showcasing the developer
:param user: developer who we are working with
"""
userProfile = UserProfile.objects.get(user = user)
devSkills = DevSkills.objects.filter(dev = user)
dev_dict = {}
user_dict = { 'dev_type' : userProfile.dev_type,
'title' : userProfile.title,
'first_name' : user.first_name,
'last_name' : user.last_name,
}
dev_dict.update(user_dict)
skills = []
for skill in devSkills:
skills.append(skill.skill)
skill_dict = {'skill' : skills}
dev_dict.update(skill_dict)
return dev_dict
I can see the value in doing this - in fact, it's much more intuitive and I think I was making it too hard the other way. But my template still shows up bare. :(
UPDATE 2:
I know I'm on the write path now. I put some logging in the view:
devs = User.objects.filter(is_staff = True, is_superuser = False)
dev_info = {}
for dev in devs:
dev_info.update(createDevDisplayDict(dev))
for key in dev_info:
for sub_key in dev_info[key]:
logfile.write('{0} = {1}\n'.format(sub_key, dev_info[key][sub_key]))
And the logfile displays:
skills = [u'Java', u'Perl', u'C++', u'Python', u'Django']
dev_type = Software Developer
first_name = Rico
last_name = Cordova
title = Owner
So, it has to be a way I'm calling it in the template, right?
UPDATE 3:
I had a realization that I was disconnecting the user_dict and their skills. So I modified the utility slightly to bring them into a single dictionary.
## Create a logging object
userProfile = UserProfile.objects.get(user = user)
devSkills = DevSkills.objects.filter(dev = user)
dev_dict = {}
user_dict = { 'dev_type' : userProfile.dev_type,
'title' : userProfile.title,
'first_name' : user.first_name,
'last_name' : user.last_name,
}
skills = []
for skill in devSkills:
skills.append(skill.skill)
user_dict.update({ 'skills' : skills })
dev_dict['user_dict'] = user_dict
return dev_dict
This is a much better solution, in my opinion. I'm still having trouble accessing the user_dict info in the template though. :(
You could be using Django's ORM features to make this a lot easier (and, we'll see, get better performance), it's a great feature!
Model code
class DevSkill(models.Model):
dev = models.ForeignKey(UserProfile, related_name = 'skill_set')
skill = models.CharField(max_length = 200)
We changed two things:
Using a UserProfile ForeignKey instead of user will simplify the rest of the code. Since you have a UserProfile <-> User mapping anyway, this is not going to be an issue.
We added a related_name attribute so that any UserProfile object now has a skill_set attribute which store it's list of DevSkills.
(Please note that related_name is not required, and Django will create a generic modelname_set attribute if you don't set it).
Also, DevSkill should be singular, the object is a single skill!
I also expect that you have the following for UserProfile, and created code assuming you did. You'll need to adapt if you don't.
class UserProfile(models.Model):
user = models.OneToOneField(User)
title = models.CharField(max_length = 40)
dev_type = # W/E you want
In the view:
devs = UserProfile.objects.all() # Or W/E queryset would fit.
# Pass context & all.
In the template:
{% extends "base.html" %}
{% block content %}
<div>
<p>Our Developers</p>
</div>
{% for dev in devs %}
{{ dev.user.first_name }} {{ dev.user.last_name }}
{{ dev.title }}
{{ dev.dev_type }}
<ul>
{% for skill in dev.skill_set.all %}
<li>skill.skill</li>
{% endfor %}
</ul>
{% endfor %}
{% endblock %}
Performance
Please be aware that this code (the one you're using now too, though) is going to absolutely kill performance. Indeed, we're doing several queries for each user (Hitting the database for their User and their DevSkills).
That's not a problem though, we can use the ORM's select_related and prefetch_related features to solve that issue:
devs = UserProfile.objects.select_related('user').prefetch_related('skill_set').all()
That way, we only do two queries, one for the UserProfile -> Userand one for the DevSkill's, for which the joining is done in Python, but you shouldn't care about that, Django does it for you.
Please be aware that prefetch_related is a Django 1.4 feature.
Footnote: the UserProfile stuff is going away in Django 1.5, check it out!
dict.update always overwrite the value of dict
In [2]: d = {'key': 'value'}
In [3]: d.update({'key': 'value1'})
In [4]: d
Out[4]: {'key': 'value1'}
Instead, you should use list and list.append.
And your template do not know what user_dict is, correct it,
dev_dict['user_dict'] = user_dict
This is a new concept for me - dict.items in a template. The following is exactly how I was able to display what I wanted.
{% extends "base.html" %}
{% block content %}
<div>
<p>Our Developers</p>
</div>
{% for key, value in devs.items %}
{{ value.first_name }} {{ value.last_name }} <br>
{{ value.title }} <br>
{{ value.dev_type }} <br>
<ul>
{% for skill in value.skills %}
<li>{{ skill }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endblock %}