Compare commits

...

3 Commits

Author SHA1 Message Date
Gregory Trullemans 85f4a661e2 Update admin files 2024-03-12 15:18:11 +01:00
Gregory Trullemans 5ff595e555 Update Passe model and update admin files 2024-03-12 11:51:27 +01:00
Gregory Trullemans 836011423c Override clean() function to PasseForm 2024-03-11 10:28:22 +01:00
11 changed files with 115 additions and 143 deletions

View File

@ -2,17 +2,15 @@ from django.contrib import admin
from .models import Citation, Email
@admin.register(Citation)
class CitationAdmin(admin.ModelAdmin):
model = Citation
list_display = ("author", "quote")
@admin.register(Email)
class EmailAdmin(admin.ModelAdmin):
model = Email
list_display = ("title", "created_at", "updated_at", "sent_at", "last_tried_at")
admin.site.register(Citation, CitationAdmin)
admin.site.register(Email, EmailAdmin)

View File

@ -24,6 +24,7 @@ from .models import (
)
@admin.register(Chrono)
class ChronoAdmin(admin.ModelAdmin):
model = Chrono
@ -38,6 +39,7 @@ class ChronoAdmin(admin.ModelAdmin):
related_search_fields = {"gymnast": ("last_name", "first_name")}
@admin.register(ChronoDetails)
class ChronoDetailsAdmin(admin.ModelAdmin):
model = ChronoDetails
@ -51,6 +53,7 @@ class ChronoDetailsAdmin(admin.ModelAdmin):
}
@admin.register(LearnedSkill)
class LearnedSkillAdmin(admin.ModelAdmin):
model = LearnedSkill
@ -66,6 +69,7 @@ class LearnedSkillAdmin(admin.ModelAdmin):
date_hierarchy = "date"
@admin.register(Point)
class PointAdmin(admin.ModelAdmin):
model = Point
@ -93,6 +97,7 @@ class PointAdmin(admin.ModelAdmin):
autocomplete_fields = ("gymnast", "event")
@admin.register(Injury)
class InjuryAdmin(admin.ModelAdmin):
model = Injury
@ -121,6 +126,7 @@ class InjuryAdmin(admin.ModelAdmin):
autocomplete_fields = ("gymnast", "skill")
@admin.register(WellBeing)
class WellBeingAdmin(admin.ModelAdmin):
model = WellBeing
@ -154,6 +160,7 @@ class WellBeingAdmin(admin.ModelAdmin):
date_hierarchy = "date"
@admin.register(GymnastHasRoutine)
class GymnastHasRoutineAdmin(admin.ModelAdmin):
model = GymnastHasRoutine
@ -166,6 +173,7 @@ class GymnastHasRoutineAdmin(admin.ModelAdmin):
autocomplete_fields = ("gymnast", "routine")
@admin.register(NumberOfRoutineDone)
class NumberOfRoutineDoneAdmin(admin.ModelAdmin):
model = NumberOfRoutineDone
@ -184,6 +192,7 @@ class NumberOfRoutineDoneAdmin(admin.ModelAdmin):
date_hierarchy = "date"
@admin.register(HeightWeight)
class HeightWeightAdmin(admin.ModelAdmin):
model = HeightWeight
@ -194,6 +203,7 @@ class HeightWeightAdmin(admin.ModelAdmin):
autocomplete_fields = ("gymnast",)
@admin.register(Plan)
class PlanAdmin(admin.ModelAdmin):
model = Plan
@ -213,6 +223,7 @@ class PlanAdmin(admin.ModelAdmin):
autocomplete_fields = ("gymnast",)
@admin.register(Note)
class NoteAdmin(admin.ModelAdmin):
model = Note
@ -233,6 +244,7 @@ class NoteAdmin(admin.ModelAdmin):
autocomplete_fields = ("gymnast",)
@admin.register(Intensity)
class IntensityAdmin(admin.ModelAdmin):
model = Intensity
@ -253,6 +265,7 @@ class IntensityAdmin(admin.ModelAdmin):
autocomplete_fields = ("gymnast",)
@admin.register(SeasonInformation)
class SeasonInformationAdmin(admin.ModelAdmin):
model = SeasonInformation
@ -274,6 +287,7 @@ class SeasonInformationAdmin(admin.ModelAdmin):
autocomplete_fields = ("gymnast",)
@admin.register(CompetitivePointsStats)
class CompetitivePointsStatsAdmin(admin.ModelAdmin):
model = CompetitivePointsStats
@ -289,19 +303,3 @@ class CompetitivePointsStatsAdmin(admin.ModelAdmin):
("statistic_type", ChoiceDropdownFilter),
("routine_type", ChoiceDropdownFilter), # A supprimer ?
)
admin.site.register(Plan, PlanAdmin)
admin.site.register(Note, NoteAdmin)
admin.site.register(Point, PointAdmin)
admin.site.register(Chrono, ChronoAdmin)
admin.site.register(Injury, InjuryAdmin)
admin.site.register(WellBeing, WellBeingAdmin)
admin.site.register(Intensity, IntensityAdmin)
admin.site.register(LearnedSkill, LearnedSkillAdmin)
admin.site.register(HeightWeight, HeightWeightAdmin)
admin.site.register(ChronoDetails, ChronoDetailsAdmin)
admin.site.register(SeasonInformation, SeasonInformationAdmin)
admin.site.register(GymnastHasRoutine, GymnastHasRoutineAdmin)
admin.site.register(NumberOfRoutineDone, NumberOfRoutineDoneAdmin)
admin.site.register(CompetitivePointsStats, CompetitivePointsStatsAdmin)

View File

@ -1,7 +1,11 @@
from django.contrib import admin
from django_admin_listfilter_dropdown.filters import (
RelatedDropdownFilter,
)
from .models import Place, Club, Country
@admin.register(Country)
class CountryAdmin(admin.ModelAdmin):
model = Country
@ -10,6 +14,7 @@ class CountryAdmin(admin.ModelAdmin):
search_fields = ("name", "nationality")
@admin.register(Club)
class ClubAdmin(admin.ModelAdmin):
model = Club
@ -20,16 +25,15 @@ class ClubAdmin(admin.ModelAdmin):
autocomplete_fields = ("place",)
@admin.register(Place)
class PlaceAdmin(admin.ModelAdmin):
model = Place
list_display = ("name", "address", "postal", "city", "is_active")
ordering = ("name",)
list_filter = ("is_active",)
list_filter = (
"is_active",
("country", RelatedDropdownFilter),
)
search_fields = ("name", "address", "postal", "city")
autocomplete_fields = ("country",) # , "place"
admin.site.register(Place, PlaceAdmin)
admin.site.register(Club, ClubAdmin)
admin.site.register(Country, CountryAdmin)

View File

@ -17,6 +17,7 @@ from .models import (
)
@admin.register(TouchPosition)
class TouchPositionAdmin(admin.ModelAdmin):
model = TouchPosition
@ -32,6 +33,7 @@ def duplicate_skill(modeladmin, request, queryset): # pylint: disable=unused-ar
obj.save()
@admin.register(Skill)
class SkillAdmin(admin.ModelAdmin):
model = Skill
@ -98,6 +100,7 @@ class SkillAdmin(admin.ModelAdmin):
)
@admin.register(Routine)
class RoutineAdmin(admin.ModelAdmin):
model = Routine
@ -158,6 +161,7 @@ class RoutineAdmin(admin.ModelAdmin):
# return super(Skill, self).get_related_filter(model, request)
@admin.register(RoutineSkill)
class RoutineSkillAdmin(admin.ModelAdmin):
model = RoutineSkill
@ -173,6 +177,7 @@ class RoutineSkillAdmin(admin.ModelAdmin):
autocomplete_fields = ("routine", "skill")
@admin.register(PrerequisiteClosure)
class PrerequisiteClosureAdmin(admin.ModelAdmin):
model = PrerequisiteClosure
@ -189,6 +194,7 @@ class PrerequisiteClosureAdmin(admin.ModelAdmin):
)
@admin.register(Passe)
class PasseAdmin(admin.ModelAdmin):
model = Passe
@ -201,11 +207,12 @@ class PasseAdmin(admin.ModelAdmin):
"informations",
)
list_display = ("label", "number_of_skill", "difficulty")
list_display = ("label", "regexp", "number_of_skill", "difficulty")
list_filter = (
("number_of_skill", DropdownFilter),
("difficulty", DropdownFilter),
)
filter_horizontal = ("educatives",)
class Media:
js = (
@ -214,6 +221,7 @@ class PasseAdmin(admin.ModelAdmin):
)
@admin.register(TrainingProgram)
class TrainingProgramAdmin(admin.ModelAdmin):
model = TrainingProgram
@ -240,12 +248,3 @@ class TrainingProgramAdmin(admin.ModelAdmin):
("gymnast", RelatedDropdownFilter),
("date", DropdownFilter),
)
admin.site.register(Skill, SkillAdmin)
admin.site.register(Passe, PasseAdmin)
admin.site.register(Routine, RoutineAdmin)
admin.site.register(RoutineSkill, RoutineSkillAdmin)
admin.site.register(TouchPosition, TouchPositionAdmin)
admin.site.register(TrainingProgram, TrainingProgramAdmin)
admin.site.register(PrerequisiteClosure, PrerequisiteClosureAdmin)

View File

@ -1,4 +1,7 @@
from django import forms
from django.core.exceptions import ValidationError
import re
from .models import Skill, Routine, RoutineSkill, Passe
@ -37,8 +40,6 @@ class CombinationForm(forms.ModelForm):
"short_label": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Routine's short name"}
),
# "is_routine": form.,
# "is_competitive": form.,
"informations": forms.Textarea(
attrs={
"class": "form-control",
@ -101,21 +102,48 @@ class PasseForm(forms.ModelForm):
),
)
# "repetition": forms.NumberInput(
# attrs={
# "class": "form-control",
# "placeholder": "x",
# "min": "0",
# "max": "1000",
# "step": "1",
# }
# ),
def clean_regexp(self):
""" """
cleaned_data = self.clean()
regexp = cleaned_data.get("regexp")
if not Passe.is_valid_regexp(regexp, None, None):
self.add_error("regexp", "Entered regexp not valid.")
"""Vérifie que la regexp entrée par l'utilisateur est valide."""
regexp = self.cleaned_data["regexp"]
if not Passe.is_valid_regexp(regexp):
raise ValidationError("Entered regexp not valid.")
return regexp
def clean(self):
"""Vérifie le contenu des champs `educatives` par rapport à la valeur de `regexp`. Si
`regexp` est définie par :
- valeurs de ROUTINE_TYPE_CHOICE il faut que Educatives soit VIDE
- avec [x-y]
- [x-y] " Educatives soit NON VIDE
- WC " il y ait 2+ Educatives
- x| " il y ait 1! Educatives
"""
cleaned_data = super().clean()
regexp = ["regexp"]
if regexp is not None:
arguments = regexp.split(" ")
educatives = cleaned_data["educatives"]
if Passe.is_valid_routine_type(arguments[0]) and educatives is not None:
raise ValidationError(
"Educatives must be empty with the entered Regexp."
)
if Passe.is_valid_subset(arguments[0]) and educatives is None:
raise ValidationError(
"Educatives can't be empty with the entered Regexp."
)
if re.match(r"[1-9]+\|", arguments[0]) and len(educatives) != 1:
raise ValidationError(
"One and only one Educatives allowed with the entered Regexp."
)
if arguments[0] == "WC" and (educatives is None or len(educatives) < 2):
raise ValidationError(
"At least two Educatives with the entered Regexp."
)
return cleaned_data

View File

@ -0,0 +1,20 @@
# Generated by Django 4.2 on 2024-03-12 09:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("objective", "0020_alter_passe_educatives"),
]
operations = [
migrations.AlterField(
model_name="passe",
name="educatives",
field=models.ManyToManyField(
blank=True, related_name="passes", to="objective.educative"
),
),
]

View File

@ -473,7 +473,9 @@ class Passe(Markdownizable):
ordering = ["label"]
label = models.CharField(max_length=30)
educatives = models.ManyToManyField(Educative, blank=True)
educatives = models.ManyToManyField(
Educative, related_name="passes", blank=True, symmetrical=False
)
regexp = models.CharField(max_length=50, null=True, blank=True)
number_of_skill = models.PositiveSmallIntegerField(default=0)
difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0)
@ -610,7 +612,9 @@ class Passe(Markdownizable):
@staticmethod
def is_valid_routine_type(routine_type):
"""Recoit une chaine de caractère et vérifie si elle est présente dans une liste."""
"""Recoit une chaine de caractère et vérifie si elle est présente dans la liste
ROUTINE_TYPE_CHOICE (Educative vide !)
"""
is_valid = False
for item in ROUTINE_TYPE_CHOICE:
if item[1] == routine_type:
@ -656,13 +660,6 @@ class Passe(Markdownizable):
def is_valid_regexp(regexp):
"""Vérifie le champ regexp
Type de string pris en compte :
- Toutes les valeurs de ROUTINE_TYPE_CHOICE (Educative vide !)
- avec [x-y] (avec X ou Y vide mais pas les deux en même temps)
- [x-y] (avec X ou Y vide mais pas les deux en même temps) (EDUCATIVE non vide !!!)
- WC
- x| (x entier)
Exemples :
- Q1R1 True
- Q1R2 [2-8] True
@ -691,76 +688,9 @@ class Passe(Markdownizable):
return False
@staticmethod
def is_valid_regexp_extended(regexp, label, educatives_list):
"""Vérifie le champ regexp
Type de string pris en compte :
- Toutes les valeurs de ROUTINE_TYPE_CHOICE (Educative vide !)
- avec [x-y] (avec X ou Y vide mais pas les deux en même temps)
- [x-y] (avec X ou Y vide mais pas les deux en même temps) (EDUCATIVE non vide !!!)
- WC
- x| (x entier)
Exemples :
- Q1R1 True (si educatives.count() vide)
- Q1R2 [2-8] True (si educatives.count() vide)
- Q1R1 [8-2] False
- Q1R1 [-] False
- Q2R1 [-5] True (si educatives.count() vide)
- SF [6-] True (si educatives.count() vide)
- FS [3-7] True (si educatives.count() vide)
- Q1R1. True (si educatives.count() vide)
- .Q1R2 True (si educatives.count() vide)
- Q1R1. [-4] True (si educatives.count() vide)
- .Q1R2 [4-] True (si educatives.count() vide)
- .FS [3-7] True (si educatives.count() vide)
- [2-8] True (si educative.count() == 1 et educative est une routine >= 8 sauts)
- [8-2] False
- [-] False
- [-5] True (si educative.count() == 1 et educative est une routine >= 8 sauts)
- WC True (si educatives.count() >= 2)
- 1| True (si educatives.count() >= 1)
"""
# devrait être en dehors de cette fonction -->
if label is None and educatives_list is None and regexp is None:
return False
# <--
argument_list = regexp.split(" ")
if len(argument_list) >= 3:
return False
if len(argument_list) == 2 and educatives_list.count() == 1:
return Passe.is_valid_regexp_two_args(argument_list[0], argument_list[1])
else:
if (
argument_list[0] == "WC"
and educatives_list is not None
and len(educatives_list) == 2
):
return True
if re.match(r"[1-9]+\|", argument_list[0]) and len(educatives_list) >= 1:
return True
if not Passe.is_valid_dot(argument_list[0]):
return False
value = argument_list[0].replace(".", "")
is_valid_routine = Passe.is_valid_routine_type(value)
if is_valid_routine:
return True
return Passe.is_valid_subset(argument_list[0])
return False
class TrainingProgram(Seasonisable, Markdownizable):
"""Classe représentant un entraînement (ensemble de passage).
"""Classe représentant ?????
TODO:
- renommer (supprimer/remettre) TrainingProgram en TrainingPasse

View File

@ -2,6 +2,7 @@ from django.contrib import admin
from .models import Gymnast
@admin.register(Gymnast)
class GymnastAdmin(admin.ModelAdmin):
model = Gymnast
@ -42,6 +43,3 @@ class GymnastAdmin(admin.ModelAdmin):
list_display = ("last_name", "first_name", "age", "email", "is_active")
list_filter = ("gender", "user__is_active")
search_fields = ("last_name", "first_name")
admin.site.register(Gymnast, GymnastAdmin)

View File

@ -31,6 +31,7 @@ class Gymnast(Markdownizable):
class Meta:
verbose_name = "Gymnast"
verbose_name_plural = "Gymnasts"
ordering = ["first_name", "last_name"]
user = models.OneToOneField(
User, on_delete=models.SET_NULL, related_name="gymnast", blank=True, null=True

View File

@ -18,6 +18,7 @@ from .models import (
# duplicate_record.short_description = 'Duplicate selected records'
@admin.register(EventType)
class EventTypeAdmin(admin.ModelAdmin):
model = EventType
@ -26,6 +27,7 @@ class EventTypeAdmin(admin.ModelAdmin):
search_fields = ("name", "acronym")
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
model = Event
@ -45,14 +47,10 @@ class EventAdmin(admin.ModelAdmin):
# filter_horizontal = ('gymnasts',)
@admin.register(EventParticipation)
class EventParticipationAdmin(admin.ModelAdmin):
model = EventParticipation
fields = ("event", "gymnast", "rank")
list_display = ("event", "gymnast", "rank")
autocomplete_fields = ("event", "gymnast")
admin.site.register(EventType, EventTypeAdmin)
admin.site.register(Event, EventAdmin)
admin.site.register(EventParticipation, EventParticipationAdmin)

View File

@ -3,12 +3,14 @@ from django_admin_listfilter_dropdown.filters import RelatedDropdownFilter
from .models import Profile, Notification, TrainerGymnast
@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
model = Profile
list_display = ("user", "template_color", "sidebar_color")
autocomplete_fields = ("user",)
@admin.register(Notification)
class NotificationAdmin(admin.ModelAdmin):
model = Notification
list_display = ("user", "gymnast", "functionality")
@ -20,6 +22,7 @@ class NotificationAdmin(admin.ModelAdmin):
)
@admin.register(TrainerGymnast)
class TrainerGymnastAdmin(admin.ModelAdmin):
model = TrainerGymnast
list_display = ("user", "gymnast")
@ -28,8 +31,3 @@ class TrainerGymnastAdmin(admin.ModelAdmin):
("user", RelatedDropdownFilter),
("gymnast", RelatedDropdownFilter),
)
admin.site.register(Profile, ProfileAdmin)
admin.site.register(Notification, NotificationAdmin)
admin.site.register(TrainerGymnast, TrainerGymnastAdmin)