Django/Python - функция Delete в UpdateView дублирует, а не удаляет

Я создал приложение на Django, которое позволяет пользователям вводить данные о своих биржевых сделках в качестве инструмента для ведения журнала. Когда пользователь нажимает на отдельную запись в журнале на индексной странице, он попадает на страницу с подробной информацией об этой отдельной записи (single_entry.html). Эта страница обрабатывается с помощью UpdateView. На этой странице пользователь может редактировать/обновлять любую информацию, а также УДАЛЯТЬ конкретную запись. Для этого я импортировал модуль DeletionMixin из django.views.generic.edit.

Однако, когда я нажимаю на кнопку "Удалить" в форме, запись дублируется, а не удаляется! Кто-нибудь знает, почему это происходит? Спасибо за помощь!

Вот мой вид, основанный на классе, в файле views.py:

class SingleEntryView(UpdateView):
  template_name = "single_entry.html"
  model = Entry
  fields = ['ticker', 'strategy', 'result', 'comments', 'image']
  success_url = '/'
    
  def post(self, request, *args, **kwargs):
    if "delete_button" in self.request.POST:
      return self.delete(request, *args, **kwargs)
    
  def update_post(self, form, pk):
    if "update_button" in self.request.POST:
      form.instance.user = self.request.user
    return super(SingleEntryView, self).update_post(form)

single_entry.html:

{% extends 'base.html' %}

{% block title %}
    Trading Journal - Entry
{% endblock title %}Trading Journal

{% block content %}

<form method="POST" action="/">
    {% csrf_token %}
    {% for field in form %}
        {{field.label_tag}}
        {{field}}
        {% if field.errors %}
            <small class="error">{{ field.errors|striptags }}</small>            
        {% endif %}
    {% endfor %}
    <button type="submit" name="update_button">Save</button>
    <button type="submit" name="delete_button">Delete</button>
    
</form>

<img src="{{ entry.image.url }}" alt="{{ entry.result }}">

{% endblock content %}

urls.py:

from django.urls import path
from django.contrib import admin
from . import views

urlpatterns = [
    path("", views.EntryView.as_view()),
    path("entries/<int:pk>/", views.SingleEntryView.as_view(), name="single-entry"),
    path("admin/", admin.site.urls)
]

Обратившись за помощью к ChatGPT, он порекомендовал следующий код в моем UpdateView (который дал мне ту же проблему):

  def post(request, self, form):
    print("post request")
    print("request.post", request.POST)
    if "delete" in request.POST:
      print("delete found")
      return self.delete_entry()
    else:
      print("else statement")
      #return super(SingleEntryView, self).post(request, form)

      return super().post(request, form)
      #return super().post(request, *args, **kwargs)      

  def delete_entry(self):
    entry = self.get_object()
    print("get object")
    entry.delete()
    messages.success(self.request, "Your entry was deleted successfully.")
    return redirect("/")

В вашем коде, похоже, вы пытаетесь обработать удаление записи в методе post() вашего класса SingleEntryView. Но DeleteView, предоставляемый Django, уже обрабатывает логику удаления, поэтому вам не нужно переопределять метод post() для удаления. Теперь измените свой код следующим образом :

from django.urls import reverse_lazy
from django.contrib import messages
from django.views.generic import DeleteView

class SingleEntryDeleteView(DeleteView):
    model = Entry
    template_name = "delete_entry.html"
    success_url = reverse_lazy('index')

    def delete(self, request, *args, **kwargs):
        messages.success(self.request, "Your entry was deleted successfully.")
        return super().delete(request, *args, **kwargs)

Теперь он будет обрабатывать процесс удаления, и запись будет удалена без дублирования.

А в вашем single_entry.html вы можете создать ссылку или кнопку для удаления вида, например, так :

<form method="POST" action="{% url 'single-entry-delete' entry.pk %}">
    {% csrf_token %}
    <button type="submit">Delete</button>
</form>

Убедитесь, что у вас есть соответствующий шаблон URL в вашем urls.py для SingleEntryDeleteView:

from django.urls import path
from .views import SingleEntryDeleteView

urlpatterns = [
    path('entries/<int:pk>/delete/', SingleEntryDeleteView.as_view(), name='single-entry-delete'),
]

Теперь все должно работать нормально. Счастливого кодинга!

Здесь есть две проблемы. Первая заключается в том, что вы не прокладываете маршрут обратно к вашему представлению, вы должны сделать POST-запрос по тому же пути, так:

<!-- no action 🖟 -->
<form method="POST">
    <!-- … -->
</form>

в представлении вы должны обработать сценарий удаления с помощью self.object.delete():

class SingleEntryView(UpdateView):
    template_name = 'single_entry.html'
    model = Entry
    fields = ['ticker', 'strategy', 'result', 'comments', 'image']
    success_url = '/'

    def post(self, request, *args, **kwargs):
        if 'delete_button' in self.request.POST:
            self.object.delete()
            return HttpResponseRedirect(self.get_success_url())
        return super().post(request, *args, **kwargs)

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

Note: Since PEP-3135 [pep], you don't need to call super(…) with parameters if the first parameter is the class in which you define the method, and the second is the first parameter (usually self) of the function.

Вернуться на верх