首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用Django-filter过滤多个字段?

如何使用Django-filter过滤多个字段?
EN

Stack Overflow用户
提问于 2021-09-05 15:51:13
回答 1查看 1.2K关注 0票数 1

我想检索按用户和类别过滤的数据。

我正在使用Django Rest框架。

models.py

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
class PracticeSerializer(serializers.ModelSerializer):
    subcategory = SubcategorySerializer()

    class Meta:
        model = Practice
        fields = ('practice_id',
                  'user',
                  'subcategory',
                  'score',
                  )

views.py

代码语言:javascript
运行
复制
@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

代码语言:javascript
运行
复制
urlpatterns = [ 
        url(r'^api/practice-filter-user$', views.practiceFilter_User),
]

在我的数据库中,我有以下3个实践数据:

代码语言:javascript
运行
复制
[
  {
    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获取实践数据,则结果如下:

api/practice-filter-user?user=1

代码语言:javascript
运行
复制
[
  {
    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

代码语言:javascript
运行
复制
[
  {
    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,
  }
]

在检索用户和类别筛选的实践数据时,上述结果是我想要的。

我尝试在这个链接上使用django过滤器,但是出现了错误。

我向views.py添加了一个类

代码语言:javascript
运行
复制
class practiceFilter_Subcategory_User(generics.ListAPIView):
    queryset = Practice.objects.all()
    serializer_class = PracticeSerializer
    filter_fields = ('user', 'category')

我在urls.py中添加了url

代码语言:javascript
运行
复制
urlpatterns = [ 
        url(r'^api/practice-filter-subcategory-user$', views.practiceFilter_Subcategory_User),
]

我尝试用id 1和所有Math category检索由所有Math category过滤的数据,如下所示:

api/practice-filter-subcategory-user?user=1&category=Math

但是我失败了,并得到了上面的错误。

是否可以通过id 1和所有user过滤所有Math category

更新我得到的跟踪错误:

代码语言:javascript
运行
复制
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 :

代码语言:javascript
运行
复制
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),
]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-05 16:39:52

是的,可以用许多参数进行滤波。Django Rest框架为我们提供了许多实现这一目标的选择。我会给你看其中一个:Filtering against query parameters。您可以重写基于类视图的api/practice-filter-subcategory-user?user=1&category=Math,以处理URL(如api/practice-filter-subcategory-user?user=1&category=Math)。

代码语言:javascript
运行
复制
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文件

非常重要:需要在url视图上调用.as_view(),如下所示:

代码语言:javascript
运行
复制
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()),
]
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69064918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档