Repository: getsentry/sentry-python

Issue:
sync_and_async_middleware throws exception
Which SDK and version?
sentry_sdk==0.20.0
uvicorn==0.13.3
gunicorn==20.0.4
django==3.1.6

### Steps to Reproduce

copy the middleware example from django [docs](https://docs.djangoproject.com/en/dev/topics/http/middleware/#asynchronous-support):
```
import asyncio
from django.utils.decorators import sync_and_async_middleware

@sync_and_async_middleware
def simple_middleware(get_response):
    # One-time configuration and initialization goes here.
    if asyncio.iscoroutinefunction(get_response):
        async def middleware(request):
            # Do something here!
            response = await get_response(request)
            return response

    else:
        def middleware(request):
            # Do something here!
            response = get_response(request)
            return response

    return middleware
```
Run django async
```
uvicorn.run(
        "apps.asgi:application",
        host="0.0.0.0", port=8000, lifespan='off', loop='asyncio', reload=True,
        ...
    )
```

### Actual Result
```
...
File "/usr/local/lib/python3.8/dist-packages/sentry_sdk/integrations/django/asgi.py
Exception Value: 'function' object has no attribute '__acall__'
```

The problem is, that the decorator style has no `__acall__` and the middleware is a function (not a class)

No problems in 0.19.x
This bug was introduced with this PR https://github.com/getsentry/sentry-python/pull/992


Discussion:
Hey @Speedy1991 Thanks for opening this issue
Looking into it 

Resolving patch:
diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py
--- a/sentry_sdk/integrations/django/asgi.py
+++ b/sentry_sdk/integrations/django/asgi.py
@@ -104,6 +104,9 @@ def _asgi_middleware_mixin_factory(_check_middleware_span):
     """
 
     class SentryASGIMixin:
+        if MYPY:
+            _inner = None
+
         def __init__(self, get_response):
             # type: (Callable[..., Any]) -> None
             self.get_response = get_response
@@ -132,7 +135,10 @@ async def __acall__(self, *args, **kwargs):
             # type: (*Any, **Any) -> Any
             f = self._acall_method
             if f is None:
-                self._acall_method = f = self._inner.__acall__  # type: ignore
+                if hasattr(self._inner, "__acall__"):
+                    self._acall_method = f = self._inner.__acall__  # type: ignore
+                else:
+                    self._acall_method = f = self._inner
 
             middleware_span = _check_middleware_span(old_method=f)
 


Test patch:
diff --git a/tests/integrations/django/asgi/test_asgi.py b/tests/integrations/django/asgi/test_asgi.py
--- a/tests/integrations/django/asgi/test_asgi.py
+++ b/tests/integrations/django/asgi/test_asgi.py
@@ -103,6 +103,43 @@ async def test_async_views_concurrent_execution(sentry_init, capture_events, set
     assert end - start < 1.5
 
 
+@pytest.mark.asyncio
+@pytest.mark.skipif(
+    django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1"
+)
+async def test_async_middleware_that_is_function_concurrent_execution(
+    sentry_init, capture_events, settings
+):
+    import asyncio
+    import time
+
+    settings.MIDDLEWARE = [
+        "tests.integrations.django.myapp.middleware.simple_middleware"
+    ]
+    asgi_application.load_middleware(is_async=True)
+
+    sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
+
+    comm = HttpCommunicator(asgi_application, "GET", "/my_async_view")
+    comm2 = HttpCommunicator(asgi_application, "GET", "/my_async_view")
+
+    loop = asyncio.get_event_loop()
+
+    start = time.time()
+
+    r1 = loop.create_task(comm.get_response(timeout=5))
+    r2 = loop.create_task(comm2.get_response(timeout=5))
+
+    (resp1, resp2), _ = await asyncio.wait({r1, r2})
+
+    end = time.time()
+
+    assert resp1.result()["status"] == 200
+    assert resp2.result()["status"] == 200
+
+    assert end - start < 1.5
+
+
 @pytest.mark.asyncio
 @pytest.mark.skipif(
     django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1"
diff --git a/tests/integrations/django/myapp/middleware.py b/tests/integrations/django/myapp/middleware.py
new file mode 100644
--- /dev/null
+++ b/tests/integrations/django/myapp/middleware.py
@@ -0,0 +1,19 @@
+import asyncio
+from django.utils.decorators import sync_and_async_middleware
+
+
+@sync_and_async_middleware
+def simple_middleware(get_response):
+    if asyncio.iscoroutinefunction(get_response):
+
+        async def middleware(request):
+            response = await get_response(request)
+            return response
+
+    else:
+
+        def middleware(request):
+            response = get_response(request)
+            return response
+
+    return middleware