Django Rest Framework:QuerySet 过滤未按预期工作
Django Rest Framework: QuerySet filtering not working as expected
我正在为 API 使用 Django 3.2 和 Django Rest Framework。我很难让它按照我期望的方式工作。我有一个 position
table,样本数据类似于:
[
{ id: 1, position_date: '2022-01-01', symbol: 'AAPL', shares: 100 },
{ id: 2, position_date: '2022-01-01', symbol: 'TSLA', shares: 100 },
{ id: 3, position_date: '2022-01-01', symbol: 'GOOG', shares: 100 },
{ id: 4, position_date: '2022-01-02', symbol: 'AAPL', shares: 200 },
{ id: 5, position_date: '2022-01-02', symbol: 'TSLA', shares: 200 },
{ id: 6, position_date: '2022-01-02', symbol: 'GOOG', shares: 200 },
{ id: 7, position_date: '2022-01-05', symbol: 'AAPL', shares: 300 },
{ id: 8, position_date: '2022-01-05', symbol: 'TSLA', shares: 300 },
{ id: 9, position_date: '2022-01-05', symbol: 'GOOG', shares: 300 },
]
此数据包含特定日期的股票头寸。此每日快照位置信息仅在 weekdays/days 市场开放时创建,因此 weekends/market 假期的日期存在差距。
我想按 position_date /api/v1/positions?position_date=<YYYY-MM-DD>
查询职位小于或等于传入日期。例如,如果我传递了一个星期日的日期,而该日期没有与之关联的职位,我希望从星期五开始收到职位。在上面的示例数据中,如果我传入的 position_date 为“2022-01-04”,我希望收到三个 position_date 为“2022-01-02”的记录。
下面是我的视图集。目前,如果我不传递 position_date,它会按预期工作并且 returns 最新位置。但是,当我传入 position_date 时,它在那个日期只有 returns 个位置。当传入日期时,查找 max_date 内容似乎被覆盖 somewhere/somehow。关于如何解决此问题的任何想法?
class PositionViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows positions to be viewed
"""
def get_queryset(self):
# only include params from filterset_fields list
params = dict(self.request.GET)
filtered_params = dict((k, params[k][0]) for k in self.filterset_fields if k in params and params[k][0])
# set default value to latest positions
if 'position_date' not in filtered_params:
filtered_params['position_date'] = date.today().isoformat()
# return all positions
if 'position_date' in filtered_params and filtered_params['position_date'] == 'all':
del filtered_params['position_date']
# find the greatest date that is lte to the passed in date
if 'position_date' in filtered_params:
max_date = Position.objects.filter(position_date__lte=filtered_params['position_date']).aggregate(position_date=Max('position_date'))['position_date'].isoformat()
# use the max date in place of original date
filtered_params['position_date'] = max_date
# fix some janky nested route issues between django and drf
filtered_kwargs = {k.replace('_pk', '_id'): v for k, v in self.kwargs.items()}
# merge kwargs and params
qs_filter = {**filtered_params, **filtered_kwargs}
qs = Position.objects.filter(**qs_filter)
return qs
serializer_class = PositionSerializer
filter_backends = [SearchFilter, OrderingFilter, DjangoFilterBackend]
filterset_fields = [
'symbol',
'shares',
'position_date',
]
search_fields = [
'^symbol',
]
ordering_fields = [
'symbol',
'shares',
'position_date',
]
ordering = ['position_date', 'symbol']
您应该尝试从 filterset_fields
中删除 position_date
,因为我认为 DjangoFilterBackend 覆盖了您的查询集。
还有一条建议:您必须在 custom filter 中对 position_date
字段进行所有过滤,而不是在 get_queryset
函数中。
我正在为 API 使用 Django 3.2 和 Django Rest Framework。我很难让它按照我期望的方式工作。我有一个 position
table,样本数据类似于:
[
{ id: 1, position_date: '2022-01-01', symbol: 'AAPL', shares: 100 },
{ id: 2, position_date: '2022-01-01', symbol: 'TSLA', shares: 100 },
{ id: 3, position_date: '2022-01-01', symbol: 'GOOG', shares: 100 },
{ id: 4, position_date: '2022-01-02', symbol: 'AAPL', shares: 200 },
{ id: 5, position_date: '2022-01-02', symbol: 'TSLA', shares: 200 },
{ id: 6, position_date: '2022-01-02', symbol: 'GOOG', shares: 200 },
{ id: 7, position_date: '2022-01-05', symbol: 'AAPL', shares: 300 },
{ id: 8, position_date: '2022-01-05', symbol: 'TSLA', shares: 300 },
{ id: 9, position_date: '2022-01-05', symbol: 'GOOG', shares: 300 },
]
此数据包含特定日期的股票头寸。此每日快照位置信息仅在 weekdays/days 市场开放时创建,因此 weekends/market 假期的日期存在差距。
我想按 position_date /api/v1/positions?position_date=<YYYY-MM-DD>
查询职位小于或等于传入日期。例如,如果我传递了一个星期日的日期,而该日期没有与之关联的职位,我希望从星期五开始收到职位。在上面的示例数据中,如果我传入的 position_date 为“2022-01-04”,我希望收到三个 position_date 为“2022-01-02”的记录。
下面是我的视图集。目前,如果我不传递 position_date,它会按预期工作并且 returns 最新位置。但是,当我传入 position_date 时,它在那个日期只有 returns 个位置。当传入日期时,查找 max_date 内容似乎被覆盖 somewhere/somehow。关于如何解决此问题的任何想法?
class PositionViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows positions to be viewed
"""
def get_queryset(self):
# only include params from filterset_fields list
params = dict(self.request.GET)
filtered_params = dict((k, params[k][0]) for k in self.filterset_fields if k in params and params[k][0])
# set default value to latest positions
if 'position_date' not in filtered_params:
filtered_params['position_date'] = date.today().isoformat()
# return all positions
if 'position_date' in filtered_params and filtered_params['position_date'] == 'all':
del filtered_params['position_date']
# find the greatest date that is lte to the passed in date
if 'position_date' in filtered_params:
max_date = Position.objects.filter(position_date__lte=filtered_params['position_date']).aggregate(position_date=Max('position_date'))['position_date'].isoformat()
# use the max date in place of original date
filtered_params['position_date'] = max_date
# fix some janky nested route issues between django and drf
filtered_kwargs = {k.replace('_pk', '_id'): v for k, v in self.kwargs.items()}
# merge kwargs and params
qs_filter = {**filtered_params, **filtered_kwargs}
qs = Position.objects.filter(**qs_filter)
return qs
serializer_class = PositionSerializer
filter_backends = [SearchFilter, OrderingFilter, DjangoFilterBackend]
filterset_fields = [
'symbol',
'shares',
'position_date',
]
search_fields = [
'^symbol',
]
ordering_fields = [
'symbol',
'shares',
'position_date',
]
ordering = ['position_date', 'symbol']
您应该尝试从 filterset_fields
中删除 position_date
,因为我认为 DjangoFilterBackend 覆盖了您的查询集。
还有一条建议:您必须在 custom filter 中对 position_date
字段进行所有过滤,而不是在 get_queryset
函数中。