Ale*_*Grs 9 python django rest django-rest-framework
我有多个API,历史上id
用作查找字段:
/api/organization/10
Run Code Online (Sandbox Code Playgroud)
我有一个消耗这些api的前端.
我正在构建一个新的界面,出于某些原因,我想使用slug而不是id:
/api/organization/my-orga
Run Code Online (Sandbox Code Playgroud)
API是使用Django Rest Framework构建的.除了查找字段的更改外,api行为应该保持不变.
有没有一个解决方案允许我的API同时使用a slug
和a pk
?这两条路径应该给他们相同的结果:
/api/organization/10
/api/organization/my-orga
Run Code Online (Sandbox Code Playgroud)
这是我的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
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助.
试试这个
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)
Run Code Online (Sandbox Code Playgroud)
然后在视图中
class Organization(MultipleFieldLookupMixin, viewsets.ModelViewSet):
queryset = OrganisationGroup.objects.all()
serializer_class = OrganizationSerializer
lookup_fields = ('pk', 'another field')
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
我知道您很久以前就问过这个问题,但考虑到视图和网址,这是我从所有答案中得到的完整解决方案:
将其放入您的views.py中:(通过drf进行一些编辑)
class MultipleFieldLookupMixin(object):
def get_object(self):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
filter = {}
for field in self.lookup_fields:
if self.kwargs.get(field, None):
filter[field] = self.kwargs[field]
obj = get_object_or_404(queryset, **filter) # Lookup the object
self.check_object_permissions(self.request, obj)
return obj
Run Code Online (Sandbox Code Playgroud)
然后从这个Mixin继承你的视图并添加你想要的字段到lookup_fields。像这样:
class YourDetailView(MultipleFieldLookupMixin, RetrieveUpdateAPIView):
...
lookup_fields = ['pk', 'slug','code']
Run Code Online (Sandbox Code Playgroud)
在 urls.py 中:
re_path(r'^organization/(?P<pk>[0-9]+)/$',
YourDetailView),
re_path(r'^organization/(?P<slug>[-a-zA-Z0-9_]+)/$',
YourDetailView),
re_path(r'^organization/sth_else/(?P<code>[0-9]+)/$',
YourDetailView),
Run Code Online (Sandbox Code Playgroud)
我通过覆盖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.
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7178 次 |
最近记录: |