【问题标题】:Make django query from database based on two models基于两种模型从数据库进行django查询
【发布时间】:2021-01-04 05:13:27
【问题描述】:

我正在研究搜索页面,医生可以在其中搜索具有namestart_dateend_date 的患者。这里 start_date 和 end_date 是上传任何文档的日期范围。结果应该返回所有姓名为name 并且在start_dateend_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)           
    
                )

【问题讨论】:

    标签: python sql django django-forms django-queryset


    【解决方案1】:

    您可以使用双下划线来查看关系,因此我们可以过滤Patients 在给定范围内的文档:

    # 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() 可防止您多次检索同一患者(范围内每个Document 一次)。

    Documents 具有与给定条件匹配的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)
    )

    【讨论】:

    • 这种方法确实有效,但几乎不需要修改。如果您注意到可能有多个 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]>
    • @amangoyal:是的,您确实可以在末尾添加.distinct()
    • 仅供日后参考和搜索。你能在答案中更新这个吗?我认为这很重要。
    • @amangoyal:我在最后更新了.distinct()(并解释了它为什么有用):)
    猜你喜欢
    • 2020-02-22
    • 2013-12-31
    • 2017-07-30
    • 2012-12-22
    • 2021-07-19
    • 2018-01-19
    • 1970-01-01
    • 2013-11-23
    • 1970-01-01
    相关资源
    最近更新 更多