如何让Django-Filter仅展示用户创建的对象?遇fields属性缺失错误
解决Django-filter的两个问题:用户专属筛选选项与'fields'属性错误
我来帮你一步步梳理并解决这两个问题:
1. 先修复'StatsFilter' object has no attribute 'fields'错误
你在__init__方法里用了self.fields['associated_portfolios'],但Django-filter的FilterSet实例并没有fields属性——fields是Meta类里的配置项,实例要访问具体过滤器得用self.filters,这就是报错的直接原因。
2. 配置'associated_portfolios'仅展示用户自身创建的对象
首先要确保你的associated_portfolios关联的模型(比如Portfolio)有一个绑定用户的字段(比如user),然后在FilterSet的初始化方法里,把该过滤器的查询集限制为当前用户的对象。另外你初始定义ModelMultipleChoiceFilter时的queryset=associated_portfolios是错误的,得先指向模型的基础查询集,再在__init__里做用户过滤。
修正后的filters.py代码
import django_filters from .models import Trade, Portfolio # 确保导入关联的Portfolio模型(如果模型名不同请替换) class StatsFilter(django_filters.FilterSet): # 先设置基础查询集,后续在初始化时过滤用户专属数据 associated_portfolios = django_filters.ModelMultipleChoiceFilter(queryset=Portfolio.objects.all()) class Meta: model = Trade fields = ['type', 'asset', 'symbol', 'broker', 'patterns', 'associated_portfolios'] def __init__(self, request, *args, **kwargs): super().__init__(*args, **kwargs) # 用self.filters访问过滤器,过滤出当前用户创建的portfolio self.filters['associated_portfolios'].queryset = Portfolio.objects.filter(user=request.user)
3. 修正views.py中的FilterSet实例化逻辑
你的StatsView里,FilterView已经自带了filterset的处理逻辑,不需要手动在get_context_data里重新实例化。另外因为我们的StatsFilter现在需要接收request参数,得覆盖get_filterset_kwargs方法来传递请求对象:
修正后的views.py代码
from django.views.generic import FilterView from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Max from .filters import StatsFilter from .models import Trade class StatsView(LoginRequiredMixin, FilterView): model = Trade template_name = 'dashboard/stats.html' filterset_class = StatsFilter def get_filterset_kwargs(self): kwargs = super().get_filterset_kwargs() # 把当前请求传递给FilterSet的初始化方法 kwargs['request'] = self.request return kwargs def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 直接使用视图自带的filter对象,无需重新实例化 filter_obj = context['filter'] # 这里的'tj3admin'建议换成self.request.user.username,实现动态获取当前用户 context['get_users_trades'] = Trade.objects.get_users_trades('tj3admin') context['get_largest_winning_trade'] = filter_obj.qs.aggregate(max_value=Max('profit_loss_value_fees'))['max_value'] return context
额外提醒
- 如果你的关联模型不是
Portfolio,记得把代码里的Portfolio替换成你实际的模型名称。 get_users_trades('tj3admin')写死了用户名,改成self.request.user能让逻辑更通用,适配任意登录用户。
内容的提问来源于stack exchange,提问作者Alex Winkler
相关产品推荐
相关产品推荐

