Django:不允许按 %filter% 过滤

Posted

技术标签:

【中文标题】Django:不允许按 %filter% 过滤【英文标题】:Django: Filtering by %filter% not allowed 【发布时间】:2011-09-20 10:18:56 【问题描述】:

我继承了一个 Django v1.2.4 应用程序,并且正在添加一些修复和改进。在这个过程中,我突然开始遇到如下错误:

SuspiciousOperation at
/hometeam/admin/players/playeryear/

Filtering by team__season__season_start_date__year not allowed

当我尝试为输入字段(通过与字段关联的放大镜访问)选择项目时,管理界面弹出窗口中会显示此错误。

我已打开调试,但无法确定此错误发生的位置或最近的哪个更改导致它启动。您能帮我正确解析调试输出以追踪导致此问题的错误过滤器吗?

players/admin.py 包含以下类:

class PlayerYearAdmin(FkAutocompleteAdmin):
    related_search_fields = 
        'team': ('school__school',),
        'player': ('first_name', 'last_name'),
    
    list_display = ['player', 'team', 'player_year_in_school']
    list_filter = ['team']
    search_fields = ['player__first_name', 'player__last_name']
    ordering = ['player__last_name', 'player__first_name']

注释掉list_displaylist_filter 语句不会改变问题。

下面是一些调试输出。我可以根据需要发布更多内容。

Request Method: GET

Request URL:    http://204.232.208.57:8010/hometeam/admin/players/playeryear/?team__season__season_start_date__year=2010&team__sport__sport=Boys%20Basketball&t=id&pop=1

Django Version: 1.2.4

Exception Type: SuspiciousOperation

Exception Value:    Filtering by team__season__season_start_date__year not allowed

Exception Location: /usr/local/lib/python2.6/dist-packages/Django-1.2.4-py2.6.egg/django/contrib/admin/views/main.py in get_query_set, line 193

Python Executable:  /usr/bin/python

我已经应用了https://code.djangoproject.com/changeset/15140建议的补丁,但是补丁之后没有任何变化。任何指导将不胜感激。

【问题讨论】:

【参考方案1】:

此问题已根据Chris Adams' blog 提供的说明解决。 Django 1.2.4 引入了一项新的安全功能,该功能限制了使用“通过查询字符串进行任意跨模型查找”的能力,正如 Daniel Roseman 在其answer 中所指出的那样。

此版本的解决方法是在 FooAdmin(在我的例子中为 'PlayerYearAdmin')中定义一个 lookup_allowed 方法,该方法为您希望的所有过滤器返回 true启用。在我的例子中,lookup_allowed 看起来像这样:

def lookup_allowed(self, key):
    if key in ('team__season__season_start_date__year', 'team__sport'):
        return True
    return super(PlayerYearAdmin, self).lookup_allowed(key)

您还可以完全绕过安全检查,有效地声明允许所有查找。这是 1.2.4 版本之前的默认行为:

def lookup_allowed(self, key):
    return True

可能值得注意的是版本 1.2.5 added a third parameter,,改为lookup_allowed。如果您使用的是该版本,您可以像这样定义lookup_allowed

def lookup_allowed(self, key, value):
    if key in ('team__season__season_start_date__year', 'team__sport'):
        return True
    return super(PlayerYearAdmin, self).lookup_allowed(key, value)

【讨论】:

【参考方案2】:

作为release notes for 1.2.4 状态,不再允许通过查询字符串进行任意跨模型查找,因为它们存在安全风险。该补丁并不意味着重新启用它们。

您需要在管理员的list_filter 属性中明确指定允许的关系。不幸的是,这只能从 1.3 版本开始,因此您需要升级。

【讨论】:

我宁愿找到错误的过滤器而不是升级。您对如何实现这一目标有任何建议吗? 您很可能会在自定义管理模板中找到它。 @chrisdpratt:好主意,但在这种情况下,我没有使用自定义管理模板。 那么,如何访问该 URL?正如@Daniel 指出的那样,问题出在回溯中提到的 URL 的查询字符串中。 “修复”是从查询字符串中删除有问题的位。 @chrisdpratt:我通过输入字段旁边的可点击链接访问该弹出窗口。经过一番调查,我确定该链接是由我们正在使用的内联自动完成模块生成的。我将调查该模块以查看 URL 是如何组装的。

以上是关于Django:不允许按 %filter% 过滤的主要内容,如果未能解决你的问题,请参考以下文章

如何按 Django-filter 包中的日期字段进行过滤?

Django按日期范围过滤但不包括年份

Django:按日期过滤日期时间忽略时间

Django 从模型中过滤:Model.objects.filter(Q())

Django ORM:按对象列表过滤

你如何使用带有参数列表的 django-filter 包?