#35083: @method_decorator and iscoroutinefunction() fail to interact properly on
async views
-----------------------------------------+------------------------
Reporter: Drew Winstel | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 5.0
Severity: Normal | Keywords: async
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
I first discovered this while trying to enforce a CSRF cookie on a
subclass of the [standard strawberry GraphQL
view](https://strawberry.rocks/docs/integrations/django), but I was able
to replicate this using exclusively plain Django code:
When trying to use a `@method_decorator` to enforce a CSRF cookie on a
parent class's method, the `iscoroutinefunction` logic appears to
incorrectly detect that the decorated view is indeed async
(https://github.com/django/django/blob/74f7deec9e334a69bfbfdd068285618534198bd5/django/utils/decorators.py#L162-L192),
leading to an exception: `AttributeError: 'coroutine' object has no
attribute 'set_cookie'`
Steps to replicate:
1. Create a simple project with the below views and URLs.
2. GET `/view1/` and observe that you see "hi" in the response
3. GET `/view2/` and observe the above attribute error
Expected behavior:
- Steps 2 and 3 return identical results
{{{
# views.py
from typing import Any
from django.http.request import HttpRequest
from django.http.response import HttpResponse
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import ensure_csrf_cookie
class View1(View):
@method_decorator(ensure_csrf_cookie)
async def dispatch(
self, request: HttpRequest, *args: Any, **kwargs: Any
) -> HttpResponse:
return await super().dispatch(request, *args, **kwargs)
async def get(self, request: HttpRequest):
return HttpResponse("hi")
@method_decorator(ensure_csrf_cookie, name="dispatch")
class View2(View1):
pass
}}}
{{{
# urls.py
import views
# snip
urlpatterns += [
path("/view1/", views.View1.as_view()),
path("/view2/", view.View2.as_view()),
]
}}}
Thanks!
--
Ticket URL: <https://code.djangoproject.com/ticket/35083>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018ccfb9df6a-acabe343-cad2-41f7-87cd-a734ded33217-000000%40eu-central-1.amazonses.com.