django - Django Rest Framework - & on 方法过滤器无法按预期工作
问题描述
我的模型:
class Detail(models.Model):
id = models.IntegerField(primary_key=True)
entry_date = models.DateTimeField(null=True)
class Meta:
managed=False
db_table = detail
class Item(models.Model):
id = models.IntegerField(primary_key=True)
name = models.Charfield(max_length=20)
qty = models.IntegerField()
@property
def from_detail(self):
return Detail.objects.filter(id=self.id).values('entry_date')
class Meta:
managed=False
db_table=item
在我的过滤器集中,我正在执行以下操作:
class ItemFilter(FilterSet):
entry_date__gte = DateTimeFilter(field_name='entry_date', method=entry_gte_filter)
entry_date__lte = DateTimeFilter(field_name='entry_date', method=entry_lte_filter)
class Meta:
model = Item
fields = ('name', 'qty', 'entry_date__gte', 'entry_date__lte')
出于某种原因,我必须在这里使用方法字段并且不能直接给出查找 expr
我的方法如下所示:
def entry_gte_filter(queryset, name, value):
name = f"{name}__gte"
queryset = Item.objects.annotate(
detail=models.Exists(Detail.objects.filter(
**{name: value, 'id': models.OuterRef('id')}))).filter(detail=True)
return queryset
和
def entry_lte_filter(queryset, name, value):
name = f"{name}__lte"
queryset = Item.objects.annotate(
detail=models.Exists(Detail.objects.filter(
**{name: value, 'id': models.OuterRef('id')}))).filter(detail=True)
return queryset
但是,当我执行以下 API 时:
GET /api/items?entry_date__gte=2021-06-29&entry_date__lte=2021-07-04
我收到以下输入日期的回复:
2021-06-30T00:00:00
2021-06-11T00:00:00
2021-07-02T00:00:00
我不清楚为什么当 API 提到 entry_date__gte=2021-06-29 时会返回 2021-06-11 的响应
在我看来,当使用方法类型时,django 过滤器没有按预期工作。任何人都可以在这里帮助我为什么 djangorestframework 的行为是这样的,是否有任何方法可以解决这个问题并获得预期的行为?
解决方案
假设请求的视图配置正确并且ItemFilter
过滤器及其方法(entry_lte_filter
, entry_gte_filter
)被执行,那么我看到两个原因它不起作用。
首先,在每个过滤方法中,您都从一个新的查询集 ( Model.objects
) 开始。您应该使用queryset
提供的作为参数并返回修改它的结果docs。
其次,您尝试将datetime
field ( entry_date
) 与表示 a 的字符串进行比较date
。您可以在使用__date
lookup时比较它们。
def entry_gte_filter(queryset, name, value):
name = f"{name}__date__gte"
queryset = queryset.annotate(
detail_date_gte_exists=models.Exists(Detail.objects.filter(
**{name: value, 'id': models.OuterRef('id')}))
).filter(detail_date_gte_exists=True)
return queryset
和
def entry_lte_filter(queryset, name, value):
name = f"{name}__date__lte"
queryset = queryset.annotate(
detail_date_lte_exists=models.Exists(Detail.objects.filter(
**{name: value, 'id': models.OuterRef('id')}))
).filter(detail_date_lte_exists=True)
return queryset
推荐阅读
- django - 使用 Django-taggit 和 django-taggit-serializer 有问题
- java - 用按下的 JButton 替换 ImageIcon
- angular - 使用 Angular 6 的 Kendo-Spreadsheet
- javascript - 如何在网络上显示参数(React Js)
- java - 射弹物理技工破碎的java
- tabulator - 加载并保存到 txt/csv 文件?
- node.js - 无法在 Windows 10 上安装浏览器同步
- algorithm - 从给定数组中形成某个数字的子序列
- java - 如何在 Android Studio 中使用 Firebase 自动登录?
- javascript - 使用阿拉伯语时,数字会颠倒