title: Django Filtering Articles by Categories
body: <p>I'm building a news web site as a part of a task I was given, homework.</p>
  
  <p>I have a "articles.html" template which renders all of my news articles by publish date. 
  I added a for loop in the template to loop over the Category model and display Categories as a list.</p>
  
  <p>What I'm trying to do now is to filter my articles by category, so when I click "sports" on the list, my site now displays only sports related articles.</p>
  
  <p>I have read so much online, and I just got confused, I'm supposed to do this today but I'm having a rough day and would appreciate some guidance !</p>
  
  <p>Here are my models.py :</p>
  
  <pre><code>from django.db import models
  from datetime import datetime
  from autoslug import AutoSlugField
  
  
  class Category(models.Model):
      category_title = models.CharField(max_length=200, default="")
  
      def __str__(self):
          return self.category_title
  
  
  class Article(models.Model):
      title = models.CharField('title', max_length=200, blank=True)
      slug = AutoSlugField(populate_from='title', default="",
                           always_update=True, unique=True)
      author = models.CharField('Author', max_length=200, default="")
      description = models.TextField('Description', default="")
      is_published = models.BooleanField(default=False)
      article_text = models.TextField('Article text', default="")
      pub_date = models.DateTimeField(default=datetime.now, blank=True)
      article_image = models.ImageField('Article Image')
      article_category = models.ForeignKey(Category, on_delete="models.CASCADE", default="")
      img2 = models.ImageField('Article Image 2', default="", blank=True)
      img3 = models.ImageField('Article Image 3', default="", blank=True)
      img4 = models.ImageField('Article Image 4', default="", blank=True)
      img5 = models.ImageField('Article Image 5', default="", blank=True)
      img6 = models.ImageField('Article Image 6', default="", blank=True)
  
      def __str__(self):
          return self.title
  </code></pre>
  
  <p>My views.py :</p>
  
  <pre><code>from django.shortcuts import render, reverse, get_object_or_404
  from django.views import generic
  from news.models import Article, Category
  from .forms import CommentForm
  from django.http import HttpResponseRedirect
  
  
  class IndexView(generic.ListView):
  
      template_name = 'news/index.html'
      context_object_name = 'latest_article_list'
  
      def get_queryset(self):
          return Article.objects.order_by("-pub_date").filter(is_published=True)[:6]
  
  
  class CategoryView(generic.ListView):
  
      template_name = 'news/categories.html'
      context_object_name = 'category'
  
      def get_queryset(self):
          return Category.objects.all()
  
  
  def article(request, article_id):
  
      article = get_object_or_404(Article, pk=article_id)
      context = {'article': article}
  
      return render(request, 'news/article.html', context)
  
  
  class ArticlesView(generic.ListView):
      context_object_name = 'latest_article_list'
      template_name = 'news/articles.html'
      queryset = Article.objects.order_by("-pub_date")
  
      def get_context_data(self, **kwargs):
          context = super(ArticlesView, self).get_context_data(**kwargs)
          context['category'] = Category.objects.all()
          return context
  
  
  def add_comment_to_article(request, pk):
      article = get_object_or_404(Article, pk=pk)
      if request.method == "POST":
          form = CommentForm(request.POST)
          if form.is_valid():
              comment = form.save(commit=False)
              comment.post = article
              comment.save()
              return HttpResponseRedirect(reverse('news:article', kwargs={"article_id": article.pk}))
      else:
          form = CommentForm()
      return render(request, 'news/add_comment_to_article.html', {'form': form})
  
  </code></pre>
  
  <p>my urls.py :</p>
  
  <pre><code>from django.urls import path, include
  
  from . import views
  
  app_name = "news"
  urlpatterns = [
      path('', views.IndexView.as_view(), name='index'),
      path('&lt;int:article_id&gt;/', views.article, name='article'),
      path('articles/', views.ArticlesView.as_view(), name='articles'),
      path('search/', include('haystack.urls')),
      path('&lt;int:pk&gt;/comment/', views.add_comment_to_article, name='add_comment_to_post'),
      path('category/&lt;int:category_id&gt;', views.CategoryView.as_view(), name="category")
  ]
  
  </code></pre>
  
  <p>And the template im trying to render everything in, articles.html:</p>
  
  <pre><code>&lt;div class="container"&gt;
      {% block articles %}
      &lt;!-- ***************************************** --&gt;
      &lt;ul&gt;
          &lt;li&gt;Categories:&lt;/li&gt;
          {% for category in category %}
  
          &lt;li&gt;
              &lt;h1&gt;{{ category.id}}&lt;/h1&gt;
              &lt;a href="#"&gt;{{ category.category_title }}&lt;/a&gt;
          &lt;/li&gt;
  
          {% endfor %}
      &lt;/ul&gt;
      &lt;!-- ***************************************** --&gt;
  
      &lt;hr class="hr-style1"&gt;
      &lt;h2 class="article-list-title"&gt;Article List :&lt;/h2&gt;
      &lt;hr class="hr-style2"&gt;
      &lt;div class="container list-wrapper"&gt;
  
          {% for article in latest_article_list %}
  
          &lt;div class="container"&gt;
              &lt;div class="well"&gt;
                  &lt;div class="media"&gt;
                      &lt;a class="pull-left" href="{% url 'news:article' article.id %}"&gt;
                          &lt;img class="media-object" src="{{ article.article_image.url }}"&gt;
                      &lt;/a&gt;
                      &lt;div class="media-body"&gt;
                          &lt;h4 class="media-heading"&gt;&lt;a href="{% url 'news:article' article.id %}"&gt;{{ article.title }}&lt;/a&gt;
                          &lt;/h4&gt;
                          &lt;p class="text-right"&gt;{{ article.author }}&lt;/p&gt;
                          &lt;p&gt;{{ article.description }}&lt;/p&gt;
                          &lt;ul class="list-inline list-unstyled"&gt;
                              &lt;li&gt;&lt;span&gt;&lt;i class="glyphicon glyphicon-calendar"&gt;&lt;/i&gt; {{ article.pub_date }} &lt;/span&gt;&lt;/li&gt;
                              &lt;li&gt;|&lt;/li&gt;
                              &lt;span&gt;&lt;i class="glyphicon glyphicon-comment"&gt;&lt;/i&gt; 2 comments&lt;/span&gt;
                              &lt;li&gt;|&lt;/li&gt;
                              &lt;li&gt;
                                  &lt;span class="glyphicon glyphicon-star"&gt;&lt;/span&gt;
                                  &lt;span class="glyphicon glyphicon-star"&gt;&lt;/span&gt;
                                  &lt;span class="glyphicon glyphicon-star"&gt;&lt;/span&gt;
                                  &lt;span class="glyphicon glyphicon-star"&gt;&lt;/span&gt;
                                  &lt;span class="glyphicon glyphicon-star-empty"&gt;&lt;/span&gt;
                              &lt;/li&gt;
                              &lt;li&gt;|&lt;/li&gt;
                              &lt;li&gt;
                                  &lt;span&gt;&lt;i class="fa fa-facebook-square"&gt;&lt;/i&gt;&lt;/span&gt;
                                  &lt;span&gt;&lt;i class="fa fa-twitter-square"&gt;&lt;/i&gt;&lt;/span&gt;
                                  &lt;span&gt;&lt;i class="fa fa-google-plus-square"&gt;&lt;/i&gt;&lt;/span&gt;
                              &lt;/li&gt;
                          &lt;/ul&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      {% endfor %}
  
  </code></pre>
  
  <p>Apologies for the messy code, still trying to learn.</p>
  
  <p>Thank you for taking the time to read this !</p>
  
  <p>I'm not asking you to do this for me, an explanation will be enough ! Thanks !</p>