Search code examples
djangoregexdjango-viewsdjango-urlsdjango-generic-views

Can't get the DeleteView of a post in a social network project


I am building a simple social network in django.

In the "home" of my social, I have the list of all posts published by all users, with author and publishing date. Under each post of the logged user, a "delete" button appears. If the user clicks on it, it should return a specific view of that post, with a message like "do you really wish to delete this post?"

However, as I click on it, the code returns this error:

NoReverseMatch at /posts/delete/7/

Reverse for 'single' with no arguments not found. 1 pattern(s) tried: ['posts/by/(?P[-\w]+)/(?P\d+)/$']

Why does it says that it cannot get the reverse for 'single' with no arguments, while in the template the delete button has a link to 'delete' view function?

Here is my urls.py, inside urlpatterns:

url(r'^$', 
views.PostList.as_view(), 
name='all'),

url(r'new/$', 
views.CreatePost.as_view(), 
name='create'),

url(r'by/(?P<username>[-\w]+)/$', 
views.UserPosts.as_view(), 
name='for_user'),

url(r'by/(?P<username>[-\w]+)/(?P<pk>\d+)/$', 
views.PostDetail.as_view(), 
name='single'),
 
url(r'delete/(?P<pk>\d+)/$', 
views.DeletePost.as_view(), 
name='delete'),

Here is my views.py:

class DeletePost(LoginRequiredMixin, SelectRelatedMixin, generic.DeleteView):

    model = models.Post
    select_related = ('user', 'group')
    success_url = reverse_lazy('posts:all')

    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.filter(user_id = self.request.user.id)

    def delete(self,*args,**kwargs):
        messages.success(self.request,'Post Deleted')
        return super().delete(*args,**kwargs)

Here is my piece of template making the delee button appear:

    {% if user.is_authenticated and post.user.username == user.username %}
       
        <a href="{% url 'posts:delete'  pk=post.pk %}" title="delete" class="btn btn-simple">
            <span class="glyphicon glyphicon-remove text-danger" aria-hidden="true"></span>
            <span class="text-danger icon-label">Delete</span>
        </a>

   {% endif %}

EDIT:

Here is my piece of template showing the post and asking the user if he/she really wants to delete it:

<h3>Do you want to delete this post?</h3>

<div class="posts">
    {% include "posts/_post.html" with post=object hide_delete=True %}
</div>

<form class="POST">
    {% csrf_token %}
    <input type="submit" value="Confirm Delete" class="btn btn-danger btn-large">
    <a href="{% url 'posts:single' username=user.username pk=object.pk %}"
    class="btn btn-simple btn-large btn-default">Cancel</a>
</form>

The model User is django's default models.User

Note: I previously encountered a similar error related to the use of regex expressions. More details can be found in this other question.


Solution

  • I was looking for the error in the part of template showing the delete button, while it lied in the template asking the user if he/she wants the post to be deleted.

    In code piece:

    <h3>Do you want to delete this post?</h3>
    
    <div class="posts">
        {% include "posts/_post.html" with post=object hide_delete=True %}
    </div>
    
    <form class="POST">
        {% csrf_token %}
        <input type="submit" value="Confirm Delete" class="btn btn-danger btn-large">
        <a href="{% url 'posts:single' %} username=user.username pk=object.pk %}"
        class="btn btn-simple btn-large btn-default">Cancel</a>
    </form>
    

    I replaced

    <a href="{% url 'posts:single' %} username=user.username pk=object.pk %}"
    

    with:

    <a href="{% url 'posts:delete' pk=post.pk %}"
    

    and now it finally takes me to the post deletion confirm view