简体   繁体   English

如何对 Django 中的外键字段使用 django-filter package?

[英]How to use django-filter package for foreign key fields in Django?

Hi all!大家好!

New in Django, and confused, help is appreciated, I've created a table, , thanks to a stackoverflow users: like: Django 中的新功能,很困惑,感谢帮助,我创建了一个表,感谢 stackoverflow 用户:喜欢:

Organization组织 Total amount of appeals上诉总数 Amount of written form appeals书面形式上诉的数量 Amount of oral form appeals口头形式上诉的数量
Organization 1组织 1 3 3 1 1 2 2
Organization 2组织 2 2 2 1 1 1 1

Have three models:拥有三种型号:

class Organization(models.Model):
    organization_name = models.CharField(max_length=50)


class AppealForm(models.Model):
    form_name = models.CharField(max_length=50)


class Appeal(models.Model):
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
    appeal_form = models.ForeignKey(AppealForm, on_delete=models.CASCADE)
    applicant_name = models.CharField(max_length=150)
    appeal_date = models.DateField()

Objects of Organization model:组织对象 model:

organization_name机构名称
Organization 1组织 1
Organization 2组织 2

Objects of AppealForm model: AppealForm model 的对象:

form_name表格名称
In written form书面
In oral form口头形式

Objects of Appeal model:上诉对象 model:

organization组织 appeal_form上诉表格 applicant_name申请人姓名
Organization 1组织 1 In written form书面 First and Last name名字和姓氏
Organization 1组织 1 In oral form口头形式 First and Last name名字和姓氏
Organization 1组织 1 In oral form口头形式 First and Last name名字和姓氏
Organization 2组织 2 In written form书面 First and Last name名字和姓氏
Organization 2组织 2 In oral form口头形式 First and Last name名字和姓氏

In the function of views.py file, I've created a query to render, like:views.py文件的function中,我创建了一个查询来渲染,比如:

from django.db.models import Count, Q

organizations = Organization.objects.annotate(
).annotate(
    total=Count('appeal'),
    total_written=Count('appeal', filter=Q(appeal__appeal_form__form_name='in written form')),
    total_oral=Count('appeal', filter=Q('appeal__appeal_form__form_name='in oral form'))
)

And now I want to filter table contents by AppealForm model and date of appeals ( appeal_date field of Appeal model ).现在我想通过AppealForm model 和上诉日期( Appeal model上诉日期字段)过滤表格内容。 Case: User opens a table and from search bar above the table chooses which appeal form and/or the range of dates to see.案例:用户打开一个表格,然后从表格上方的搜索栏中选择要查看的上诉表格和/或日期范围。

Question: How to filter the query which is above in views.py using django-filter package?问题:如何使用 django-filter package 过滤 views.py 中的上述查询?

The most general way to define a complicated filter is to use the method argument.定义复杂过滤器的最通用方法是使用方法参数。 I can't say I completely understand your problem, but you can apply any filter for which you can dream up a queryset in this way.我不能说我完全理解你的问题,但你可以应用任何你可以通过这种方式设计查询集的过滤器。 In outline:概述:

import django-filters as DF将 django-filters 导入为 DF

class SomeFilters( DF.FilterSet):

    name = DF.xxxFilter( method='my_method', field_name='object_field', label='whatever',  ...)
    ...

    def my_method( self, qs, name, value):
        # in here you create a new more restrictive queryset based on qs
        # to implement your filter, and return it.
        # name is the field name. Note, you don't have to use or follow it
        # value is the value that the user typed

        qs = qs.filter( ...) # or .exclude, or complicated stuff  
        return qs

Here's a fairly simple method that I wrote to create an annotation with the value of a field stripped of spaces, and then to do a text-contains filter on that.这是我编写的一个相当简单的方法,用于创建一个带有去掉空格的字段值的注释,然后对其进行文本包含过滤器。

    def filter_array_desc( self, qs, name, value):
        value = value.replace(' ','')
        qs = qs.annotate(
            arr_d_nospaces = Replace( 'array_desc', Value(' '), Value('')) # delete all spaces
        ).filter(
            arr_d_nospaces__icontains = value )
        return qs

Here's a general one that can be applied to any field through a ChoiceFilter to filter whether the field is blank or not:这是一个通用的,可以通过ChoiceFilter应用于任何字段以过滤该字段是否为空白:

    YESNO = (('Y','Yes'), ('N','No'))
    marr_b = FD.ChoiceFilter( field_name='marr', label='M_array is blank',  method='filter_blank_yesno', 
                              choices=YESNO, empty_label="Don't Care" )
    ...

    def filter_blank_yesno( self, qs, name, value):
        if value=="Y":
            return qs.filter(**{ name:'' })
        elif value=="N":
            return qs.exclude( **{ name:'' })
        raise ValueError(f'filter_blank_yesno received value="{value}" which is neither "Y" nor "N"')

Hope this helps.希望这可以帮助。 You will basically be filtering by following relationships between your models, using double-underscores to move between models, and possibly annotating and filtering on the anotation, or doing things with Q objucts and suchlike.您基本上将通过遵循模型之间的关系进行过滤,使用双下划线在模型之间移动,并可能对注释进行注释和过滤,或者使用 Q 对象等进行操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM