I have models, views & template in Django and want to display the total count of category.
class Entry (models.Model):
title = models.CharField(max_length=200)
category = models.ForeignKey('entry.Category')
class Category(models.Model):
title = models.CharField(max_length=100)
parent = models.ForeignKey('self', blank=True, null=True, related_name='children')
def category(request):
category = Category.objects.all()
return render_to_response('category.html', locals(), context_instance=RequestContext(request))
<ul>
{% for category in category %}
<li>{{ category.title }} ({{ category.entry_set.all.count }})</li>
{% endfor %}
</ul>
Current output:
-Category 1 (0)
--Sub Category 1 (3)
--Sub Category 2 (6)
And desire output is like this:
-Category 1 (9)
--Sub Category 1 (3)
--Sub Category 2 (6)
How to get that output?
Use category.entry_set.count instead of category.entry_set.all.count.
Also, you are using same variable name category for referencing multiple values, you may want to change that.
Update template as:
<ul>
{% for cat in category %}
<li>{{ cat.title }} ({{ cat.entry_set.count }})</li>
{% endfor %}
</ul>
Solved by using Django-MPTT and update my view & template like this:
views.py:
def category(request):
category = Category.tree.add_related_count(Category.objects.all(), Entry, 'category', 'cat_count', cumulative=True)
return render_to_response('category.html', locals(), context_instance=RequestContext(request))
category.html:
{% recursetree category %}
<ul>
{{ node.title }} ({{ node.cat_count }})
{% if not node.is_leaf_node %}
<li class="children">
{{ children }}
</li>
{% endif %}
</ul>
{% endrecursetree %}
Related
I have Blog with posts that have multiple categories
class BlogDetailPage(Page):
heading = models.CharField(max_length=150, blank=False, null=False)
categories = ParentalManyToManyField("blog.BlogCategory", blank=False)
...
class BlogCategory(models.Model):
title = models.CharField(max_length=30,unique=True)
slug = AutoSlugField(populate_from='title')
...
My posts are as follows:
Post 1: Category A
Post 2: Category A, Category B
Post 3: Category B
I want regroup posts by category as below:
Category A
Post 1
Post 2
Category B
Post 2
Post 3
My current solution is not giving me correct results.
{% regroup posts by categories.all as posts_by_categories %}
<ul>
{% for category in posts_by_categories %}
<li>{{ category.grouper.0 }} # first category name
<ul>
{% for post in category.list %}
<li>{{ post.id }}, {{post.categories.all}}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
Amy ideas?
If you don't have to use 'regroup', How about using 'related_name'?
In python
class BlogDetailPage(Page):
categories = ParentalManyToManyField("blog.BlogCategory", blank=False, related_name="blog_posts")
...
In Django_html
<ul>
{% for category in categories.all %}
<li>{{ category.title }} # first category name
<ul>
{% for post in category.blog_posts.all %}
<li>{{ post.id }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
I am looking for my web page to display a list of categories and a list of each post within the category.
For example:
However, it is looping through and displaying each category and associated post separately, like this:
Here is Template:
<ul>
{% for p in object_list %}
<li>
{{p.category.name}}
<ul>
<li>
{{p.title}}
</li>
</ul>
</li>
{% endfor %}
</ul>
Model
class Category(models.Model):
name = models.CharField(max_length=200, blank=True, null=True)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='category', null=False)
Views
class CategoryList(ListView):
template_name = 'category_list.html'
def get_queryset(self):
return Post.objects.all().select_related('category')
Try changing your template code to this
{% regroup object_list by category as post_list %}
<ul>
{% for post_category in post_list %}
<li>{{ post_category.grouper }}
<ul>
{% for post in post_category.list %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
try this:
views.py:
def get_queryset(request):
categorys = {category: Post.objects.filter(category = category) for category in Category.objects.all()}
Template:
<ul>
{% for category, posts in categorys.items %}
<li>
{{category.name}}
{% for comment in comments %}
<ul>
<li>
{{posts.title}}
</li>
</ul>
{% endfor %}
<li>
{% endfor %}
</ul>
Use 2-layer nested loops to display posts and categories, each item in the outer loop is a category, and each item category in the inner loop is the title of the posts.
You can do that in the template with regroup. Also order the items to be grouped by the field you wish to group with.
https://docs.djangoproject.com/en/3.1/ref/templates/builtins/#regroup
Main model:
class MainCategory(models.Model):
title = models.CharField(max_length=120, unique=True)
App#1:
class Category(models.Model):
title = models.CharField(max_length=120, unique=True)
main_category = models.ForeignKey(MainCategory, default=1, related_name='car_category')
App#2:
class Category(models.Model):
title = models.CharField(max_length=120, unique=True)
main_category = models.ForeignKey(MainCategory, default=1, related_name='classifieds_category')
on home page I want a combined list of both category list items as follows.
{% for object in main_cat_list %}
{{ object.title }}
{% for item in object.car_category %}
{{ item.title }}
{% endfor %}
{% endfor %}
How I can insert classifieds category also inside this list?
If you merely want to also display the classified_category as you have the car_category.
{% for object in main_cat_list %}
{{ object.title }}
{% for item in object.car_category %}
{{ item.title }}
{% endfor %}
{% for item in object.classified_category %}
{{ item.title }}
{% endfor %}
{% endfor %}
I have a model Category like so :
class Category(TimeStampedModel):
category_parent = models.ForeignKey('self', blank=True, null=True)
name = models.CharField(max_length = 200)
slug = models.SlugField(unique=True)
def __str__(self):
return self.name
What I want is to display all the categories that do not have parents at first, and then, in nested lists, their respective children : for example :
Flowers
Lilac
Rose
Trees
Maple
So what I have tried is that :
def get_categories(request):
categories = Category.objects.filter(category_parent=None)
return {'categories' : categories}
But when I try to display the children of each category, none appears, following my example, I only get Flowers and Trees..
<ul class="nav-list">
{% for category in categories %}
<li class="nav-item"><a class="nav-link" href="#">{{ category.name }}</a>
{% if category.categories %}
<ul class="nav-submenu">
{% for subcategory in category.categories %}
<li class="nav-submenu-item">{{ subcategory.name }}</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
How can I get the children too ?
You didn't specify related name "categories" to the category_parent field so you can't access it via category.categories. You can try using this expression
{% for subcategory in category.category_set.all %}
<!-- subcategory staff -->
{% endfor %}
in your template.
class Property(models.Model):
title = models.CharField(max_length=255)
class CurrentPrice(models.Model):
current = models.ForeignKey(Current)
prop = models.ForeignKey(Property)
price = models.DecimalField(max_digits=5, decimal_places=2)
class Current(models.Model):
name = models.CharField(max_length=20)
views.py:
...
p = Property.objects.all()
return render_to_response('index.html',{'p':p},context_instance=RequestContext(request))
How to get price of Property and display it in my template?
template:
{% for item in p %}
{{ item.title }}
{{ item.price }} # ???
{% endfor %}
I'm not sure what is your purpose/design of models, which doesn't look appropriate from what you have shown.
You will have many CurrentPrice per Property object, so in template you can do is
{% for item in p %}
{{ item.title }}
{% for cp in item.currentprice_set.all %}
{{ cp.price }}
{% endfor %}
{% endfor %}
If Property can have multiple CurrentPrice objects (what is by default):
{% for item in p %}
{{ item.title }}
{% for current_price in item.currentprice_set.all %}
{{ current_price.price }}
{% endofor %}
{% endfor %}
If only one (but in that case it is better to use o2o field instead of the FK fiel else it is up on you to prevent multiple CurrentPrice records pointing to the same Property):
{% for item in p %}
{{ item.title }}
{{ item.currentprice_set.get.price }}
{% endfor %}
I think what you're trying to do is something like that below.
class Property(models.Model):
title = models.CharField(max_length=255)
#property
def current_price(self):
# The current price is the last price that was given.
if self.pricing_history.count() > 0:
return self.pricing_history.order_by('-when')[0].amount
return None
class Price(models.Model):
prop = models.ForeignKey(Property, related_name='pricing_history')
amount = models.DecimalField(max_digits=5, decimal_places=2)
when = models.DateTimeField(auto_now_add=True)
example in template:
{% for item in p %}
{{ item.title }}
{{ item.current_price }}
{% endfor %}