Мне нужно получить доступ к значению обратным способом, используя ForeignKey. Я хочу перейти от дочерней модели Category
к родительской модели Post
и получить значение title
в свой шаблон
Я пробовал category.posts.title
, но это не показывает никакого успеха для меня.
Основная цель этого — создать <div>
для каждой категории и перечислить сообщения в блоге с этой категорией внизу.
Модели:
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)
Вид:
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)
Шаблон
<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 %}
Вам нужно перебрать сообщения в каждой категории
{% for post in category.posts.all %}
<a href = "{% url 'blog_detail' category.name post.slug post.pk %}">{{ post.title }}</a>
{% endfor %}
Вам также следует использовать prefetch_related в наборе запросов категорий, чтобы уменьшить количество запросов к БД, которые вы делаете при доступе к category.posts.all
, поскольку вам больше не нужен набор запросов сообщений.
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)
Добавлен аннотация для получения количества сообщений для каждой категории.
{% category.post_count %}
Как я могу подсчитать общее количество сообщений в данной категории? Я пробовал {{category.posts.title.count}}
, но это не работает.
Вы можете использовать category.posts.count
, но это будет выполнять запрос БД для каждой категории. Лучше использовать annotate
, я обновлю свой ответ
Спасибо за обновление ответа! Я получаю эту ошибку в представлениях name 'Count' is not defined
Вам нужно импортировать Count: from django.db.models import Count
Поскольку у одного Category
может быть несколько сообщений, вам нужно будет перебрать их:
category.posts.all()
В шаблоне:
{% for category in categories %}
{{ category.name }}
{ % for post in category.posts.all %}
{{ post.title }}
{% endfor %}
{% endfor%}
Также правильный ответ, но он решил отметить ответ Лэйна как правильный, так как он добавил в свой ответ некоторую оптимизацию БД. Спасибо!
Абсолютно в точку! Спасибо за помощь и дополнительную информацию по оптимизации вызовов базы данных!