I want to convert user deletion from FBV to CBV
My FBV
def delete_student(request, pk):
student = get_object_or_404(Student, pk=pk)
student.delete()
return HttpResponseRedirect(reverse("students:get_students"))
My CBV
class DeleteStudentView(DeleteView):
model = Student
form_class = StudentForm
template_name = "students/students_list.html"
success_url = reverse_lazy("students:get_students")
student_list.html
<td><a type="button"
href="{% url 'students:delete_student' student.pk %}">Delete</a>
</td>
There is no error, but no selection occurs. What could be the problem?
CodePudding user response:
A DeleteView
deletes with a POST or DELETE request. This is mandatory by the specs of the HTTP protocol. Your FBV is not HTTP compliant.
You thus will need to make a mini-form to do this. For example make a hidden form with:
<td><button onclick="delete_item({{ student.pk }});">Delete</button></td> <!-- … --> <form method="post" action="{% url 'students:delete_student' %}" id="delete_form"> {% csrf_token %} <input type="hidden" name="pk" id="delete_pk"> </form> <script> function delete_item(pk) { var hidden_item = document.getElementById("delete_pk"); hidden_item.value = pk; var form = document.getElementById("delete_form"); form.submit(); } </script>
In the urls.py
we define an entry for the StudentDeleteView
without parameters:
# students/urls.py
from django.urls import path
app_name = 'students'
urlpatterns = [
# …
path('student/delete/', StudentDeleteView.as_view(), 'delete_student'),
# …
]
In the DeleteView
, you then determine the object with the primary key:
from django.shortcuts import get_object_or_404
class DeleteStudentView(DeleteView):
model = Student
success_url = reverse_lazy('students:get_students')
def get_object(self, *args, **kwargs):
return get_object_or_404(Student, pk=self.request.POST.get('pk'))
To make your function-based view HTTP compliant, you should enforce that it can only do this with a POST or DELETE request, for example with a @require_http_methods(…)
decorator [Django-doc]:
from django.shortcuts import get_object_or_404, redirect
from django.views.decorators.http import require_http_methods
@require_http_methods(["DELETE", "POST"])
def delete_student(request):
student = get_object_or_404(Student, pk=request.POST.get('pk'))
student.delete()
return redirect('students:get_students')
and thus use the same "trick" with the mini-form.