Improperly configured at /18/delete, Django views issue

I have searched through the other questions similar to my own problem and have come to no solution so im hoping someone can help me figure out where i went wrong.

I'm trying to implement a delete post option in my blog program but it is throwing the following error once you click the 'delete' button:

ImproperlyConfigured at /18/delete/ Deletepost is missing a QuerySet. Define Deletepost.model, Deletepost.queryset, or override Deletepost.get_queryset().

I am nearly sure its a problem with my URLS.py though what exactly i cannot figure out.

the following is the code in question:

Views.py

# delete post
class Deletepost(LoginRequiredMixin, DeleteView):
    form_class = Post
    success_url = reverse_lazy('blog:home')
    template_name = 'templates/post.html'

    def test_func(self):
        post = self.get_object()
        if self.request.user == post.author:
            return True
        return False

urls.py

urlpatterns = [
    # home
    path('', views.postslist.as_view(), name='home'),

    # add post
    path('blog_post/', views.PostCreateView.as_view(), name='blog_post'),

    # posts/comments
    path('<slug:slug>/', views.postdetail.as_view(), name='post_detail'),

    # edit post
    path('<slug:slug>/edit/', views.Editpost.as_view(), name='edit_post'),

    # delete post
    path('<int:pk>/delete/', views.Deletepost.as_view(), name='delete_post'),

    # likes
    path('like/<slug:slug>', views.PostLike.as_view(), name='post_like'),

]

post.html

<a class="btn btn-outline-danger" href="{% url 'delete_post' post.id %}">Delete</a>

Thanks for your time and i'm sorry for the trivial question but you guys are much smarter than me!

I think it should be model not form_class so:

class Deletepost(LoginRequiredMixin, DeleteView):
    model = Post
    success_url = reverse_lazy('blog:home')
    template_name = 'templates/post.html'

    def test_func(self):
        post = self.get_object()
        if self.request.user == post.author:
            return True
        return False

@SunderamDubey's answer is correct. The test_func will however not run, since this is method of the UserPassesTestMixin [Django-doc], not LoginRequiredMixin.

But using a test function as is done here is not efficient: it will fetch the same object twice from the database. You can simply restrict the queryset, like:

from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.views.generic import DeleteView


class DeletePostView(LoginRequiredMixin, DeleteView):
    model = Post
    success_url = reverse_lazy('blog:home')
    template_name = 'templates/post.html'

    def get_queryset(self, *args, **kwargs):
        return (
            super().get_queryset(*args, **kwargs).filter(author=self.request.user)
        )

This will do filtering at the database side, and thus return a 404 in case the logged in user is not the author of the Post object you want to delete.

In the template, you will need to make a mini-form to make a POST request, for example:

<form method="post" action="{% url 'delete_post' post.id %}">
    {% csrf_token %}
    <button class="btn btn-outline-danger" type="submit">Delete</button>
</form>

In my opinion, you should change url to below 'path('delete/int:pk', views.Deletepost.as_view(), name='delete_post'),'

if didn't work you can do this

def delete_post(request, post_id):
    post = Post.objects.get(pk=post_id)
    post.delete()
    return redirect('blog:home')
Back to Top