Django Admin:将TabularInline改造为带分页等功能的列表
解决Django Admin TabularInline大数据量问题的实用方案
一、第三方工具包快速实现
1. django-admin-inline-paginator(分页+每页条目设置)
安装后,让你的Inline类继承该包的分页Inline类,直接开启分页功能:
from django_admin_inline_paginator.admin import PaginatorTabularInline class DiscountCodeUsageInline(PaginatorTabularInline): model = DiscountCodeUsage per_page = 50 # 自定义每页显示条数 extra = 0
2. 扩展筛选、搜索与多选删除
搭配django-admin-enhancer可以给Inline添加搜索和筛选,配置方式和普通Admin一致:
from admin_enhancer.admin import EnhancedTabularInline class DiscountCodeUsageInline(EnhancedTabularInline): model = DiscountCodeUsage per_page = 50 search_fields = ('user__username', 'used_at') # 搜索字段 list_filter = ('used_at', 'user__is_active') # 筛选条件
多选删除功能可通过该工具包自带的批量操作支持,或在模板中添加复选框后,重写Inline的批量处理逻辑实现。
二、自定义实现(无第三方依赖)
如果不想依赖外部包,可手动改造:
1. 重写TabularInline模板
复制Django默认的admin/edit_inline/tabular.html到项目模板目录,命名为admin/custom_tabular_inline.html,在模板中添加:
- 分页控件:基于分页数据生成分页链接
- 搜索表单:添加搜索输入框,提交时传递
q参数 - 筛选表单:添加日期/字段筛选下拉框
- 多选复选框:每行前置复选框,name设为
selected_ids
2. 自定义Inline类处理请求逻辑
from django.contrib import admin from django.core.paginator import Paginator from django.db.models import Q class CustomDiscountCodeUsageInline(admin.TabularInline): model = DiscountCodeUsage template = 'admin/custom_tabular_inline.html' extra = 0 def get_queryset(self, request): qs = super().get_queryset(request) # 处理搜索 search_query = request.GET.get('q') if search_query: qs = qs.filter( Q(user__username__icontains=search_query) | Q(used_at__icontains=search_query) ) # 处理日期筛选 used_date = request.GET.get('used_date') if used_date: qs = qs.filter(used_at__date=used_date) # 分页处理 page_num = request.GET.get('page', 1) self.paginator = Paginator(qs, per_page=50) return self.paginator.get_page(page_num) def render_change_form(self, request, context, **kwargs): # 传递分页数据到模板 context['paginator'] = self.paginator context['page_obj'] = self.get_queryset(request) return super().render_change_form(request, context, **kwargs) def save_formset(self, request, form, formset, change): # 处理批量删除 if 'delete_selected' in request.POST: selected_ids = request.POST.getlist('selected_ids') self.model.objects.filter(id__in=selected_ids).delete() super().save_formset(request, form, formset, change)
三、替代方案:关联Admin页面跳转
如果改造Inline成本高,可给DiscountCodeUsage单独配置Admin,然后在DiscountCode的Admin中添加跳转链接,直接使用完整的Admin列表功能:
from django.contrib import admin from django.urls import reverse from django.utils.html import format_html class DiscountCodeAdmin(admin.ModelAdmin): list_display = ('code', 'usage_count', 'view_usages_link') def usage_count(self, obj): return obj.discountcodeusage_set.count() def view_usages_link(self, obj): changelist_url = reverse('admin:your_app_discountcodeusage_changelist') filtered_url = f"{changelist_url}?discount_code__id__exact={obj.id}" return format_html('<a href="{}">查看所有使用记录</a>', filtered_url)
点击链接后会进入自动筛选当前优惠码使用记录的列表页,直接用Django Admin自带的分页、筛选、搜索和批量删除功能。
内容的提问来源于stack exchange,提问作者Ahima
相关产品推荐
相关产品推荐

