Django multiselect checkboxes - python

I have a list of objects, each with it's own checkbox, where the user can select multiple of these. The list is a result of a query.
How can I mark in the view which checkboxes are already selected? There doesn't seem to be an in operator in the template language.
I want something along the lines of:
<input {% if id in selectedIds %}checked {% endif %}>

You could use a templatetag like the one in this snippet comments:
http://www.djangosnippets.org/snippets/177/
#register.filter
def in_list(value,arg):
return value in arg
To be used in templates:
The item is
{% if item|in_list:list %}
in list
{% else %}
not in list
{% endif %}
Not very smart, but it works.

Related

Looping through nested dictionary in Django template

My context dictionary for my Django template is something like the following:
{'key1':'1',
'key2':'2',
'key3':'3',
'key4':{'key5':{'key6':'6', 'key7':'7', 'key8':'8'}}}
I would like to iterate through the dictionary and print something like:
some label = 6
some label = 7
some label = 8
How can I achieve this in my Django template?
What's wrong with this ?
<ul>
{% for key, value in key4.key5.items %}
<li>{{ key }} : {{ value }}</li>
{% endfor %}
</ul>
NB: you didn't ask for looping over all keys in the context, just about accessing key4['key5'] content. if this wasn't wath you were asking for pleasit eadit your question to make it clearer ;-)
I am guessing you want to use a for loop in the django template to do this you must first pass the dictionary to the template in the views file like so make sure you add square brackets around the dictionary like this:
data = [{'key1':'1',
'key2':'2',
'key3':'3',
'key4':{'key5':{'key6':'6', 'key7':'7', 'key8':'8'}}
}]
return render(request,'name of template',{'data':data})
then in the html template:
{% for i in data%}
<p>{{i.key1}}</p>
<p>{{i.key2}}</p>
<p>{{i.key3}}</p>
<p>{{i.key4.key5.key6}}</p>
{% endfor %}
Now when you do the for loop you can access all the iteams in key4 like i have above when I put {{i.key4.key5.key6}}
Here is the docs for the for loop in django templates https://docs.djangoproject.com/en/3.0/ref/templates/builtins/
I am assuming thats what you want to do.
This has worked for me:
{% for key, value in context.items %}
{% ifequal key "key4" %}
{% for k, v in value.items %}
some label = {{ v.key6 }}
some label = {{ v.key7 }}
some label = {{ v.key8 }}
{% endfor %}
{% endif %}
{% endfor %}
If you want to print only what you have mentioned in question then it is possible but if we don't know the exact structure of dictionary then it is possible in django views not in django template.
You can't print value which is also a dictionary one by one in django template,
But you can do this in django view.
Check this post click here and do some changes in views.

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

Django filter field on the context processor

I want to filter a result of a field in django in an html file.
Something like this
{{ model.field where id = 2 }}
I've been looking for in django docs but i only could find a way to do it on the views.py.
I also so something like javascript when u write a "|" simbol after the request but i still couldnt archieve it
You can use the {% if %} template tag. So:
{% if model.field == 2 %}
# do something
{% endif %}
Here is the official documentation:
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#operator
Edit:
If model.field has a value of 2 then it just needs to be the above.
Edit 2:
Without seeing your code, it is hard to tell, but here is how to filter for Users based on Gender in a template:
{% for user in users %}
{% if user.gender == "male" %}
# do something
user.username
{% endif %}
{% endfor %}

How can I tell if a value is a string or a list in Django templates?

I've got a tuple of values I'm iterating in a Django template (1.4). Some of the values are strings which must just print out, others are tuples containing strings, which must be iterated themselves to print out their values. Is there a way, within the template, that I can decide if a given value, as I iterate over the master tuple, is a string or a list (tuple) ?
There's no builtin way to do so. A (somewhat dirty IMHO) workaround would be to implement a custom "is_string" filter, but the best solution would be to preprocess the values in the view to make it an uniform list of tuples (or list).
for the filter solution:
#register.filter
def is_string(val):
return isinstance(val, basestring)
and then in your templates:
<ul>
{% for whatever in something %}
<li>
{% if whatever|is_string %}
{{ whatever }}
{% else %}
<ul>
{{ whatever|unordered_list }}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
cf the excellent Django doc for more on custom filters and templatetags:
https://docs.djangoproject.com/en/stable/howto/custom-template-tags/
You can create an isinstance filter in the view or a helper module:
from django.template.defaultfilters import register
#register.filter(name="isinstance")
def isinstance_filter(val, instance_type):
return isinstance(val, eval(instance_type))
Then in the template you could do:
{% load isinstance %}
{% if some_value|isinstance:"list" %}
// iterate over list
{% else %}
// use string
{% endif %}

Django templates: accessing the previous and the following element of the list

I am rather new to django templates and have an impression that I have not understood some basics.
I have a list of elements and I need to render an element of the list based on conditions against the the previous and the next elements (in case the following or the previous elements are hidden, I need to mark the current element as border element).
How can I reference the previous and the following elements within a for loop in Django templates?
You could write a custom template filter for next and previous:
def next(value, arg):
try:
return value[int(arg)+1]
except:
return None
and in the template:
{% for ... %}
{% with list|next:forloop.counter0 as next %}
{% if next.is_hidden %}
...
{% endif %}
{% endwith %}
{% endfor %}
but like others have said, there are probably more elegants solutions doing this via your view
You can't do this strictly with built-in template tags. You need to involve some Python.
One method would be to zip the list with itself:
new = ([(None, orig[0], orig[1])] +
zip(orig, orig[1:], orig[2:]) +
[(orig[-2], orig[-1], None)])
and pass that to the template, then loop over it like this:
{% for prev, current, next in new %}
{% if prev.hidden or next.hidden %}
BORDER
{% endif %}
{{ current }}
{% endfor %}
You really shouldn't use the Django templates for this kind of logic. You have your views to handle it. I would figure out which elements of the list are borders and pass in an extra parameter that I can handle in the template using a simple if statement. For example:
{% for element,is_border in data.items %}
{% if is_border %}
do something
{% endif %}
{% endfor %}
There are tons of similar ways you can do this. I presented just one example.
You can create an external tag which does that but django templating system which was build to be lightweight has no such feature in for loops.

Categories

Resources