From abe4a1a9657f8d6cd011e77caaf6d846ddce2d85 Mon Sep 17 00:00:00 2001 From: mrtoine Date: Thu, 11 Dec 2025 09:38:00 +0100 Subject: [PATCH] Add Premium feature with UI, model changes, and admin configuration --- home/urls.py | 1 + home/views.py | 7 +- templates/courses/partials/_course_toc.html | 34 +++++++-- templates/premium.html | 78 +++++++++++++++++++++ users/admin.py | 23 +++++- users/migrations/0003_profile_is_premium.py | 18 +++++ users/models.py | 1 + 7 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 templates/premium.html create mode 100644 users/migrations/0003_profile_is_premium.py diff --git a/home/urls.py b/home/urls.py index 7aa620c..a1ea3c1 100644 --- a/home/urls.py +++ b/home/urls.py @@ -4,4 +4,5 @@ from . import views app_name = 'home' urlpatterns = [ path('', views.home, name='home'), + path('premium/', views.premium, name='premium'), ] \ No newline at end of file diff --git a/home/views.py b/home/views.py index f4650f4..5bd3838 100644 --- a/home/views.py +++ b/home/views.py @@ -1,6 +1,11 @@ -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404 from courses.models import Course def home(request): courses = Course.objects.order_by('-created_at')[:6] return render(request, 'home.html', {'courses': courses}) + +def premium(request, course_id): + """Landing page présentant les avantages du Premium.""" + course = get_object_or_404(Course, pk=course_id) + return render(request, 'premium.html', {'course': course}) diff --git a/templates/courses/partials/_course_toc.html b/templates/courses/partials/_course_toc.html index 3feeea3..fb3923d 100644 --- a/templates/courses/partials/_course_toc.html +++ b/templates/courses/partials/_course_toc.html @@ -11,15 +11,41 @@
    {% for item in group.list %}
  1. - - {{ item.name }} + + {{ item.name }} {% if item.is_premium %}PREMIUM{% endif %} {% if lesson and lesson.id == item.id %}(cours actuel){% endif %} {% if lesson and lesson.id == item.id %}
    -
    +
    {% if lesson.video_id %} - VIDEO {{ lesson.video_id }}
    + {% if not lesson.is_premium %} + VIDEO {{ lesson.video_id }}
    + {% else %} + + {% if not user.profile.is_premium %} +
    +
    + +
    +

    Contenu réservé aux membres Premium

    + {% if user.is_authenticated %} +

    Devenez membre Premium pour accéder à la vidéo de ce cours.

    + + {% else %} +

    Connectez-vous ou devenez membre Premium pour accéder à la vidéo.

    + + {% endif %} +
    +
    +
    + {% endif %} + {% endif %} {% endif %} {{ lesson.content|safe }}
    diff --git a/templates/premium.html b/templates/premium.html new file mode 100644 index 0000000..614c108 --- /dev/null +++ b/templates/premium.html @@ -0,0 +1,78 @@ +{% extends 'layout.html' %} + +{% block content %} +
    +
    +
    +
    + +
    + + {% if course %} +

    Débloquez le cours "{{ course.name }}"

    +

    Ce contenu est réservé aux membres Premium. Rejoignez-nous pour accéder immédiatement à ce projet et aux sources.

    + {% else %} +

    Passez à la vitesse supérieure

    +

    Accédez aux cours complets, aux projets concrets et aux corrections détaillées pour progresser plus vite.

    + {% endif %} + +
    + {% if course %} + + Débloquer ce cours maintenant + + {% else %} + + Voir le catalogue + + {% endif %} + + Retourner à l'accueil +
    + + +
    + +
    + +{% if course %} +
    +
    +
    + {{ course.name }} +
    +
    +

    Ce que vous allez apprendre

    +
      +
    • Créer une application complète de A à Z
    • +
    • Les bonnes pratiques professionnelles
    • +
    • Accès au code source complet
    • +
    +
    +
    +
    +{% endif %} + +
    +
    +
    +

    Parcours complets

    +

    Des modules structurés du niveau débutant à avancé.

    +
    +
    +
    +

    Projets de A à Z

    +

    Construisez des applications réelles et apprenez les bonnes pratiques.

    +
    +
    +
    +

    Corrections détaillées

    +

    Vidéos explicatives pas-à-pas et ressources téléchargeables.

    +
    +
    + +{% endblock %} \ No newline at end of file diff --git a/users/admin.py b/users/admin.py index 8c38f3f..0567ce1 100644 --- a/users/admin.py +++ b/users/admin.py @@ -1,3 +1,24 @@ from django.contrib import admin +from .models import Profile -# Register your models here. + +@admin.register(Profile) +class ProfileAdmin(admin.ModelAdmin): + list_display = ( + 'user', + 'first_name', + 'last_name', + 'is_premium', + 'birth_date', + ) + search_fields = ( + 'user__username', + 'first_name', + 'last_name', + 'biography', + ) + list_filter = ( + 'is_premium', + 'birth_date', + ) + autocomplete_fields = ('user',) diff --git a/users/migrations/0003_profile_is_premium.py b/users/migrations/0003_profile_is_premium.py new file mode 100644 index 0000000..b8c04d0 --- /dev/null +++ b/users/migrations/0003_profile_is_premium.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0 on 2025-12-10 21:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0002_alter_profile_avatar'), + ] + + operations = [ + migrations.AddField( + model_name='profile', + name='is_premium', + field=models.BooleanField(default=False), + ), + ] diff --git a/users/models.py b/users/models.py index f46640d..f946dc0 100644 --- a/users/models.py +++ b/users/models.py @@ -11,6 +11,7 @@ class Profile(models.Model): last_name = models.CharField(max_length=64, blank=True) birth_date = models.DateField(null=True, blank=True) biography = models.TextField(blank=True) + is_premium = models.BooleanField(default=False) def __str__(self): return self.user.username \ No newline at end of file