I have a project with a Post model, that is basic posts. I want to create a link on each post page to be able to delete that post (with appropriate security).
There are
Indeed, using a GET method to delete your objects makes you vulnerable to CSRF attacks.
DeleteView only deletes on POST, and shows a confirmation page on GET.
Your code should look something like this in views.py
:
from django.views.generic import DeleteView
class PostDelete(DeleteView):
model = Post
success_url = reverse_lazy('posts.views.all_posts')
In urls.py
:
url(r'^delete/(?P<pk>\d+)/$', PostDelete.as_view(),
name='entry_delete'),
Your form (without using a confirmation template. There is an example of confirmation template in the docs):
<form action="{% url 'entry_delete' object.pk %}" method="post">
{% csrf_token %}
<input type="submit" value="Delete" />
</form>
If you are not using a confirmation template, make sure to point the form's action
attribute to the DeleteView
(this is why).
To ensure the user deleting the post is the user that owns it, I like to use mixins. Assuming your Post
model has a created_by
foreign key pointing to User
, you could write a mixin like:
from django.core.exceptions import PermissionDenied
class PermissionMixin(object):
def get_object(self, *args, **kwargs):
obj = super(PermissionMixin, self).get_object(*args, **kwargs)
if not obj.created_by == self.request.user:
raise PermissionDenied()
else:
return obj
Finally, your DeleteView
should inherit from this mixin:
class PostDelete(PermissionMixin, DeleteView):
model = Post
success_url = reverse_lazy('posts.views.all_posts')