Let's say I have a simple model set:
class Category(MPTTModel):
name = CharField(max_length=50)
parent = TreeForeignKey(
'self',
null=True,
blank=True,
related_name='children',
db_index=True
)
class Record(Model):
name = CharField(max_length=50)
category = TreeManyToManyField(SectionArt)
And let's imagine I have a Record that belongs to 3 different categories. How do I make breadcrumbs track from which category I opened my record?
You can track where user came from with request.META['HTTP_REFERER']
views.py
def get_context_data(self, **kwargs):
c = super(RecordDetail, self).get_context_data(**kwargs)
if 'HTTP_REFERER' in self.request.META:
referer = self.request.META['HTTP_REFERER'].split('/')[-2]
c['categories'] = [models.Category.objects.get(slug=referer)]
else:
c['categories'] = self.object.categories.all()
return c
template.html
<ul class="breadcrumbs">
<li>{{ sections.home.title }}</li>
{% if categories %}
{% with category=categories.0 %}
{% for obj in category.get_ancestors %}
<li>{{ obj.title }}</li>
{% endfor %}
<li>{{ category.title }}</li>
{% endwith %}
{% endif %}
<li class="current">{{ object.short_title }}</li>
</ul>
Source
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
after querying my database, my template doesn't display anything. Please find attached my model, url, templates
MODEL
class ScrumyUser(models.Model):
userRole = (
('O', 'Owner'),
('A', 'Admin'),
('Q', 'Quality Analyst'),
('D', 'Developer'),
)
fullname = models.CharField(max_length=100)
role = models.CharField(max_length=1, choices=userRole)
class GoalStatus(models.Model):
goalStatus = (
('P', 'Pending'),
('V', 'Verified'),
('D', 'Done'),
)
status = models.CharField(max_length=1, choices=goalStatus)
class ScrumyGoals(models.Model):
goalType = (
('WG', 'Weekly Goal'),
('DT', 'Daily Task'),
)
user_id = models.ForeignKey(ScrumyUser, on_delete=models.CASCADE)
status_id = models.ForeignKey(GoalStatus, on_delete=models.CASCADE)
goal_type = models.CharField(max_length=2, choices=goalType)
goal_description = models.TextField()
date_created = models.DateTimeField('dateCreated')
date_updated = models.DateTimeField(null=True, blank=True)
VIEWS
from django.views import generic
from .models import ScrumyGoals, ScrumyUser, GoalStatus
class IndexView(generic.ListView):
template_name = 'greyscrumy/index.html'
context_object_name = 'goals'
def get_queryset(self):
return ScrumyGoals.objects.all()
TEMPLATE INDEX
THIS TEMPLATE DOESN'T DISPLAY ANY DATA ON THE BROWSER
{% if goals %}
<h1>{{ object_list.fullname }}</h1>
<ul>
{% for goal in goals.scrumygoals_set.all %}
<li>{{ goal.goal_type }}</li>
{% endfor %}
</ul>
{% else %}
<p>No goals are available.</p>
{% endif %}
THE SECOND DISPLAYS BUT I DON'T KNOW HOW TO ACCESS SCRUMYUSER AND GOALSTATUS
PLEASE I WOULD REALLY LOVE TO UNDERSTAND THIS, I HAVE MADE SEARCHES ON GOOGLE SINCE YESTERDAY AND COULDN'T FIND ANYTHING
{% for goal in goals %}
{% for innergoal in goals %}
{{ innergoal.id }} {{ innergoal.goal_description }}
{% endfor %}
{% endfor %}
Like this:
{% for goal in goals %}
<h1>{{ goal.user_id.fullname }}</h1>
<p>{{ goal.goal_type }}</p>
<p>{{ goal.goal_description }}</p>
<p>{{ goal.date_created }}</p>
<p>{{ goal.date_updated }}</p>
<p>{{ goal.user_id.role }}</p>
<p>{{ goal.status_id.status }}</p>
{% 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.
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 %}