You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django ListView实现用户数据双表过滤展示需求

嘿,我来帮你搞定这个需求!要在页面上展示两个过滤后的用户表格,咱们不用局限于单一的ListView,而是可以用TemplateView来同时传递两个经过筛选的查询集,这样模板就能分别渲染它们了。下面一步步来:

1. 先确认模型字段(以自定义会员模型为例)

假设你的用户模型是扩展了Django自带User的自定义Member模型,里面包含会员过期日期和注册日期字段(注册日期Django自带User的date_joined就有,不用额外加):

# models.py
from django.db import models
from django.contrib.auth.models import AbstractUser

class Member(AbstractUser):
    membership_expire_date = models.DateField(null=True, blank=True, verbose_name="会员过期日期")

2. 修改视图:用TemplateView传递两个过滤后的查询集

ListView默认只处理一个查询集,所以咱们换用TemplateView,在get_context_data方法里生成两个筛选后的用户集合,再传递给模板:

# views.py
from django.views.generic.base import TemplateView
from django.utils import timezone
from datetime import timedelta
from .models import Member

class UserStatsView(TemplateView):
    template_name = 'template.html'  # 你的模板路径

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        current_date = timezone.now().date()  # 考虑时区,避免时间偏移问题

        # 筛选30天内即将过期的会员:过期日期在今天到30天后之间
        thirty_days_later = current_date + timedelta(days=30)
        context['expiring_members'] = Member.objects.filter(
            membership_expire_date__lte=thirty_days_later,
            membership_expire_date__gte=current_date
        )

        # 筛选注册不足1个月的新用户:注册日期在30天前到今天之间
        one_month_ago = current_date - timedelta(days=30)
        context['new_users'] = Member.objects.filter(
            date_joined__gte=one_month_ago
        )

        # 如果需要保留全部用户数据,也可以加上这行:
        # context['all_users'] = Member.objects.all()
        return context

3. 配置URL映射

把这个视图绑定到一个URL,方便访问:

# urls.py
from django.urls import path
from .views import UserStatsView

urlpatterns = [
    # 其他URL规则...
    path('user-stats/', UserStatsView.as_view(), name='user_stats'),
]

4. 修改模板:渲染两个独立表格

在你的template.html里,分别循环两个查询集,生成对应的表格:

<!-- template.html -->
<h1>用户统计面板</h1>

<!-- 30天内即将过期的会员表格 -->
<h2>⚠️ 30天内即将过期的会员</h2>
<table border="1" cellpadding="8" cellspacing="0">
    <thead>
        <tr>
            <th>用户名</th>
            <th>邮箱</th>
            <th>会员过期日期</th>
        </tr>
    </thead>
    <tbody>
        {% for member in expiring_members %}
        <tr>
            <td>{{ member.username }}</td>
            <td>{{ member.email }}</td>
            <td>{{ member.membership_expire_date }}</td>
        </tr>
        {% empty %}
        <tr>
            <td colspan="3">暂无即将过期的会员</td>
        </tr>
        {% endfor %}
    </tbody>
</table>

<br>

<!-- 注册不足1个月的新用户表格 -->
<h2>🎉 注册不足1个月的新用户</h2>
<table border="1" cellpadding="8" cellspacing="0">
    <thead>
        <tr>
            <th>用户名</th>
            <th>邮箱</th>
            <th>注册日期</th>
        </tr>
    </thead>
    <tbody>
        {% for user in new_users %}
        <tr>
            <td>{{ user.username }}</td>
            <td>{{ user.email }}</td>
            <td>{{ user.date_joined|date:"Y-m-d H:i" }}</td>
        </tr>
        {% empty %}
        <tr>
            <td colspan="3">暂无新用户</td>
        </tr>
        {% endfor %}
    </tbody>
</table>

几个注意点

  • 如果你的会员过期日期是通过OneToOneField扩展到User模型的(比如单独的UserProfile表),过滤时要用到反向查询,比如User.objects.filter(userprofile__membership_expire_date__lte=thirty_days_later)
  • 若项目开启了时区(USE_TZ = True),一定要用timezone.now()而不是原生的datetime.today(),避免时间偏差
  • 可以根据需求调整过滤逻辑:比如要包含已过期的用户,去掉membership_expire_date__gte=current_date即可

内容的提问来源于stack exchange,提问作者Dicky Raambo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:52:10