ปิดใช้งานเมธอดใน ViewSet, django-rest-framework


125

ViewSets มีวิธีการอัตโนมัติในการแสดงรายการเรียกค้นสร้างอัปเดตลบ ...

ฉันต้องการปิดการใช้งานบางส่วนและวิธีแก้ปัญหาที่ฉันคิดขึ้นมานั้นอาจไม่ใช่วิธีที่ดีนักเนื่องจากOPTIONSยังคงระบุว่าได้รับอนุญาต

มีความคิดเกี่ยวกับวิธีการทำอย่างไรให้ถูกต้อง?

class SampleViewSet(viewsets.ModelViewSet):
    queryset = api_models.Sample.objects.all()
    serializer_class = api_serializers.SampleSerializer

    def list(self, request):
        return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
    def create(self, request):
        return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)

คำตอบ:


250

คำจำกัดความของModelViewSetคือ:

class ModelViewSet(mixins.CreateModelMixin, 
                   mixins.RetrieveModelMixin, 
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet)

ดังนั้นแทนที่จะขยายModelViewSetทำไมไม่ใช้อะไรก็ได้ที่คุณต้องการล่ะ ตัวอย่างเช่น:

from rest_framework import viewsets, mixins

class SampleViewSet(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    viewsets.GenericViewSet):
    ...

ด้วยวิธีนี้เราเตอร์ควรสร้างเส้นทางสำหรับวิธีการที่รวมไว้เท่านั้น

อ้างอิง :

ModelViewSet


@SunnySydeUp ลองตอนนี้ดูเหมือนว่าเราเตอร์จะสร้างเส้นทางสำหรับมุมมองรายการ แต่เป็น 404 เนื่องจาก ViewSet ไม่ทราบวิธีจัดการกับคำขอ นี่คือสิ่งที่คุณคาดหวังหรือไม่?
Steve Jalim

3
คุณสามารถปิดการใช้งาน GET, POST, PUT, DELETE Methods ได้โดยใช้เฉพาะ mixins เท่านั้น แต่ฉันไม่พบวิธีปิดใช้งานเมธอด PATCH โดยเฉพาะหากคุณใช้เราเตอร์
Muneeb Ahmad

3
@MuneebAhmad เมธอด PATCH ถูกเปิดใช้งานจากไฟล์UpdateModelMixin. หากคุณต้องการใช้การอัปเดต แต่ไม่ใช่แพตช์ตอนนี้ฉันสามารถคิดได้สองวิธี คุณสามารถลบล้างเมธอดที่อนุญาตในมุมมองและลบ "แพตช์" หรือคุณสามารถแทนที่partial_updateเมธอดและเรียกhttp_method_not_allowed(request, *args, **kwargs)ใช้ ฉันยังไม่ได้ทดสอบดังนั้นฉันไม่แน่ใจว่ามันได้ผลหรือไม่
SunnySydeUp

1
@JulioMarins ฉันได้เพิ่มข้อมูลอ้างอิงแล้ว ฉันไม่แน่ใจว่านี่คือสิ่งที่คุณต้องการหรือไม่
SunnySydeUp

1
หากมีคนต้องการสร้าง viewset แบบอ่านอย่างเดียวก็สามารถclass SampleViewSet(viewsets.ReadOnlyModelViewSet)ใช้ได้
Bikash kharel

133

คุณสามารถใช้viewsets.ModelViewSetและกำหนดhttp_method_namesบน ViewSet ของคุณได้

ตัวอย่าง

class SampleViewSet(viewsets.ModelViewSet):
    queryset = api_models.Sample.objects.all()
    serializer_class = api_serializers.SampleSerializer
    http_method_names = ['get', 'post', 'head']

เมื่อคุณเพิ่มhttp_method_namesคุณจะไม่สามารถที่จะทำputและpatchอีกต่อไป

หากคุณต้องการputแต่ไม่ต้องการpatchคุณสามารถเก็บไว้ได้http_method_names = ['get', 'post', 'head', 'put']

ภายใน DRF Views ขยายจาก Django CBV Django CBV มีแอตทริบิวต์ที่เรียกว่า http_method_names คุณจึงสามารถใช้ http_method_names กับมุมมอง DRF ได้เช่นกัน

[หน้าด้านเสียบ]: ถ้าคำตอบนี้เป็นประโยชน์คุณจะชอบชุดของฉันโพสต์ใน DRF ที่https://www.agiliq.com/blog/2019/04/drf-polls/


16
ปัญหาเกี่ยวกับวิธีนี้คือไม่มีวิธีปิดการใช้งานรายการหรือดึงข้อมูล ต้องปิดการใช้งานทั้งสองอย่างหรือไม่
Fuad

1
สิ่งนี้ไม่ได้ผลสำหรับฉันหลังจากรวมการรับและหัวฉันก็ยังสามารถโพสต์ได้
RunLoop

สิ่งนี้ใช้ได้กับฉันใน django 1.9 ทางออกที่ดี มีความเสี่ยงที่ผู้ใช้สามารถขอ GET ด้วยวิธีอื่นได้หรือไม่?
Ycon

โซลูชันที่ยอดเยี่ยม ใช้งานได้python3และDjango 1.10ดี
Urda

2
ฉันชอบแนวทางนี้เพราะฉันไม่สามารถเปลี่ยนการสืบทอดของมิกซ์อินเพื่อรวม PATCH ได้ แต่ไม่สามารถใส่ได้เนื่องจากทั้งคู่เป็นการใช้งาน mixins.UpdateModelMixin
ThatsAMorais

5

แม้ว่าจะใช้เวลาสักพักแล้วสำหรับโพสต์นี้ แต่ฉันก็พบว่าจริงๆแล้วมันเป็นวิธีปิดการใช้งานฟังก์ชันเหล่านั้นคุณสามารถแก้ไขได้ใน views.py โดยตรง

ที่มา: https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions

from rest_framework import viewsets, status
from rest_framework.response import Response

class NameWhateverYouWantViewSet(viewsets.ModelViewSet):

    def create(self, request):
        response = {'message': 'Create function is not offered in this path.'}
        return Response(response, status=status.HTTP_403_FORBIDDEN)

    def update(self, request, pk=None):
        response = {'message': 'Update function is not offered in this path.'}
        return Response(response, status=status.HTTP_403_FORBIDDEN)

    def partial_update(self, request, pk=None):
        response = {'message': 'Update function is not offered in this path.'}
        return Response(response, status=status.HTTP_403_FORBIDDEN)

    def destroy(self, request, pk=None):
        response = {'message': 'Delete function is not offered in this path.'}
        return Response(response, status=status.HTTP_403_FORBIDDEN)

นี่ควรเป็นวิธีที่ดีกว่า
ดิจิทัล

ฉันคิดว่า HTTP_400_BAD_REQUEST จะเหมาะสมกว่าที่นี่หากไม่เกี่ยวข้องกับการตรวจสอบสิทธิ์
Santiago Magariños

4

หากคุณกำลังพยายามปิดใช้งานเมธอด PUT จากมุมมอง DRF คุณสามารถสร้างเราเตอร์แบบกำหนดเองได้:

from rest_framework.routers import DefaultRouter

class NoPutRouter(DefaultRouter):
    """
    Router class that disables the PUT method.
    """
    def get_method_map(self, viewset, method_map):

        bound_methods = super().get_method_map(viewset, method_map)

        if 'put' in bound_methods.keys():
            del bound_methods['put']

        return bound_methods

เมื่อปิดใช้งานเมธอดที่เราเตอร์เอกสาร api schema ของคุณจะถูกต้อง


เนื่องจากโปรแกรมแก้ไขบางส่วนไม่ได้รับการติดตั้งอย่างถูกต้องภายใน DRF จึงควรนำออกทั่วโลกด้วยวิธีที่อธิบายไว้ที่นี่
oden

1

วิธีปิดการใช้งานเมธอด "DELETE" สำหรับ ViewSet ใน DRF

class YourViewSet(viewsets.ModelViewSet):
    def _allowed_methods(self):
        return [m for m in super(YourViewSet, self)._allowed_methods() if m not in ['DELETE']]

ป.ล. สิ่งนี้มีความน่าเชื่อถือมากกว่าการระบุวิธีการที่จำเป็นทั้งหมดอย่างชัดเจนดังนั้นจึงมีโอกาสน้อยที่จะลืมวิธีการสำคัญบางอย่าง OPTIONS HEAD ฯลฯ

PPS โดยค่าเริ่มต้น DRF มี http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']


คุณไม่สามารถเรียกในระดับชั้นไม่มีsuper self
ต้อง

0

ใน Django Rest Framework 3.xx คุณสามารถเปิดใช้งานทุกวิธีที่คุณต้องการเปิดใช้งานModelViewSetโดยส่งผ่านพจนานุกรมไปยังas_viewวิธีการ ในพจนานุกรมนี้คีย์ต้องมีประเภทคำขอ (GET, POST, DELETE ฯลฯ ) และค่าต้องมีชื่อเมธอดที่เกี่ยวข้อง (รายการดึงข้อมูลอัปเดต ฯลฯ ) ตัวอย่างเช่นสมมติว่าคุณต้องการSampleสร้างหรืออ่านแบบจำลอง แต่คุณไม่ต้องการแก้ไข ดังนั้นก็หมายความว่าคุณต้องการlist, retrieveและcreateวิธีการที่จะเปิดใช้งาน (และคุณต้องการให้คนอื่นเป็นคนพิการ.)

สิ่งที่คุณต้องทำคือเพิ่มเส้นทางที่จะurlpatternsชอบสิ่งเหล่านี้:

path('sample/', SampleViewSet.as_view({
    'get': 'list',
    'post': 'create'
})),
path('sample/<pk>/', SampleViewSet.as_view({  # for get sample by id.
    'get': 'retrieve'
}))

ดังที่คุณเห็นว่าไม่มีdeleteและputคำขอในการตั้งค่าการกำหนดเส้นทางด้านบนตัวอย่างเช่นหากคุณส่งputคำขอไปยัง url จะตอบสนองคุณด้วย 405 Method Not Allowed:

{
    "detail": "Method \"PUT\" not allowed."
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.