Django删除视图异常:点击任意删除按钮均指向同一条目
问题描述
我想让delete_entry视图删除对应的条目,但无论点击哪个删除按钮,都会引用同一个item_id。我修改了视图,让它只打印要删除的条目而不执行删除,但不管选列表里哪个按钮,选中的都是同一个条目。
请问我的视图有问题吗?我的编辑功能正常运行,要不要把delete_entry改成和EditHealth一样的工作方式?
相关代码
Health_hub_history.html
{% for item in stats %} <tr> <td>{{ item.user }}</td> <td>{{ item.weight }} </td> <td>{{ item.date }}</td> <td>{{ item.run_distance }}</td> <td>{{ item.run_time }}</td> <!-- Button trigger modal --> <td> <a href="edit/{{ item.id }}"><button type="button" class="btn btn-primary"> Edit </button> </a> </td> <td> <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#staticBackdrop"> Delete </button> </td> <!-- Modal --> <div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="staticBackdropLabel">Are you sure you want to delete this entry?</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> If you just need to amend something, try the edit button. </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> <a href="delete/{{ item.id }}"><button class="btn btn-danger">I'm sure</button></a> </div> </div> </div> </div> </tr> {% endfor %}
Views.py
def health_history(request): serialized_stats = [] for stats in HealthStats.objects.filter(user=request.user): serialized_stats.append({ "user": stats.user, "weight": stats.weight, "date": stats.date, "run_distance": stats.run_distance, "run_time": stats.run_time, "id": stats.id, }) context = { "stats": serialized_stats } return render(request, 'health_hub_history.html', context) def delete_entry(request, item_id): entry = get_object_or_404(HealthStats, id=item_id) print(entry) # entry.delete() return redirect("HealthHub:health_hub_history") class EditHealth(UpdateView): model = HealthStats template_name = 'health_hub_edit.html' fields = ['weight', 'run_distance', 'run_time']
Urls.py
urlpatterns = [ path('', views.home, name='home'), path('MyHealth/', views.health_hub, name='health_hub'), path('MyHealth/update', views.UpdateHealth.as_view(), name='health_hub_update'), path('MyHealth/history', views.health_history, name='health_hub_history'), path('favicon.ico', RedirectView.as_view(url=staticfiles_storage.url("favicon.ico"))), path('MyHealth/delete/<item_id>', views.delete_entry, name='health_hub_delete'), path('MyHealth/edit/<int:pk>', views.EditHealth.as_view(), name='health_hub_edit'), ]
Models.py
from django.db import models from django.contrib.auth.models import User from django.urls import reverse class HealthStats(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) date = models.DateTimeField(auto_now_add=True) weight = models.DecimalField(max_digits=5, decimal_places=2) run_distance = models.DecimalField(max_digits=5, decimal_places=2) run_time = models.DurationField() class Meta: db_table = 'health_stats' ordering = ['-date'] def get_absolute_url(self): return reverse('HealthHub:health_hub_history') def __str__(self): return f"{self.user} | {self.date}"
解决方案
1. 修复Modal的ID冲突问题
问题核心是所有删除按钮绑定的Modal ID都是staticBackdrop,HTML中ID必须唯一,所以无论点击哪个按钮,都会触发页面中第一个(或最后一个)Modal,导致跳转的item_id固定。
修改HTML代码,给每个Modal和对应的触发按钮添加唯一ID:
{% for item in stats %} <tr> <!-- ... 其他列保持不变 ... --> <td> <!-- 修改data-bs-target为带item.id的唯一ID --> <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#staticBackdrop-{{ item.id }}"> Delete </button> </td> <!-- Modal --> <!-- 修改Modal的id为staticBackdrop-{{ item.id }} --> <div class="modal fade" id="staticBackdrop-{{ item.id }}" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel-{{ item.id }}" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <!-- 标题ID也保持唯一 --> <h5 class="modal-title" id="staticBackdropLabel-{{ item.id }}">Are you sure you want to delete this entry?</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <!-- ... 其他Modal内容保持不变 ... --> </div> </div> </div> </tr> {% endfor %}
2. 修正URL路径的参数类型
在Urls.py中,删除路径的参数应该指定为整数类型,和编辑路径保持一致:
# 把 <item_id> 改成 <int:item_id> path('MyHealth/delete/<int:item_id>', views.delete_entry, name='health_hub_delete'),
3. (可选)改用类视图实现删除功能
既然编辑用了UpdateView,删除可以用Django自带的DeleteView,保持代码风格统一:
修改Views.py:
from django.views.generic import DeleteView from django.urls import reverse_lazy # 替换原来的delete_entry函数 class DeleteHealth(DeleteView): model = HealthStats success_url = reverse_lazy('HealthHub:health_hub_history') # 可以自定义确认模板,或者直接用默认的 # template_name = 'health_hub_delete_confirm.html'
修改Urls.py:
# 替换原来的delete路径 path('MyHealth/delete/<int:pk>', views.DeleteHealth.as_view(), name='health_hub_delete'),
调整HTML中的跳转链接:
<!-- 把 delete/{{ item.id }} 改成 delete/{{ item.id }}(因为DeleteView用pk参数,和item.id一致) --> <a href="delete/{{ item.id }}"><button class="btn btn-danger">I'm sure</button></a>
内容的提问来源于stack exchange,提问作者BenD2525
相关产品推荐
相关产品推荐

