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

Django如何基于admin用户/组权限过滤SQL查询结果生成HTML页面

Django 按用户/用户组动态过滤查询结果实现方案

1. 新建可后台配置的权限规则模型

要实现admin后台可视化配置过滤规则,首先在对应app的models.py中新增规则存储模型,支持绑定单个用户或用户组,存储对应的SQL过滤片段:

# models.py
from django.db import models
from django.contrib.auth.models import User, Group

class DataQueryFilterRule(models.Model):
    # 规则可单独绑定用户,也可绑定用户组,两类绑定互斥即可
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, verbose_name="关联用户")
    group = models.ForeignKey(Group, on_delete=models.CASCADE, null=True, blank=True, verbose_name="关联用户组")
    # 存储SQL过滤条件片段,不需要带WHERE前缀,例如 email LIKE '%@bait.com'
    filter_condition = models.TextField(verbose_name="SQL过滤条件")
    priority = models.IntegerField(default=10, verbose_name="生效优先级,数字越小优先级越高")
    is_active = models.BooleanField(default=True, verbose_name="规则是否启用")

    class Meta:
        verbose_name = "数据查询权限规则"
        verbose_name_plural = verbose_name
        ordering = ['priority']

将模型注册到admin后台,即可在后台可视化增删改规则,在admin.py添加如下代码:

# admin.py
from django.contrib import admin
from .models import DataQueryFilterRule

@admin.register(DataQueryFilterRule)
class DataQueryFilterRuleAdmin(admin.ModelAdmin):
    list_display = ['id', 'user', 'group', 'filter_condition', 'priority', 'is_active']
    list_filter = ['is_active', 'group']
    search_fields = ['user__username', 'filter_condition']

配置完成后执行python manage.py makemigrations和python manage.py migrate完成数据表创建。

2. 改造查询逻辑动态拼接过滤条件

原有的硬编码SQL逻辑需要调整,先获取当前登录用户匹配的所有生效规则,再将规则拼接为WHERE子句,同时添加登录校验避免匿名用户访问,修改views.py代码如下:

# views.py
from django.http import HttpResponse, HttpResponseForbidden
from django.db import connection
from django.contrib.auth.decorators import login_required
from .models import DataQueryFilterRule

def get_user_match_filters(user):
    """拉取当前用户匹配的所有生效过滤条件"""
    conditions = []
    # 优先加载绑定到用户本人的规则
    user_level_rules = DataQueryFilterRule.objects.filter(
        user=user, is_active=True
    )
    for rule in user_level_rules:
        conditions.append(rule.filter_condition)
    
    # 再加载用户所属用户组绑定的规则
    user_owned_groups = user.groups.all()
    group_level_rules = DataQueryFilterRule.objects.filter(
        group__in=user_owned_groups, is_active=True, user__isnull=True
    )
    for rule in group_level_rules:
        conditions.append(rule.filter_condition)
    
    return conditions

def query(user):
    base_sql = "SELECT some, stuff FROM here"
    match_filters = get_user_match_filters(user)
    
    # 无匹配规则默认返回无权限,避免越权查看全量数据
    if not match_filters:
        return None
    
    # 拼接最终执行SQL
    final_sql = f"{base_sql} WHERE {' AND '.join(match_filters)};"
    with connection.cursor() as cursor:
        cursor.execute(final_sql)
        query_result = cursor.fetchall()
    return query_result

# 登录校验装饰器,未登录用户自动跳转登录页
@login_required
def index(request):
    data = query(request.user)
    if data is None:
        return HttpResponseForbidden("当前账号未配置数据访问权限,请联系管理员")
    
    # 渲染为HTML表格返回,复杂页面建议使用Django模板引擎实现自动转义
    html = """
    <table border="1" cellpadding="8" cellspacing="0">
        <thead><tr><th>some字段</th><th>stuff字段</th></tr></thead>
        <tbody>
    """
    for line in data:
        html += f"<tr><td>{line[0]}</td><td>{line[1]}</td></tr>"
    html += "</tbody></table>"
    return HttpResponse(html)

3. 规则配置示例

以BAIT用户组的过滤规则为例:

  • 先在Django自带的用户组管理中创建BAIT组,将需要归属该组的用户加入组内
  • 在admin后台新增一条数据查询权限规则:关联组选择BAIT组,过滤条件填email LIKE '%@bait.com',设置启用状态
  • 配置完成后,所有属于BAIT组的用户访问接口时,会自动拼接该过滤条件,仅返回符合邮箱规则的数据;如果给单个用户配置了专属规则,会和组规则同时生效,取交集结果。

注意事项

  • 规则编辑权限仅开放给超级管理员,禁止普通用户接触规则配置入口,避免SQL注入风险
  • 如果需要更灵活的规则配置,可扩展规则模型,将字段名、匹配规则、匹配值、逻辑连接符拆分为独立字段,代码层面动态拼接SQL,不需要直接存储SQL片段,安全性更高
  • 手动拼接HTML时要对返回的字段内容做转义,避免XSS漏洞,推荐使用Django模板渲染页面,默认自带转义能力
  • 如果业务上存在固定的全局过滤条件,可直接和动态获取的用户/组规则一起拼接到WHERE子句中即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 16:27:22