Search code examples
djangopaginationtagsdjango-taggit

Is anyone familiar with Django-Taggit and Paginator? I keep receiving a TypeError when I click on my tags


So I am following a digital book on how to add tags to Django using Taggit. The List page is also using Paginator, but what is happening is I am getting this Type Error when I click on one of the tags which is supposed to take you to keep you on the list page, but list the number of posts with the same tag.

Please let me know if you need more information from me. I really appreciate all of your help. I'm excited because this is my first real Django project, creating a blog for a friend and so far things are coming along well except for this one issue that is beyond me. I also want to learn how to be able to look at error screens and know what to look for and then how to solve my own issues one day.

Thanks again!

Chris

This is the Error Screen Shot

views.py

from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import ListView
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Count
from taggit.models import Tag
from .models import Post
from .forms import PostForm



class PostListView(ListView):
    queryset = Post.published.all()
    context_object_name = 'posts'
    paginate_by = 3
    template_name = 'blog/post/list.html'

def post_list(request, tag_slug=None):
    object_list = Post.published.all()
    tag = None
    if tag_slug:
        tag = get_object_or_404(Tag, slug=tag_slug)
        object_list = object_list.filter(tags__in=[tag])
    paginator = Paginator(object_list, 3)
    page = request.GET.get('page')
    try:
        posts = paginator.page(page)
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)
    return render(request, 'blog/post/list.html', {'page': page, 'posts': posts, 'tag': tag})



def post_detail(request, year, month, day, post):
    post = get_object_or_404(Post, slug=post, status='published', publish__year=year, publish__month=month, publish__day=day)
    post_tags_ids = post.tags.values_list('id', flat=True)
    similar_posts = Post.published.filter(tags__in=post_tags_ids).exclude(id=post.id)
    similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:3]
    return render(request, 'blog/post/detail.html', {'post': post, 'similar_posts': similar_posts})


def create_post(request):
    form = PostForm()

    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('blog:post_list')

    return render(request, 'blog/post/post_form.html', {'form': form})



def update_post(request, pk):
    post = Post.objects.get(title=pk)
    form = PostForm(instance=post)

    if request.method == 'POST':
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            form.save()
            return redirect('blog:post_list')

    return render(request, 'blog/post/post_form.html', {'form': form})



def delete_post(request, pk):
    post = Post.objects.get(title=pk)
    if request.method == 'POST':
        post.delete()
        return redirect('blog:post_list')
        
    context = {'object': post}
    return render(request, 'blog/post/delete_post.html', context)



def about(request):
    return render(request, 'blog/post/about.html')



def send_mail(request):
    return render(request, 'blog/post/contact.html')

models.py

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
from taggit.managers import TaggableManager


class PublishedManager(models.Manager):
    def get_queryset(self):
        return super(PublishedManager, self).get_queryset().filter(status='published')

class Post(models.Model):
    tags = TaggableManager()

    def get_absolute_url(self):
        return reverse('blog:post_detail', args=[self.publish.year, self.publish.month, self.publish.day, self.slug])

    objects = models.Manager()
    published = PublishedManager()

    STATUS_CHOICES = (
        ('draft', 'Draft'),
        ('published', 'Published'),
    )

    title = models.CharField(max_length=250)
    slug = models.SlugField(max_length=250, unique_for_date='publish')
    author  = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_post')
    body = models.TextField()  
    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='published')

    class Meta:
        ordering = ('-publish',)
    def __str__(self):
        return self.title

urls.py

from . import views

app_name = 'blog'

urlpatterns = [
    path('', views.post_list, name='post_list'),
    path('tag/<slug:tag_slug>/', views.post_list, name='post_list_by_tag'),
    path('<int:year>/<int:month>/<int:day>/<slug:post>/', views.post_detail, name='post_detail'),

    path('create_post/', views.create_post, name='create_post'),
    path('update_post/<str:pk>/', views.update_post, name='update_post'),
    path('delete_post/<str:pk>/', views.delete_post, name='delete_post'),
    
    path('send_mail/', views.send_mail, name='send_mail'),
    path('about/', views.about, name='about'),
]

list.html

{% extends 'blog/base.html' %}

{% block title %} Healthy Lifestyles with Gretchen {% endblock %}

{% block content %}

{% if tag %}
<h2>Posts tagged with "{{ tag.name }}" </h2>
{% endif %}

{% for post in posts %}
<div id="cards">
<div id="supplyPhoto"></div>
<h2 class="cardHeading">
    <a href="{{post.get_absolute_url}}">{{post.title|truncatewords:8}}</a>
</h2>

<p class="tagsText">
    
    TAGS: {% for tag in post.tags.all %}

    <a href="{% url 'blog:post_list_by_tag' tag.slug %}">{{ tag.name }}</a>

    {% if not forloop.last %}, {% endif %}
    {% endfor %}
</p>

<p class="maintext"> {{post.body|truncatewords:40}} </p>
<p class="author"><i> Published by: {{post.author}} </i> </p>
<p class="date"> <i> {{post.updated}} </i></p>
</div>
{% endfor %}

{% include "pagination.html" with page=posts %}

{% endblock %}

pagination.html

<div class="pagination">
    <span class="step_links">
        {% if page.has_previous %}
        <a class="pagination" href="?page={{ page.previous_page_number }}">< PREVIOUS</a>
        {% endif %}
        <span class="current">
        <p class="footer">PAGE  {{page.number}}  OF  {{page.paginator.num_pages}}</p>
        </span>
        {% if page.has_next %}
        <a class="pagination" href="?page={{ page.next_page_number }}">NEXT ></a>
        {% endif %}
    </span>
</div>

Solution

  • I'm following the same book.

    It is a problem with Taggit and the Django update. There is now a Taggit update that make it work with Django 4.0.

    pip uninstall django-taggit

    pip install git+https://github.com/jazzband/djangotaggit.git@d0833966d357ed1e1b9b1f40c39c1ed99affbf9b