如何实现Django动态删除功能?无需重复编写多模型删除函数
实现Django多模型通用删除功能的方案
要实现这种不用为每个模型单独写删除逻辑的动态功能,核心就是动态获取模型类,而不是像现在这样硬编码死models.Post。咱们可以通过从请求里传递模型名称,结合Django自带的apps.get_model()方法来搞定,下面是具体的修改步骤:
1. 改造后端视图:支持动态模型
首先修改views.py里的删除视图,把原本固定的Post模型改成动态获取的:
from django.apps import apps from django.http import Http404 from django.views.generic.edit import DeleteView from django.urls import reverse_lazy def delete_data(request): # 从GET请求里拿到模型名称和对象ID model_name = request.GET.get('model') obj_id = request.GET.get('id') # 动态获取模型类——这里要注意替换成你实际的app名称(比如你的模型都在`system` app下) try: model = apps.get_model('system', model_name) except LookupError: # 如果传的模型不存在,直接返回404 raise Http404("指定的模型不存在") # 获取要删除的对象(替代你原本的`post = models.Post.objects.get(id=id)`) obj = model.objects.get(id=obj_id) # 把对象和模型名称传给模板,方便后续生成正确的删除URL return render(request, 'system/ajax/delete.html', {'obj': obj, 'model_name': model_name}) # 通用的删除类视图,替代原来的PostDelete class GenericDeleteView(DeleteView): def get_model(self): # 从URL参数里获取模型名称 model_name = self.kwargs.get('model') return apps.get_model('system', model_name) def get_queryset(self): # 动态返回对应模型的查询集 model = self.get_model() return model.objects.all() def get_success_url(self): # 这里需要给每个模型配置对应的列表页URL,你可以根据实际情况补充 url_mapping = { 'Post': reverse_lazy("system:post_list"), # 比如以后加个Comment模型,就加一行: # 'Comment': reverse_lazy("system:comment_list"), } return url_mapping[self.kwargs.get('model')]
2. 更新URL配置:适配通用路由
修改urls.py,把原来的post_delete路由改成通用的,同时确保ajax路由正常:
from django.urls import path # 建议用path代替旧的url语法,更清晰 urlpatterns = [ path('post-list/', views.PostList.as_view(), name='post_list'), # 通用删除路由:捕获模型名称和对象PK path('<str:model>-delete/<int:pk>/', views.GenericDeleteView.as_view(), name='generic_delete'), path('ajax/delete/', views.delete_data, name='ajax_delete_data'), ]
3. 调整前端模板:传递模型参数
post_list.html:给删除按钮加模型标识
修改删除按钮,添加data-model属性来传递模型名称,同时更新ajax请求的参数:
<!-- 以Post模型为例,其他模型的按钮只需要改data-model的值就行 --> <button data-id="{{ post.id }}" data-model="Post" data-url="{% url 'system:ajax_delete_data' %}" type="button" class="delete-post"> delete </button> <script> $(document).on('click','.delete-post',function(){ var url = $(this).data('url'); var id = $(this).data('id'); var model = $(this).data('model'); // 拿到模型名称 $.ajax({ url:url, data:{ 'id': id, 'model': model // 把模型名称传给后端 }, success:function(data){ $('#delete-data').html(data); }, }); }); </script>
delete.html:动态生成删除表单的action
把原本固定的post变量改成通用的obj,同时动态生成通用删除的URL:
<form method="post" action="{% url 'system:generic_delete' model=model_name pk=obj.pk %}"> {% csrf_token %} <input type="submit" class="btn btn-danger" value="delete"> </form>
一些关键细节说明
- 动态模型的安全性:
apps.get_model()只会返回你项目中存在的模型,不用担心传入非法模型的问题(我们也加了try-except做异常处理)。 - 扩展性:以后要支持新模型的删除,你只需要两步:
- 在
GenericDeleteView的url_mapping里添加新模型对应的列表页URL - 在前端页面的删除按钮上加上
data-model="你的新模型类名"
- 在
- 关于类视图的灵活性:如果你的模型列表页URL有规律(比如
模型名小写_list),可以不用写url_mapping,直接动态生成,比如return reverse_lazy(f"system:{model_name.lower()}_list"),这样更省心。
内容的提问来源于stack exchange,提问作者Dicky Raambo
相关产品推荐
相关产品推荐

