2013-09-23 51 views
22

Về cơ bản, tôi đang cố tìm cách tốt để đính kèm nhiều chế độ xem hơn vào Bộ định tuyến mà không cần tạo Bộ định tuyến tùy chỉnh. Cách tốt nhất để thực hiện việc này là gì?Thêm nhiều chế độ xem vào Bộ định tuyến hoặc chế độ xem (Django-Rest-Framework)

Dưới đây là thứ gì đó tương đương với những gì tôi đang cố gắng hoàn thành. Tên biến đã được thay đổi và phương pháp ví dụ tôi muốn giới thiệu cực kỳ đơn giản vì lợi ích của câu hỏi này.

Router:

router = routers.SimpleRouter(trailing_slash=False) 
router.register(r'myobjects', MyObjectViewSet, base_name='myobjects') 
urlpatterns = router.urls 

ViewSet

class MyObjectsViewSet(viewsets.ViewSet): 
""" Provides API Methods to manage MyObjects. """ 

def list(self, request): 
    """ Returns a list of MyObjects. """ 
    data = get_list_of_myobjects() 
    return Response(data) 

def retrieve(self, request, pk): 
    """ Returns a single MyObject. """ 
    data = fetch_my_object(pk) 
    return Response(data) 

def destroy(self, request, pk): 
    """ Deletes a single MyObject. """ 
    fetch_my_object_and_delete(pk) 
      return Response() 

Một ví dụ về một loại phương pháp tôi cần phải bao gồm. (Có nhiều trong số này):

def get_locations(self, request): 
    """ Returns a list of location objects somehow related to MyObject """ 
    locations = calculate_something() 
    return Response(locations) 

Kết quả cuối cùng là URL sau sẽ hoạt động chính xác và được triển khai 'sạch'.

GET example.com/myobjects/123/locations 

Trả lời

23

Số answer given by mariodev ở trên là chính xác, miễn là bạn chỉ đang tìm kiếm các yêu cầu GET.

Nếu bạn muốn POST đến một chức năng bạn đang phụ thêm vào một ViewSet, bạn cần phải sử dụng action trang trí:

from rest_framework.decorators import action, link 
from rest_framework.response import Response 

class MyObjectsViewSet(viewsets.ViewSet): 

    # For GET Requests 
    @link() 
    def get_locations(self, request): 
     """ Returns a list of location objects somehow related to MyObject """ 
     locations = calculate_something() 
     return Response(locations) 

    # For POST Requests 
    @action() 
    def update_location(self, request, pk): 
     """ Updates the object identified by the pk """ 
     location = self.get_object() 
     location.field = update_location_field() # your custom code 
     location.save() 

     # ...create a serializer and return with updated data... 

Sau đó, bạn sẽ POST đến một URL được định dạng như: /myobjects/123/update_location/

http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing có thêm thông tin nếu bạn quan tâm!

+1

tôi đang cố gắng tải tệp lên một phương thức tùy chỉnh. bạn có biết làm thế nào tôi có thể đạt được điều đó? – psychok7

+7

Có '@ action' không được chấp nhận - Liên kết đề xuất các phương thức làm đối số cho trang trí' @ detail_route'. – rtindru

8

Bạn xác định phương pháp như bạn làm bây giờ, nhưng bạn cần phải sử dụng url giống như tên phương pháp và thêm liên kết trang trí, vì vậy cho

/myobjects/123/locations/ 

Bạn thêm phương pháp như thế này

@link(permission_classes=[...]) 
def locations(self, request, pk=None): 
    ... 

và bộ định tuyến sẽ tự động chọn nó.

+1

câu trả lời nhanh và rất chính xác. Điều duy nhất tôi sẽ thêm là "từ liên kết nhập khẩu rest_framework.decorators". Cảm ơn! – Kurtis

+0

Nếu có thể, bạn có thể (hoặc bất kỳ ai) cũng chỉ cho tôi một ví dụ về việc thêm phương thức vào Bộ định tuyến không được 'chứa' trong ViewSet của tôi không? – Kurtis

3

Từ Routing to extra methods on a ViewSet:

Tôi nghĩ rằng bạn có thể cần phải tuyến đường phương pháp này bằng tay, ví dụ: The Old-Fashioned Way ™.

Đầu kéo phương pháp hiện như một cái nhìn riêng biệt:

set_password_view = UserViewSet.as_view({'post': 'set_password'}) 

(hoặc như vậy)

Sau đó gán URL của bạn:

url(r'^users/username_available/$', set_password_view, name-=...) 

(Hoặc ví dụ)

Có một số related question on SO.

14

Bây giờ bạn có thể làm điều này với list_route và trang trí detail_route: http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing

Ví dụ:

from rest_framework.decorators import list_route 
from rest_framework.response import Response 
... 

class MyObjectsViewSet(viewsets.ViewSet): 
    ... 

    @list_route() 
    def locations(self, request): 
     queryset = get_locations() 
     serializer = LocationSerializer(queryset, many=True) 
     return Response(serializer.data) 
+0

Hi im mới với django, điều gì sẽ là điểm kết thúc cho việc này? cảm ơn! –

+0

@ ShiftN'Tab Nếu bạn có 'myobjects-list' và' myobjects-detail', thì đây sẽ là 'myobjects-locations'. – cezar

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