在Django休息框架中,有没有办法拥有多个查找字段?我知道它听起来不是那么 REST 友好。
我有一个Company
模型,我想首先在他们的国家/地区列出它们,然后是一个slug字段,例如:/companies/<iso_country>/<slug>/
。有没有办法做到这一点?
答案 0 :(得分:10)
创建mixin,如:
class MultipleFieldLookupMixin(object):
def get_object(self):
queryset = self.get_queryset() # Get the base queryset
queryset = self.filter_queryset(queryset) # Apply any filter backends
filter = {}
for field in self.lookup_fields:
filter[field] = self.kwargs[field]
return get_object_or_404(queryset, **filter) # Lookup the object
并将此mixin添加到您的视图集中:
class YourCountryViewSet(MultipleFieldLookupMixin, generics.RetrieveAPIView):
lookup_fields = ('iso_country', 'slug')
...
来源:http://www.django-rest-framework.org/api-guide/generic-views/#creating-custom-mixins
答案 1 :(得分:0)
假设您正在使用路由器,我认为您可以执行以下操作:
router.register(r'companies/(?P<iso_country>[^/.]+)/', YourCompanyViewSet, 'company-base')
您必须在ViewSet中将slug
定义为lookup_field
。
然后,例如,您的类看起来像
class YourCountryViewSet(GenericViewSet):
lookup_field = 'slug'
def create(self, request, iso_country):
...
def retrieve(self, request, iso_country, slug):
...
答案 2 :(得分:0)
针对这个主题测试了几个答案,并决定将这些答案编译成这种方法:
(这是使用 Permission
中的 django.contrib.auth.models
模型的示例)
"""
Example serializers
"""
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from rest_framework import serializers
class ContentTypeReadSerializer(serializers.ModelSerializer):
"""
ContentType read serializer
"""
app_label = serializers.CharField(read_only=True, max_length=100)
model = serializers.CharField(read_only=True, max_length=100)
class Meta:
model = ContentType
fields = '__all__'
class PermissionReadSerializer(serializers.ModelSerializer):
"""
Permission read serializer
"""
name = serializers.CharField(read_only=True, max_length=255)
content_type = ContentTypeReadSerializer(read_only=True)
codename = serializers.CharField(read_only=True, max_length=100)
class Meta:
model = Permission
fields = '__all__'
"""
Viewsets mixins
"""
from rest_framework.generics import get_object_or_404
class MultipleLookupFieldsMixin(object):
"""
Multiple lookup fields mixin
"""
lookup_fields = None
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
filters = {}
for field in self.lookup_fields:
if field in self.kwargs:
if self.kwargs[field] != '':
filters[field] = self.kwargs[field]
if len(filters) == 0:
return queryset
return queryset.filter(**filters)
"""
Example views
"""
from django.contrib.auth.models import Permission
from rest_framework import viewsets
from common.viewsets import MultipleLookupFieldsMixin
from . import serializers
class PermissionViewSet(MultipleLookupFieldsMixin,
viewsets.mixins.ListModelMixin,
viewsets.mixins.RetrieveModelMixin,
viewsets.GenericViewSet):
"""
Permission viewset
"""
queryset = Permission.objects.all()
serializer_class = serializers.PermissionReadSerializer
lookup_fields = ['content_type__app_label', 'codename']
lookup_field = 'codename'
"""
Example urls
"""
from django.conf.urls import url, include
from rest_framework.routers import SimpleRouter
from . import views
router = SimpleRouter()
router.register(r'permission/?(?P<content_type__app_label>\w+|)', views.PermissionViewSet, basename='permission')
urlpatterns = [
url(r'', include(router.urls)),
]
通过这种方法,您可以拥有 3 个工作端点:
/permission/
/permission/{content_type__app_name}/
/permission/{content_type__app_name}/{codename}/
尽管如此,这只是专用嵌套路由库(如 drf-nested-routers
)的一种替代方案