2017-08-07 23 views
9

Tôi có một mô hình mà nhiều hơn hoặc ít hơn vẻ bề ngoài như thế này:Khung công tác Django REST - nhiều trường tra cứu?

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) 

Tôi có một không đáng kể StarshipDetailSerialiserStarshipListSerialiser (Tôi muốn cuối cùng hiển thị các lĩnh vực khác nhau nhưng bây giờ họ giống hệt nhau), cả hai subclassing serializers.ModelSerializer. Nó có một HyperlinkedIdentityField đề cập trở lại (UU) ID, sử dụng một lớp home-brew rất giống với bản gốc HyperlinkedIdentityField nhưng với khả năng bình thường hóa và xử lý UUIDs:

class StarshipListSerializer(HyperlinkedModelSerializer): 
uri = UUIDHyperlinkedIdentityField(view_name='starships:starship-detail', format='html') 

    class Meta: 
     model = Starship 
     fields = ('uri', 'name', 'hull_no') 

Cuối cùng, có một cái nhìn danh sách (một ListAPIView) và một cái nhìn chi tiết trông như thế này:

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) 

schema URL Quan điểm chi tiết của hiện đang gọi quan điểm dựa trên UUID:

... 
url(r'vessels/id/(?P<pk>[0-9A-Fa-f\-]+)/$', StarshipDetail.as_view(), name='starship-detail'), 
... 

Tôi bây giờ muốn người dùng có thể điều hướng và tìm thấy cùng một tàu không chỉ bởi UUID mà còn bởi số thân tàu của họ, ví dụ: vessels/id/abcde1345...and so on.../vessels/hull/H1025/ sẽ có thể giải quyết cho cùng một pháp nhân. Và lý tưởng, bất kể một người đến xem chi tiết từ ID hoặc số thân, serialiser, được sử dụng với những thay đổi nhỏ trong danh sách là tốt, có thể có liên kết ID tới liên kết dựa trên ID và liên kết thân tàu vào liên kết dựa trên số thân tàu (vessels/hull/H1025/). Đây có phải là ở tất cả có thể? Và nếu vậy, làm thế nào tôi sẽ đi về nó?

Trả lời

9

1. Thêm tuyến đường mới

# 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'), 
] 

Tweak regex cho hull_no như bạn muốn. Lưu ý rằng tôi đã đặt tên riêng cho mỗi tuyến đường, starship-detail-pkstarship-detail-hull.

2. Thêm các lĩnh vực thân trong serializer

# 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') 

3. Sửa đổi quan điểm vì thế nó cũng có thể giải quyết các đối tượng dựa trên thân tàu

# 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) 

Đó nên là đủ để giúp bạn có đi với chế độ xem chi tiết:

drf screencap

Cuối cùng lưu ý, bạn nên lưu ý rằng nó không phải RESTful cho cùng một tài nguyên để có sẵn tại hai URL khác nhau như thế này. Có lẽ, với tư cách là một quyết định thiết kế thay thế, bạn có thể cân nhắc việc chỉ định "một tuyến đường thực" cho tài nguyên và thêm chuyển hướng "tiện lợi" từ trình định vị khác vào URL chuẩn.

Các vấn đề liên quan