Django template if statement return wrong value - django

In my home page I have blog, on the right side there is Posts category list like:
Sports
Crime
and etc.. I try to make that when I'm in certain category that active category button will be highlighted.
I'm doing that by setting GET parameter to my home page like: /?category=1
NOW... In index.html template I'm doing this:
{% for category in category_list %}
{{ category.pk }} != {{ request.GET.category }} // This is for debugging. Returns 1==1
{% if category.pk == request.GET.category %}
<li>{{ category }}<span class="pull-right">({{ category.post_set.count }})</span></li>
{% else %}
<li class="active">{{ category }}<span class="pull-right">({{ category.post_set.count }})</span></li>
{% endif %}
{% endfor %}
But this is not working. Any suggestions how to solve this, maybe there is another way?
EDITED:
I figured that category.pk returns int and request.GET.category returns string. Next question. How to convert int<==>string, so I could compare them?

It worked by doing this:
{% if category.pk != request.GET.category|add:"0" %}
apparently |add:"0" converts string to int.

Related

Passing parameters to template for NavBar menu in Django

I am trying to switch my head to start using MVC.
I have a Base HTML template, with an include NavBar code:
{% include "navBar.html" %}
So far, so good. Now, I want to send information to it (to the navBar.html template) regarding the Menu buttons. I have some simple buttons, and others with drop-button behavior.
My buttons are objects, they have information about name, href, position, etc, type (simple-button or drop-button)
So, I created a nested list in this way:
outer_list = []
for a in UserModule.objects.filter(user=user_id, is_active=True):
inner_list = []
inner_list.append(UserModule(a))
for b in Submodule.objects.filter(module=a.module, is_active=True):
inner_list.append(Submodule(b))
outer_list.append(inner_list)
return {'outer_list': outer_list}
So, my first element in every inner_list is the head of the possible drop-button or a simple button depending on his type attribute.
The list at the end is like this:
[0] Button-Simple-A
[1] Button-Drop-A => [sub-button-1, sub-button-2, sub-button-3]
[2] Button-Simple-B
and so on.
When I pass this outer_list to the template, the thing I have to do to arrange the buttons into the menu are crazy things. It has no sense to use MVC if I am going to write a lot of code in the template.
Until now, I am doing this over the template, and It is missing the first element identification, to recognize the button type, etc...
{% with isFirst=true %}
{% for inner_list in outer_list %}
{% for object in inner_list %}
{% if isFirst == true %}
<li><a href=#>Drop_parent</a></li>
{% else %}
<li><a href=#>Drop-Child</a></li>
{% endif %}
{% endfor %}
<li><a href=#>Static Button</a></li>
{% endfor %}
{% endwith %}
It is not finished at all, but I believe I am taking the wrong way.
Good advice will be thankful.
Thanks
Finally,
I got something that works. I would like to know if this is acceptable or there is another better way.
On the view side:
for a in UserModule.objects.filter(user=user_id, is_active=True):
x = Module.objects.get(id=a.module_id, is_active=True)
if x.type == 'drop-parent':
list.append(x)
for b in Submodule.objects.filter(module=a.module_id, is_active=True):
list.append(b)
list.append('drop_end')
return {'menu_list': list}
On the template site:
{% for object in menu_list %}
{% if object.type == 'drop-parent' %}
<li class="dropdown">
{{object.name}}
<div class="dropdown-content">
{% endif %}
{% if object.type == 'drop-child' %}
<a href=#>{{ object.name }}</a>
{% endif %}
{% if object == 'drop_end' %}
</div>
</li>
{% endif %}
{% endfor %}
Another question: Why adding the class identifier inside the list, I can not see the attributes in the template? I mean list.append(Module(x)) is not seen as an object Module inside template; otherwise, if I avoid adding the class I can access the attributes.
Thanks, I appreciate it

if-statement doesn't work in for-loop

I have an issue with the if-statement and need some help. This is a short code-snippet in html:
{% for category in categories %}
{% if category == 'christmas' %}
<p>{{category}} 1</p>
{% else %}
<p>{{category}} 2</p>
{% endif %}
{% endfor %}
With the for-loop I walk through categories and check them with an if-statement for the string 'christmas'. The paragraph is always the second one, ending with a 2. Still, it appears that the category with the name 'christmas' comes up. That means, that in the if-statement "category" is different than in the p-tag. In fact, category is empty in the if-statement.
Why? Can someone help here, please. Thanks!
Edit: Added two pictures. On the right you see the output:
length is zero
showing no fit, although it should
I'm guessing you're looping over category objects from a model meaning categories is not a list of strings but a queryset? In that case you should do something like this:
{% for category in categories %}
{% if category.name == 'christmas' %}
<p>{{category}} 1</p>
{% else %}
<p>{{category}} 2</p>
{% endif %}
{% endfor %}
Replace .name by whatever your correct attribute is.
Your {{category}} is probably displayed correctly because of your __unicode__ or __str__ method.

Rendering template object in an if comparison string

I've been trying to do this and getting no results
<ul>
{% for topic in topics %}
<li {% if request.get_full_path == "/topic/{{ topic.topic_slug }}/" %}class="is-active"{% endif %}>
{{ topic.topic_name }}
</li>
{% endfor %}
</ul>
The error, I'm guessing is from the {{ topic.topic_slug }} being rendered in the string. I'd like it to be "/topic/tech/" during rendering but that seems not to be working.
I don't believe you can use {{ }} inside a {% %} so you need to do this in a different way. There are many possibilities.
Try using
{% if request.get_full_path == "/topic/"+topic.topic_slug+"/" %}
but the way I would do it is to simply use your class to do the work of returning the path. /topic/tech/ looks like what people usually return from a get_absolute_url class function:
class Topic:
...
def get_absolute_url(self):
return '/topic/{}/'.format(self.topic_slug)
and then in your template, simply use:
{% if request.get_full_path == topic.get_absolute_url %}
(Note that if you already have an absolute_url, simply use another function name. e.g. get_my_topic_slug_url()).

Detect row difference (view or model)?

I would like to display a list of publications on my website; however, I would also like to diaplay a header stating the year for each set of publications published on that particular year.
So I would like for my end result to be like this (my reputation is 1 :( I could not upload the image):
https://dl.dropboxusercontent.com/u/10752936/Screen%20Shot%202013-06-21%20at%206.00.15%20PM.png
I have a table with three columns; id (primary key), title (the title of the article), and date (the date of publications)
In my template file; doing the following will print the header before every article:
{% for curr_pub in all_publications %}
<h1>{{ curr_pub.date.year }}</h1>
<li>{{ curr_pub.title }}</li>
{% endfor %}
I am passing all_publications ordered by '-date' which means that I can compare the year of the current row curr_pub with the previous one and check if it differs or not; and print (or not print) the header accordingly. It seems however, that I cannot do that in the template.
Since I am new to Django and Python, I wasn't sure what to do and this is where I need help; my thoughts were the following:
1) Add a function in the model (def is_it_first_publication(self):) that returns true or false - but I really wasn't able to do that :| - ...and I'm not sure if that is what I needed to do or not!
2) Second one is to do in in the view, and pass extra variable(s) to the template; here's an example (which works just fine for this case):
In the view:
def publications(request):
all_publications = Publications.objects.order_by('-date')
after_first_row_flag = False
f_year = 'Null'
list_of_ids_of_first_publications = []
for curr_pub in all_publications:
if after_first_row_flag:
if curr_pub.date.year != f_year:
list_of_ids_of_first_publications.append(curr_pub.id)
f_year = curr_pub.date.year
else:
# The year of first (or earliest) publication has to be added
#
list_of_ids_of_first_publications.append(curr_pub.id)
f_year = curr_pub.date.year
after_first_row_flag = True
template = loader.get_template('counters/publications.html')
context = RequestContext(request, {
'all_publications': all_publications,
'list_of_first_publications': list_of_ids_of_first_publications,
})
return HttpResponse(template.render(context))
In the template:
{% for curr_pub in all_publications %}
{% if curr_pub.id in list_of_first_publications %}
<h1> {{ curr_pub.date.year }} </h1>
{% endif %}
<li> Placeholder for [curr_pub.title] </li>
{% endfor %}
The regroup built in filter can do this for you without annotating your objects in the view. As the documentation says, it's kind of complicated.
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#regroup
{% regroup all_publications by date.year as year_list %}
{% for year in year_list %}
<h1>{{ year.grouper }}</h1>
{% for publication in year.list %}
<li>{{ publication.title }}</li>
{% endfor %}
{% endfor %}
I think you want the regroup template tag;
{% regroup all_publications by date as publication_groups %}
<ul>
{% for publication_group in publication_groups %}
<li>{{ publication_group.grouper }}
<ul>
{% for publication in publication_group.list %}
<li>{{ publication.title }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Maybe the template tag regroup could help.
Alternatively, you could do this grouping by year in the view function (will try to provide code later).

Django: How to get selected text of DropDown in Template?

In the template I get the whole DropDown correctly shown with something like this:
{{form.deal_type}}
But what if I wanted just the text of the selected dropdown shown?
This shows me just a foreignkey.
{{form.deal_type.value}}
I don't know why you want to do this exactly, but try this.
TO LOOP:
{% for value, text in form.deal_type.field.choices %}
{{ value }}: {{ text }}
{% if value == form.deal_type.value %}
<strong>{{ text }}</strong> <!-- THIS IS THE SELECTED ONE... -->
{% endif %}
{% endfor %}
EDIT:
I meant the above code as an illustration, not that you should use it verbatim. This code will do more like what you want.
{{ form.deal_type.label_tag }}
{% for value, text in form.deal_type.field.choices %}
{% if value == form.deal_type.value %}
{{ text }}
<input type="hidden" name="deal_type" value="{{ value }}" />
{% endif %}
{% endfor %}
I had a similar issue. To solve it I just passed the value to the template directly from the view. So in your view you presumably have something in the way of
data = {'form' :form,}
return render_to_response('destination.html', data, context_instance = RequestContext)
In data you are passing the form that includes deal_type. Add to
data a variable deal_type set equal to Object.deal_type.display_value with
data = {'form' :form,}
if Object.deal_type: data['deal_type'] = Object.deal_type.display_value
return render_to_response('destination.html', data, context_instance = RequestContext)
Then on your template you can just use
{% if condition_to_show_just_text %}
{{deal_type}} {{form.deal_type.as_hidden}}
{% else %}
{{form.deal_type}}
{% endif %}
It may be insiginificant in this case, but it seemed to me that if the list was long, iterating with the for loop on the template would be less efficient than pulling directly from the object