#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.

Reply via email to