如何在 Django Rest Framework 中使用 lookup_field 和 FilterSet?
How to use lookup_field along with FilterSet in Django Rest Framework?
我正在为一个项目开发 API,它包含一个课程列表页面,其中
- 列出了特定学院提供的所有课程。
- 应支持使用 lookup_field 作为 course_slug 检索特定课程。
- 支持基于我在 Django FilterSet 和 filterset_class (filterset_class) 的帮助下实现的一些其他参数的过滤课程。
问题是,根据要求过滤课程后,查询参数也会包含在 URL 中。现在,我无法对其执行检索操作,因为 URL 无法识别添加的 lookup_field 并将其误认为是查询参数中的模式。
ViewSet.py
class CollegeCourseViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = CourseSerializer
lookup_field = 'slug'
filter_backends = (SearchFilter, DjangoFilterBackend,)
search_fields = ['name']
filterset_class = CourseFilter
def get_queryset(self):
queryset = Course.objects.all()
return queryset.filter(college_courses__college__slug=self.kwargs['college_slug'])
def get_object(self):
obj = super().get_object()
if self.action == 'retrieve':
obj.additional = CollegeCourse.objects.filter(course=obj, college__slug=self.kwargs['college_slug']).first()
return obj
def get_serializer_class(self):
if self.action == 'retrieve':
return CollegeCourseSerializer
return super().get_serializer_class()
filters.py
class CourseFilter(filters.FilterSet):
name = filters.MultipleChoiceFilter(field_name='college_courses__stream__name',
choices=choices("STREAM_NAME_CHOICES"))
category = filters.MultipleChoiceFilter(field_name='college_courses__stream__category',
choices=choices("STREAM_CATEGORY_CHOICES"))
program = filters.MultipleChoiceFilter(field_name='college_courses__stream__program',
choices=choices("STREAM_PROGRAM_CHOICES"))
class Meta:
model = Course
fields = [
'name',
'category',
'program'
]
urls.py
router = routers.DefaultRouter()
router.register(r'courses', CollegeCourseViewSet, basename='college_course')
urlpatterns = [
path('api/college/v1/colleges/<slug:college_slug>/', include(router.urls)),
]
假设我根据类别 = 农业进行过滤,我得到了包含三门课程的列表。现在,我想使用它的 slug 检索其中一门课程。但这是 Bad Request 消息
URL
GET /api/college/v1/colleges/clslug1/courses/?category=Agriculture/crslug2
crslug2 是课程中的 slug。
留言
"Select a valid choice. Agriculture/crslug2 is not one of the available choices."
有什么方法可以在查询参数后添加 lookup_field 吗?
提前致谢。
好吧,我自己回答 post。基本上一切都很好,除了 URL 不是 RESTful.
lookup_field 必须在 RESTful api 中的任何查询参数之前给出。
所以正确的格式是
GET /api/college/v1/colleges/clslug1/courses/crslug2/?category=Agriculture
我正在为一个项目开发 API,它包含一个课程列表页面,其中
- 列出了特定学院提供的所有课程。
- 应支持使用 lookup_field 作为 course_slug 检索特定课程。
- 支持基于我在 Django FilterSet 和 filterset_class (filterset_class) 的帮助下实现的一些其他参数的过滤课程。
问题是,根据要求过滤课程后,查询参数也会包含在 URL 中。现在,我无法对其执行检索操作,因为 URL 无法识别添加的 lookup_field 并将其误认为是查询参数中的模式。
ViewSet.py
class CollegeCourseViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = CourseSerializer
lookup_field = 'slug'
filter_backends = (SearchFilter, DjangoFilterBackend,)
search_fields = ['name']
filterset_class = CourseFilter
def get_queryset(self):
queryset = Course.objects.all()
return queryset.filter(college_courses__college__slug=self.kwargs['college_slug'])
def get_object(self):
obj = super().get_object()
if self.action == 'retrieve':
obj.additional = CollegeCourse.objects.filter(course=obj, college__slug=self.kwargs['college_slug']).first()
return obj
def get_serializer_class(self):
if self.action == 'retrieve':
return CollegeCourseSerializer
return super().get_serializer_class()
filters.py
class CourseFilter(filters.FilterSet):
name = filters.MultipleChoiceFilter(field_name='college_courses__stream__name',
choices=choices("STREAM_NAME_CHOICES"))
category = filters.MultipleChoiceFilter(field_name='college_courses__stream__category',
choices=choices("STREAM_CATEGORY_CHOICES"))
program = filters.MultipleChoiceFilter(field_name='college_courses__stream__program',
choices=choices("STREAM_PROGRAM_CHOICES"))
class Meta:
model = Course
fields = [
'name',
'category',
'program'
]
urls.py
router = routers.DefaultRouter()
router.register(r'courses', CollegeCourseViewSet, basename='college_course')
urlpatterns = [
path('api/college/v1/colleges/<slug:college_slug>/', include(router.urls)),
]
假设我根据类别 = 农业进行过滤,我得到了包含三门课程的列表。现在,我想使用它的 slug 检索其中一门课程。但这是 Bad Request 消息
URL
GET /api/college/v1/colleges/clslug1/courses/?category=Agriculture/crslug2
crslug2 是课程中的 slug。
留言
"Select a valid choice. Agriculture/crslug2 is not one of the available choices."
有什么方法可以在查询参数后添加 lookup_field 吗?
提前致谢。
好吧,我自己回答 post。基本上一切都很好,除了 URL 不是 RESTful.
lookup_field 必须在 RESTful api 中的任何查询参数之前给出。
所以正确的格式是
GET /api/college/v1/colleges/clslug1/courses/crslug2/?category=Agriculture