But create a request in each functions inside views.py I do not want.
Is it possible to output the model in each template using only one request?
I tried to use templateetags but
that so
#register.simple_tag(takes_context=True)
def header_categories(context):
return Categorie.objects.all().order_by('id')
what is like that
#register.simple_tag(takes_context=True)
def header_categories(context):
categories = Categorie.objects.all().order_by('id')
args = {}
for cat in categories:
args[cat.text] = {
'id':cat.id,
}
if cat.parent:
args[cat.text]['parent_id'] = cat.parent.id
args[cat.text]['parent_text'] = cat.parent.text
return args
Nothing works correctly
{% for cat in header_categories %}
cat.text
{% endfor %}
I tried through js
var arr = {%header_categories%}
but django changes everything
{'dresses': {'id': 19},
Before going deeper into your question, I think you should have
{% for cat in header_categories %}
{{ cat.text }}
{% endfor %}
You need to make a custom context processor (See Using RequestContext [Django docs]). What this would do is add a variable to the context for each template. Quoting the documentation:
The context_processors option is a list of callables – called
context processors – that take a request object as their argument and return a dictionary of items to be merged into the context.
In some suitable app of yours make a file named context_processors.py and add this code in it:
def header_categories(request):
return {'header_categories': Categorie.objects.all().order_by('id')}
Now in your settings in the TEMPLATES settings add this context processor to the list context_processors, so it should look like:
[
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'your_app.context_processors.header_categories',
]
Now in your templates you can simply write:
{% for cat in header_categories %}
{{ cat.text }}
{% endfor %}
Related
I need to check if the url is exactly:
http://127.0.0.1:8000/shop/
and based on this render a header.
If it is, for example:
http://127.0.0.1:8000/shop/stickers/stickers-por-hoja/medida-y-cantidad
Header shouldn't render.
I've read you can do something like this:
{% if "/shop/$" in request.path %}
{% include 'header.html' %}
{% endif %}
But this doesn't work. On the other hand this works, but is not what I need:
{% if "/shop/" in request.path %}
{% include 'header.html' %}
{% endif %}
So, Can I use regex in the if condition?
Create a context processor has_shop_in_url.py having this code below.
import re
def has_shop(request):
shop_in_request = your_regex_validation
return {
'has_shop_in_url': any([shop_in_request]) }
Add that context processor
TEMPLATES = [
{
.....
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'your_module.has_shop_in_url.has_shop' # YOUR PROCESSOR
],
},
},
]
Now it is available for your whole web application. In template just write {{has_shop_in_url}}. Your can see True/False.
You could move the regex check into the view and add a field to the context for the template like so:
class MyView(View):
def action(self, request, *args, **kwargs):
shop_in_request = re.findall(r"/shop/$", request.path)
context = {"include_header": any(shop_in_request)}
return render(template, context)
Then in your view you could use:
{% if include_header %}
{% include 'header.html' %}
{% endif %}
Create a template tag to do that.
The url whitelisted must be somewhere in the settings. For example you can add something like this
HEADER_WHITELIST_URLS = (
'regex1',
'regex2',
)
2) Your template tags will check the current URL and if one of the regex matches, you can render your header. In a hypothetical version2, you can also add the header to show for a specific regex.
Use this snippet as starting point for your template tag
import datetime
from django import template
from django.conf import settings
register = template.Library()
#register.simple_tag(takes_context=True)
def render_header(context, format_string):
regexs = settings.HEADER_WHITELIST_URLS
# maybe you can add some try/exception if the settings is not available.
for regex in regexs:
# test the regex with the url in the context.
# if matches return the code to render the header and break
return None
Check here for more details about the template tags: https://docs.djangoproject.com/en/2.1/howto/custom-template-tags/#writing-custom-template-tags
mydict = {"key1":"value1", "key2":"value2"}
The regular way to lookup a dictionary value in a Django template is {{ mydict.key1 }}, {{ mydict.key2 }}. What if the key is a loop variable? ie:
{% for item in list %} # where item has an attribute NAME
{{ mydict.item.NAME }} # I want to look up mydict[item.NAME]
{% endfor %}
mydict.item.NAME fails. How to fix this?
Write a custom template filter:
from django.template.defaulttags import register
...
#register.filter
def get_item(dictionary, key):
return dictionary.get(key)
(I use .get so that if the key is absent, it returns none. If you do dictionary[key] it will raise a KeyError then.)
usage:
{{ mydict|get_item:item.NAME }}
Fetch both the key and the value from the dictionary in the loop:
{% for key, value in mydict.items %}
{{ value }}
{% endfor %}
I find this easier to read and it avoids the need for special coding. I usually need the key and the value inside the loop anyway.
You can't by default. The dot is the separator / trigger for attribute lookup / key lookup / slice.
Dots have a special meaning in template rendering. A dot in a variable
name signifies a lookup. Specifically, when the template system
encounters a dot in a variable name, it tries the following lookups,
in this order:
Dictionary lookup. Example: foo["bar"]
Attribute lookup. Example: foo.bar
List-index lookup. Example: foo[bar]
But you can make a filter which lets you pass in an argument:
https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-filters
#register.filter(name='lookup')
def lookup(value, arg):
return value[arg]
{{ mydict|lookup:item.name }}
For me creating a python file named template_filters.py in my App with below content did the job
# coding=utf-8
from django.template.base import Library
register = Library()
#register.filter
def get_item(dictionary, key):
return dictionary.get(key)
usage is like what culebrón said :
{{ mydict|get_item:item.NAME }}
I had a similar situation. However I used a different solution.
In my model I create a property that does the dictionary lookup. In the template I then use the property.
In my model: -
#property
def state_(self):
""" Return the text of the state rather than an integer """
return self.STATE[self.state]
In my template: -
The state is: {{ item.state_ }}
Environment: Django 2.2
Example code:
from django.template.defaulttags import register
#register.filter(name='lookup')
def lookup(value, arg):
return value.get(arg)
I put this code in a file named template_filters.py in my project folder named portfoliomgr
No matter where you put your filter code, make sure you have __init__.py in that folder
Add that file to libraries section in templates section in your projectfolder/settings.py file. For me, it is portfoliomgr/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'libraries':{
'template_filters': 'portfoliomgr.template_filters',
}
},
},
]
In your html code load the library
{% load template_filters %}
Since I can't comment, let me do this in the form of an answer:
to build on culebrón's answer or Yuji 'Tomita' Tomita's answer, the dictionary passed into the function is in the form of a string, so perhaps use ast.literal_eval to convert the string to a dictionary first, like in this example.
With this edit, the code should look like this:
# code for custom template tag
#register.filter(name='lookup')
def lookup(value, arg):
value_dict = ast.literal_eval(value)
return value_dict.get(arg)
<!--template tag (in the template)-->
{{ mydict|lookup:item.name }}
env: django 2.1.7
view:
dict_objs[query_obj.id] = {'obj': query_obj, 'tag': str_tag}
return render(request, 'obj.html', {'dict_objs': dict_objs})
template:
{% for obj_id,dict_obj in dict_objs.items %}
<td>{{ dict_obj.obj.obj_name }}</td>
<td style="display:none">{{ obj_id }}</td>
<td>{{ forloop.counter }}</td>
<td>{{ dict_obj.obj.update_timestamp|date:"Y-m-d H:i:s"}}</td>
mydict = {"key1":"value1", "key2":"value2"}
The regular way to lookup a dictionary value in a Django template is {{ mydict.key1 }}, {{ mydict.key2 }}. What if the key is a loop variable? ie:
{% for item in list %} # where item has an attribute NAME
{{ mydict.item.NAME }} # I want to look up mydict[item.NAME]
{% endfor %}
mydict.item.NAME fails. How to fix this?
Write a custom template filter:
from django.template.defaulttags import register
...
#register.filter
def get_item(dictionary, key):
return dictionary.get(key)
(I use .get so that if the key is absent, it returns none. If you do dictionary[key] it will raise a KeyError then.)
usage:
{{ mydict|get_item:item.NAME }}
Fetch both the key and the value from the dictionary in the loop:
{% for key, value in mydict.items %}
{{ value }}
{% endfor %}
I find this easier to read and it avoids the need for special coding. I usually need the key and the value inside the loop anyway.
You can't by default. The dot is the separator / trigger for attribute lookup / key lookup / slice.
Dots have a special meaning in template rendering. A dot in a variable
name signifies a lookup. Specifically, when the template system
encounters a dot in a variable name, it tries the following lookups,
in this order:
Dictionary lookup. Example: foo["bar"]
Attribute lookup. Example: foo.bar
List-index lookup. Example: foo[bar]
But you can make a filter which lets you pass in an argument:
https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-filters
#register.filter(name='lookup')
def lookup(value, arg):
return value[arg]
{{ mydict|lookup:item.name }}
For me creating a python file named template_filters.py in my App with below content did the job
# coding=utf-8
from django.template.base import Library
register = Library()
#register.filter
def get_item(dictionary, key):
return dictionary.get(key)
usage is like what culebrón said :
{{ mydict|get_item:item.NAME }}
I had a similar situation. However I used a different solution.
In my model I create a property that does the dictionary lookup. In the template I then use the property.
In my model: -
#property
def state_(self):
""" Return the text of the state rather than an integer """
return self.STATE[self.state]
In my template: -
The state is: {{ item.state_ }}
Environment: Django 2.2
Example code:
from django.template.defaulttags import register
#register.filter(name='lookup')
def lookup(value, arg):
return value.get(arg)
I put this code in a file named template_filters.py in my project folder named portfoliomgr
No matter where you put your filter code, make sure you have __init__.py in that folder
Add that file to libraries section in templates section in your projectfolder/settings.py file. For me, it is portfoliomgr/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'libraries':{
'template_filters': 'portfoliomgr.template_filters',
}
},
},
]
In your html code load the library
{% load template_filters %}
Since I can't comment, let me do this in the form of an answer:
to build on culebrón's answer or Yuji 'Tomita' Tomita's answer, the dictionary passed into the function is in the form of a string, so perhaps use ast.literal_eval to convert the string to a dictionary first, like in this example.
With this edit, the code should look like this:
# code for custom template tag
#register.filter(name='lookup')
def lookup(value, arg):
value_dict = ast.literal_eval(value)
return value_dict.get(arg)
<!--template tag (in the template)-->
{{ mydict|lookup:item.name }}
env: django 2.1.7
view:
dict_objs[query_obj.id] = {'obj': query_obj, 'tag': str_tag}
return render(request, 'obj.html', {'dict_objs': dict_objs})
template:
{% for obj_id,dict_obj in dict_objs.items %}
<td>{{ dict_obj.obj.obj_name }}</td>
<td style="display:none">{{ obj_id }}</td>
<td>{{ forloop.counter }}</td>
<td>{{ dict_obj.obj.update_timestamp|date:"Y-m-d H:i:s"}}</td>
I have a problem trying to figure out why below will render an html page showing 'hi' and 1, instead of just 1.
views method.
def index(request):
context = {
'test' : 1,
}
return render(request, 'index.html', context)
template html. Rendering index.html will show both 'hi' and 1. But there's no user in context, so why is the if user going through?
{% if user %}
<h1>hi</h1>
{% endif %}
{% if test %}
<h1>{{ test }}</h1>
{% endif %}
The answer is Django's builtin context processor called django.contrib.auth.context_processors.auth. It is enabled by default which means an auth.User object representing the currently logged-in user is sent to all templates with the name user automatically.
From docs:
The context_processors option is a list of callables – called context processors – that take a request object as their argument and return a dictionary of items to be merged into the context.
In the default generated settings file, the default template engine contains the following context processors:
[
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
]
if there is a user logged in django will create a AUTH_USER_MODEL representing the currently logged-in user. Also from the request object you can access the user model without specifying context. For example if a user is logged in you can do request.user.username and the username will appear in the template.
hopefully this is a rather simple question.
If i have the following stored in request.session. Assuming i have multiple items (only one shown here), I'd like to be able to loop over these items and render them as part of a template.
How can i access the quantity key and value for use within a for loop?
Here's what I'm trying, however there's no output.
{% for item in request.session.bookingContents.items %}
{{ item.quantity }}
{% endfor %}
Variable:
'bookingContents'
Value:
{u'cartID': 51,
u'items':
{u'1':
{
u'quantity': 25},
}
}
}
Further information (updated as this question evolves):
Active template context processors are:
'django.core.context_processors.request',
'django.contrib.auth.context_processors.auth',
#allauth specific template processors below
'allauth.account.context_processors.account',
'allauth.socialaccount.context_processors.socialaccount',
'django.contrib.messages.context_processors.messages',
You need to add django.core.context_processors.request to your template context processors.
Add this to your settings.py
from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP
TEMPLATE_CONTEXT_PROCESSORS = TCP + (
'django.core.context_processors.request',
)
Then you can access the session from your templates like this and your code should work:
{{ request.session.foo}}
UPDATE:
Ok your settings and view is fine, then you could try:
{% for key, value in request.session.bookingContents.items.items %}
{{ value.quantity }}
{% endfor %}