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