如何使用 Django-filter 过滤多个字段?
Posted
技术标签:
【中文标题】如何使用 Django-filter 过滤多个字段?【英文标题】:How to filter multiple fields using Django-filter? 【发布时间】:2021-11-02 23:24:50 【问题描述】:我想检索按用户和类别过滤的数据。
我正在使用 Django Rest 框架。
models.py
class Practice(models.Model):
practice_id = models.BigAutoField(primary_key=True)
user = models.ForeignKey('User', models.DO_NOTHING, default=None)
subcategory = models.ForeignKey('Subcategory', models.DO_NOTHING, default=None)
score = models.SmallIntegerField(null=True)
def __str__(self):
return str(self.practice_id)
class User(models.Model):
user_id = models.BigAutoField(primary_key=True)
fullname = models.CharField(max_length=50)
def __str__(self):
return self.fullname
class Subcategory(models.Model):
subcategory_id = models.BigAutoField(primary_key=True)
category = models.CharField(max_length=30)
def __str__(self):
return f" self.category "
serializers.py
class PracticeSerializer(serializers.ModelSerializer):
subcategory = SubcategorySerializer()
class Meta:
model = Practice
fields = ('practice_id',
'user',
'subcategory',
'score',
)
views.py
@api_view(['GET'])
def practiceFilter_User(request):
if request.method == 'GET':
exercises = Practice.objects.all()
user = request.GET.get('user', None)
if user is not None:
practice_filtered = exercises.filter(user__user_id__icontains=user)
exercises_serializer = PracticeSerializer(practice_filtered, many=True)
return JsonResponse(exercises_serializer.data, safe=False)
urls.py
urlpatterns = [
url(r'^api/practice-filter-user$', views.practiceFilter_User),
]
在我的数据库中,我有 3 个练习数据如下:
[
practice_id: 1,
user: 1,
subcategory:
subcategory_id: 1,
category: "Math",
,
score: 7,
,
practice_id: 2,
user: 1,
subcategory:
subcategory_id: 1,
category: "Math",
,
score: 8,
,
practice_id: 3,
user: 1,
subcategory:
subcategory_id: 2,
category: "History",
,
score: 9,
]
如果执行上述代码通过user id = 1获取练习数据,结果如下:
api/practice-filter-user?user=1
[
practice_id: 1,
user: 1,
subcategory:
subcategory_id: 1,
category: "Math",
,
score: 7,
,
practice_id: 2,
user: 1,
subcategory:
subcategory_id: 1,
category: "Math",
,
score: 8,
,
practice_id: 3,
user: 1,
subcategory:
subcategory_id: 2,
category: "History",
,
score: 9,
]
我想检索由 ID 为 1 的所有 user
和所有 Math category
过滤的数据,如下所示:
api/practice-filter-subcategory-user?user=1&category=Math
[
practice_id: 1,
user: 1,
subcategory:
subcategory_id: 1,
category: "Math",
,
score: 7,
,
practice_id: 2,
user: 1,
subcategory:
subcategory_id: 1,
category: "Math",
,
score: 8,
]
上面的结果是我在检索按用户和类别过滤的练习数据时想要的。
我已尝试在此 link 上使用 django-filter,但出现错误。
我在 views.py
中添加了一个类class practiceFilter_Subcategory_User(generics.ListAPIView):
queryset = Practice.objects.all()
serializer_class = PracticeSerializer
filter_fields = ('user', 'category')
我将 url 添加到 urls.py
urlpatterns = [
url(r'^api/practice-filter-subcategory-user$', views.practiceFilter_Subcategory_User),
]
我尝试检索所有user
过滤的数据,ID 为 1 和所有Math category
,如下所示:
api/practice-filter-subcategory-user?user=1&category=Math
但是我失败了,得到了如上的错误。
是否可以按 id 1 过滤所有user
和所有Math category
?
更新我得到的 Traceback 错误:
Environment:
Request Method: GET
Request URL: http://192.168.1.2:8080/api/practice-filter-subcategory-user?user_id=1&category=Math
Django Version: 3.2.5
Python Version: 3.7.9
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_bulk',
'yasn.apps.yasnConfig',
'corsheaders',
'django_filters']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware']
Traceback (most recent call last):
File "C:\Users\Me\Documents\Python\env\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\Me\Documents\Python\env\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
Exception Type: TypeError at /api/practice-filter-subcategory-user
Exception Value: __init__() takes 1 positional argument but 2 were given
更新 urls.py :
from django.conf.urls import url
from yasn import views
urlpatterns = [
url(r'^api/practice-filter-user$', views.practiceFilter_User),
url(r'^api/practice-filter-subcategory-user$', views.practiceFilter_Subcategory_User),
]
【问题讨论】:
请将整个回溯作为文本发布(在错误页面上的“切换到复制粘贴视图”按钮旁边),而不仅仅是几行图片。 感谢您的回复,我已经包含了上面的错误回溯更新。 你能把你的url文件贴在这里吗? 我在上面的问题末尾包含了 urls.py。 验证你的url在get_queryset()
中检索到的参数是user_id
,category
你的url包含user
和category
。尝试更正它并告诉我们
【参考方案1】:
是的,可以使用许多参数进行过滤。 Django Rest Framework 为我们提供了许多选项来实现这一目标。我将向您展示其中之一:Filtering against query parameters
。
您可以覆盖基于类的视图的 .get_queryset()
以处理诸如 api/practice-filter-subcategory-user?user=1&category=Math
class practiceFilter_Subcategory_User(generics.ListAPIView):
serializer_class = PracticeSerializer
def get_queryset(self):
# If they are no parameters return all objects
queryset = Practice.objects.all()
# Retrieve the query parameters in the url
user_id = self.request.query_params.get('user_id')
category = self.request.query_params.get('category')
# If they are present
if user_id is not None and category is not None:
practice_filtered = exercises.filter(user__user_id=user_id)
# Filter by category, you can chain filter of course
practice_filtered = practice_filtered.filter(subcategory__category=category)
queryset = practice_filtered
return queryset
这里是DRF documentation
非常重要:您需要在您的url
视图上调用.as_view()
,如下所示:
from django.conf.urls import url
from yasn import views
urlpatterns = [
url(r'^api/practice-filter-user$', views.practiceFilter_User.as_view()),
url(r'^api/practice-filter-subcategory-user$', views.practiceFilter_Subcategory_User.as_view()),
]
【讨论】:
感谢您的回复,我已尝试按照您的指示进行操作,但出现错误。我在上面的问题末尾包含了错误。以上是关于如何使用 Django-filter 过滤多个字段?的主要内容,如果未能解决你的问题,请参考以下文章
Django-Filter:外键字段上的多个 select2 选择
Django-Filter 包:如何过滤对象以创建统计信息而不是列表
带有 DRF 的 Django-filter - 如何在使用相同查找应用多个值时执行“和”?