Django自定义Filter未按登录用户过滤返回全量用户数据问题求助
问题原因分析
- Account归属校验不足:你直接通过URL参数
pk查询Account对象,即使有own_account_only装饰器,如果装饰器逻辑存在漏洞,用户可以通过修改URL中的pk参数获取其他用户的Account数据,进而拿到对应Account下的所有Automation。 - 时间过滤字段名不匹配:你在过滤器中定义的
start_date、end_date指定的字段名date_joined不存在于Automation模型中(Automation的时间字段为date_created),字段名错误导致这两个时间过滤条件完全失效。 - 多对多关联字段无范围限制:你在FilterSet中使用
fields = '__all__'会自动将多对多关联字段messages加入可过滤范围,而django-filter默认对关联字段执行全局查询。当你通过messages字段过滤时,ORM会关联全局Message表查询,导致结果范围超出当前Account的限制。
解决方案
1. 强化Account归属校验
将view中查询Account的逻辑改为带用户校验的查询,确保只能拿到当前登录用户关联的Account:
from django.shortcuts import get_object_or_404 # 替换原account查询逻辑,将user改为你Account模型中关联Django用户表的实际外键字段名 account = get_object_or_404(Account, id=pk, user=request.user)
2. 修正时间过滤字段名
修改AutomationFilter中的时间字段配置,匹配模型实际字段:
start_date = DateFilter(field_name='date_created', lookup_expr='gte') end_date = DateFilter(field_name='date_created', lookup_expr='lte')
3. 限制多对多关联字段的查询范围
重写FilterSet的初始化方法,动态传入当前Account,限制关联字段的可选范围:
class AutomationFilter(django_filters.FilterSet): start_date = DateFilter(field_name='date_created', lookup_expr='gte') end_date = DateFilter(field_name='date_created', lookup_expr='lte') class Meta: model = Automation # 建议显式指定可过滤字段,替代__all__避免暴露不必要的字段 fields = ['name', 'description', 'messages', 'start_date', 'end_date'] exclude = ['account', 'date_created'] def __init__(self, *args, **kwargs): # 接收传入的account参数 self.account = kwargs.pop('account', None) super().__init__(*args, **kwargs) if self.account: # 限制messages只能选择当前account下的消息 self.filters['messages'].queryset = Message.objects.filter(account=self.account)
4. 实例化过滤器时传入Account参数
修改view中过滤器的实例化逻辑,传入当前Account:
filter = AutomationFilter(request.GET, queryset=automations, account=account)
Message过滤器的同步修改
Message过滤器出现相同问题的解决逻辑完全一致:
- 显式指定可过滤字段,避免全局关联查询
- 重写初始化方法,限制关联的
automations字段的查询范围为当前Account下的Automation - 实例化时传入当前Account参数
内容的提问来源于stack exchange,提问作者user8758206
相关产品推荐
相关产品推荐

