I am building a simple travel blog website that will serve as a project and a portfolio for my job search.get_absolute_value() function previously worked but after renaming article-detail to article_detail to match the rest of the URLs it throws this error
NoReverseMatch at /addpost/
Reverse for ‘article_detail’ with arguments ‘(‘1’, ‘4’)’ not found. 1 pattern(s) tried: [‘article/(?P[0-9]+)\Z’]
it looks like my posts in my model are automatically being assigned two IDs as their primary key but my code is only built to take a single PK so im not sure whats going on or how to fix it here?
i read about 20 other stack overflow posts with similar questions but im still struggling to see what i need to do to fix this. below i posted my models.py, views.py and urls.py please let me know if you need to see anything else. the error appears to be at the bottom of my post model where redirect for adding a post is.
Here is my model
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from datetime import datetime, date
from ckeditor.fields import RichTextField
class Post(models.Model):
title = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = RichTextField(blank=True, null=True)
summary = models.CharField(max_length=255)
adventure_date = models.DateField()
published = models.DateTimeField(default=datetime.now)
likes = models.ManyToManyField(User, related_name='blog_post')
def total_likes(self):
return self.likes.count()
def __str__(self):
return self.title + ' | ' + str(self.author)
#need a redirect for when you create a post on the website
def get_absolute_url(self):
return reverse('article_detail', args=(str(self.id)))
here is my views
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView, CreateView
from .models import Post
from .forms import PostForm
from django.urls import reverse_lazy, reverse
from django.http import HttpResponseRedirect
def LikeView(request, pk):
post = get_object_or_404(Post, id=request.POST.get('post_id'))
liked = False
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
liked = False
else:
post.likes.add(request.user)
liked = True
return HttpResponseRedirect(reverse('article_detail', args=[str(pk)]))
def home(request):
return render(request, 'home.html', {})
class HomeView(ListView):
model = Post
template_name = 'travel_blog.html'
ordering = ['-id']
class ArticleDetailView(DetailView):
model = Post
template_name = 'article_details.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
post_by_id = get_object_or_404(Post, id=self.kwargs['pk'])
total_likes = post_by_id.total_likes()
liked = False
if post_by_id.likes.filter(id=self.request.user.id).exists():
liked = True
context['total_likes'] = total_likes
context['liked'] = liked
return context
class AddPostView(CreateView):
model = Post
form_class = PostForm
template_name = 'add_post.html'
and here is my URLs
from django.urls import path
from .views import HomeView, ArticleDetailView, home, AddPostView, LikeView
urlpatterns = [
path('', home, name='home'),
path('travelblog', HomeView.as_view(), name='blog'),
path('article/<int:pk>', ArticleDetailView.as_view(), name='article_detail'),
path('addpost/', AddPostView.as_view(), name='addpost'),
path('like/<int:pk>', LikeView, name='like_post'),
]
>Solution :
The issue seems to be with the get_absolute_url method in your Post model. Specifically, the args parameter in the reverse function call needs to be a tuple. In your case, it’s missing a comma, which means it’s being interpreted as just a single argument.
To fix the issue, you can simply add a comma after str(self.id) in the reverse function call like so:
def get_absolute_url(self):
return reverse('article_detail', args=(str(self.id),))
This will ensure that args is interpreted as a tuple with a single element, rather than a single argument.
Also, you mentioned that your posts in your model are automatically being assigned two IDs as their primary key. This seems unusual, as Django models should only have one primary key field by default. Double-check your database schema and make sure that your Post model only has a single primary key field (i.e. an AutoField or IntegerField with primary_key=True).