Home > Software engineering >  improperly configured at /18/delete, Django views issue
improperly configured at /18/delete, Django views issue

Time:11-16

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

     {% extends 'base.html' %} {% block content %}
 {% load crispy_forms_tags %}
 <div >
    <div >
        <div >
            <div >
                <!-- Post title goes in these h1 tags -->
                <h1 >{{ post.title }}</h1>
                <!-- Post author goes before the | the post's created date goes after -->
                <p >{{ post.author }} | {{ post.created_on }}</p>
            </div>
            <div >
                <!-- The featured image URL goes in the src attribute -->
                {% if "placeholder" in post.featured_image.url %}
                <img src="https://codeinstitute.s3.amazonaws.com/fullstack/blog/default.jpg" width="100%">
                {% else %}
                <img src=" {{ post.featured_image.url }}" width="100%">
                {% endif %}
            </div>
        </div>
    </div>
</div>

<div >
    <div >
        <div >
            <div >
                <!-- The post content goes inside the card-text. -->
                <!-- Use the | safe filter inside the template tags -->
                <p >
                    {{ post.content | safe }}
                </p>
                <div >

                    <div >
                        <strong>
                            {% if user.is_authenticated %}
                            <form  action="{% url 'post_like' post.slug %}" method="POST">
                                {% csrf_token %}
                                {% if liked %}
                                <button type="submit" name="blogpost_id" value="{{post.slug}}" ><i ></i></button>
                                {% else %}
                                <button type="submit" name="blogpost_id" value="{{post.slug}}" ><i ></i></button>
                                {% endif %}
                            </form>
                            {% else %}
                            <span ><i ></i></span>
                            {% endif %}
                        <!-- The number of likes goes before the closing strong tag -->
                        <span >{{ post.number_of_likes }} </span>
                        </strong>
                    </div>
                    <div >
                        {% with comments.count as total_comments %}
                        <strong ><i ></i>
                            <!-- Our total_comments variable goes before the closing strong tag -->
                            {{ total_comments }}</strong>
                        {% endwith %}
                    </div>
                    <div >
                        <a  href="{% url 'delete_post' post.id %}">Delete It</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div >
        <div >
            <hr>
        </div>
    </div>
    <div >
        <div >
            <h3 >Comments:</h3>
            <div >
                <!-- We want a for loop inside the empty control tags to iterate through each comment in comments -->
                {% for comment in comments %}
                <div  style="padding: 10px;">
                    <p >
                        <!-- The commenter's name goes here. Check the model if you're not sure what that is -->
                        {{ comment.name }}
                        <span >
                            <!-- The comment's created date goes here -->
                            {{ comment.created_on }}
                        </span> wrote:
                    </p>
                    <!-- The body of the comment goes before the | -->
                    {{ comment.body | linebreaks }}
                </div>
                <!-- Our for loop ends here -->
                {% endfor %}
            </div>
        </div>
        <div >
            <div >
                <!-- For later -->
                {% if commented %}
                <div  role="alert">
                    Your comment is awaiting approval
                </div>
                {% else %}
                {% if user.is_authenticated %}

                <h3 >Leave a comment:</h3>
                <p >Posting as: {{ user.username }}</p>
                <form  method="post" style="margin-top: 1.3em;">
                    {{ comment_form | crispy }}
                    {% csrf_token %}
                    <button type="submit" >Submit</button>
                </form>
                {% endif %}
                {% endif %}
            </div>
        </div>
    </div>
</div>

{% endblock content %}

Any ideas?

CodePudding user response:

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

CodePudding user response:

@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  type="submit">Delete</button>
</form>

CodePudding user response:

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')
  • Related