File size: 4,174 Bytes
fafd0bb |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# ============================================
# apps/analytics/models.py - Analytics & Search Tracking
# ============================================
from django.db import models
from apps.core.models import TimestampMixin
from apps.users.models import User
class SearchLog(TimestampMixin):
"""
Enregistre chaque recherche effectuée sur la plateforme
pour analyser les intérêts et comportements des utilisateurs
"""
CATEGORY_CHOICES = [
('QUESTIONS', 'Questions du Forum'),
('MENTORS', 'Recherche de Mentors'),
('OPPORTUNITIES', 'Opportunités'),
('TOOLS', 'Outils Pédagogiques'),
('USERS', 'Utilisateurs'),
('GENERAL', 'Recherche Générale'),
]
# Qui a effectué la recherche
user = models.ForeignKey(
User,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='search_logs',
help_text="Utilisateur qui a effectué la recherche (null si anonyme)"
)
# Catégorie de la recherche
category = models.CharField(
max_length=20,
choices=CATEGORY_CHOICES,
db_index=True,
help_text="Type de contenu recherché"
)
# Terme de recherche
search_query = models.CharField(
max_length=500,
db_index=True,
help_text="Texte saisi par l'utilisateur"
)
# Filtres appliqués (JSON pour flexibilité)
filters_applied = models.JSONField(
default=dict,
blank=True,
help_text="Filtres appliqués lors de la recherche (ex: {\"status\": \"solved\", \"tags\": [\"math\"]})"
)
# Résultats
results_count = models.IntegerField(
default=0,
help_text="Nombre de résultats retournés"
)
# Métadonnées de session
session_id = models.CharField(
max_length=100,
blank=True,
db_index=True,
help_text="ID de session pour regrouper les recherches d'une même visite"
)
ip_address = models.GenericIPAddressField(
null=True,
blank=True,
help_text="Adresse IP de l'utilisateur"
)
user_agent = models.TextField(
blank=True,
help_text="User agent du navigateur"
)
# Page d'origine
page_url = models.CharField(
max_length=500,
blank=True,
help_text="URL de la page où la recherche a été effectuée"
)
# Interaction
clicked_result_id = models.CharField(
max_length=100,
null=True,
blank=True,
help_text="ID du résultat cliqué (si applicable)"
)
clicked_result_position = models.IntegerField(
null=True,
blank=True,
help_text="Position du résultat cliqué dans la liste"
)
class Meta:
db_table = 'search_logs'
verbose_name = 'Recherche'
verbose_name_plural = 'Recherches'
indexes = [
models.Index(fields=['category', '-created_at']),
models.Index(fields=['user', '-created_at']),
models.Index(fields=['search_query']),
models.Index(fields=['-created_at']),
]
ordering = ['-created_at']
def __str__(self):
user_info = self.user.email if self.user else "Anonyme"
return f"{user_info} - {self.category}: '{self.search_query}'"
class PopularSearch(models.Model):
"""
Vue matérialisée des recherches les plus populaires
Mise à jour périodiquement pour optimiser les performances
"""
category = models.CharField(max_length=20, choices=SearchLog.CATEGORY_CHOICES)
search_query = models.CharField(max_length=500)
search_count = models.IntegerField(default=0)
last_searched = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'popular_searches'
verbose_name = 'Recherche Populaire'
verbose_name_plural = 'Recherches Populaires'
unique_together = ['category', 'search_query']
ordering = ['-search_count', '-last_searched']
def __str__(self):
return f"{self.category}: '{self.search_query}' ({self.search_count}x)"
|