Merge pull request #14341 from GeekMasher/py-django-restframework

Python - Add support for RestFramework ModelViewSet functions
This commit is contained in:
Rasmus Wriedt Larsen 2023-10-02 10:50:11 +02:00 коммит произвёл GitHub
Родитель 0dd3837c31 3162033d56
Коммит e7384da162
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 59 добавлений и 22 удалений

Просмотреть файл

@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Django Rest Framework better handles custom `ModelViewSet` classes functions

Просмотреть файл

@ -131,7 +131,10 @@ private module RestFramework {
"initial", "http_method_not_allowed", "permission_denied", "throttled",
"get_authenticate_header", "perform_content_negotiation", "perform_authentication",
"check_permissions", "check_object_permissions", "check_throttles", "determine_version",
"initialize_request", "finalize_response", "dispatch", "options"
"initialize_request", "finalize_response", "dispatch", "options",
// ModelViewSet
// https://github.com/encode/django-rest-framework/blob/master/rest_framework/viewsets.py
"create", "retrieve", "update", "partial_update", "destroy", "list"
]
}
}

Просмотреть файл

@ -1,2 +1,2 @@
failures
testFailures
failures

Просмотреть файл

@ -1,2 +1,8 @@
import python
import experimental.meta.ConceptsTest
class DedicatedTest extends DedicatedResponseTest {
DedicatedTest() { this = "response_test.py" }
override predicate isDedicatedFile(File file) { file.getShortName() = this }
}

Просмотреть файл

@ -0,0 +1 @@
semmle-extractor-options: --max-import-depth=1 -r testapp

Просмотреть файл

@ -81,7 +81,7 @@ def test_taint(request: Request, routed_param): # $ requestHandler routedParamet
)
ensure_not_tainted(request.user.password)
return Response("ok") # $ HttpResponse responseBody="ok"
return Response("ok") # $ HttpResponse
# class based view
@ -105,7 +105,7 @@ class MyClass(APIView):
# same as for standard Django view
ensure_tainted(self.args, self.kwargs) # $ tainted
return Response("ok") # $ HttpResponse responseBody="ok"
return Response("ok") # $ HttpResponse

Просмотреть файл

@ -9,10 +9,11 @@ router.register(r"foos", views.FooViewSet)
router.register(r"bars", views.BarViewSet)
urlpatterns = [
path("", include(router.urls)),
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
path("class-based-view/", views.MyClass.as_view()), # $routeSetup="lcass-based-view/"
path("function-based-view/", views.function_based_view), # $routeSetup="function-based-view/"
path("cookie-test/", views.cookie_test), # $routeSetup="function-based-view/"
path("exception-test/", views.exception_test), # $routeSetup="exception-test/"
path("", include(router.urls)), # $ routeSetup=""
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")), # $ routeSetup="api-auth/"
path("class-based-view/", views.MyClass.as_view()), # $ routeSetup="class-based-view/"
path("function-based-view/", views.function_based_view), # $ routeSetup="function-based-view/"
path("cookie-test/", views.cookie_test), # $ routeSetup="cookie-test/"
path("exception-test/", views.exception_test), # $ routeSetup="exception-test/"
path("viewset-entrypoints-test/", views.EntrypointViewSet.as_view()) # $ routeSetup="viewset-entrypoints-test/"
]

Просмотреть файл

@ -19,19 +19,41 @@ class BarViewSet(viewsets.ModelViewSet):
queryset = Bar.objects.all()
serializer_class = BarSerializer
class EntrypointViewSet(viewsets.ModelViewSet):
queryset = Bar.objects.all()
serializer_class = BarSerializer
def create(self, request, *args, **kwargs): # $ requestHandler
return Response("create") # $ HttpResponse
def retrieve(self, request, *args, **kwargs): # $ requestHandler
return Response("retrieve") # $ HttpResponse
def update(self, request, *args, **kwargs): # $ requestHandler
return Response("update") # $ HttpResponse
def partial_update(self, request, *args, **kwargs): # $ requestHandler
return Response("partial_update") # $ HttpResponse
def destroy(self, request, *args, **kwargs): # $ requestHandler
return Response("destroy") # $ HttpResponse
def list(self, request, *args, **kwargs): # $ requestHandler
return Response("list") # $ HttpResponse
# class based view
# see https://www.django-rest-framework.org/api-guide/views/#class-based-views
class MyClass(APIView):
def initial(self, request, *args, **kwargs):
def initial(self, request, *args, **kwargs): # $ requestHandler
# this method will be called before processing any request
super().initial(request, *args, **kwargs)
def get(self, request):
return Response("GET request")
def get(self, request): # $ requestHandler
return Response("GET request") # $ HttpResponse
def post(self, request):
return Response("POST request")
def post(self, request): # $ requestHandler
return Response("POST request") # $ HttpResponse
# function based view
@ -39,21 +61,21 @@ class MyClass(APIView):
@api_view(["GET", "POST"])
def function_based_view(request: Request):
return Response({"message": "Hello, world!"})
def function_based_view(request: Request): # $ requestHandler
return Response({"message": "Hello, world!"}) # $ HttpResponse
@api_view(["GET", "POST"])
def cookie_test(request: Request):
resp = Response("wat")
def cookie_test(request: Request): # $ requestHandler
resp = Response("wat") # $ HttpResponse
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
resp.set_cookie(key="key4", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
resp.set_cookie(key="key4", value="value") # $ CookieWrite CookieName="key4" CookieValue="value"
resp.headers["Set-Cookie"] = "key2=value2" # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
resp.cookies["key3"] = "value3" # $ CookieWrite CookieName="key3" CookieValue="value3"
return resp
@api_view(["GET", "POST"])
def exception_test(request: Request):
def exception_test(request: Request): # $ requestHandler
# see https://www.django-rest-framework.org/api-guide/exceptions/
# note: `code details` not exposed by default
raise APIException("exception details", "code details")
raise APIException("exception details", "code details") # $ HttpResponse