Django Rest框架中的多个lookup字段

2024-09-27 17:31:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我有多个API,它们以前使用id作为查找字段:

/api/organization/10

我有一个前端正在使用这些api。

我正在构建一个新的界面,出于某些原因,我想使用slug代替id:

/api/organization/my-orga

API是用Django Rest框架构建的。除了更改查找字段之外,api的行为应该保持不变。

有没有解决方案允许我的API同时使用aslug和apk?这两条路应该给他们同样的结果:

/api/organization/10
/api/organization/my-orga

以下是我的API定义:

# urls.py
router = DefaultRouter()
router.register(r'organization', Organization)
urlpatterns = router.urls

#view.py
class Organization(viewsets.ModelViewSet):
    queryset = OrganisationGroup.objects.all()
    serializer_class = OrganizationSerializer

# serializer.py
class OrganizationSerializer(PermissionsSerializer):
    class Meta:
        model = Organization

谢谢你的帮助。


Tags: pyapiid界面my原因urlsclass
3条回答

我通过重写retrieve方法并根据任何模式检查pk字段的值来解决类似的问题。例如,如果它只包含数字。

def retrieve(self, request, *args, **kwargs):
    if kwargs['pk'].isdigit():
        return super(Organization, self).retrieve(request, *args, **kwargs)
    else:
        # get and return object however you want here.

&13;
&13;
class MultipleFieldLookupMixin(object):
    """
    Apply this mixin to any view or viewset to get multiple field filtering
    based on a `lookup_fields` attribute, instead of the default single field filtering.
    """

    def get_object(self):
        queryset = self.get_queryset()  # Get the base queryset
        queryset = self.filter_queryset(queryset)
        filter = {}
        for field in self.lookup_fields:
            if self.kwargs[field]:  # Ignore empty fields.
                filter[field] = self.kwargs[field]
        return get_object_or_404(queryset, **filter)  # Lookup the object


class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_fields = ('account', 'username')

试试这个

from django.db.models import Q
import operator
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]
        q = reduce(operator.or_, (Q(x) for x in filter.items()))
        return get_object_or_404(queryset, q)

然后在视图中

class Organization(MultipleFieldLookupMixin, viewsets.ModelViewSet):
    queryset = OrganisationGroup.objects.all()
    serializer_class = OrganizationSerializer
    lookup_fields = ('pk', 'another field')

希望这有帮助。

相关问题 更多 >

    热门问题