I am trying to show number of articles in each category in my django project. But it shows category id instead of category_name. I want to display category_name and the corresponding number of articles.
blog/views.py
def searchView(request):
statistics = Post.objects.values('cid').annotate(num_articles = Count('cid')).order_by()
return render(request, 'blog/search.html', {'statistics': statistics})
blog/search.html -> here stat.cid shows the category id but I want to show category_name here.
{% extends 'users/base.html' %}
{% block content %}
<div >
<br>
<div >
<div > </div>
<div >
<h4 >POPULAR CATEGORIES!!</h4>
<table id="myTable" >
<thead>
<tr>
<th>Category</th>
<th>Articles Available</th>
</tr>
</thead>
<tbody>
{% for stat in statistics %}
<tr>
<td>
{{ stat.cid }}
</td>
<td>
{{ stat.num_articles }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock content %}
blog/models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth import get_user_model
from django.urls import reverse
from ckeditor.fields import RichTextField
# Create your models here.
class Category(models.Model):
cid = models.AutoField(primary_key=True)
category_name = models.CharField(max_length=100)
def __str__(self):
return self.category_name
class Post(models.Model):
aid = models.AutoField(primary_key=True)
image = models.ImageField(default='blog-default.png', upload_to='images/')
title = models.CharField(max_length=200)
content = RichTextField()
created = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
cid = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name='specialization')
approved = models.BooleanField('Approved', default=False)
like = models.ManyToManyField(get_user_model(), related_name='likes', blank=True)
def __str__(self):
return self.title
CodePudding user response:
Post.objects.values('cid')
would only give you the pk
of the Category
. To access the category_name
of the Category
you should also include that in the values():
# Note the double underscore between cid and category_name
`Post.objects.values('cid', 'cid__category_name')`
Now that the category_name
is available, access it in the template like this:
{{ stat.cid__category_name }}
While this is specific to your case, a better answer is here:
https://stackoverflow.com/a/27181936/10951070
CodePudding user response:
I would be going at this from the opposite direction, meaning I would be accessing this data from Category
rather than from Post
which for some reason you call statistics
.
First off I'd suggest you to use a ListView
and then I'd proceed as follows:
# views
from django.views.generic import ListView
class CategoryListView(ListView):
model = Category
template_name = 'blog/search.html'
context_object_name = "categories"
# template
<table>
<thead>
...
</thead>
<tbody>
{% for category in categories %}
<tr>
<td>{{ category.cid }}</td>
<td>{{ category.post_set.count }}</td>
</tr>
{% endfor %}
</tbody>
</table>
If you add a related_name
in your Post
model in the cid
attribute and call it posts
, you can then in the template write category.posts.count
which is more readable. This is just a personal preference and definitely not a rule.