Django : How to hide a variable in a template - django

I have a template with a tree
Ceramic Composite Metals general
I want to hide general
I wrote
{% for category in object_list %}
{% if category != "general" %}
<li class="closed"><span class="folder"><a >{{ category }}</a></span></li>
{% endif %}
it does not work
What is the error

In the template, {{ category }} is interpreted as Category.__str__() and a string is displayed.
But in {% if category != "general" %}, category is an object that will always be different to the String "general". What you want to do is: {% if category.name != "general" %}
Also, note that if you don't use categories named "general" in this template, you should filter them out when querying the db. It will be more efficient.

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

template condition of FK value

I have two models, Item and Quality. Item has a field named quality which is a FK to Quality.name. The two tables look something like this:
Item
-----
itemId int PK
name varchar
quality varchar FK - Quality.name
Quality
-----
qualityId int PK
name varchar
I'm trying to make a template that lists all Items that have a certain quality. This is my code in question:
{% for Item in items %}
{% if Item.quality == "Common" %}
<div id="name_{{ Item.id }}" class="itemName">{{ Item.name }}</div>
{% endif %}
{% endfor %}
I know that my table contains at least one tuple with quality="Common", but I'm not getting any output.
If I try to condition any other field then it works fine (ex: if Item.name == "exampleName").
How do I use an if-statement on a value from a FK?
quality is the related object, ie an instance of Quality. If you want to compare on the basis of the name, then you have to use that attribute of the instance.
(Also, please use proper cases; instances should not have capital letters.)
{% for item in items %}
{% if item.quality.name == "Common" %}
<div id="name_{{ item.id }}" class="itemName">{{ item.name }}</div>
{% endif %}
{% endfor %}

Django template if statement return wrong value

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.

tree structure of parent child relation in django templates

how do i implement the tree structure in django templates with out using django-mptt.
i have model.
class Person(TimeStampedModel):
name = models.CharField(max_length=32)
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
now i want ..
Parent
Child 1
subchild 1.1
subchild 1.2
nextsubchild 1.2.1
Child 2
Child 3
there names should be click able to show their profile.
I just finished implementing this. I wanted a tree structure for a sub-navigation, but I did not want to do anything strange with recursive templates.
The solution I implemented is very simple: I simply recurse in the view (in my case a generic helper function) and flatten out the hierarchical structure into a simple list. Then, in my template I just use a for loop to iterate over the list.
Each element in the list can be one of three things: "in", the object, or "out". In my case, I'm constructing a series of ul li elements in the view, so when I encounter "in" I create a new ul, when I encounter "out" I close the ul. Otherwise, I render the item.
My template code looks like this:
<ul>
{% for item in sub_nav %}
{% if item == "in" %}
<ul>
{% else %}
{% if item == "out" %}
</ul>
</li>
{% else %}
<li>
<a href='{{item.full_url}}'>{{item.name}}</a>
{% if item.leaf %}
</li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
The code in the helper function looks like this:
def get_category_nav(request,categories=None):
"""Recursively build a list of product categories. The resulting list is meant to be iterated over in a view"""
if categories is None:
#get the root categories
categories = ProductCategory.objects.filter(parent=None)
categories[0].active=True
else:
yield 'in'
for category in categories:
yield category
subcats = ProductCategory.objects.select_related().filter(parent=category)
if len(subcats):
category.leaf=False
for x in get_category_nav(request,subcats):
yield x
else:
category.leaf=True
yield 'out'
Using those snippets, you should be able to build any sort of hierarchical tree you'd like without doing any recursion in the template, and keeping all the logic in the view.
I know there was already an accepted answer for this, but I thought I'd post the technique in case it helps anyone else.
from Django while loop question and
http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags
# view.py
#register.inclusion_tag('children.html')
def children_tag(person):
children = person.children.all()
return {'children': children}
# children.html
<ul>
{% for child in children %}
<li> {{ child }}</li>
{% if child.children.count > 0 %}
{% children_tag child %}
{% endif %}
{% endfor %}
</ul>
# your template
{% children_tag parent %}
These are great answers but I consolidated a bit and put it on the actual model.
class RecursiveThing(models.Model):
name = models.CharField(max_length=32)
parent = models.ForeignKey('self', related_name='children', blank=True, null=True)
def as_tree(self):
children = list(self.children.all())
branch = bool(children)
yield branch, self
for child in children:
for next in child.as_tree():
yield next
yield branch, None
And then in your template:
<ul>
{% for thing in things %}
{% for branch, obj in thing.as_tree %}
{% if obj %}
<li>{{ obj.name }}
{% if branch %}
<ul>
{% else %}
</li>
{% endif %}
{% else %}
{% if branch %}
</ul>
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
</ul>
It's very simple
All you have to do in your view is get all objects:
people = Person.objects.all()
Then in your template :
{% for person in people %}
<li>- {{person.name}} </li>
{% for child in person.children.all %}
<ul>* {{child.nom}} </ul>
{% endfor %}
</li>
{% endfor %}

List products by category in Django template

What's the best way to generate HTML which has a heading for each Category, and Products under that category in a Django template?
I toyed with the idea of having a passing a dictionary, or an ordered list...
Take a look at the regroup template filter
http://docs.djangoproject.com/en/dev/ref/templates/builtins/#regroup
With it you could do something like this:
{% regroup products by category as products_by_category %}
{% for c in products_by_category %}
<h1>{{c.grouper}}</h1>
<ul>
{% for p in c.list %}
<li>{{p.name}}</li>
{% endfor %}
</ul>
{% endfor %}
In addition to what #Wade suggests you can also add a method to your Category model to return the products it has.
Example..
class Category:
...
...
def get_products(self):
return Product.objects.filter(category=self)
Then in a template you can..
{% for category in categories %} # assuming categories is passed from the view.
{% for product in category.get_products %}
...
used a sorted list in the view code,
sorted(dom_obj.objects.all(), key=lambda d: d.sort_key)
and then used the filter tag
{% ifchanged %}<h1>{{ prod.cat }}</h1>{% endifchanged %}