Here's my 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
And my 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'))
]
However, only languages
and frameworks
work. language
doesn't exists. Is this because of the get_queryset
? I even tried removing the <int:language_id>
in the url params but it still won't show up.
EDIT:
Forgive my naiveness, I'm quite new to django and DRF
What I meant to do was like this (without DRF):
In the 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)
And in urls.py :
path('language/<int:language_id>', views.frameworks_from_language, name='getframeworks')
So the whole flow would be:
This is working on a normal template-based Django. However I have no idea how to execute something like this on DRF, with all the viewsets etc.
Yes, it's because of your get_queryset
(and your URL definitions).
At first, drop <int:language_id>
from URL prefix, as DRF router generates the list and detail URL endpoints for you automatically. Moreover, as you're using Regex path language/<int:language_id>
is taken literally ( <int:language_id>
has a meaning while using path
, not re_path
).
In your SelectedLanguageViewSet.get_queryset
, you're trying to return all Framework
instances related with a certain Language
(you thought you would take that from language_id
query param). The viewset is for Language
model, and at most you should do some filtering on the default queryset
inside get_queryset
; absolutely don't return a whole different queryset from another model. What will happen (after fixing your URL) when you pass /language/1/
? (Will 1 be a Language
ID or a Framework
ID ? Hint: as per you current design it would refer a Framework
instance ID).
FWIW, the URL captures come as kwargs
attribute in a viewset instance (ie self.kwargs
), not via the query string.
Answer to edits:
To implement that in DRF, you can define a serializer for language with only the frameworks
field:
from viewsets import ReadOnlyModelViewSet
class SelectedLanguageViewSet(ReadOnlyModelViewSet):
queryset = Language.objects.all()
serializer_class = LangaugeRelationSerializer
only list
and retrieve
actions should be supported, hence inherited from ReadOnlyModelViewSet
.
Now, the serializer (with only one field -- frameworks
):
class LangaugeRelationSerializer(serializers.ModelSerializer):
frameworks = FrameworkSerializer(source='framework_set', many=True)
class Meta:
model = Language
fields = ('frameworks',)
By default ModelSerializer
sets the related fields as PrimaryKeyRelatedField
, so the related objects are represented as their primary keys. If you want that instead of using the FrameworkSerializer
:
class LangaugeRelationSerializer(serializers.ModelSerializer):
frameworks = serializers.PrimaryKeyRelatedField(source='framework_set', many=True)
class Meta:
model = Language
fields = ('frameworks',)
As PrimaryKeyRelatedField
is the default, you can also define the source
in Meta.extra_kwargs
(to save you from writing the field definition yourself):
class LangaugeRelationSerializer(serializers.ModelSerializer):
class Meta:
model = Language
fields = ('frameworks',)
extra_kwargs = {
'frameworks': {
'source': 'framework_set',
'many': True,
},
}
您是否尝试过将 url 作为/language/id-of-language
代替id-of-language
传递整数,即数据库中语言的 id。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.