- Neues Modell UsageEvent (device_id, Plattform/Browser aus User-Agent serverseitig geparst, Standalone-Flag, Zeitstempel) - komplett anonym, device_id ist eine zufällige, nur lokal im Browser gespeicherte ID - POST /app/track/: nimmt ein Nutzungssignal entgegen (max. 1x pro Gerät/Tag, siehe home01.js: pingUsageIfNeeded()) - GET /app/dashboard/: Übersicht für Admins (staff_member_required, nutzt bestehenden Django-Admin-Login) - Geräte heute/7/30 Tage, Plattform- und Browser-Verteilung, Standalone-Quote, letzte Signale - UsageEvent zusätzlich im normalen Django-Admin registriert - Migration bewusst nicht mitcommittet (Projekt-Konvention, siehe .gitignore) - muss auf jedem Environment einmalig per `manage.py makemigrations app && manage.py migrate` erzeugt werden Lokal getestet: Track-Endpoint, Dashboard-Rendering mit Testdaten, Admin-Login- Schutz (unauthenticated -> 302), Django-Admin-Listing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>main
parent
722eacbee7
commit
6ff0813f6f
@ -1,3 +1,12 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
# Register your models here.
|
from .models import UsageEvent
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(UsageEvent)
|
||||||
|
class UsageEventAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ("device_id", "created_at", "app_version", "platform", "browser", "is_standalone")
|
||||||
|
list_filter = ("platform", "browser", "is_standalone", "app_version")
|
||||||
|
search_fields = ("device_id",)
|
||||||
|
date_hierarchy = "created_at"
|
||||||
|
ordering = ("-created_at",)
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
def parse_user_agent(user_agent):
|
||||||
|
"""Sehr einfache, dependency-freie Grobzuordnung von Plattform/Browser aus dem
|
||||||
|
User-Agent-String - reicht für die Dashboard-Statistik, muss nicht exakt sein."""
|
||||||
|
ua = (user_agent or "").lower()
|
||||||
|
|
||||||
|
if "iphone" in ua or "ipad" in ua or "ipod" in ua:
|
||||||
|
platform = "iOS"
|
||||||
|
elif "android" in ua:
|
||||||
|
platform = "Android"
|
||||||
|
elif "windows" in ua:
|
||||||
|
platform = "Windows"
|
||||||
|
elif "macintosh" in ua or "mac os x" in ua:
|
||||||
|
platform = "macOS"
|
||||||
|
elif "linux" in ua:
|
||||||
|
platform = "Linux"
|
||||||
|
else:
|
||||||
|
platform = "Unbekannt"
|
||||||
|
|
||||||
|
if "edg/" in ua or "edga" in ua or "edgios" in ua:
|
||||||
|
browser = "Edge"
|
||||||
|
elif "opr/" in ua or "opera" in ua:
|
||||||
|
browser = "Opera"
|
||||||
|
elif "firefox" in ua or "fxios" in ua:
|
||||||
|
browser = "Firefox"
|
||||||
|
elif "crios" in ua or "chrome" in ua:
|
||||||
|
browser = "Chrome"
|
||||||
|
elif "safari" in ua:
|
||||||
|
browser = "Safari"
|
||||||
|
else:
|
||||||
|
browser = "Unbekannt"
|
||||||
|
|
||||||
|
return platform, browser
|
||||||
Loading…
Reference in new issue