Search code examples
djangodjango-viewsdjango-templates

How do I override the delete() method in Django's DeleteView to send a success message?


I'm using Django 5.0.3. I have a job listings app, with a DeleteListingView. I want to override the delete() method, so that I can use messages.success() to send a message to the success url's template once a listing is deleted.

However, the delete() method isn't being overridden. A listing gets deleted, and I'm redirected to the correct url, but the message isn't sent. I've even tried to add a print() statement inside delete() to see if it appears in cmd, but it doesn't.

from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages

from django.urls import reverse_lazy

from django.views.generic import ListView, DetailView
from django.views.generic.edit import UpdateView, DeleteView, CreateView

from .models import Listings

class ListingsListView(ListView):
    model = Listings
    template_name = 'listings/listings_list.html'
    context_object_name = 'listings'


class DeleteListingView(LoginRequiredMixin, DeleteView):
    model = Listings
    template_name = 'listings/listing_delete.html'
    context_object_name = 'listing'
    success_url = reverse_lazy('listings')

    def delete(self, request, *args, **kwargs):
        listing = self.get_object()
        listing_title = listing.job_title  

        messages.success(self.request, f"Listing titled '{listing_title}' was deleted successfully.")
        print(f"delete() has been overridden successfully.") # To appear in cmd
        return super().delete(request, *args, **kwargs)

and in listings_list.html template:

{% for message in messages %}
   <p> {{ message }}</p>
{% endfor %}

Nothing I've tried is working, and I can't seem to find a solution anywhere. What am I missing?

#Update: After research, even using ChatGPT, I still can't make the custom delete() method execute. I've tried a function-based view, and it worked. The messages.success() was executed accordingly, and displayed in the success_url's template. Here's the view:

def delete_item(request, pk):
    listing = get_object_or_404(Listings, pk=pk)

    if request.method == 'POST':
        listing_title = listing.job_title
        listing.delete()
        messages.success(request, f"Listing titled '{listing_title}' was deleted successfully.")
        return redirect(reverse('listings'))

    return render(request, 'listings/listing_delete.html', {'listing': listing})

Solution

  • Since Django 4.0 DeleteView uses the FormMixin and hence depends on the form_valid method instead. As a consequence it now also supports the SuccessMessageMixin which you should use:

    from django.contrib.messages.views import SuccessMessageMixin
    
    
    class DeleteListingView(LoginRequiredMixin, SuccessMessageMixin, DeleteView):
        model = Listings
        template_name = 'listings/listing_delete.html'
        context_object_name = 'listing'
        success_url = reverse_lazy('listings')
        success_message = "Listing titled '%(title)s' was deleted successfully."
        
        def get_success_message(self, cleaned_data):
            return self.success_message % dict(
                cleaned_data,
                title=self.object.job_title,
            )