Django 1.11如何整合auth.models与自定义Model字段?
最优实现方案:在User Admin中展示所有用户的Response提交状态
你想要在Django Admin的用户列表里显示全部注册用户,同时关联他们的Response模型中的created字段(包括未提交过响应的用户),这个需求可以通过Django的annotate结合Subquery来高效实现,避免常见的N+1查询性能问题,具体步骤如下:
1. 核心思路
我们需要给User的查询集添加一个注解字段,用来关联每个用户对应的最新(或最早)Response的created时间。通过Subquery可以在一次数据库查询中完成关联,而不需要为每个用户单独发起查询。
2. 修改Admin代码
更新你的survey/admin.py文件,代码如下:
from django.contrib import admin from django.contrib.auth.models import User from django.db.models import Subquery, OuterRef from survey.models.response import Response # 先取消默认的User注册 admin.site.unregister(User) class UserAdmin(admin.ModelAdmin): # 把自定义的字段加入列表展示 list_display = ('username', 'response_submit_time') def get_queryset(self, request): # 子查询:获取每个用户最新的Response记录的created时间 latest_responses = Response.objects.filter( user=OuterRef('pk') ).order_by('-created') # 按创建时间倒序,取最新的一条 # 给User查询集添加注解字段 return super().get_queryset(request).annotate( _latest_response_created=Subquery(latest_responses.values('created')[:1]) ) def response_submit_time(self, obj): # 处理未提交过响应的用户,显示友好提示 return obj._latest_response_created if obj._latest_response_created else "未提交" # 设置列表表头的显示名称 response_submit_time.short_description = '响应提交时间' # 重新注册自定义的UserAdmin admin.site.register(User, UserAdmin)
3. 方案优势
- 覆盖所有用户:不管用户有没有提交过
Response,都会出现在列表中,未提交的用户会显示“未提交”,完美满足你查看「谁没提交」的需求。 - 性能高效:通过
Subquery实现一次关联查询,避免了为每个用户单独查询Response的N+1性能问题,即使是200个用户也能快速加载。 - 灵活可扩展:如果想展示最早的提交时间,只需要把
order_by('-created')改成order_by('created')即可;如果需要展示其他Response字段,也可以用同样的方式扩展。
为什么不推荐其他方式?
如果直接在response_submit_time方法中通过obj.response_set.first().created获取时间,会导致每个用户加载时都发起一次额外的数据库查询,当用户数量多的时候,性能会明显下降,这也是我们优先选择annotate+Subquery的原因。
内容的提问来源于stack exchange,提问作者ron_g
相关产品推荐
相关产品推荐

