我目前使用django rest设置的是:
模型名称:动漫
模型名称:剧集
所以基本上我想实现的是:
如果我请求 api / episodes / {anime_name} /
我列出了特定动漫的情节。
我该怎么做?
EpisodesSerializer
class EpisodesSerializer(serializers.ModelSerializer):
class Meta:
model = Episodes
fields = '__all__'
路由器
router = routers.DefaultRouter()
router.register('animes', AnimesViewSet, 'animes')
router.register('episodes', EpisodesViewSet, 'episodes')
urlpatterns = router.urls
EpisodesViewSet
class EpisodesViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.AllowAny]
MainModel = Episodes
queryset = Episodes.objects.all()
serializer_class = EpisodesSerializer
答案 0 :(得分:1)
编辑
正如评论中提到的OP一样,DRF的较新版本使用@action代替,因为不推荐使用@detail_route和@list_route。
要使用其他字段进行查找,可以实现自己获取对象的逻辑,但是必须确保用于查找的字段是唯一的,否则可能会返回许多对象。
因此,假设动漫@action(detail=True, methods=['get'])
def episodes(self, *args, **kwargs):
anime = Anime.objects.get(name=self.kwarg[self.lookup_field])
episodes = Episode.objects.filter(anime=anime)
...
是唯一的,并且您想将其用于查找,则可以执行以下操作:
get_object()
您还可以检查class AlternateLookupFieldsMixin(object):
"""
Looks up objects for detail endpoints using alternate
lookup fields assigned in `alternate_lookup_fields` apart
from the default lookup_field. Only unique fields should be used
else Http404 is raised if multiple objects are found
"""
alternate_lookup_fields = []
def get_object(self):
try:
return super().get_object()
except Http404:
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
queryset = self.filter_queryset(self.get_queryset())
obj = None
for lookup_field in self.alternate_lookup_fields:
filter_kwargs = {lookup_field: self.kwargs[lookup_url_kwarg]}
try:
obj = get_object_or_404(queryset, **filter_kwargs)
except Http404:
pass
if obj:
self.check_object_permissions(self.request, obj)
return obj
raise Http404
的实现方式,使其更强大。
我为自己制作了一个通用的视图mixin,它允许从主pk查找字段中的多个唯一字段进行查找:
alternate_lookup_fields
所有您需要做的就是将其添加到视图的基类中,并在api/anime/<anime_id>/episodes/
属性中添加用于lookup(根据情况命名)的字段。当然,只能使用唯一字段。
关于过滤,您可以检查完成过滤的程度here。 但是,我建议您使用更通用的过滤器后端,例如django-filter
原始答案
首先,URL看起来像这样更具创意:
from rest_framework.decorators import detail_route
@detail_route(methods=['get'])
def episodes(self, *args, **kwargs):
anime = self.get_object()
episodes = Episode.objects.filter(anime=anime)
page = self.paginate_queryset(anime)
if page is not None:
serialier = EpisodesSerializer(page, context=self.get_serializer_context(), many=True)
return self.get_paginated_response(serializer.data)
serializer = EpisodesSerializer(episodes, context=self.get_serializer_context()) many=True)
return Response(serializer.data)
这是因为您通常应该从更通用的资源开始,到更具体的资源。
要实现此目的,请在您的AnimeViewSet(而不是EpisodesViewSet)中,为这些情节提供详细的路线:
api/episodes?anime=<anime_id>
您还可以仅使用EpisodesViewSet上的过滤器以这种方式获取属于特定动漫的剧集:
$('#AdvertsListe').initDataTables(routes.datatable_settings, {
"dom": "Blfrtip",
'searching' : true,
"bFilter": true,
'ordering' : true,
"columnDefs": [
{
"targets": 0,
"width": "8%"
},
{
"targets": 0,
"width": "8%"
}
]
}).then(function(dt) {
// dt contains the initialized instance of DataTables
dt.on('init', function() {
$('.column_filter').on('change', function (e) {
let index = $(this).data('column');
let searchStr = $(this).val();
if ($(this).val() != ''){
dt.column(index).search(searchStr).draw();
}
e.stopPropagation();
return false;
});
})
});