如何在Django Admin中基于关联CustomUser的date_created字段实现筛选功能
嘿,我来帮你搞定这个Admin筛选的问题!你遇到的报错是因为date_created并不是EmailConfirmed模型本身的字段,它属于关联的CustomUser模型,直接把date_created加到list_filter里,Django会找不到对应的字段。下面给你两种实用的解决办法:
方法一:用跨关系筛选语法(最简单直接)
Django Admin支持通过双下划线__来关联外键模型的字段,你只需要修改EmailConfirmedAdmin的list_filter配置,把关联字段的路径user__date_created加进去就行:
修改admin.py里的EmailConfirmedAdmin类:
class EmailConfirmedAdmin(admin.ModelAdmin): list_display = ('user', 'first_name', 'last_name', 'date_created', 'email_confirmed', 'date_confirmed') # 新增user__date_created来关联CustomUser的date_created字段 list_filter = ('email_confirmed', 'date_confirmed', 'user__date_created', ) def date_created(self, obj): return obj.user.date_created def first_name(self, obj): return obj.user.first_name def last_name(self, obj): return obj.user.last_name
修改完成后刷新Admin面板,你就能看到基于用户创建时间的筛选器了,和默认的筛选器功能完全一致。
方法二:自定义筛选器(更灵活,适合定制需求)
如果想要给筛选器设置更友好的名称,或者需要自定义筛选逻辑(比如按最近7天、30天筛选),可以继承admin.SimpleListFilter来创建自定义筛选器:
首先在admin.py中添加自定义筛选器类:
from django.contrib import admin from .models import EmailConfirmed from django.utils.translation import gettext_lazy as _ from django.utils import timezone from datetime import timedelta class UserCreationDateFilter(admin.SimpleListFilter): # 筛选器显示在Admin侧边栏的名称 title = _('User Creation Date') # 用于URL参数的标识(避免和其他筛选器冲突) parameter_name = 'user_creation_date' def lookups(self, request, model_admin): # 定义筛选选项,这里可以根据需求自定义 return ( ('last_7_days', _('Last 7 Days')), ('last_30_days', _('Last 30 Days')), ('older_than_30', _('Older than 30 Days')), ) def queryset(self, request, queryset): # 根据用户选择的选项过滤查询集 selected_value = self.value() if not selected_value: return queryset if selected_value == 'last_7_days': cutoff_date = timezone.now() - timedelta(days=7) return queryset.filter(user__date_created__gte=cutoff_date) elif selected_value == 'last_30_days': cutoff_date = timezone.now() - timedelta(days=30) return queryset.filter(user__date_created__gte=cutoff_date) elif selected_value == 'older_than_30': cutoff_date = timezone.now() - timedelta(days=30) return queryset.filter(user__date_created__lt=cutoff_date) return queryset
然后在EmailConfirmedAdmin中使用这个自定义筛选器:
class EmailConfirmedAdmin(admin.ModelAdmin): list_display = ('user', 'first_name', 'last_name', 'date_created', 'email_confirmed', 'date_confirmed') # 替换成自定义筛选器 list_filter = ('email_confirmed', 'date_confirmed', UserCreationDateFilter, ) def date_created(self, obj): return obj.user.date_created def first_name(self, obj): return obj.user.first_name def last_name(self, obj): return obj.user.last_name
这样修改后,Admin侧边栏会出现一个名为“User Creation Date”的筛选器,里面有你自定义的时间区间选项,用户体验更友好。
小提醒
注意到你的CustomUser模型里date_created字段用的是auto_now=True,这个参数会在用户每次被修改时更新时间。如果你的目的是记录用户的创建时间(而不是最后修改时间),建议改成auto_now_add=True,这样只会在用户创建时设置一次时间,不会后续被修改。
内容的提问来源于stack exchange,提问作者fatmanur eraslan

