这是我的 views.py :
class LanguageViewSet(viewsets.ModelViewSet):
queryset = Language.objects.all().order_by('name')
serializer_class = LanguageSerializer
class FrameworkViewSet(viewsets.ModelViewSet):
queryset = Framework.objects.all()
serializer_class = FrameworkSerializer
class SelectedLanguageViewSet(viewsets.ModelViewSet):
queryset = Language.objects.all()
serializer_class = FrameworkSerializer
def get_queryset(self):
request = self.request
language_id = request.query_params.get('language_id')
language = Language.objects.filter(id=language_id)
self.queryset = language.framework_set.all()
return self.queryset
还有我的 urls.py :
router = routers.DefaultRouter()
router.register(r'languages', views.LanguageViewSet)
router.register(r'frameworks', views.FrameworkViewSet)
router.register(r'language/<int:language_id>', views.SelectedLanguageViewSet)
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
但是,只有languages
和frameworks
有效。 language
不存在。是因为get_queryset
吗?我什至尝试删除url参数中的<int:language_id>
,但仍然不会显示。
编辑:
请原谅我,我对django和DRF还是陌生的
我的意思是这样的(没有DRF):
在 views.py :
def frameworks_from_language(request, language_id):
language = Language.objects.get(pk=language_id)
if language == None:
# Do some stuffs
frameworks = language.framework_set.all()
template = 'app/language.html'
context = {
'frameworks': frameworks
}
return render(request, template, context)
在 urls.py 中:
path('language/<int:language_id>', views.frameworks_from_language, name='getframeworks')
因此整个流程将是:
这正在基于普通模板的Django上进行。但是我不知道如何在DRF上使用所有视图集等执行类似的操作。
答案 0 :(得分:5)
是的,这是因为您的get_queryset
(以及您的URL定义)。
首先,从URL前缀中删除<int:language_id>
,因为DRF路由器会自动为您生成列表和详细信息URL端点。此外,在使用正则表达式时,路径language/<int:language_id>
是按字面意义使用的(<int:language_id>
在使用path
时具有含义,而不是re_path
)。
在您的SelectedLanguageViewSet.get_queryset
中,您尝试返回与某个Framework
相关的所有Language
实例(您认为应该从language_id
查询参数中获取该实例)。该视图集适用于Language
模型,至多您应该在queryset
内部的默认get_queryset
上进行一些过滤;绝对不要从另一个模型返回完全不同的查询集。传递/language/1/
时会发生什么(固定URL之后)? (根据您当前的设计,1将是Language
ID还是Framework
ID?提示:。它将引用一个Framework
实例ID)。
FWIW,URL捕获是视图集实例(即kwargs
)中的self.kwargs
属性,而不是通过查询字符串。
修改答案:
要在DRF中实现该功能,您可以仅使用frameworks
字段为语言定义一个序列化器:
from viewsets import ReadOnlyModelViewSet
class SelectedLanguageViewSet(ReadOnlyModelViewSet):
queryset = Language.objects.all()
serializer_class = LangaugeRelationSerializer
仅应支持list
和retrieve
操作,因此这些操作是从ReadOnlyModelViewSet
继承的。
现在,序列化程序(只有一个字段-frameworks
):
class LangaugeRelationSerializer(serializers.ModelSerializer):
frameworks = FrameworkSerializer(source='framework_set', many=True)
class Meta:
model = Language
fields = ('frameworks',)
默认情况下,ModelSerializer
将相关字段设置为PrimaryKeyRelatedField
,因此相关对象被表示为其主键。如果您希望使用它而不是使用FrameworkSerializer
:
class LangaugeRelationSerializer(serializers.ModelSerializer):
frameworks = serializers.PrimaryKeyRelatedField(source='framework_set', many=True)
class Meta:
model = Language
fields = ('frameworks',)
由于PrimaryKeyRelatedField
是默认设置,因此您还可以在source
中定义Meta.extra_kwargs
(以免您自己编写字段定义):
class LangaugeRelationSerializer(serializers.ModelSerializer):
class Meta:
model = Language
fields = ('frameworks',)
extra_kwargs = {
'frameworks': {
'source': 'framework_set',
'many': True,
},
}
答案 1 :(得分:1)
您是否尝试过将URL作为/language/id-of-language
而不是id-of-language
传递整数,即db中语言的ID。