У меня есть три модели с простым соотношением, как показано ниже:
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
между двумя полями фильтра, я думаю этот пост связан с этой проблемой, но в настоящее время я не смог найти способ получить желаемый результат. Я использую djang 1.10.3.
Редактировать
Я пытаюсь написать пример , чтобы показать, что мне нужно и что я получаю из фильтра 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
Edit2
Это данные, к которым относятся мои запросы в этом примере, и, используя их, вы можете увидеть, что должно возвращаться в запросах, о которых я упоминал выше:
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
Edit3
Я пытаюсь использовать prefetch_related
для объединения таблиц и получения результатов, как я ожидал, потому что я думал, что дополнительное объединение вызывает эту проблему, но это не сработало, и я все еще получаю тот же результат, и это не имело никаких эффектов.
Edit4
Эта проблема имеет ту же проблему.