#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 django-updates+unsubscr...@googlegroups.com.
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.

Reply via email to