Compare commits
3 commits
babd9f2aba
...
b58d85198a
Author | SHA1 | Date | |
---|---|---|---|
|
b58d85198a | ||
|
6c3a1e6ddc | ||
|
3d1b8a9bee |
56
beesgospel/admin.py
Normal file
56
beesgospel/admin.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.contrib.auth.admin import UserAdmin
|
||||||
|
|
||||||
|
from beesgospel.models import Agenda, Document, Membre, User
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Agenda)
|
||||||
|
class AgendaAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ["titre", "lieu", "date_heure", "prive"]
|
||||||
|
ordering = ["-date_heure"]
|
||||||
|
search_fields = ["titre", "lieu"]
|
||||||
|
date_hierarchy = "date_heure"
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Document)
|
||||||
|
class DocumentAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ["titre", "quand", "prive"]
|
||||||
|
ordering = ["-quand"]
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Membre)
|
||||||
|
class MembreAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ["nom", "prenom", "localite", "user__email"]
|
||||||
|
ordering = ["nom"]
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(User)
|
||||||
|
class UserAdmin(UserAdmin):
|
||||||
|
list_display = ["email", "is_active", "is_staff", "last_login"]
|
||||||
|
search_fields = ["email"]
|
||||||
|
ordering = ["email"]
|
||||||
|
fieldsets = (
|
||||||
|
(None, {"fields": ("email", "password",)}),
|
||||||
|
(
|
||||||
|
"Permissions",
|
||||||
|
{
|
||||||
|
"fields": (
|
||||||
|
"is_active",
|
||||||
|
"is_staff",
|
||||||
|
"is_superuser",
|
||||||
|
"groups",
|
||||||
|
"user_permissions",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
("Important dates", {"fields": ("last_login", "date_joined")}),
|
||||||
|
)
|
||||||
|
add_fieldsets = (
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
{
|
||||||
|
"classes": ("wide",),
|
||||||
|
"fields": ("email", "usable_password", "password1", "password2"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
31
beesgospel/forms.py
Normal file
31
beesgospel/forms.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
from dajngo import forms
|
||||||
|
from django.contrib.auth import forms as auth_forms
|
||||||
|
|
||||||
|
|
||||||
|
class BootstrapMixin:
|
||||||
|
required_css_class = "required"
|
||||||
|
|
||||||
|
widget_classes = {
|
||||||
|
"checkbox": "form-check-input",
|
||||||
|
"select": "form-select",
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
for field in self.fields.values():
|
||||||
|
if getattr(field.widget, "_bs_enabled", False):
|
||||||
|
continue
|
||||||
|
widgets = getattr(field.widget, "widgets", [field.widget])
|
||||||
|
for widget in widgets:
|
||||||
|
input_type = getattr(widget, "input_type", "")
|
||||||
|
class_name = self.widget_classes.get(input_type, "form-control")
|
||||||
|
if "class" in widget.attrs:
|
||||||
|
widget.attrs["class"] += " " + class_name
|
||||||
|
else:
|
||||||
|
widget.attrs.update({"class": class_name})
|
||||||
|
|
||||||
|
|
||||||
|
class LoginForm(BootstrapMixin, auth_forms.AuthenticationForm):
|
||||||
|
username = forms.EmailField(
|
||||||
|
widget=forms.EmailInput(attrs={"autofocus": True}),
|
||||||
|
)
|
166
beesgospel/migrations/0001_initial.py
Normal file
166
beesgospel/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
import beesgospel.models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("auth", "0012_alter_user_first_name_max_length"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="User",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("password", models.CharField(max_length=128, verbose_name="password")),
|
||||||
|
(
|
||||||
|
"last_login",
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True, null=True, verbose_name="last login"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"is_superuser",
|
||||||
|
models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text="Designates that this user has all permissions without explicitly assigning them.",
|
||||||
|
verbose_name="superuser status",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"first_name",
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=150, verbose_name="first name"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"last_name",
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=150, verbose_name="last name"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"email",
|
||||||
|
models.EmailField(
|
||||||
|
blank=True, max_length=254, verbose_name="email address"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"is_staff",
|
||||||
|
models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text="Designates whether the user can log into this admin site.",
|
||||||
|
verbose_name="staff status",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"is_active",
|
||||||
|
models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
|
||||||
|
verbose_name="active",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"date_joined",
|
||||||
|
models.DateTimeField(
|
||||||
|
default=django.utils.timezone.now, verbose_name="date joined"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"groups",
|
||||||
|
models.ManyToManyField(
|
||||||
|
blank=True,
|
||||||
|
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
|
||||||
|
related_name="user_set",
|
||||||
|
related_query_name="user",
|
||||||
|
to="auth.group",
|
||||||
|
verbose_name="groups",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"user_permissions",
|
||||||
|
models.ManyToManyField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Specific permissions for this user.",
|
||||||
|
related_name="user_set",
|
||||||
|
related_query_name="user",
|
||||||
|
to="auth.permission",
|
||||||
|
verbose_name="user permissions",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
managers=[
|
||||||
|
("objects", beesgospel.models.CustomUserManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Membre",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("nom", models.CharField(max_length=40, verbose_name="Nom")),
|
||||||
|
("prenom", models.CharField(max_length=40, verbose_name="Prénom")),
|
||||||
|
(
|
||||||
|
"avatar",
|
||||||
|
models.ImageField(
|
||||||
|
blank=True, upload_to="avatars", verbose_name="Avatar"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"rue",
|
||||||
|
models.CharField(blank=True, max_length=80, verbose_name="Rue"),
|
||||||
|
),
|
||||||
|
("npa", models.CharField(blank=True, max_length=5, verbose_name="NPA")),
|
||||||
|
(
|
||||||
|
"localite",
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=40, verbose_name="Localité"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"tel1",
|
||||||
|
models.CharField(blank=True, max_length=20, verbose_name="Tél. 1"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"tel2",
|
||||||
|
models.CharField(blank=True, max_length=20, verbose_name="Tél. 2"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"user",
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddConstraint(
|
||||||
|
model_name="user",
|
||||||
|
constraint=models.UniqueConstraint(
|
||||||
|
fields=("email",), name="unique_user_email"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
74
beesgospel/migrations/0002_agenda_document.py
Normal file
74
beesgospel/migrations/0002_agenda_document.py
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
# Generated by Django 5.2.5.dev20250725113223 on 2025-07-26 15:59
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("beesgospel", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Agenda",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("titre", models.CharField(max_length=150, verbose_name="Titre")),
|
||||||
|
(
|
||||||
|
"lieu",
|
||||||
|
models.CharField(blank=True, max_length=80, verbose_name="Lieu"),
|
||||||
|
),
|
||||||
|
("date_heure", models.DateTimeField(verbose_name="Date/heure")),
|
||||||
|
("infos", models.TextField(verbose_name="Informations")),
|
||||||
|
(
|
||||||
|
"prive",
|
||||||
|
models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text="Un évènement privé ne peut être consulté que par les membres de l'association, tandis qu'un évènement public est visible de tous.",
|
||||||
|
verbose_name="Privé",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={'verbose_name': 'Agenda', 'verbose_name_plural': 'Agenda'},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Document",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"fichier",
|
||||||
|
models.FileField(
|
||||||
|
blank=True, upload_to="documents", verbose_name="Fichier"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("url", models.URLField(blank=True, verbose_name="URL")),
|
||||||
|
("quand", models.DateField(verbose_name="Date")),
|
||||||
|
("titre", models.CharField(max_length=150, verbose_name="Titre")),
|
||||||
|
("infos", models.TextField(blank=True, verbose_name="Infos")),
|
||||||
|
(
|
||||||
|
"prive",
|
||||||
|
models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text="Un document privé ne peut être consulté que par les membres de l'association, tandis qu'un document public est visible de tous.",
|
||||||
|
verbose_name="Privé",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
0
beesgospel/migrations/__init__.py
Normal file
0
beesgospel/migrations/__init__.py
Normal file
75
beesgospel/models.py
Normal file
75
beesgospel/models.py
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
from django.contrib.auth.models import AbstractUser, UserManager
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class CustomUserManager(UserManager):
|
||||||
|
def create_superuser(self, **kwargs):
|
||||||
|
return super().create_superuser("foo", **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class User(AbstractUser):
|
||||||
|
username = None
|
||||||
|
USERNAME_FIELD = "email"
|
||||||
|
REQUIRED_FIELDS = []
|
||||||
|
|
||||||
|
objects = CustomUserManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
constraints = [
|
||||||
|
models.UniqueConstraint(name="unique_user_email", fields=["email"]),
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, *args, username=None, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Membre(models.Model):
|
||||||
|
nom = models.CharField("Nom", max_length=40)
|
||||||
|
prenom = models.CharField("Prénom", max_length=40)
|
||||||
|
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
avatar = models.ImageField("Avatar", upload_to="avatars", blank=True)
|
||||||
|
rue = models.CharField("Rue", max_length=80, blank=True)
|
||||||
|
npa = models.CharField("NPA", max_length=5, blank=True)
|
||||||
|
localite = models.CharField("Localité", max_length=40, blank=True)
|
||||||
|
tel1 = models.CharField("Tél. 1", max_length=20, blank=True)
|
||||||
|
tel2 =models.CharField("Tél. 2", max_length=20, blank=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.nom} {self.prenom}"
|
||||||
|
|
||||||
|
|
||||||
|
class Agenda(models.Model):
|
||||||
|
titre = models.CharField("Titre", max_length=150)
|
||||||
|
lieu = models.CharField("Lieu", max_length=80, blank=True)
|
||||||
|
date_heure = models.DateTimeField("Date/heure")
|
||||||
|
infos = models.TextField("Informations")
|
||||||
|
prive = models.BooleanField(
|
||||||
|
"Privé", default=False, help_text=(
|
||||||
|
"Un évènement privé ne peut être consulté que par les membres de "
|
||||||
|
"l'association, tandis qu'un évènement public est visible de tous."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "Agenda"
|
||||||
|
verbose_name_plural = "Agenda"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.titre} {self.date_heure}"
|
||||||
|
|
||||||
|
|
||||||
|
class Document(models.Model):
|
||||||
|
fichier = models.FileField("Fichier", upload_to="documents", blank=True)
|
||||||
|
url = models.URLField("URL", blank=True)
|
||||||
|
quand = models.DateField("Date")
|
||||||
|
titre = models.CharField("Titre", max_length=150)
|
||||||
|
infos = models.TextField("Infos", blank=True)
|
||||||
|
prive = models.BooleanField(
|
||||||
|
"Privé", default=False, help_text=(
|
||||||
|
"Un document privé ne peut être consulté que par les membres de "
|
||||||
|
"l'association, tandis qu'un document public est visible de tous."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.titre} {self.date}"
|
|
@ -73,3 +73,8 @@ nav {
|
||||||
.left-red {
|
.left-red {
|
||||||
border-left: 2px solid red;
|
border-left: 2px solid red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prive {
|
||||||
|
background-image: linear-gradient(45deg, #333333 41.67%, #6b0c0c 41.67%, #6b0c0c 50%, #333333 50%, #333333 91.67%, #6b0c0c 91.67%, #6b0c0c 100%);
|
||||||
|
background-size: 33.94px 33.94px;
|
||||||
|
}
|
||||||
|
|
27
beesgospel/views.py
Normal file
27
beesgospel/views.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
from datetime import date, timedelta
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.views.generic import ListView, TemplateView
|
||||||
|
|
||||||
|
from .models import Agenda, Membre
|
||||||
|
|
||||||
|
|
||||||
|
class AgendaView(ListView):
|
||||||
|
model = Agenda
|
||||||
|
template_name = "agenda.html"
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
qs = Agenda.objects.filter(
|
||||||
|
date_heure__gt=date.today() - timedelta(days=3),
|
||||||
|
).order_by("date_heure")
|
||||||
|
if not self.request.user.is_authenticated:
|
||||||
|
qs = qs.filter(prive=False)
|
||||||
|
return qs
|
||||||
|
|
||||||
|
|
||||||
|
class EspaceMembresView(LoginRequiredMixin, TemplateView):
|
||||||
|
template_name = "membres/index.html"
|
||||||
|
|
||||||
|
|
||||||
|
class ListeMembresView(LoginRequiredMixin, ListView):
|
||||||
|
model = Membre
|
||||||
|
template_name = "membres/liste.html"
|
|
@ -4,6 +4,8 @@ Django settings for beesgospel project.
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / "subdir".
|
# Build paths inside the project like this: BASE_DIR / "subdir".
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
@ -69,7 +71,7 @@ DATABASES = {
|
||||||
"NAME": BASE_DIR / "db.sqlite3",
|
"NAME": BASE_DIR / "db.sqlite3",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
|
||||||
|
@ -88,16 +90,17 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
AUTH_USER_MODEL = "beesgospel.User"
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/5.2/topics/i18n/
|
# https://docs.djangoproject.com/en/5.2/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = "fr"
|
LANGUAGE_CODE = "fr-ch"
|
||||||
|
|
||||||
TIME_ZONE = "UTC"
|
TIME_ZONE = "Europe/Zurich"
|
||||||
|
|
||||||
USE_I18N = False
|
USE_I18N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
@ -108,6 +111,8 @@ USE_TZ = True
|
||||||
STATIC_URL = "static/"
|
STATIC_URL = "static/"
|
||||||
STATIC_ROOT = BASE_DIR / "static"
|
STATIC_ROOT = BASE_DIR / "static"
|
||||||
|
|
||||||
|
LOGOUT_REDIRECT_URL = reverse_lazy("presentation")
|
||||||
|
|
||||||
# Default primary key field type
|
# Default primary key field type
|
||||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path
|
from django.urls import include, path
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
|
from beesgospel import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
|
path("accounts/", include("django.contrib.auth.urls")),
|
||||||
path("", TemplateView.as_view(template_name="index.html"), name="home"),
|
path("", TemplateView.as_view(template_name="index.html"), name="home"),
|
||||||
path("v2", TemplateView.as_view(template_name="index2.html"), name="home"),
|
path("v2", TemplateView.as_view(template_name="index2.html"), name="home"),
|
||||||
path("presentation/", TemplateView.as_view(template_name="presentation.html"), name="presentation"),
|
path("presentation/", TemplateView.as_view(template_name="presentation.html"), name="presentation"),
|
||||||
path("contact/", TemplateView.as_view(template_name="contact.html"), name="contact"),
|
path("contact/", TemplateView.as_view(template_name="contact.html"), name="contact"),
|
||||||
|
path("membres/", views.EspaceMembresView.as_view(), name="membres"),
|
||||||
|
path("membres/liste/", views.ListeMembresView.as_view(), name="liste-membres"),
|
||||||
|
path("agenda/", views.AgendaView.as_view(), name="agenda"),
|
||||||
]
|
]
|
||||||
|
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
django==5.2.*
|
||||||
|
pillow==11.3.*
|
5
templates/admin/base_site.html
Normal file
5
templates/admin/base_site.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{% extends 'admin/base.html' %}
|
||||||
|
|
||||||
|
{% block branding %}
|
||||||
|
<div id="site-name"><a href="{% url 'admin:index' %}">Administration du site beesgospel.ch</a></div>
|
||||||
|
{% endblock %}
|
20
templates/agenda.html
Normal file
20
templates/agenda.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block page_title %} - Agenda{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2 class="mb-5">Agenda des prochaines prestations de la chorale</h2>
|
||||||
|
|
||||||
|
{% for item in object_list %}
|
||||||
|
<div class="border-bottom border-danger mt-3{% if item.prive %} prive{% endif %}">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-12 col-sm-4 col-lg-2 bg-white text-black rounded align-self-center text-center fw-bold pt-2 pb-2">
|
||||||
|
{{ item.date_heure|date:'D d F à H:i' }}
|
||||||
|
</div>
|
||||||
|
<div class="col col-12 col-sm-8 col-lg-10 fs-4">{{ item.titre }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 mb-2">{{ item.lieu }}</div>
|
||||||
|
<div class="pb-3">{{ item.infos }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Le Gospel de l’Abeille - Bee's Gospel</title>
|
<title>Le Gospel de l’Abeille - Bee's Gospel{% block page_title %}{% endblock %}</title>
|
||||||
<link href="{% static 'vendor/bootstrap.min.css' %}" rel="stylesheet">
|
<link href="{% static 'vendor/bootstrap.min.css' %}" rel="stylesheet">
|
||||||
<link href="{% static 'css/main.css' %}" rel="stylesheet">
|
<link href="{% static 'css/main.css' %}" rel="stylesheet">
|
||||||
<script src="{% static 'vendor/bootstrap.bundle.min.js' %}"></script>
|
<script src="{% static 'vendor/bootstrap.bundle.min.js' %}"></script>
|
||||||
|
@ -26,11 +26,11 @@
|
||||||
<li class="nav-sep">•</li>
|
<li class="nav-sep">•</li>
|
||||||
<li class="nav-item"><a class="nav-link{% if request.path == "/contact/" %} active{% endif %}" href="{% url 'contact' %}">Contact</a></li>
|
<li class="nav-item"><a class="nav-link{% if request.path == "/contact/" %} active{% endif %}" href="{% url 'contact' %}">Contact</a></li>
|
||||||
<li class="nav-sep">•</li>
|
<li class="nav-sep">•</li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#">Agenda</a></li>
|
<li class="nav-item"><a class="nav-link" href="{% url 'agenda' %}">Agenda</a></li>
|
||||||
<li class="nav-sep">•</li>
|
<li class="nav-sep">•</li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#">Médias</a></li>
|
<li class="nav-item"><a class="nav-link" href="#">Médias</a></li>
|
||||||
<li class="nav-sep">•</li>
|
<li class="nav-sep">•</li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#">Espace membres</a></li>
|
<li class="nav-item"><a class="nav-link{% if request.path == "/membres/" %} active{% endif %}" href="{% url 'membres' %}">Espace membres</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
17
templates/membres/index.html
Normal file
17
templates/membres/index.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="float-end">
|
||||||
|
<form action="{% url 'logout' %}" method="post">{% csrf_token %}<button class="btn btn-sm btn-light" type="submit">Déconnexion</button></form>
|
||||||
|
</div>
|
||||||
|
<h2>Espace membres</h2>
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col col-4"><a href="{% url 'liste-membres' %}">Liste des membres</a></div>
|
||||||
|
{% if perms.beesgospel.change_agenda %}
|
||||||
|
<div class="col col-4"><a href="{% url 'admin:beesgospel_agenda_changelist' %}">Gestion de l’agenda</a></div>
|
||||||
|
{% endif %}
|
||||||
|
{% if perms.beesgospel.change_document %}
|
||||||
|
<div class="col col-4"><a href="{% url 'admin:beesgospel_document_changelist' %}">Gestion des documents</a></div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
14
templates/membres/liste.html
Normal file
14
templates/membres/liste.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>Liste des membres</h2>
|
||||||
|
<table class="table table-responsive">
|
||||||
|
{% for membre in object_list %}
|
||||||
|
<tr><td>{{ membre.nom }} {{ membre.prenom }}</td>
|
||||||
|
<td>{{ membre.rue }}<br>{{ membre.npa }} {{ membre.localite }}</td>
|
||||||
|
<td>{{ membre.tel1 }}<br>{{ membre.tel2 }}</td>
|
||||||
|
<td>{{ membre.email }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
26
templates/registration/login.html
Normal file
26
templates/registration/login.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="wrapper container">
|
||||||
|
<div class="col-11 col-lg-5 mx-auto">
|
||||||
|
<form class="form-sign mb-3" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<h1 class="fs-2 mb-4">Connexion</h1>
|
||||||
|
|
||||||
|
{{ form.non_field_errors }}
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="id_username" class="form-label w-100">Adresse électronique</label>
|
||||||
|
{{ form.username.errors }} {{ form.username }}
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="id_password" class="form-label w-100">Mot de passe</label>
|
||||||
|
{{ form.password.errors }} {{ form.password }}
|
||||||
|
</div>
|
||||||
|
<!--div class="mb-4">
|
||||||
|
<a href="{% url 'password_reset' %}" class="text-link">Mot de passe oublié</a>
|
||||||
|
</div-->
|
||||||
|
<button class="btn btn-cta btn-light" type="submit">Se connecter</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
Loading…
Reference in a new issue