First Commit

This commit is contained in:
mrtoine 2025-09-12 11:11:44 +02:00
commit ce0758fbbb
496 changed files with 52062 additions and 0 deletions

303
forum/views.py Executable file
View file

@ -0,0 +1,303 @@
from django.core.paginator import Paginator
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseForbidden
from django.utils import timezone
from .models import Category, Forum, Topic, Post, TopicRead
from .forms import CreateTopic, CreatePost, EditPost
from django.db.models import Max, F
from users.decorators import groups_required
from users.models import UserLevel
def forum_home(request):
categories = Category.objects.all()
forums = Forum.objects.all()
last_posts = {}
count_topics = {}
unread_topics = {}
for forum in forums:
# Dernier post du forum avec une seule requête
last_post = Post.objects.select_related(
'topic',
'author',
'topic__forum'
).filter(
topic__forum=forum
).order_by('-created').first()
last_posts[forum.id] = last_post
# Nombre de topics (pas de changement)
count_topic = Topic.objects.filter(forum=forum).count()
count_topics[forum.id] = count_topic
# Optimisation de la vérification des topics non lus
if request.user.is_authenticated:
# Récupérer le dernier post de chaque topic du forum en une seule requête
latest_posts_per_topic = Post.objects.filter(
topic__forum=forum
).values('topic_id').annotate(
last_post_date=Max('created')
)
# Récupérer les dernières lectures de l'utilisateur pour tous les topics du forum
topic_reads = TopicRead.objects.filter(
user=request.user,
topic__forum=forum
).values_list('topic_id', 'last_read')
# Convertir en dictionnaire pour un accès plus rapide
read_dates = dict(topic_reads)
# Un forum est non lu si au moins un topic a un post plus récent que la dernière lecture
is_unread = False
for post_info in latest_posts_per_topic:
topic_id = post_info['topic_id']
last_post_date = post_info['last_post_date']
# Si le topic n'a jamais été lu
if topic_id not in read_dates:
is_unread = True
break
# Si le dernier post est plus récent que la dernière lecture
if last_post_date > read_dates[topic_id]:
is_unread = True
break
unread_topics[forum.id] = is_unread
else:
unread_topics[forum.id] = False
print(unread_topics)
context = {
'categories': categories,
'forums': forums,
'last_posts': last_posts,
'count_topics': count_topics,
'unread_topics': unread_topics,
}
return render(request, "components/forum_home.html", context)
def topic_list(request, forum_id):
forum = Forum.objects.get(id=forum_id)
topics = Topic.objects.filter(forum=forum).order_by('-created')
paginator = Paginator(topics, 20)
page_number = request.GET.get('page')
topics = paginator.get_page(page_number)
count_posts = {}
last_posts = {}
page_numbers = {}
unread_topics = {}
for topic in topics:
count_post = Post.objects.filter(topic=topic).count()
count_posts[topic.id] = count_post
last_post = Post.objects.filter(topic=topic).order_by('-created').first()
last_posts[topic.id] = last_post
if request.user.is_authenticated:
# Récupérer le dernier post du topic
latest_post = Post.objects.filter(topic=topic).aggregate(last_post_date=Max('created'))['last_post_date']
# Récupérer la dernière lecture de l'utilisateur pour ce topic
topic_read = TopicRead.objects.filter(user=request.user, topic=topic).first()
# Un topic est non lu si le dernier post est plus récent que la dernière lecture
if topic_read:
unread_topics[topic.id] = latest_post > topic_read.last_read
else:
unread_topics[topic.id] = True
else:
unread_topics[topic.id] = False
if last_post:
# Position du dernier message (nombre de messages jusqu'à ce message)
post_position = Post.objects.filter(
topic=topic,
created__lte=last_post.created
).count()
# Calcul du numéro de page (20 messages par page comme dans topic_detail)
page_number = (post_position + 19) // 20 # équivalent à ceil(post_position/20)
page_numbers[topic.id] = page_number
context = {
'forum': forum,
'topics': topics,
'count_posts': count_posts,
'last_posts': last_posts,
'page_numbers': page_numbers,
'unread_topics': unread_topics,
'is_paginated': topics.has_other_pages(),
'page_obj': topics,
'paginator': paginator,
}
return render(request, "forum/topic_list.html", context)
@login_required
def create_topic(request, forum_id):
if not request.user.is_active:
return HttpResponseForbidden("Vous n'êtes pas autorisé à créer un sujet.")
if request.method == 'POST':
topic_form = request.POST
# On créer le topic via le model Topic
topic = Topic(
forum=Forum.objects.get(id=forum_id),
author=request.user,
title=topic_form['title'],
)
# Puis le premier post du topic
post = Post(
topic=topic,
author=request.user,
content=topic_form['content'],
)
topic.save()
post.save()
messages.success(request, 'Topic créer avec succès.')
UserLevel.objects.update(user=request.user, experience=F('experience') + 15)
# on renvoie l'utilisateur sur la page du topic contenu l'id du forum et du topic créer
return redirect('post_list', forum_id=forum_id, topic_id=topic.id)
forum = Forum.objects.get(id=forum_id)
topic_form = CreateTopic()
context = {
'forum': forum,
'topic_form': topic_form,
}
return render(request, "forum/create_topic.html", context)
def topic_detail(request, topic_id, forum_id):
if request.method == 'POST':
if not request.user.is_active or not request.user.is_authenticated:
return HttpResponseForbidden("Vous n'êtes pas autorisé à poster un message.")
post_form = CreatePost(request.POST)
if post_form.is_valid():
post = Post(
topic=Topic.objects.get(id=topic_id),
author=request.user,
content=post_form.cleaned_data['content'],
)
post.save()
UserLevel.objects.update(user=request.user, experience=F('experience') + 10)
messages.success(request, 'Message posté avec succès.')
topic = Topic.objects.get(id=topic_id)
posts = Post.objects.filter(topic=topic, active=True)
paginator = Paginator(posts, 20)
page_number = request.GET.get('page')
posts = paginator.get_page(page_number)
# Marquer comme lu si l'utilisateur est connecté
if request.user.is_authenticated:
TopicRead.objects.update_or_create(
user=request.user,
topic=topic,
defaults={'last_read': timezone.now()}
)
# On compte le nombre de posts de l'auteur
count_posts = {}
for post in posts:
count_post = Post.objects.filter(author=post.author).count()
count_posts[post.author.id] = count_post
context = {
'topic': topic,
'posts': posts,
'count_posts': count_posts,
'post_form': CreatePost(),
'is_paginated': posts.has_other_pages(),
'page_obj': posts,
'paginator': paginator,
}
return render(request, "forum/topic_detail.html", context)
@groups_required('Modérateur', 'Admininistrateur', 'Super Admin')
def lock_topic(request, topic_id):
topic = Topic.objects.get(id=topic_id)
topic.state = 'closed'
topic.save()
messages.success(request, 'Sujet verrouillé avec succès.')
return redirect('post_list', forum_id=topic.forum.id, topic_id=topic_id)
@groups_required('Modérateur', 'Admininistrateur', 'Super Admin')
def unlock_topic(request, topic_id):
topic = Topic.objects.get(id=topic_id)
topic.state = 'open'
topic.save()
messages.success(request, 'Sujet déverrouillé avec succès.')
return redirect('post_list', forum_id=topic.forum.id, topic_id=topic_id)
@groups_required('Modérateur', 'Admininistrateur', 'Super Admin')
def deactivate_post(request, post_id):
post = Post.objects.get(id=post_id)
post.active = False
post.save()
messages.success(request, 'Message désactivé avec succès.')
return redirect('post_list', forum_id=post.topic.forum.id, topic_id=post.topic.id)
@groups_required('Modérateur', 'Admininistrateur', 'Super Admin')
def activate_post(request, post_id):
post = Post.objects.get(id=post_id)
post.active = True
post.save()
messages.success(request, 'Message activé avec succès.')
return redirect('post_list', forum_id=post.topic.forum.id, topic_id=post.topic.id)
@groups_required('Modérateur', 'Admininistrateur', 'Super Admin')
def deactivate_topic(request, topic_id):
topic = Topic.objects.get(id=topic_id)
topic.active = False
topic.save()
messages.success(request, 'Sujet désactivé avec succès.')
return redirect('topic_list', forum_id=topic.forum.id)
@groups_required('Modérateur', 'Admininistrateur', 'Super Admin')
def activate_topic(request, topic_id):
topic = Topic.objects.get(id=topic_id)
topic.active = True
topic.save()
messages.success(request, 'Sujet activé avec succès.')
return redirect('topic_list', forum_id=topic.forum.id)
@login_required
def edit_post(request, post_id):
post = Post.objects.get(id=post_id)
# Vérifier si l'utilisateur a le droit d'éditer
if not (request.user == post.author or request.user.groups.filter(name__in=['Administrateur', 'Super Admin']).exists()):
return HttpResponseForbidden("Vous n'êtes pas autorisé à éditer ce message.")
if request.method == 'POST':
form = EditPost(request.POST)
if form.is_valid():
post.content = form.cleaned_data['content']
post.updated = timezone.now()
post.save()
messages.success(request, 'Message modifié avec succès.')
return redirect('post_list', forum_id=post.topic.forum.id, topic_id=post.topic.id)
else:
form = EditPost(initial={'content': post.content})
context = {
'form': form,
'post': post
}
return render(request, "forum/edit_post.html", context)