Chr*_*vCB 10 python django rest django-rest-framework
我有一个或多或少看起来像这样的模型:
class Starship(models.Model):
id = models.UUIDField(default=uuid4, editable=False, primary_key=True)
name = models.CharField(max_length=128)
hull_no = models.CharField(max_length=12, unique=True)
Run Code Online (Sandbox Code Playgroud)
我有一个不起眼的StarshipDetailSerialiser
和StarshipListSerialiser
(我想最终呈现出不同的领域,但现在他们是相同的),这两个子类serializers.ModelSerializer
.它有一个HyperlinkedIdentityField
引用回(UU)ID,使用与原始类似的home-brew类,HyperlinkedIdentityField
但具有规范化和处理UUID的能力:
class StarshipListSerializer(HyperlinkedModelSerializer):
uri = UUIDHyperlinkedIdentityField(view_name='starships:starship-detail', format='html')
class Meta:
model = Starship
fields = ('uri', 'name', 'hull_no')
Run Code Online (Sandbox Code Playgroud)
最后,有一个列表视图(a ListAPIView
)和一个如下所示的详细视图:
class StarshipDetail(APIView):
"""
Retrieves a single starship by UUID primary key.
"""
def get_object(self, pk):
try:
return Starship.objects.get(pk=pk)
except Starship.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
vessel = self.get_object(pk)
serializer = StarshipDetailSerialiser(vessel, context={'request': request})
return Response(serializer.data)
Run Code Online (Sandbox Code Playgroud)
详细视图的URL模式当前正在基于UUID调用视图:
...
url(r'vessels/id/(?P<pk>[0-9A-Fa-f\-]+)/$', StarshipDetail.as_view(), name='starship-detail'),
...
Run Code Online (Sandbox Code Playgroud)
我现在希望用户能够导航并且不仅通过UUID而且通过他们的船体编号来找到相同的船只,以便例如vessels/id/abcde1345...and so on.../
并且vessels/hull/H1025/
能够解析到同一实体.理想情况下,无论是从ID还是船体编号到达详细视图,序列化程序(也用于列表中的轻微更改)应该能够将ID链接到基于ID的链接并且机身已超链接基于船体编号的链接(vessels/hull/H1025/
).这是可能吗?如果是这样,我该怎么做呢?
wim*_*wim 11
# in urls.py
urlpatterns = [
...,
url(r'vessels/id/(?P<pk>[0-9A-Fa-f\-]+)/$', StarshipDetail.as_view(), name='starship-detail-pk'),
url(r'vessels/hull/(?P<hull_no>[0-9A-Za-z]+)/$', StarshipDetail.as_view(), name='starship-detail-hull'),
]
Run Code Online (Sandbox Code Playgroud)
根据需要调整正则表达式hull_no
.请注意,我为每条路线指定了不同的名称,starship-detail-pk
并且starship-detail-hull
.
# in serializers.py
class StarshipListSerialiser(HyperlinkedModelSerializer):
uri = UUIDHyperlinkedIdentityField(view_name='starship-detail-pk', format='html')
hull_no = UUIDHyperlinkedIdentityField(view_name='starship-detail-hull', format='html', lookup_field='hull_no')
class Meta:
model = Starship
fields = ('uri', 'name', 'hull_no')
Run Code Online (Sandbox Code Playgroud)
# in serializers.py
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView, Response
from starwars.serializers import StarshipDetailSerialiser
from starwars.models import Starship
class StarshipDetail(APIView):
def get(self, request, pk=None, hull_no=None, format=None):
lookup = {'hull_no': hull_no} if pk is None else {'pk': pk}
vessel = get_object_or_404(Starship, **lookup)
serializer = StarshipDetailSerialiser(vessel, context={'request': request})
return Response(serializer.data)
Run Code Online (Sandbox Code Playgroud)
这应该足以让你进入详细视图:
最后要注意的是,您应该知道,在这样的两个不同的URL上提供相同的资源并不是RESTful.也许,作为一个替代设计决策,您可能只想考虑为资源定义"一条真实路线",并添加从其他定位器到规范URL的"便利"重定向.
归档时间: |
|
查看次数: |
4728 次 |
最近记录: |