使用Django过滤器和Q对象来根据多列中的任意一个来筛选数据
总结
使用Django过滤器和Q对象来实现本次任务。
-
- 名前
- カナ
我想解释一下如何筛选出满足以下条件的数据:
例如,如果想通过姓名或假名进行筛选,可以使用以下示例中的”name”查询参数进行筛选。
'http://127.0.0.1:8080/api/customer/?name=大阪'
'http://127.0.0.1:8080/api/customer/?name=オオサカ'
因为不需要特意创建假名查询参数,所以在想要进行假名搜索时很方便,我希望实施它。
前提- 就像這句中所說的,需要用中文來翻譯
-
- django-filtersをインストール済み
-
- django-filtersの基本的な使い方を知っている
- 必須ではないが最後にSwaggerで検証するため、Swaggerを設定済み
文件结构
文件的结构如下所示。
application
├── __init__.py
├── admin.py
├── apps.py
├── filters.py
├── fixtures
| └── fixture.json
├── migrations
├── models.py
├── serializers
| └── customer.py
├── urls.py
└── views
└── customer.py
以上提及的部分
-
- models.py
-
- serializers/customer.py
-
- views/customer.py
-
- urls.py
-
- fixtures/fixture.json
- filters.py
我会逐步记录所需的设置。
起初,Q对象是什么呢?
当在进行复杂查询时,会使用OR或AND来搜索。这次我们将在filters.py中使用它来进行name和kana的OR搜索。
模型.py
本次我们将创建一个供客户使用的模型,并添加kana和name两列。
import uuid
from django.core.validators import RegexValidator
from django.db import models
class Customer(models.Model):
"""お客様"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
kana = models.CharField(max_length=255)
"""カナ氏名"""
name = models.CharField(max_length=255)
"""氏名"""
birthday = models.DateField()
"""誕生日"""
phone_no = models.CharField(
max_length=11,
validators=[RegexValidator(r"^[0-9]{11}$", "11桁の数字を入力してください。")],
blank=True,
)
"""電話番号"""
class Meta:
db_table = "Customer"
序列化器/顾客.py
本次我们将使用ModelSerializer。
from rest_framework import serializers
from application.models import Customer
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = "__all__"
视图/顾客.py
创建CustomerViewSet,并进行django-filters的配置。
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.viewsets import ModelViewSet
from application.filters import CustomerFilter
from application.models import Customer
from application.serializers.customer import CustomerSerializer
class CustomerViewSet(ModelViewSet):
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
filter_backends = (DjangoFilterBackend,)
filterset_class = CustomerFilter
urls.py 的中文释义是什么?
为客户创建一个URL
from django.urls import include, path
from rest_framework_nested import routers
from application.views.customer import CustomerViewSet
router = routers.DefaultRouter()
router.register(r"customer", CustomerViewSet, basename="customer")
urlpatterns = [
path(r"", include(router.urls)),
]
赛程.json
请放入客户的测试数据。
python manage.py loaddata fixtures.json
可以一次性全部放进去。
[
{
"model": "application.Customer",
"pk": 1,
"fields": {
"kana": "オオサカタロウ",
"name": "大阪太郎",
"birthday": "1992-01-06",
"phone_no": "08011112222",
"address": 1
}
},
{
"model": "application.Customer",
"pk": 2,
"fields": {
"kana": "キョウトジロウ",
"name": "京都二郎",
"birthday": "1994-01-06",
"phone_no": "08022223333",
"address": 2
}
},
{
"model": "application.Customer",
"pk": 3,
"fields": {
"kana": "ヒョウゴサブロウ",
"name": "兵庫三郎",
"birthday": "1995-03-06",
"phone_no": "08033334444",
"address": 3
}
}
]
过滤器.py
我需要在这里进行过滤器的设置。
import django_filters
from django.db.models import Q
from application.models import Customer
class CustomerFilter(django_filters.FilterSet):
"""お客様の
- 氏名・カナ氏
で絞り込むFilter
Args:
django_filters
"""
name = django_filters.CharFilter(method="search_name", label="name")
class Meta:
model = Customer
fields = ["name"]
def search_name(self, queryset, name, value):
return queryset.filter(
Q(name__contains=value) | Q(kana__contains=value)
)
由于普通的CharFilter只能通过name对数据进行筛选,因此我们将创建一个名为search_name的自定义搜索方法。
name = django_filters.CharFilter(method="search_name", label="name")
在这里使用前面提到的Q对象进行筛选。
def search_name(self, queryset, name, value):
return queryset.filter(
Q(name__contains=value) | Q(kana__contains=value)
)
搜寻名称()函数的参数
-
- querysetの変数内にはCustomerのオブジェクトが入ります
-
- value内には指定した検索条件が入ります
例えば”大阪”で絞り込もうと思った場合はvalue内に”大阪”が入ります
search_name()の引数にdjango-filtersで指定したfilter名(今回だとname)も入れないとカスタムメソッドが機能しないので注意です
print(queryset)
<QuerySet [<Customer: Customer object (00000000-0000-0000-0000-000000000001)>, <Customer: Customer object (00000000-0000-0000-0000-000000000002)>, <Customer: Customer object (00000000-0000-0000-0000-000000000003)>]>
print(value)
'大阪'
print(name)
'name'
关于已发出的SQL
我发现queryset中有Customer对象,所以让我们在Shell中进行确认。
如果你不知道如何使用django-debug-toolbar,你可以参考下面的文章,它可以方便地查看Django ORM生成的SQL语句。
python manage.py debugsqlshell
Python 3.11.3 (main, Apr 12 2023, 14:31:14) [GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from application.models import Customer
>>> from django.db.models import Q
>>> Customer.objects.filter(Q(name__contains="大阪") | Q(kana__contains="大阪"))
SELECT `Customer`.`id`,
`Customer`.`kana`,
`Customer`.`name`,
`Customer`.`birthday`,
`Customer`.`phone_no`,
`Customer`.`address_id`
FROM `Customer`
WHERE (`Customer`.`name` LIKE BINARY '%大阪%'
OR `Customer`.`kana` LIKE BINARY '%大阪%')
LIMIT 21 [1.05ms]
<QuerySet [<Customer: Customer object (00000000-0000-0000-0000-000000000001)>]>
通过在WHERE条件中使用OR,可以确认正在筛选包含在name或kana列中含有”大阪”的对象。
让我们使用Swagger进行验证






请提供更多上下文以便我更好地理解您所需的信息。