#python #sql #django #django-forms #django-queryset
#python #sql #django #django-forms #django-queryset
Вопрос:
Я работаю над страницей поиска, на которой врач может искать пациента с name
помощью, start_date
и end_date
. Здесь start_date и end_date — это диапазон дат, в котором был загружен любой документ. Результат должен возвращать всех пациентов, чье имя name
и документы загружены между start_date
и end_date
.
class Document(models.Model):
name = models.CharField(max_length=15, blank=True)
document = models.FileField(upload_to='documents/')
uploaded_at = models.DateTimeField(auto_now_add=True)
patient = models.ForeignKey(to=Patient, on_delete=models.CASCADE, unique=False)
class Meta:
unique_together = ('name', 'document', 'patient')
# many document can have same patient
def __str__(self) -> str:
return f'{self.name}'
def __repr__(self) -> str:
return f'{self.name}'
class Patient(models.Model):
# required fields
first_name = models.CharField(max_length=55, blank=False, null=False)
last_name = models.CharField(max_length=55, blank=False, null=False)
email = models.EmailField(max_length=255, blank=False, null=False, unique=True)
# not required fields
address = models.TextField(max_length=255, blank=True, null=True)
postal_zip = models.IntegerField(max_length=255, blank=True, null=True)
city = models.CharField(max_length=255, blank=True, null=True)
country = models.CharField(max_length=255, blank=True, null=True)
phone_number = models.IntegerField(max_length=17, blank=True, null=True) # mobile
alternate_number = models.IntegerField(max_length=17, blank=True, null=True) # alternate
def __str__(self) -> str:
return f"{self.first_name} {self.last_name}"
def __repr__(self) -> str:
return f"{self.first_name} {self.last_name}"
Я могу получить все документы, загруженные между определенными датами следующим образом
documents = Document.objects.filter(
uploaded_at__gte=start_date
).intersection(
Document.objects.filter(uploaded_at__lte=end_date)
)
но я не могу найти способ объединить приведенный выше результат с этим
query = Patient.objects.filter(
Q(first_name__icontains=search_key) |
Q(last_name__icontains=search_key) |
Q(email__icontains=search_key) |
Q(city__icontains=search_key) |
Q(phone_number__icontains=search_key) |
Q(alternate_number__icontains=search_key) |
Q(country__icontains=search_key)
)
Ответ №1:
Вы можете использовать двойные подчеркивания для просмотра отношения, поэтому здесь мы можем фильтровать по Patient
s, у которых есть документ в заданном диапазоне:
# Patients which match the search_key, and have
# documents uploaded in the (start_date, end_date) range
query = Patient.objects.filter(
Q(first_name__icontains=search_key) |
Q(last_name__icontains=search_key) |
Q(email__icontains=search_key) |
Q(city__icontains=search_key) |
Q(phone_number__icontains=search_key) |
Q(alternate_number__icontains=search_key) |
Q(country__icontains=search_key),
document__uploaded_at__range=(start_date, end_date)
).distinct()
Как .distinct()
вы прокомментировали, here предотвращает извлечение одного и того же пациента несколько раз ( Document
один раз в диапазоне).
или Document
ы, у которых есть a Patient
, соответствующий заданным условиям:
# Documents uploaded in the (start_date, end_date) range
# which match a Patient with the search_key.
query = Document.objects.filter(
Q(patient__first_name__icontains=search_key) |
Q(patient__last_name__icontains=search_key) |
Q(patient__email__icontains=search_key) |
Q(patient__city__icontains=search_key) |
Q(patient__phone_number__icontains=search_key) |
Q(patient__alternate_number__icontains=search_key) |
Q(patient__country__icontains=search_key),
uploaded_at__range=(start_date, end_date)
)
Комментарии:
1. Этот подход действительно работает, но требует небольшой модификации. Если вы заметили, что может быть несколько
document
связанных одиночныхpatient
. Поэтому, когда я использую это `uploaded_at__range= (start_date, end_date)` Я получаю несколько экземпляров одного и того же пациента в наборе запросов. Чтобы ответить на этот вопрос, можно ли использоватьdistinct()
метод? Прямо сейчас, когда я запускаю это, я получаю следующий выводIn [16]: Patient.objects.filter(document__uploaded_at__range=[start_date, end_date]) Out[16]: <QuerySet [Aman Goyal, Aman Goyal, patient lname, patient lname, Aman Goyal]>
2. @amangoyal: да, вы действительно можете добавить a
.distinct()
в конце.3. Просто для будущих ссылок и поисковиков. Не могли бы вы обновить это в ответе? Я считаю, что это важно.
4. @amangoyal: я обновил его с помощью a
.distinct()
в конце (и объяснил, почему это полезно) 🙂