2015-08-28 85 views
3

我有一個像ViewSetDjango的REST框架@detail_route yeilds 404

class CustomerViewSet(ModelViewSet): 
    queryset = models.Customer.objects.all() 
    serializer_class = serializers.CustomerSerializer 
    filter_class = filters.CustomerFilterSet 

    @detail_route 
    def licenses(self, request, pk=None): 
     customer = self.get_object() 
     licenses = Item.objects.active().sold().for_customer(customer) 
     serializer = serializers.ItemSerializer(licenses, many=True) 
     return Response(serializer.data) 

urls.pyrouter.register(r'customers', views.CustomerViewSet)

我可以GET /api/customersGET /api/customers/1000,但GET /api/customers/1000/licenses找不到。它給我404。流程永遠不會進入licenses方法。

我在這裏看到類似的問題,但他們使用了不正確的簽名,我不:def licenses(self, request, pk=None)

python 3.4.0 
djangorestframework==3.2.3 

編輯:詢問後再次,我發現我的回答不到一分鐘... Apparantly裝飾者需要像@detail_route()這樣的圓括號。我認爲這些總是可選的......?

+1

不,沒有圓括號的約定。裝飾者實際上只是可調用的,它接受函數作爲它的參數。所以'detail_route'是返回可調用的函數。 – beezz

+0

我找到了一個解釋,詳細說明了如何在我的示例中對包裝器進行雙重包裝,以便兩種形式都將得到支持。很高興知道這不是一種語言慣例,而是由開發者決定 – Eldamir

回答

-2

默認情況下,路由器將追加斜槓添加到URL。因此,GET /api/customers/將工作,而不是GET /api/customers。如果您不想使用尾部斜槓,則可以將trailing_slash = False傳遞給路由器初始化程序。

E.g.-

router = DefaultRouter(trailing_slash = False) 
router.register(r'customers', views.CustomerViewSet) 

如果不工作,那麼,這是您要導入路由器網址,進入主URL的方式有問題。

+0

由於您的兩個行爲都能正常工作,因此與問題無關。 'GET/api/customers'只會301到'GET/api/customers /' – Eldamir

1

對於post請求,您需要指定方法,因爲detail_route裝飾器將默認路由get請求。 像這樣:@detail_route(methods=['POST'])