I'm working to add some business details as a context processor within an app called Business. I've included in it a folder titled templatetags for the __init__.py and business_tags.py files. My problem is while the context processor shows a result, I am unable to display the results as a loop.
business_tags.py file:
from django import template
register = template.Library()
from django.contrib.auth.models import User
from ..models import Businessprofile
#register.simple_tag
def my_biz(request):
current_user = request.user.id
biz = Businessprofile.objects.filter(owner=current_user)
return biz
On my view file I am currently made a for/endfor for the loop:
<!--content-->
{% load business_tags %}
{% my_biz request %}
{% for biz in my_biz %}
{{ biz }}
{% endfor %}
<!--end content-->
How do I display the results of the context processor as a for loop?
Your simple tag is just returning the object (it is not saved in "my_biz"), you need to save the return in a variable in this way:
{% my_biz request as my_biz_var %}
{% for biz in my_biz_var %}
{{ biz }}
{% empty %}
my_biz_var is empty
{% endfor %}
Aditional note: as is pointed by Daniel Roseman, what you are doing is not a context processor but a simple tag.
context procesors:
https://docs.djangoproject.com/en/1.11/ref/templates/api/#django.template.RequestContext
Simple tags:
https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/#simple-tags
Related
I am creating a database website with python and django. My problem is that the content I try to get data from my class' fields doesn't appear on the id-page on django. I am able to make a successful search, and I get links for my searches. The name-field is visible in searches and on the page, but nothing else appears. When I click on the link, I go to luokka_id/number. I must be missing something but can't figure out what the problem is.
models.py
class luokka(models.Model):
nimi = models.CharField('Pääkäyttöluokka', max_length=100)
vara = models.CharField('Varakäyttöluokka', max_length=100)
varaaja = models.CharField('Varakäyttöluokka', max_length=100)
def __str__(self):
return self.nimi
and on the näytä_luokka.html (show class):
{% extends 'tietokanta/base.html' %}
{% block content %}
<center>
{{luokkalistaus}}
{{luokka}}
{{ luokka.nimi }}
{{ luokka.vara }}
{{ luokka.varaaja }}
</center>
{% endblock %}
and views.py:
def näytä_luokka(request, luokka_id):
luokkalistaus = luokka.objects.get(pk=luokka_id)
return render(request, 'tietokanta/näytä_luokat.html',
{'luokkalistaus': luokkalistaus})
I don't get any errors to help me out here. It's just an empty page, but it should show some extra data.
You have named the key of context as luokkalistaus not luokka, so the template should be:
{% extends 'tietokanta/base.html' %}
{% block content %}
<center>
{{ luokkalistaus.nimi }}
{{ luokkalistaus.vara }}
{{ luokkalistaus.varaaja }}
</center>
{% endblock %}
I currently following a tutorial at https://wsvincent.com/django-allauth-tutorial-custom-user-model/
I look at how they implemented home view.
pages/views.py
# pages/views.py
from django.views.generic import TemplateView
class HomePageView(TemplateView):
template_name = 'home.html'
templates/home.html
<!-- templates/home.html -->
<h1>Django Login Mega-Tutorial</h1>
{% if user.is_authenticated %}
<p>Hi {{ user.username }}
<p>Log out</p>
{% else %}
<p>Sign Up</p>
<p>Log In </p>
{% endif %}
However, I don't see how user variable is being passed to the home view template (templates/home.html). May I know how that happen?
Assuming you have the default template CONTEXT_PROCESSORS in your settings module, one of which includes django.contrib.auth.context_processors.auth which sets the user variable in all of your templates.
Also, you can look at the source code.
(Django , Python) I have created a list of book objects and it is being passed as context in my views.py along with the current session. On my template, i was to check if the books in that list are stored in the session, and if they are i want to access some info relating to that book within that session. how do i access the books in the session dynamically? is there a way?
i know i can access them by using "request.session.name" (where "name" is the same of the space in the session it is stored)
There are several book titles saved in the session, the way they are saved are as follows (in a function under views.py)
request.session["random book title"] = "random dollar price"
i want to access that "random dollar price" dynamically in a template.
this is the block of code in the template
{% for book in book_list %}
{% if book.title in request.session %}
{{ request.session.??? }}
{% endif %}
{% endfor %}
Thank you in advance!
You can make a custom template tag to look up by attribute like here
Performing a getattr() style lookup in a django template:
# app/templatetags/getattribute.py
import re
from django import template
from django.conf import settings
numeric_test = re.compile("^\d+$")
register = template.Library()
def getattribute(value, arg):
"""Gets an attribute of an object dynamically from a string name"""
if hasattr(value, str(arg)):
return getattr(value, arg)
elif hasattr(value, 'has_key') and value.has_key(arg):
return value[arg]
elif numeric_test.match(str(arg)) and len(value) > int(arg):
return value[int(arg)]
else:
return settings.TEMPLATE_STRING_IF_INVALID
register.filter('getattribute', getattribute)
Now change your template to
{% load getattribute %}
{% for book in book_list %}
{% if book.title in request.session %}
{{ request.session|getattribute:book.title }}
{% endif %}
{% endfor %}
This is a basic custom template tag example:
Django - Simple custom template tag example
and docs:
https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/
From what I remember from my django days should work
You can put session data in a dictionary and send this data to target template when you want to render it in view function.
def some_function(request):
context={
'data':sessionData #put session data here
}
return render(request,"pass/to/template.html",context)
Now you can access 'data' in your template.html
I think you should just send a list of book names from your view instead of a queryset so when you are crosschecking with session you use the title directly instead.
{% for book in book_list %}
{% if book in request.session %}
{{ request.session.book }}
{% endif %}
{% endfor %}
I am making kind of dynamic menu. when you click menu on the top, it show sub menu on the left side. I searched with keyword 'dynamic menu' from stackoverflow and google. I got idea to build that kind of menu. I made it like below.
1) render data(menu list) in context to template by custom context processor.
2) using custom template tag which is provided by django-mptt package.
3) show top menu in base template.
4) move to another template to show sub menu according to what top menu you click
I made custom context_processor to use menu in context in every template.
context_processor.py
from manager.models import Menu
def menu(request):
menu_list = list(Menu.objects.all())
return {'menu':menu_list}
template.py(example)
{% load mptt_tags %}
<nav id="{{ menu_id }}" class="tree-menu">
<ul>
{% recursetree menu %}
<li class="menu
{% if node.is_root_node %}root{% endif %}
{% if node.is_child_node %}child{% endif %}
{% if node.is_leaf_node %}leaf{% endif %}
{% if current_menu in node.get_descendants %}open{% else %}closed{% endif %}
">
{{ node.menu_name }}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
{% if node.items and node.items.exists %}
<ul class="items">
{% for item in node.items.all %}
{% if item_template %}
{% include item_template %}
{% else %}
{% include "menu/tree-item.html" %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
</nav>
mptt_tags.py
#register.tag
def recursetree(parser, token):
"""
Iterates over the nodes in the tree, and renders the contained block for each node.
This tag will recursively render children into the template variable {{ children }}.
Only one database query is required (children are cached for the whole tree)
Usage:
<ul>
{% recursetree nodes %}
<li>
{{ node.name }}
{% if not node.is_leaf_node %}
<ul>
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
"""
bits = token.contents.split()
if len(bits) != 2:
raise template.TemplateSyntaxError(_('%s tag requires a queryset') % bits[0])
queryset_var = template.Variable(bits[1])
template_nodes = parser.parse(('endrecursetree',))
parser.delete_first_token()
return RecurseTreeNode(template_nodes, queryset_var)
My Question
If you see django manual about QuerySet, it says that "Each QuerySet contains a cache to minimize database access". It is obvious that, if you query same data in certain rule, it doesn't seem hit database again but return result from cache. Then I am querying Menu.objects.all() in custom context processor. This result(menu_list = Menu.objects.all()) will be in context every time, you can use menu data on every template repeately. So does it reuse the result from cache without hitting database again?
If menu_list = Menu.objects.all() in custom context processor hit database every time whenever template load this menu list, Does it work in this way to reuse menu data from cache without hitting database everytime?
context_processors.py
from manager.models import Menu
from django.core.cache import cache
def menu(request):
menu_list = cache.get_or_set('menu_list', list(Menu.objects.all()))
return {'menu':menu_list, 'redis':"Food"}
Lastly, I don't know if there are many people using django-mptt package. I guess just a few people have experience using it in person. It says "Only one database query is required (children are cached for the whole tree)" so does it mean if I use django-mptt package and get menu from it on template, it automatically cache its data?
Well, I am not clear about django cache system.
It would be really appreciate if you can give me answer and insight for my questions. Thanks for reading!
I am working on a small web app to view some logfiles. But the
queries I issue to the database use to get very big.
I wanted to implement some pagination following this example pagination.
I put the class into a single file which gets loaded in the Flask view. Next I implemented
my pagination view like this:
#app.route('/index/', defaults={'page':1})
#app.route('/index/page/<int:page>')
def index(page):
count = db_session.execute("select host,facility,level,msg from messages").rowcount
tblqry = db_session.execute("select host,facility,level,msg from messages").fetchmany(size=1000)
if not tblqry and page != 1:
abort(404)
pagination = Pagination(page, PER_PAGE, count)
return render_template('index.html', pagination=pagination, tblqry=tblqry)
after that I created a macro file named _pagination_helper.html with the macro contents from the macro example. Then I imported the pagination_helper macro with:
{% from "_pagination_helper.html" import render_pagination %}
but when I then try to do something like this:
{{ render_pagination(host[0]) }}
flask claims:
UndefinedError: 'str object' has no attribute 'iter_pages'
so why does flask fails to find the 'iter_pages' because I included the pagination class in the views file?
And also I am not really sure where to put the URL Generation Helper from the How To.
Edit:
This is what my pagination_helper looks like:
{% macro render_pagination(pagination) %}
<div class=pagination>
{% for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
{{ page }}
{% else %}
<strong>{{ page }}</strong>
{% endif %}
{% else %}
<span class=ellipsis>…</span>
{% endif %}
{%- endfor %}
{% if pagination.has_next %}
Next »
{% endif %}
</div>
{% endmacro %}
You are expected to pass a Pagination object to the macro, not a string. host[0] is a string, not the pagination value you created in your view function.
Use:
{{ render_pagination(pagination) }}