185 lines
6 KiB
Python
185 lines
6 KiB
Python
"""
|
|
Interface d'administration pour les modèles Analytics.
|
|
"""
|
|
|
|
from django.contrib import admin
|
|
from django.utils.html import format_html
|
|
from django.urls import reverse
|
|
from django.utils.translation import gettext_lazy as _
|
|
from .models import PageView, UserSession, DailyPageViewSummary
|
|
|
|
|
|
@admin.register(PageView)
|
|
class PageViewAdmin(admin.ModelAdmin):
|
|
"""Interface d'administration pour les vues de pages."""
|
|
|
|
list_display = [
|
|
'timestamp', 'user_link', 'path', 'method',
|
|
'response_time_colored', 'ip_address'
|
|
]
|
|
list_filter = [
|
|
'method', 'timestamp',
|
|
('user', admin.RelatedOnlyFieldListFilter),
|
|
]
|
|
search_fields = ['path', 'user__username', 'ip_address', 'full_url']
|
|
readonly_fields = [
|
|
'user', 'session_key', 'path', 'full_url', 'method',
|
|
'timestamp', 'ip_address', 'user_agent', 'referer', 'response_time_ms'
|
|
]
|
|
date_hierarchy = 'timestamp'
|
|
ordering = ['-timestamp']
|
|
|
|
# Pagination
|
|
list_per_page = 50
|
|
|
|
def user_link(self, obj):
|
|
"""Lien vers la page de l'utilisateur."""
|
|
if obj.user:
|
|
url = reverse('admin:auth_user_change', args=[obj.user.id])
|
|
return format_html('<a href="{}">{}</a>', url, obj.user.username)
|
|
return _("Anonyme")
|
|
user_link.short_description = _("Utilisateur")
|
|
|
|
def response_time_colored(self, obj):
|
|
"""Affiche le temps de réponse avec une couleur selon la performance."""
|
|
if obj.response_time_ms is None:
|
|
return '-'
|
|
|
|
# Définir les seuils de couleur
|
|
if obj.response_time_ms < 100:
|
|
color = 'green'
|
|
elif obj.response_time_ms < 500:
|
|
color = 'orange'
|
|
else:
|
|
color = 'red'
|
|
|
|
return format_html(
|
|
'<span style="color: {}; font-weight: bold;">{} ms</span>',
|
|
color,
|
|
obj.response_time_ms
|
|
)
|
|
response_time_colored.short_description = _("Temps de réponse")
|
|
response_time_colored.admin_order_field = 'response_time_ms'
|
|
|
|
def has_add_permission(self, request):
|
|
"""Désactiver l'ajout manuel."""
|
|
return False
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
"""Désactiver la modification."""
|
|
return False
|
|
|
|
|
|
@admin.register(UserSession)
|
|
class UserSessionAdmin(admin.ModelAdmin):
|
|
"""Interface d'administration pour les sessions utilisateurs."""
|
|
|
|
list_display = [
|
|
'login_time', 'user_link', 'duration_formatted',
|
|
'page_views_count', 'status_colored', 'ip_address'
|
|
]
|
|
list_filter = [
|
|
'is_active', 'login_time',
|
|
('user', admin.RelatedOnlyFieldListFilter),
|
|
]
|
|
search_fields = ['user__username', 'session_key', 'ip_address']
|
|
readonly_fields = [
|
|
'user', 'session_key', 'login_time', 'last_activity',
|
|
'logout_time', 'ip_address', 'user_agent', 'page_views_count',
|
|
'is_active', 'duration_formatted'
|
|
]
|
|
date_hierarchy = 'login_time'
|
|
ordering = ['-login_time']
|
|
|
|
# Pagination
|
|
list_per_page = 50
|
|
|
|
def user_link(self, obj):
|
|
"""Lien vers la page de l'utilisateur."""
|
|
url = reverse('admin:auth_user_change', args=[obj.user.id])
|
|
return format_html('<a href="{}">{}</a>', url, obj.user.username)
|
|
user_link.short_description = _("Utilisateur")
|
|
|
|
def status_colored(self, obj):
|
|
"""Affiche le statut avec une couleur."""
|
|
if obj.is_active:
|
|
return format_html(
|
|
'<span style="color: green; font-weight: bold;">● {}</span>',
|
|
_("Active")
|
|
)
|
|
else:
|
|
return format_html(
|
|
'<span style="color: gray;">○ {}</span>',
|
|
_("Terminée")
|
|
)
|
|
status_colored.short_description = _("Statut")
|
|
status_colored.admin_order_field = 'is_active'
|
|
|
|
def duration_formatted(self, obj):
|
|
"""Affiche la durée de la session formatée."""
|
|
seconds = obj.duration_seconds
|
|
if seconds < 60:
|
|
return f"{int(seconds)}s"
|
|
elif seconds < 3600:
|
|
minutes = int(seconds / 60)
|
|
return f"{minutes}min"
|
|
else:
|
|
hours = int(seconds / 3600)
|
|
minutes = int((seconds % 3600) / 60)
|
|
return f"{hours}h {minutes}min"
|
|
duration_formatted.short_description = _("Durée")
|
|
|
|
def has_add_permission(self, request):
|
|
"""Désactiver l'ajout manuel."""
|
|
return False
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
"""Désactiver la modification."""
|
|
return False
|
|
|
|
|
|
@admin.register(DailyPageViewSummary)
|
|
class DailyPageViewSummaryAdmin(admin.ModelAdmin):
|
|
"""Interface d'administration pour les résumés quotidiens."""
|
|
|
|
list_display = [
|
|
'date', 'total_page_views', 'unique_users',
|
|
'unique_sessions', 'total_sessions_started',
|
|
'avg_response_colored',
|
|
]
|
|
list_filter = ['date']
|
|
search_fields = ['date']
|
|
readonly_fields = [
|
|
'date', 'total_page_views', 'unique_users', 'unique_sessions',
|
|
'unique_ips', 'avg_response_time_ms', 'max_response_time_ms',
|
|
'top_paths', 'top_users', 'method_counts',
|
|
'total_sessions_started', 'created_at', 'updated_at',
|
|
]
|
|
date_hierarchy = 'date'
|
|
ordering = ['-date']
|
|
list_per_page = 50
|
|
|
|
def avg_response_colored(self, obj):
|
|
"""Affiche le temps de réponse moyen avec couleur."""
|
|
if obj.avg_response_time_ms is None:
|
|
return '-'
|
|
val = obj.avg_response_time_ms
|
|
if val < 100:
|
|
color = 'green'
|
|
elif val < 500:
|
|
color = 'orange'
|
|
else:
|
|
color = 'red'
|
|
return format_html(
|
|
'<span style="color: {}; font-weight: bold;">{} ms</span>',
|
|
color,
|
|
f'{val:.0f}',
|
|
)
|
|
avg_response_colored.short_description = _("Temps de rép. moyen")
|
|
avg_response_colored.admin_order_field = 'avg_response_time_ms'
|
|
|
|
def has_add_permission(self, request):
|
|
return False
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return False
|