pk argument on Django blog

Question:

I’m working on a blog and I was following instructions but now I don’t understand why I have problem with pk.

This is my views.py

from django.shortcuts import render, get_object_or_404
from django.utils import timezone
from .models import Category, Post

def post_list(request):
    posts =  Post.objects.filter(created_at__lte=timezone.now()).order_by('created_at')
    latest_posts =  Post.objects.filter(created_at__lte=timezone.now()).order_by('created_at')[:9]

    context = {'posts': posts, 'latest_posts': latest_posts}
    return render(request, 'home.html', context)

def post_detail(request, post, pk):
    latest_posts =  Post.objects.filter(created_at__lte=timezone.now()).order_by('created_at')[:9]
    post = get_object_or_404(Post, pk=pk)

    context = {'post': post, 'latest_posts': latest_posts}
    return render(request, 'post_detail.html', context)

This is blog/urls.py

urlpatterns = [
    path('', views.post_list, name='home'),
    path('<slug:post>/', views.post_detail,  name='post_detail'),
]

This is models.py

class Post(models.Model):
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created at")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="Updated at")
    is_published = models.BooleanField(default=False, verbose_name="Is published?")
    published_at = models.DateTimeField(null=True, blank=True, editable=False, verbose_name="Published at")
    title = models.CharField(max_length=200, verbose_name="Title")
    slug = models.SlugField(max_length=200, unique=True)
    author = models.ForeignKey('auth.User', verbose_name="Author", on_delete=models.CASCADE)
    category = models.ForeignKey(Category, verbose_name="Category", on_delete=models.CASCADE)
    body = RichTextField(blank=True, null=True)
    image = StdImageField(upload_to='featured_image/%Y/%m/%d/', variations={'standard':(1170,820),'banner':(1170,530),'thumbnail':(500,500)})
    status = models.IntegerField(choices=STATUS, default=0)

    def get_absolute_url(self):
        return reverse('post_detail', args=[self.slug])

    class Meta:
        verbose_name = "Post"
        verbose_name_plural = "Posts"
        ordering = ['-created_at']

    def publish(self):
        self.is_published = True
        self.published_at = timezone.now()
        self.save()

    def __str__(self):
        return self.title

Also, I’m adding a list of post, it might be connected with get_absolute_url


{% extends "base.html" %}
{% load static %} 
    {% block content %}
    <!-- Main Wrap Start -->
    <main class="position-relative">
        <div class="post-carausel-1-items mb-50">
            {% for post in latest_posts %}
            <div class="col">
                <div class="slider-single bg-white p-10 border-radius-15">
                    <div class="img-hover-scale border-radius-10">
                        <!--<span class="top-right-icon bg-dark"><i class="mdi mdi-flash-on"></i></span>-->
                        <a href="{{ post.get_absolute_url }}">
                            <img class="border-radius-10" src="{{ post.image.standard.url }}" alt="post-slider">
                        </a>
                    </div>
                    <h6 class="post-title pr-5 pl-5 mb-10 mt-15 text-limit-2-row">
                        <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                    </h6>
                    <div class="entry-meta meta-1 font-x-small color-grey float-left text-uppercase pl-5 pb-15">
                        <span class="post-by">By <a href="#">{{ post.author }}</a></span>
                        <span class="post-on">{{ post.created_at}}</span>
                    </div>
                </div>
            </div>
            {% endfor %}
        </div>
    </main>
    {% endblock content%}

I have an error…

post_detail() missing 1 required positional argument: 'pk'

Everything was working until I was started working on post detail. Any ideas why this is happening?

Asked By: mdev

||

Answers:

You seem to be confused with what the primary key for your model is. The primary key is the auto-generated id (pk) but according to your urls.py you want to use slug for fetching records.

First, change your path to:

path('<slug:slug>/', views.post_detail, name='post_detail'),

then your view signature to:

def post_detail(request, slug):

and finally, fetch your record using:

post = get_object_or_404(Post, slug=slug)
Answered By: Selcuk
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.