Django templates _set.all two sub table - django

I have two tables I want to check if there is data or not!
Models:
class Children(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
photo = models.ImageField(blank=True, default='avatar.jpg')
class Groups(models.Model):
child = models.ForeignKey(Children, on_delete=models.CASCADE)
Templates:
{% if user.children_set.all.groups_set.all.exists %}
It's Like:
get_groups = Groups.objects.fitler(child__user=request.user).count
BUT I need this statement to be in templates, because I am trying to create for loop on User table:
{% for user in users %}
{{user.username}}
{% if user.children_set.all.groups_set.all.exists %}
Yes
{% else %}
No
{% endif %}
{% endfor %}

you can also use if condition in template if checking numbers is the ultimate goal like this:
{% if user.children_set.all.groups_set.count == 0 %}
<p>this table is empty</p>
{% else %}
<p>this table is not empty and go with the looping to print items etc<p>
{% endif %}
this may help

Related

Django ListView how loop in one field in the template?

I have django ListView I know I can loop in it like this
{% for i in object_list %}
{% i.id %}
{% endfor %}
I want to loop in one field only
{% for i in object_list.id %}
{% i %}
{% endfor %}
update:
my model:
class Weather(models.Model):
temperature = models.FloatField(
validators=[MaxValueValidator(28), MinValueValidator(19)]
)
humidity = models.FloatField(
validators=[MaxValueValidator(65), MinValueValidator(35)]
)
time_recorded = models.DateTimeField(auto_now_add=True, blank=True)
ListView:
class WeatherListView(ListView):
template_name = "frontend/weather_list.html"
model = Weather
I want to loop for each of these fields in different position in the html template so I don't want to loop in the whole list each time for instance if I want to loop in temperature only:
I want to do this:
{% for i in object_list.temperature %}
{% i %}
{% endfor %}
instead of:
{% for i in object_list %}
{% i.temperature %}
{% endfor %}
OK, I think there is a misunderstanding on what object_list in the template represents. You are not looping over the "whole context". object_list is a variable in the context representing the QuerySet of the particular view.
In the case of WeatherListView it's Weather.objects.all(). So when you write {% for i in object_list %} you are looping over all the Weather instances in the database.
I'm not sure what you are trying to optimize. Perhaps it's the amount of database queries? In that case I can tell you that QuerySets in Django are evaluated lazily, but once they are evaluated the result is cached. So if you loop over object_list once the next time you loop over it will not result in a new database query.

Django Template Tag - Display only one value in nested for loop

I'm working on a Django web app and have the following query:
I have a model called 'AppQoSList' which lists the applications available to all users.
I have then another model called 'BasicAppSDWANProfiles' which has a ManyToMany relationship with 'AppQoSList' .
In short, it means a user can have multiple 'BasicAppSDWANProfiles' associated to his account and multiple AppQoS can be within a particular BasicAppSDWANProfiles:
class AppQoSList(models.Model):
app_qos_name = models.CharField(max_length=50, blank=None, null=True)
app_qos_description = models.CharField(max_length=500)
def __str__(self):
return u'%s' % self.app_qos_name
class BasicAppSDWANProfiles(models.Model):
profile_name = models.CharField(max_length=30)
profile_basic_app_qos = models.ManyToManyField(AppQoSList)
tenant_id = models.ForeignKey(Tenant, default=3)
I'm facing issue in my template when I try to display the list of apps available and the associated BasicAppSDWANProfile:
{% for app in apps %}
{% for profile_app in sdwan_prof %}
{% for specific_app in profile_app.profile_basic_app_qos.all %}
{% ifchanged specific_app.pk %}
{% if app.pk == specific_app.pk %}
<td><h4><span class="label label-primary">{{ profile_app.profile_name }}</span></h4></td>
{% else %}
<td><h4><span class="label label-warning">Not Assigned</span></h4></td>
{% endif %}
{% endifchanged %}
{% endfor %}
{% endfor %}
{% endfor %}
Issue with this code is that 'Not Assigned' is displayed 6 times on each row (which corresponds to the number of Apps found in BasicAppSDWANProfiles associated with this user) whereas I would like to display it only once:
Would you have any solution for this ?
Thanks in advance.
I was able to address this issue.
First I did clean up my view code to remove duplicate 'Not Assigned' values.
I pass to my template context a dictionary with only apps that have a profile assigned such as below:
{'citrix-static': 'DPS-BLACKLIST',
'exchange': 'DPS-BLACKLIST',
'ms-lync-audio': 'DPS-WHITELIST',
'ms-update': 'DPS-GREYLIST',
'rtp': 'DPS-WHITELIST',
'share-point': 'DPS-WHITELIST'}
In my template, I only loop through this dictionary:
{% for k,v in app_prof_assign.items %}
{% if app.app_qos_name == k %}
<td><h4><span class="label label-primary">{{ v }}</span></h4></td>
{% endif %}
{% endfor %}
I then simply check if the app is not in the profile dictionary, outside the loop:
{% if app.app_qos_name not in app_prof_assign %}
<td><h4><span class="label label-warning">Not Assigned</span></h4></td>
{% endif %}
Finally, I can get the table populated as expected:

Django: one-to-many relationship and reverse lookup

i have a Problem which i am unsure what the most django/pythonic way to solve it would be.
I have the following models:
class Order(models.Model):
ord_someinformation = models.CharField(max_length=10)
class Articles(models.Model):
myFK = models.ForeignKey(Order)
detail_article= models.CharField(max_length=10)
so every Order can have multiple Order_Details think about it like a shopping basket where i have an Order and within it i have multiple articles.
I want to iterate over the orders and the articles within the template. I thought about something like.
myOrder = Order.objects.("" i have no idea what to put here "")
within the template i thought about something like this:
{% for order in myOrder %}
{{ order.ord_someinformation }}
{% for articles in order.articles %}
{{ detail_article }}
{% endif %}
{% endif %}
is this possible?
If so how ?
I don't know why you think you need to put anything there. You just want to send all the orders to the template, then iterate through them their articles there.
myOrder = Order.objects.all()
...
{% for order in myOrder %}
{{ order.ord_someinformation }}
{% for article in order.articles_set.all %}
{{ article.detail_article }}
{% endif %}
{% endif %}

Iterate set in template

I have this models:
class House(models.Model):
name = models.CharField()
class BedRoom(models.Model):
name = models.CharField()
class Catalog(models.Model):
name = models.CharField()
house = models.ForeignKey(House)
bedroom = models.ForeignKey(BedRoom)
at admin.py Catalog is inline to House
class CatalogInline(admin.TabularInline):
model = Catalog
class HomeAdmin(admin.ModelAdmin):
inline = [CatalogInline]
then I need obtain at view the list of Bedrooms from House Catalog, at Home model I have:
def bedrooms(self):
return self.catalog_set.all()
but when I do at template obtaining "houses" from a view:
{% for house in houses %}
{% for h in house %}
<p>{{h.name}}</p>
{% endfor %}
{% endfor %}
I get an error:
'Catalog' object is not iterable
what I'm doing wrong?
I should define the model in a different way?
As I mentioned, you don't seem to actually be calling the bedrooms method. I guess (and it is just a guess) you mean this:
{% for house in houses %}
{% for h in house.bedrooms %}
<p>{{h.name}}</p>
{% endfor %}
{% endfor %}
The bedrooms method is pointless though, as you can just as easily do this:
{% for house in houses %}
{% for h in house.catalog_set.all %}
<p>{{h.name}}</p>
{% endfor %}
{% endfor %}

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