禁用 rest_framework 的 RelatedField 上的选择
Disabling choices on rest_framework's RelatedField
我正在使用 django rest framework 版本 3.3.2。
我们在数百个不同的地方使用 HyperlinkedRelatedField
,我的问题是它通过 RelatedField
继承了 choices
方法,该方法执行以下操作:
class RelatedField(Field):
...
@property
def choices(self):
queryset = self.get_queryset()
if queryset is None:
# Ensure that field.choices returns something sensible
# even when accessed with a read-only field.
return {}
return OrderedDict([
(
six.text_type(self.to_representation(item)),
self.display_value(item)
)
for item in queryset
])
该查询集与另一个 table 有关系,可以包含数十万行。对 api 的 OPTIONS 请求现在消耗所有可用内存,因为它试图为关系的可用选择生成 json 响应。即使 html_cutoff
选项将此数字截断为 1000,问题仍然存在,因为查询集在被截断限制之前已经被消耗。
我正在寻找一种非侵入式的方法来禁用外键的选项枚举。我想避免创建自定义字段 class,如果可能的话,有没有办法通过其余框架 api 影响此行为?我根本不需要在选项响应中看到 choices
。
您可以使用元数据 API.
在 Django REST 框架中修改任何OPTIONS
请求的内容
这涉及定义您自己的元数据 class - 请参阅 this documentation page。
您可以将自定义元数据 class 添加到导致问题的视图中。
在当前的 DRF (v3.3.2) 中有 this problem,OPTIONS 响应尝试评估 'choices' 的外键。这是一个糟糕的主意,如果您的数据库中有大量内容,那么可浏览的 API 将无法使用。
DRF 维护者知道这个事实,并且 there is a PR currently scheduled for the 3.4.0 release 会解决这个问题。
在上游修复之前,这是我的解决方法。 注意:要覆盖该行为,您需要在 settings.py
中的 REST_FRAMEWORK
选项下设置 DEFAULT_METADATA_CLASS
。
这有意不禁用 ChoiceField
和朋友的选择枚举,仅针对相关字段。
from copy import copy
from functools import wraps
from rest_framework.metadata import SimpleMetadata
from rest_framework.relations import RelatedField
class MyMetadata(SimpleMetadata):
def get_field_info(self, field):
if isinstance(field, RelatedField):
def kill_queryset(f):
@wraps(f)
def wrapped(*args, **kwargs):
qs = f(*args, **kwargs)
if qs is not None:
qs = qs.none()
return qs
return wrapped
field = copy(field)
field.get_queryset = kill_queryset(field.get_queryset)
result = super(MyMetadata, self).get_field_info(field)
if not result.get('choices'):
result.pop('choices', None)