Skip to content

Commit 31f6d16

Browse files
committed
add __acall__
1 parent d76bfe6 commit 31f6d16

File tree

3 files changed

+39
-10
lines changed

3 files changed

+39
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 6.7.5 - 2025-09-16
2+
3+
- feat: Django middleware now supports async request handling.
4+
15
# 6.7.4 - 2025-09-05
26

37
- fix: Missing system prompts for some providers

posthog/integrations/django.py

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
from typing import TYPE_CHECKING, cast
2-
from posthog import contexts, capture_exception
2+
from posthog import contexts
33
from posthog.client import Client
44

5+
try:
6+
from asgiref.sync import iscoroutinefunction
7+
except ImportError:
8+
# Fallback for older Django versions
9+
import asyncio
10+
11+
iscoroutinefunction = asyncio.iscoroutinefunction
12+
513
if TYPE_CHECKING:
614
from django.http import HttpRequest, HttpResponse # noqa: F401
715
from typing import Callable, Dict, Any, Optional # noqa: F401
@@ -33,9 +41,14 @@ class PosthogContextMiddleware:
3341
frontend. See the documentation for `set_context_session` and `identify_context` for more details.
3442
"""
3543

44+
# Django middleware capability flags
45+
sync_capable = True
46+
async_capable = True
47+
3648
def __init__(self, get_response):
3749
# type: (Callable[[HttpRequest], HttpResponse]) -> None
3850
self.get_response = get_response
51+
self._is_coroutine = iscoroutinefunction(get_response)
3952

4053
from django.conf import settings
4154

@@ -159,6 +172,13 @@ def extract_request_user(self, request):
159172

160173
def __call__(self, request):
161174
# type: (HttpRequest) -> HttpResponse
175+
# Purely defensive around django's internal sync/async handling - this should be unreachable, but if it's reached, we may
176+
# as well return something semi-meaningful
177+
if self._is_coroutine:
178+
raise RuntimeError(
179+
"PosthogContextMiddleware received sync call but get_response is async"
180+
)
181+
162182
if self.request_filter and not self.request_filter(request):
163183
return self.get_response(request)
164184

@@ -168,14 +188,19 @@ def __call__(self, request):
168188

169189
return self.get_response(request)
170190

171-
def process_exception(self, request, exception):
191+
async def __acall__(self, request):
192+
# type: (HttpRequest) -> HttpResponse
172193
if self.request_filter and not self.request_filter(request):
173-
return
194+
if self._is_coroutine:
195+
return await self.get_response(request) # type: ignore
196+
else:
197+
return self.get_response(request) # type: ignore
174198

175-
if not self.capture_exceptions:
176-
return
199+
with contexts.new_context(self.capture_exceptions, client=self.client):
200+
for k, v in self.extract_tags(request).items():
201+
contexts.tag(k, v)
177202

178-
if self.client:
179-
self.client.capture_exception(exception)
180-
else:
181-
capture_exception(exception)
203+
if self._is_coroutine:
204+
return await self.get_response(request) # type: ignore
205+
else:
206+
return self.get_response(request) # type: ignore

posthog/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION = "6.7.4"
1+
VERSION = "6.7.5"
22

33
if __name__ == "__main__":
44
print(VERSION, end="") # noqa: T201

0 commit comments

Comments
 (0)