Saya menulis sebuah API menggunakan Django REST Framework dan saya bertanya-tanya jika dapat menentukan izin per metode ketika menggunakan kelas berdasarkan pandangan.
Membaca dokumentasi saya melihat bahwa cukup mudah untuk dilakukan jika anda menulis fungsi berdasarkan pandangan, hanya menggunakan @permission_classes
dekorator alih fungsi dari pandangan anda ingin melindungi dengan izin. Namun, saya don't melihat cara untuk melakukan hal yang sama ketika menggunakan CBVs dengan APIView
kelas, karena itulah aku menentukan hak akses untuk kelas penuh dengan permission_classes
atribut, tapi yang akan diterapkan kemudian untuk semua metode kelas (get
, post
, masukan
...).
Jadi, adalah mungkin untuk memiliki pandangan API tertulis dengan CBVs dan juga menentukan hak akses yang berbeda untuk masing-masing metode melihat kelas?
I've menemukan masalah yang sama ketika menggunakan CBV's, seperti yang telah saya cukup kompleks izin logika tergantung pada permintaan metode.
Solusi saya datang dengan adalah untuk menggunakan pihak ketiga 'rest_condition' aplikasi yang tercantum di bagian bawah halaman ini
http://www.django-rest-framework.org/api-guide/permissions
https://github.com/caxap/rest_condition
Aku hanya membagi izin aliran logika sehingga masing-masing cabang akan berjalan, tergantung pada permintaan metode.
from rest_condition import And, Or, Not
class MyClassBasedView(APIView):
permission_classes = [Or(And(IsReadOnlyRequest, IsAllowedRetrieveThis, IsAllowedRetrieveThat),
And(IsPostRequest, IsAllowedToCreateThis, ...),
And(IsPutPatchRequest, ...),
And(IsDeleteRequest, ...)]
Jadi 'Atau' menentukan cabang izin yang harus dijalankan tergantung pada permintaan metode dan 'Dan' membungkus izin yang berkaitan dengan diterima metode permintaan, jadi semua harus melewati izin yang akan diberikan. Anda juga dapat mencampur 'Atau', 'Dan' dan 'Tidak' dalam masing-masing aliran untuk membuat bahkan lebih kompleks izin.
Izin kelas untuk menjalankan setiap cabang hanya terlihat seperti ini,
class IsReadyOnlyRequest(permissions.BasePermission):
def has_permission(self, request, view):
return request.method in permissions.SAFE_METHODS
class IsPostRequest(permissions.BasePermission):
def has_permission(self, request, view):
return request.method == "POST"
... #You get the idea
Izin yang diterapkan untuk seluruh kelas, tapi anda bisa memperhitungkan aspek dari permintaan tersebut (seperti metode GET atau POST) dalam keputusan otorisasi.
Lihat built-in IsAuthenticatedOrReadOnly
sebagai contoh:
SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS']
class IsAuthenticatedOrReadOnly(BasePermission):
"""
The request is authenticated as a user, or is a read-only request.
"""
def has_permission(self, request, view):
if (request.method in SAFE_METHODS or
request.user and
request.user.is_authenticated()):
return True
return False
Aku berlari ke dalam masalah ini dan benar-benar ingin menggunakan @permission_classes
dekorator untuk menandai beberapa tampilan kustom metode dengan izin khusus. Saya akhirnya datang dengan mixin:
class PermissionsPerMethodMixin(object):
def get_permissions(self):
"""
Allows overriding default permissions with @permission_classes
"""
view = getattr(self, self.action)
if hasattr(view, 'permission_classes'):
return [permission_class() for permission_class in view.permission_classes]
return super().get_permissions()
Contoh kasus penggunaan:
from rest_framework.decorators import action, permission_classes # other imports elided
class MyViewset(PermissionsPerMethodMixin, viewsets.ModelViewSet):
permission_classes = (IsAuthenticatedOrReadOnly,) # used for default ViewSet endpoints
queryset = MyModel.objects.all()
serializer_class = MySerializer
@action(detail=False, methods=['get'])
@permission_classes((IsAuthenticated,)) # overrides IsAuthenticatedOrReadOnly
def search(self, request):
return do_search(request) # ...
Saya tahu ini adalah pertanyaan lama tapi aku baru saja berlari ke dalam masalah yang sama dan ingin berbagi solusi saya (sejak diterima jawaban itu't cukup apa yang saya butuhkan). @GDorn's jawaban menempatkan saya pada jalur yang benar, tetapi hanya bekerja dengan ViewSet karena
diri.aksi`
I've dipecahkan itu membuat saya sendiri dekorator:
python def method_permission_classes(kelas): def dekorator(func): def decorated_func(mandiri, *args, **kwargs): mandiri.permission_classes = kelas kembali func(mandiri, *args, **kwargs) kembali decorated_func kembali dekorator
Bukan menetapkan permission_classes
properti pada fungsi, seperti built-in dekorator tidak, saya dekorator membungkus memanggil dan menetapkan izin kelas pada melihat contoh yang dipanggil. Dengan cara ini, normal get_permissions()
doesn't membutuhkan perubahan, karena itu hanya bergantung pada diri.permission_classes
.
Contoh kasus penggunaan:
``python dari rest_framework impor pandangan, izin
kelas MyView(pandangan.APIView): permission_classes = (permissions.IsAuthenticatedOrReadOnly,) # digunakan untuk default APIView endpoint queryset = MyModel.benda-benda.semua() serializer_class = MySerializer
@method_permission_classes((permissions.IsAdminUser,)) # menimpa IsAuthenticatedOrReadOnly def menghapus(mandiri, permintaan, id): contoh = self.get_object() # ... ``
Semoga ini bisa membantu seseorang menjalankan ke dalam masalah yang sama!