Accessing session variable based on variable in for loop django template - python

I have some products listed which can be in a cart, this cart is stored in a session variable dictionary for which the key is the product id and the value is some information about the quantity and stuff. I want to add the option to view (on the products page) how many of that product are in your cart.
I know I can access session variables in a django template like this:
{{ request.session.cart.2323.quantity }}
Problem is, the key (2323 in this case) is a variable which depends on a for loop:
{% for prod in products %}
<p>{{ request.session.cart[prod.name].quantity }}</p>
{% endfor %}
But implementing it like that unfortunately is not possible. Is there any way in which this would be possible or would I have to change the way my cart works?

You should implement a custom template filter like this to have the ability to use getattr.
from django import template
register = template.Library()
#register.simple_tag
def get_object_property_dinamically(your_object, first_property, second_property):
return getattr(getattr(your_object, first_property), second_property)
{% load get_object_property_dinamically %}
{% for prod in products %}
<p>{% multiple_args_tag request.session.cart prod.name 'quantity' %}</p>
{% endfor %}

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 %}

Django generating the form tags instead of hardcoding them

I am having issues with having to hardcode the tags into the templates in Django. The reason I have issues is that I need to have the forms generated dynamically based on a framework I am working on.
That framework (written in Python) has a webinterface (hence Django) that requires forms for each module in the framework, depending on the data that needs to be submitted to that module.
So I am trying to get the form information (which fields, type of fields, labels etc.) from the module, which I currently am trying like so:
#framework/module.py
def form():
forms = '"upload": {"filename": "file","directory": "text"}'
return forms
The reason it is constructed like that, at this moment, is because I try to pass this information to the forms.py from Django so it can then be translated into what Django needs to create the output for the template.
Now I have tried a couple of ways on how to get it onto the template. The only problem is, that I have to create the form tags hardcoded into the template. I am trying to figure out how to get the form tags also generated dynamically based on the information supplied by the module. Because there could be modules that require multiple forms on the same page.
So in short, I am trying to do this:
{% for f in forms %}
{{f}}
{% endfor %}
Instead of this:
<form name="upload" action="foo" method="POST">
{{form}}
</form>
Is this possible in Django?
You can render your form fields manually in django, here is how.
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
EDIT: I didn't get the question properly
You could have your form tag attributes in a dictionary and iterate through your forms in a structure like this:
Python:
forms = {
form_object: {"name": "upload", "action": "foo", "method": "POST"}
}
Template:
{% for form, tag_attributes in forms.items %}
<form name="{{tag_attributes.name}}" action="{{tag_attributes.action}}" action="{{tag_attributes.method}}">
Do stuff with your {{form}}
</form>
{% endfor %}

how do i access the values in a session dynamically using django?

(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 %}

Django - create custom tag to acces variable by index in template

I have a HTML template in django. It get's two variables: list of categories (queryset, as it it returned by .objects.all() function on model in django) and dictionary of contestants. As a key of the dictionary, I'm using id of category, and value is list of contestats.
I want to print name of the category and then all the contestants. Now I have this:
{% for category in categories_list %}
<h1>category.category_name</h1>
{% for contestant in contestants_dict[category.id] %}
{{ contestant }} </br>
{% endfor %}
{% endfor %}
However, when I run it, I get error:
TemplateSyntaxError at /olympiada/contestants/
Could not parse the remainder: '[category.id]' from 'contestants_dict[category.id]'
What I know so far is that I can't use index in template. I thought that {% something %} contains pure Python, but it shoved up it's just a tag. I know that I have to create my own simple_tag, but I don't know how. I read the docs Writing custom template tags, but there is such a little information and I wasn't able to fiqure out how to create (and mainly use in a for loop) a tag, that will take dict, key and return the value. What I tried is:
templatetags/custom_tags.py:
from django import template
register = template.Library()
#register.simple_tag
def list_index(a, b):
return a[b]
and in template:
{% for contestant in list_index contestants_dict category.id %}
But I get TemplateSyntaxError.
Could you please explain/show me how to create the tag, or is there a better way to do this?
Thanks.
//EDIT:
I managed to do it this way:
{% list_index contestants_list category.id as cont %}
{% for contestant in cont %}
it works, but it takes 2 lines and I need to create another variable. Is there any way to do it without it?
If you don't want 2 lines like that you should be able to use a filter i think
#register.filter
def list_index(a, b):
return a[b]
Then the usage like this
{% for contestant in contestants_dict|list_index:category.id %}
{{ contestant }} </br>
{% endfor %}

Python/Django: Simple Django Template

Hi I am using App Engine/Python to do a simple website. I have some trouble with a Django template problem.
In short, I want to use a "ShortName" to access a "LongName".
The soource code:
LongName={"so":"stackoverflow","su":"superuser"}
ShortName=['so','su']
Then I pass these two parameters to the templates.
In the template I write:
{% for aname in ShortName %}
{{ aname }} stands for {{ LongName.aname }},
{% endfor %}
The output is:
so stands for, su stands for
No error is given. The LongName.aname wont work.
I have no idea whats wrong.
This is trying to access LongName['aname'], not LongName[aname].
You might have to write a custom template tag/filter to get this to work. This Django bug (marked WONTFIX) has a simple implementation:
def get(d, key):
return d.get(key, '')
register.filter(get)
which you would use by
{{ LongName|get:aname }}
after adding it to your app (that SO answer shows how to do it on GAE).
You could also pre-make a variable to loop over in the view, by passing in
# in view
name_abbrevs = [(k, LongName[k]) for k in ShortName]
# in template
{% for short_name, long_name in name_abbrevs %}
{{ short_name }} stands for {{ long_name }}
{% endif %}
If you really don't want to add a template tag -- which isn't that bad! you just make one file! :) -- or pass in an extra variable, Vic's approach will let you do this without touching the Python files at all. As he mentions, it involves a lot of pointless iteration, but it'll work fine for small lists.
Django templates have a drawback here. I've been in the same situation before. What you have to do is iterate over all the keys in LongName, and check if the key you're looking for matches the ShortName. Here you go:
{% for aname in ShortName %}
{% for short_version, long_version in LongName %}
{% if aname == short_version %}
{{ aname }} stands for {{ long_version }},
{% endif %}
{% endfor %}
{% endfor%}
It's inefficient, and essentially a pointless O(n^2) mechanism. However, there's no better way in pure Django templates to refer to entries of a dict by a variable name.

Categories

Resources