【发布时间】:2018-10-04 17:04:09
【问题描述】:
我有三个模型,简单的关系如下:
models.py
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
class PersonSession(models.Model):
start_time = models.DateTimeField(auto_now_add=True)
end_time = models.DateTimeField(null=True,
blank=True)
person = models.ForeignKey(Person, related_name='sessions')
class Billing(models.Model):
DEBT = 'DE'
BALANCED = 'BA'
CREDIT = 'CR'
session = models.OneToOneField(PersonSession,
blank=False,
null=False,
related_name='billing')
STATUS = ((BALANCED, 'Balanced'),
(DEBT, 'Debt'),
(CREDIT, 'Credit'))
status = models.CharField(max_length=2,
choices=STATUS,
blank=False,
default=BALANCED
)
views.py
class PersonFilter(django_filters.FilterSet):
start_time = django_filters.DateFromToRangeFilter(name='sessions__start_time',
distinct=True)
billing_status = django_filters.ChoiceFilter(name='sessions__billing__status',
choices=Billing.STATUS,
distinct=True)
class Meta:
model = Person
fields = ('first_name', 'last_name')
class PersonList(generics.ListCreateAPIView):
queryset = Person.objects.all()
serializer_class = PersonSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend)
filter_class = PersonFilter
我想从具有DE 状态的个人端点获取帐单,并且在一段时间之间:
api/persons?start_time_0=2018-03-20&start_time_1=2018-03-23&billing_status=DE
但结果不是我想要的,这将返回所有人在该期间都有一个会话并且有一个DE 状态的帐单,无论该帐单是否在该期间。
换句话说,似乎在两个过滤字段之间使用or 操作,我认为this post 与此问题有关,但目前我找不到获得我想要的结果的方法。我正在使用 djang 1.10.3。
编辑
我尝试写一个example 来展示我需要什么以及我从 django 过滤器中得到什么。如果我在示例中使用以下查询的人,我只有两个人:
select *
from
test_filter_person join test_filter_personsession on test_filter_person.id=test_filter_personsession.person_id join test_filter_billing on test_filter_personsession.id=test_filter_billing.session_id
where
start_time > '2000-02-01' and start_time < '2000-03-01' and status='DE';
这让我只有第 1 个人和第 2 个人。但如果我从 url 得到预期相似的东西,我会得到所有的人,相似的 url(至少一个我期望相同的)如下:
http://address/persons?start_time_0=2000-02-01&start_time_1=2000-03-01&billing_status=DE
编辑2
这是我在示例中的查询所依据的数据,使用它们您可以看到我上面提到的查询中必须返回的内容:
id | first_name | last_name | id | start_time | end_time | person_id | id | status | session_id
----+------------+-----------+----+---------------------------+---------------------------+-----------+----+--------+------------
0 | person | 0 | 0 | 2000-01-01 16:32:00+03:30 | 2000-01-01 17:32:00+03:30 | 0 | 0 | DE | 0
0 | person | 0 | 1 | 2000-02-01 16:32:00+03:30 | 2000-02-01 17:32:00+03:30 | 0 | 1 | BA | 1
0 | person | 0 | 2 | 2000-03-01 16:32:00+03:30 | 2000-03-01 17:32:00+03:30 | 0 | 2 | DE | 2
1 | person | 1 | 3 | 2000-01-01 16:32:00+03:30 | 2000-01-01 17:32:00+03:30 | 1 | 3 | BA | 3
1 | person | 1 | 4 | 2000-02-01 16:32:00+03:30 | 2000-02-01 17:32:00+03:30 | 1 | 4 | DE | 4
1 | person | 1 | 5 | 2000-03-01 16:32:00+03:30 | 2000-03-01 17:32:00+03:30 | 1 | 5 | DE | 5
2 | person | 2 | 6 | 2000-01-01 16:32:00+03:30 | 2000-01-01 17:32:00+03:30 | 2 | 6 | DE | 6
2 | person | 2 | 7 | 2000-02-01 16:32:00+03:30 | 2000-02-01 17:32:00+03:30 | 2 | 7 | DE | 7
2 | person | 2 | 8 | 2000-03-01 16:32:00+03:30 | 2000-03-01 17:32:00+03:30 | 2 | 8 | BA | 8
编辑3
我尝试使用prefetch_related 连接表并获得预期的结果,因为我认为额外的连接会导致此问题,但这不起作用,我仍然得到相同的结果,这没有任何影响。
编辑4
这个issue也有同样的问题。
【问题讨论】:
-
将您的过滤器放置在 filters.py 文件中,而不是在 views.py 中。查看 django-filters 是否在 settings.py 中的 INSTALLED_APPS 列表中
-
Person与PersonSession或Billing模型有什么关系?上面的代码看起来不完整。我可以从给定的信息中弥补的是,您将PersonSession与Billing(计费具有session属性)和Person(假设branch_sessions反向映射在过滤器中使用)相关联.尝试使用此人拥有的帐单进行过滤。像这样的东西应该可以工作 -start_time = django_filters.DateFromToRangeFilter(name='billings__sessions__start_time',distinct=True)假设Person有一个属性billing。让我知道这是否有帮助。 -
对于模型中的问题我很抱歉我忘记了模型中的一些字段。
session与person具有外键,billing与session具有一对一的关系。使用这些假设,我认为我的过滤器没有问题,并且必须按预期工作,但事实并非如此。 -
@GeancarloMurillo 我不明白为什么更改过滤器实现的文件和位置会影响过滤器的结果?正如我解释的那样,我从过滤器中得到了一些结果,但这不是我所期望的。
-
是 Django 文档推荐的关于更好地组织代码和良好实践技能的建议。
filters.py中的过滤器,signals.py中的信号,views.py中的视图等等。抱歉,如果它不能解决您的问题。你能举一些例子说明你得到了什么以及你除了什么吗?
标签: django django-rest-framework django-filter django-filters