Reputation: 375
I'm in need of accessing a value the reverse way using ForeignKey. I want to go from child model Category
to parent model Post
and grab the value title
into my template
I've tried category.posts.title
but it isn't showing any success for me.
The main purpose of this is to create a <div>
for each Category and list the blog posts with that category down below.
Models:
class Category(models.Model):
name = models.CharField(max_length=30)
class Post(models.Model):
slug = models.SlugField(max_length = 250, null = True, blank = True)
title = models.CharField(max_length = 250, default="Blog Post")
body = models.TextField()
created_on = models.DateTimeField(null=True)
last_modified = models.DateTimeField(null=True)
categories = models.ForeignKey('Category', related_name='posts', default="2", unique=False, on_delete=models.CASCADE)
View:
def blog_index(request):
posts = Post.objects.all().order_by('-created_on')
categories = Category.objects.all()
context = {
"posts": posts,
"categories": categories,
}
return render(request, "blog_index.html", context)
Template
<div class="row">
<div style="padding: 0px;" class="col l12">
{% for category in categories %}
<div class="col l3">
<div style="background-color: white; box-shadow: 0 1px 15px 1px rgba(62,57,107,.07); border-radius: .6rem;" class="card ">
<div class="card-body text-center">
<div class="mb-4 pb-3"><i class="ti-briefcase text-muted font-40"></i></div>
<h5 class="mb-3"> <a href="{% url 'blog_category' category %}">{{ category.name }}</a></h5>
<div><a class="d-inline-flex align-items-center text-danger" ><a href="{% url 'blog_detail' category.name category.posts.slug category.posts.pk %}">{{ category.posts.title }}</a><i class="material-icons">
keyboard_arrow_right
</i></a></div>
</div>
</div>
</div>
{% endfor %}
Upvotes: 0
Views: 119
Reputation: 32274
You need to loop over the posts in each category
{% for post in category.posts.all %}
<a href="{% url 'blog_detail' category.name post.slug post.pk %}">{{ post.title }}</a>
{% endfor %}
You should also use prefetch_related on your categories queryset to reduce the number of DB queries you make when you access category.posts.all
as you no longer need your posts queryset
def blog_index(request):
categories = Category.objects.annotate(
post_count=Count('posts')
).prefetch_related('posts')
context = {
"categories": categories,
}
return render(request, "blog_index.html", context)
Added the annotation for getting the count of posts for each category
{% category.post_count %}
Upvotes: 1
Reputation: 5669
As far as one Category
can have multiple posts you would need to iterate over them:
category.posts.all()
In template:
{% for category in categories %}
{{ category.name }}
{ % for post in category.posts.all %}
{{ post.title }}
{% endfor %}
{% endfor%}
Upvotes: 2