Merge branch 'review/pylint' of grimbox.be:Sulley/Ultron
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Gregory Trullemans 2022-01-08 07:13:30 +01:00
commit cb37b56465
40 changed files with 312 additions and 322 deletions

View File

@ -87,7 +87,13 @@ disable=raw-checker-failed,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead
use-symbolic-message-instead,
empty-docstring,
missing-class-docstring,
missing-module-docstring,
missing-function-docstring,
consider-using-f-string,
duplicate-code,
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -15,15 +15,15 @@ class HomeTests(TestCase):
def test_home_view_anonymous_redirected_statuts_code(self):
url = reverse("home")
response = self.client.get(url)
self.assertEquals(response.status_code, 302)
self.assertEqual(response.status_code, 302)
def test_home_view_status_code_with_user_connected(self):
"""Note: This test will switch to green once we will get rid of whitenoise
See https://stackoverflow.com/questions/50658241/django-doesnt-load-static-files-valueerrormissing-staticfiles-manifest-entry
See https://stackoverflow.com/questions/50658241/django-doesnt-load-static-files-valueerrormissing-staticfiles-manifest-entry # pylint: disable=line-too-long
"""
login_result = self.client.login(username="jbond", password="007")
self.client.login(username="jbond", password="007")
url = reverse("home")
response = self.client.get(url, follow=True)
self.assertEquals(response.status_code, 200)
self.assertEqual(response.status_code, 200)

View File

@ -1,10 +1,8 @@
from datetime import datetime, timedelta, date
from datetime import datetime
from django.db.models import Q
from django.shortcuts import render
from django.template import RequestContext
from django.utils import timezone
from django.utils.html import format_html
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
@ -12,7 +10,7 @@ from django.views.decorators.http import require_http_methods
from ultron.objective.models import Routine
from ultron.profiles.models import Profile
from ultron.followup.models import Accident, Skill, MindState, Point
from ultron.followup.models import Skill, Point
from ultron.location.models import Place, Club
from ultron.people.models import Gymnast
from ultron.planning.models import Event
@ -43,8 +41,8 @@ def login(request):
pass
request.session["clubid"] = request.POST.get("clubid", None)
return HttpResponseRedirect("/")
else:
context = {"message": "Account disabled."}
context = {"message": "Account disabled."}
else:
context = {"message": "Wrong login/password."}
else:
@ -106,7 +104,8 @@ def home(request):
# check if gymnast have point
# ---------------------------
# 1. récupérer tous les évènements passés
# 2. pour chaque event, vérifier que tous les gymnastes renseignés dans les participants ont des points associés.
# 2. pour chaque event, vérifier que tous les gymnastes renseignés
# dans les participants ont des points associés.
# S'il n'y a pas de point, faire une alerte à l'utilisateur qui se connecte.
# Check if gymnast have update

View File

@ -1,5 +1,6 @@
from django.contrib import admin
from django.db.models import fields
from django_extensions.admin import ForeignKeyAutocompleteAdmin
from .models import (
Chrono,
@ -12,7 +13,6 @@ from .models import (
HeightWeight,
Plan
)
from django_extensions.admin import ForeignKeyAutocompleteAdmin
class ChronoAdmin(ForeignKeyAutocompleteAdmin):

View File

@ -1,10 +1,7 @@
# coding=UTF-8
from django import forms
from datetime import date
from django.db import models
from django.forms import fields, widgets
from django import forms
from .models import (
Chrono,
LearnedSkill,
@ -114,40 +111,23 @@ class ScoreForm(forms.ModelForm):
"event": forms.HiddenInput(),
"routine_type": forms.Select(attrs={"class": "form-control selectpicker"}),
"point_execution": forms.NumberInput(
attrs={
"class": "form-control",
"placeholder": "xx,xx",
"min": "0"
}
attrs={"class": "form-control", "placeholder": "xx,xx", "min": "0"}
),
"point_difficulty": forms.NumberInput(
attrs={
"class": "form-control",
"placeholder": "xx,xx",
"min": "0"
}
attrs={"class": "form-control", "placeholder": "xx,xx", "min": "0"}
),
"point_time_of_flight": forms.NumberInput(
attrs={
"class": "form-control",
"placeholder": "xx,xx",
"min": "0"
}
attrs={"class": "form-control", "placeholder": "xx,xx", "min": "0"}
),
"point_horizontal_displacement": forms.NumberInput(
attrs={
"class": "form-control",
"placeholder": "x,xx",
"min": "0"
}
attrs={"class": "form-control", "placeholder": "x,xx", "min": "0"}
),
"penality": forms.NumberInput(
attrs={
"class": "form-control",
"placeholder":
"xx,xx",
"placeholder": "xx,xx",
"value": "0",
"min": "0"
"min": "0",
}
),
"total": forms.TextInput(
@ -201,7 +181,7 @@ class AccidentForm(forms.ModelForm):
"informations": forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Informations about accident: context (why, where, …), consequencies, re-education exercices, …",
"placeholder": "Informations about accident: context (why, where, …), consequencies, re-education exercices, …", # pylint: disable=line-too-long
}
),
}
@ -244,16 +224,16 @@ class MindStateForm(forms.ModelForm):
"event": forms.HiddenInput(),
"score": forms.NumberInput(
attrs={
"class": "form-control",
"placeholder": "x",
"min": "0",
"max": "10"
"class": "form-control",
"placeholder": "x",
"min": "0",
"max": "10",
}
),
"informations": forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Informations about the psychological state of mind : context (why, where, …), possible consequencies, …",
"placeholder": "Informations about the psychological state of mind : context (why, where, …), possible consequencies, …", # pylint: disable=line-too-long
}
),
}
@ -343,7 +323,7 @@ class HeightWeightForm(forms.ModelForm):
"class": "form-control",
"placeholder": "xxx,x",
"min": "100",
"max": "220"
"max": "220",
}
),
"hips_height": forms.NumberInput(
@ -351,7 +331,7 @@ class HeightWeightForm(forms.ModelForm):
"class": "form-control",
"placeholder": "xxx,x",
"min": "50",
"max": "110"
"max": "110",
}
),
"weight": forms.NumberInput(
@ -359,7 +339,7 @@ class HeightWeightForm(forms.ModelForm):
"class": "form-control",
"placeholder": "xxx,x",
"min": "20",
"max": "110"
"max": "110",
}
),
}
@ -378,7 +358,14 @@ class HeightWeightForm(forms.ModelForm):
class NumberOfRoutineDoneForm(forms.ModelForm):
class Meta:
model = NumberOfRoutineDone
fields = ("gymnast", "routine", "routine_type", "date", "number_of_try", "number_of_successes")
fields = (
"gymnast",
"routine",
"routine_type",
"date",
"number_of_try",
"number_of_successes",
)
widgets = {
"gymnast": forms.HiddenInput(),
"routine": forms.HiddenInput(),
@ -393,7 +380,7 @@ class NumberOfRoutineDoneForm(forms.ModelForm):
"class": "form-control",
"placeholder": "x",
"min": "0",
"max": "50"
"max": "50",
}
),
"number_of_successes": forms.NumberInput(
@ -401,7 +388,7 @@ class NumberOfRoutineDoneForm(forms.ModelForm):
"class": "form-control",
"placeholder": "x",
"min": "0",
"max": "50"
"max": "50",
}
),
}
@ -448,7 +435,7 @@ class PlanForm(forms.ModelForm):
"cando": forms.Select(attrs={"class": "form-control selectpicker"}),
"is_done": forms.CheckboxInput(
attrs={"class": "form-control form-check-input ml-0 mt-0"}
)
),
}
gymnast_related = forms.CharField(

View File

@ -1,6 +1,7 @@
from django.db import models
from datetime import date
from django.db.models.deletion import CASCADE
from django.db import models
from ultron.tools.models import Markdownizable
from ultron.people.models import Gymnast

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,6 +1,4 @@
from django.urls import path, re_path
from ultron.followup.models import MindState
from django.urls import path
from . import views
@ -152,4 +150,4 @@ plan_urlpatterns = [
views.plan_create_or_update,
name="plan_update",
),
]
]

View File

@ -1,3 +1,5 @@
from datetime import datetime
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
@ -8,6 +10,7 @@ from django.urls import reverse
from ultron.people.models import Gymnast
from ultron.planning.models import Event
from ultron.objective.models import Skill
from .models import (
Plan,
Point,
@ -18,6 +21,7 @@ from .models import (
HeightWeight,
NumberOfRoutineDone,
)
from .forms import (
PlanForm,
ScoreForm,
@ -29,9 +33,6 @@ from .forms import (
NumberOfRoutineDoneForm,
)
from datetime import datetime
import simplejson
@login_required
@require_http_methods(["GET"])
@ -65,10 +66,7 @@ def chrono_create_or_update(request, chronoid=None, gymnast_id=None):
data = None
if gymnast_id is not None:
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
data = {
"gymnast": gymnast_id,
"gymnast_related": gymnast
}
data = {"gymnast": gymnast_id, "gymnast_related": gymnast}
if request.method == "POST":
form = ChronoForm(request.POST, instance=chrono)
@ -87,8 +85,8 @@ def chrono_create_or_update(request, chronoid=None, gymnast_id=None):
return HttpResponseRedirect(
"/gymnast/details/" + str(new_chrono.gymnast.id) + "/"
)
else:
print(form.errors)
print(form.errors)
else:
form = ChronoForm(instance=chrono, initial=data)
@ -116,12 +114,12 @@ def gymnast_learn_skill(request):
)
learned_skill.save()
return HttpResponse(status=200)
if gymnast_id:
print("Error : can not link Gymnast and skill. Missing Skill_ID.")
else:
if gymnast_id:
print("Error : can not link Gymnast and skill. Missing Skill_ID.")
else:
print("Error : can not link Gymnast and skill. Missing Gymnast_ID.")
return HttpResponse(status=500)
print("Error : can not link Gymnast and skill. Missing Gymnast_ID.")
return HttpResponse(status=500)
@login_required
@ -145,9 +143,11 @@ def learnedskill_create_or_update(request, gymnast_id=None):
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)))
else:
print(form.errors)
return HttpResponseRedirect(
reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,))
)
print(form.errors)
else:
form = LearnedSkillForm(initial=data)
@ -173,24 +173,23 @@ def score_create_or_update(request, scoreid=None, gymnast_id=None):
data = None
if gymnast_id is not None:
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
data = {
"gymnast": gymnast_id,
"gymnast_related": str(gymnast)
}
data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)}
if request.method == "POST":
form = ScoreForm(request.POST, instance=score)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)))
return HttpResponseRedirect(
reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,))
)
# return HttpResponseRedirect(
# "/gymnast/details/"
# + str(form.cleaned_data["gymnast"].id)
# + "/"
# )
else:
print(form.errors)
print(form.errors)
else:
form = ScoreForm(instance=score, initial=data)
@ -210,8 +209,7 @@ def score_listing(request, gymnast_id=None):
if pattern:
score_list = Point.objects.filter(
Q(event__icontains=pattern)
| Q(gymnast__icontains=pattern)
Q(event__icontains=pattern) | Q(gymnast__icontains=pattern)
)
elif gymnast_id:
score_list = Point.objects.filter(gymnast=gymnast_id)
@ -261,22 +259,20 @@ def accident_create_or_update(request, accidentid=None, gymnast_id=None):
data = None
if gymnast_id is not None:
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
data = {
"gymnast": gymnast_id,
"gymnast_related": str(gymnast)
}
data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)}
if request.method == "POST":
form = AccidentForm(request.POST, instance=accident)
if form.is_valid():
form.save()
if accidentid:
return HttpResponseRedirect("/accident/" + str(accidentid) + "/")
else:
return HttpResponseRedirect("/accident/")
else:
print(form.errors)
return HttpResponseRedirect("/accident/")
print(form.errors)
else:
form = AccidentForm(instance=accident, initial=data)
@ -314,32 +310,25 @@ def mindstate_listing(request, gymnast_id=None):
@login_required
@require_http_methods(["GET", "POST"])
def mindstate_create_or_update(request, mindstateid=None, gymnast_id=None, eventid=None):
def mindstate_create_or_update(
request, mindstateid=None, gymnast_id=None, eventid=None
):
"""
Formulaire de création d'un nouvel accident.
"""
if mindstateid:
mindstate = get_object_or_404(MindState, pk=mindstateid)
data = {
"gymnast_related": mindstate.gymnast,
"event_related": mindstate.event
}
data = {"gymnast_related": mindstate.gymnast, "event_related": mindstate.event}
else:
mindstate = None
data = None
if gymnast_id is not None:
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
data = {
"gymnast": gymnast_id,
"gymnast_related": str(gymnast)
}
data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)}
if eventid is not None:
event = get_object_or_404(Event, pk=eventid)
data = {
"event": eventid,
"event_related": str(event)
}
data = {"event": eventid, "event_related": str(event)}
if request.method == "POST":
form = MindStateForm(request.POST, instance=mindstate)
@ -348,10 +337,10 @@ def mindstate_create_or_update(request, mindstateid=None, gymnast_id=None, event
form.save()
if mindstateid:
return HttpResponseRedirect("/mindstate/" + str(mindstateid) + "/")
else:
return HttpResponseRedirect(reverse("mindstate_list"))
else:
print(form.errors)
return HttpResponseRedirect(reverse("mindstate_list"))
print(form.errors)
else:
form = MindStateForm(instance=mindstate, initial=data)
@ -401,25 +390,32 @@ def heightweight_create_or_update(request, heightweight_id=None, gymnast_id=None
heightweight = None
data = None
if gymnast_id:
heightweight = HeightWeight.objects.filter(gymnast=gymnast_id).order_by('-date').first()
heightweight = (
HeightWeight.objects.filter(gymnast=gymnast_id)
.order_by("-date")
.first()
)
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
data = {
"gymnast": gymnast_id,
"gymnast_related": str(gymnast)
}
data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)}
if request.method == "POST":
form = HeightWeightForm(request.POST, instance=heightweight)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)))
else:
print(form.errors)
return HttpResponseRedirect(
reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,))
)
print(form.errors)
else:
form = HeightWeightForm(instance=heightweight, initial=data)
context = {"form": form, "gymnast_id": gymnast_id, "heightweight_id": heightweight_id}
context = {
"form": form,
"gymnast_id": gymnast_id,
"heightweight_id": heightweight_id,
}
return render(request, "followup/heightweight/create.html", context)
@ -451,26 +447,25 @@ def routinedone_create_or_update(request, routinedone_id=None, gymnast_id=None):
"gymnast": routinedone.gymnast.id,
"gymnast_related": str(routinedone.gymnast),
"routine": routinedone.routine.id,
"routine_related": str(routinedone.routine)
"routine_related": str(routinedone.routine),
}
else:
routinedone = None
data = None
if gymnast_id is not None:
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
data = {
"gymnast": gymnast_id,
"gymnast_related": gymnast
}
data = {"gymnast": gymnast_id, "gymnast_related": gymnast}
if request.method == "POST":
form = NumberOfRoutineDoneForm(request.POST, instance=routinedone)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)))
else:
print(form.errors)
return HttpResponseRedirect(
reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,))
)
print(form.errors)
else:
form = NumberOfRoutineDoneForm(instance=routinedone, initial=data)

View File

@ -1,7 +1,6 @@
# coding=UTF-8
from django import forms
from datetime import date
from .models import Place

View File

@ -1,4 +1,3 @@
# coding=UTF-8
from django.db import models
@ -55,7 +54,8 @@ class Club(models.Model):
Représente un club. Un club est associé à un lieu. Pour faciliter les filtres,
un club peut être actif ou non.
.. todo:: Un club peut avoir plusieurs salle et une salle peut-être louée par plusieurs clubs... M2M ?
.. todo:: Un club peut avoir plusieurs salle
et une salle peut-être louée par plusieurs clubs... M2M ?
"""
class Meta:

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,4 +1,3 @@
# coding=UTF-8
from django.urls import path

View File

@ -1,21 +1,12 @@
from datetime import datetime, timedelta, date
from functools import reduce
import operator
from datetime import datetime
import simplejson
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
from django.contrib.auth.decorators import login_required
from django.db.models import Q, Count
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.template import RequestContext
from django.utils.html import format_html
from django.views.decorators.http import require_http_methods
from ultron.planning.models import (
Event,
)
from .models import (
Club,
Place,
@ -24,7 +15,7 @@ from .models import (
from .forms import PlaceForm
def __diffTime(end, start):
def __difference_between_times(end, start):
"""
Prend deux `datetime.time` en paramètre et calcul la différence entre les deux.
"""
@ -153,11 +144,11 @@ def club_lookup(request):
@login_required
def chooseStatistics(request):
def choose_statistics(request):
"""
Renvoie la liste des clubs et des saisons pour que l'utilisateur choisisse quelles statistiques il veut voir.
Renvoie la liste des clubs et des saisons pour que l'utilisateur
choisisse quelles statistiques il veut voir.
"""
pass
# year = int(request.GET.get("year", date.today().year))
@ -185,7 +176,6 @@ def club_statistics(request, clubid):
.. todo:: tenir compte de la saison.
"""
pass
# courses = Course.objects.filter(club__in=clubid).order_by(
@ -204,7 +194,9 @@ def club_statistics(request, clubid):
# list_of_gymnasts = Gymnast.objects.filter(to_gym__in=course.to_subgroup.all())
# gymnasts.extend(list_of_gymnasts)
# nbgymnast = len(list_of_gymnasts)
# # gymnasts = set(gymnasts.extend(Gymnast.objects.filter(to_gym__in=course.to_subgroup.all())))
# # gymnasts = set(gymnasts.extend(Gymnast.objects.filter(
# to_gym__in=course.to_subgroup.all()))
# )
# nbhour = __diffTime(course.hour_end, course.hour_begin) # timedelta
# totalHoursByWeek += nbhour.seconds
@ -292,7 +284,8 @@ def club_statistics(request, clubid):
# - gymnastsDict[gymnast.id]["nbattendance"]
# )
# # tmp = (gymnastsDict[gymnast.id]['nbhourattendance'].days * 24) + (gymnastsDict[gymnast.id]['nbhourattendance'].seconds/3600)
# # tmp = (gymnastsDict[gymnast.id]['nbhourattendance'].days * 24)
# + (gymnastsDict[gymnast.id]['nbhourattendance'].seconds/3600)
# gymnastsDict[gymnast.id]["nbhourattendance"] = (
# gymnastsDict[gymnast.id]["nbhourattendance"].days * 24
# ) + (gymnastsDict[gymnast.id]["nbhourattendance"].seconds / 3600)

View File

@ -1,8 +1,9 @@
from django.contrib import admin
from .models import Educative, TouchPosition, Skill, Routine, RoutineSkill
from django_extensions.admin import ForeignKeyAutocompleteAdmin
from .models import TouchPosition, Skill, Routine, RoutineSkill
class TouchPositionAdmin(admin.ModelAdmin):
model = TouchPosition
@ -13,10 +14,10 @@ class TouchPositionAdmin(admin.ModelAdmin):
list_filter = ("allowed_in_competition",)
def duplicate_skill(self, SkillAdmin, request, queryset):
for object in queryset:
object.id = None
object.save()
def duplicate_skill(modeladmin, request, queryset): # pylint: disable=unused-argument
for obj in queryset:
obj.id = None
obj.save()
class SkillAdmin(ForeignKeyAutocompleteAdmin):
@ -141,4 +142,4 @@ class RoutineSkillAdmin(admin.ModelAdmin):
admin.site.register(TouchPosition, TouchPositionAdmin)
admin.site.register(Skill, SkillAdmin)
admin.site.register(Routine, RoutineAdmin)
admin.site.register(RoutineSkill, RoutineSkillAdmin)
admin.site.register(RoutineSkill, RoutineSkillAdmin)

View File

@ -1,6 +1,6 @@
from django import forms
from datetime import date
from .models import Routine, RoutineSkill
from .models import Routine
class RoutineForm(forms.ModelForm):
@ -24,10 +24,10 @@ class RoutineForm(forms.ModelForm):
"informations": forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Informations about the psychological state of mind : context (why, where, …), possible consequencies, …",
"placeholder": "Informations about the psychological state of mind : context (why, where, …), possible consequencies, …", # pylint: disable=line-too-long
}
),
"difficulty": forms.HiddenInput(),
"level": forms.HiddenInput(),
"active": forms.HiddenInput(),
}
}

View File

@ -1,7 +1,9 @@
from django.db import models
from ultron.tools.models import Markdownizable
from django.db.models import Q, Count
from datetime import date
from ultron.tools.models import Markdownizable
class Educative(Markdownizable):
@ -68,7 +70,7 @@ def get_default_position():
"""
try:
return TouchPosition.objects.get(default=True).id
except:
except TouchPosition.DoesNotExist:
return None
@ -77,8 +79,13 @@ class Skill(Educative):
Classe représentant une figure (aka un saut acrobatique).
"""
# SELECT * FROM `objective_skill` WHERE educative_ptr_id NOT IN (SELECT DISTINCT(from_educative_id) FROM `objective_educative_prerequisite`)
# SELECT * FROM `objective_skill`, `objective_educative` WHERE `objective_educative`.id = `objective_skill`.educative_ptr_id
# SELECT * FROM `objective_skill`
# WHERE educative_ptr_id NOT IN (
# SELECT DISTINCT(from_educative_id) FROM `objective_educative_prerequisite`
# )
#
# SELECT * FROM `objective_skill`, `objective_educative`
# WHERE `objective_educative`.id = `objective_skill`.educative_ptr_id
class Meta:
verbose_name = "Skill"

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -30,13 +30,6 @@ routine_urlpatterns = [
views.link_skill_to_routine,
name="link_skill_to_routine",
),
# # path(r'<int:routineid>/del_skill/<int:skillid>/order/<int:order>/', views.delete_skill_from_routine, name="delete_skill_from_routine"),
# path(
# r"<int:routineid>/order/<int:order>/",
# views.delete_skill_from_routine,
# name="delete_skill_from_routine",
# ),
# path(r"suggest/", views.suggest_routine, name="suggest_routine",),
path(r"", views.routine_listing, name="routine_list"),
path(r"gymnast/<int:gymnast_id>", views.routine_listing, name="routine_list_for_gymnast"),
]

View File

@ -1,17 +1,17 @@
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
from django.http import HttpResponse, HttpResponseRedirect
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views.decorators.http import require_http_methods
from django.urls import reverse
from ultron.people.models import Gymnast
from .models import Skill, Routine, RoutineSkill
from ultron.followup.models import Plan
from .forms import RoutineForm
import simplejson
from ultron.people.models import Gymnast
from .forms import RoutineForm
from .models import Skill, Routine, RoutineSkill
@login_required
@require_http_methods(["GET"])
@ -27,8 +27,7 @@ def skill_lookup(request):
# Ignore queries shorter than length 2
if pattern is not None and len(pattern) > 2:
model_results = Skill.objects.filter(
Q(short_label__icontains=pattern)
| Q(long_label__icontains=pattern)
Q(short_label__icontains=pattern) | Q(long_label__icontains=pattern)
)
results = [
{"ID": x.id, "Name": str(x), "Notation": x.notation} for x in model_results
@ -52,8 +51,7 @@ def skill_listing(request, field=None, expression=None, value=None, level=None):
if pattern:
skill_list = Skill.objects.filter(
Q(long_label__icontains=pattern)
| Q(short_label__icontains=pattern)
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
)
elif field and expression and value:
kwargs = {"{0}__{1}".format(field, expression): value}
@ -70,9 +68,10 @@ def skill_listing(request, field=None, expression=None, value=None, level=None):
@login_required
@require_http_methods(["GET"])
def skill_details(request, skillid):
"""
Récupère toutes les informations d'un skill.
La méthode en profite pour vérifier les champs level, rank, age_boy et age_girl par rapport aux pré-requis.
"""Récupère toutes les informations d'un skill.
La méthode en profite pour vérifier les champs level, rank, age_boy et age_girl
par rapport aux pré-requis.
:param skillig: id d'un `skill`
:type skillid: int
@ -103,16 +102,14 @@ def skill_details(request, skillid):
@login_required
@require_http_methods(["GET"])
def routine_listing(request, gymnast_id=None):
"""
Récupère la liste des routines (série) suivant un pattern si celui-ci est définit.
"""Récupère la liste des routines suivant un pattern si celui-ci est défini
"""
gymnast = None
pattern = request.GET.get("pattern", None)
if pattern:
routine_list = Routine.objects.filter(
Q(long_label__icontains=pattern)
| Q(short_label__icontains=pattern)
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
)
else:
if gymnast_id:
@ -121,7 +118,11 @@ def routine_listing(request, gymnast_id=None):
else:
routine_list = Routine.objects.all()
context = {"routine_list": routine_list, "gymnast_id": gymnast_id, "gymnast": gymnast}
context = {
"routine_list": routine_list,
"gymnast_id": gymnast_id,
"gymnast": gymnast,
}
return render(request, "objectives/routines/list.html", context)
@ -135,8 +136,7 @@ def routine_lookup(request):
if pattern is not None and len(pattern) >= 3:
results = Routine.objects.filter(
Q(long_label__icontains=pattern)
| Q(short_label__icontains=pattern)
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
)
place_list = [{"id": x.id, "label": str(x)} for x in results]
@ -231,11 +231,11 @@ def routine_create_or_update(request, routineid=None):
routine = form.save()
# ici faire un FOR skill in form_skills_list:
# record.save() # ca sauve le record dans la table RoutineSkill
# something like this : http://stackoverflow.com/questions/3074938/django-m2m-form-save-through-table
# something like this : http://stackoverflow.com/questions/3074938/django-m2m-form-save-through-table # pylint: disable=line-too-long
# TO_FRED : can you help me ?
return HttpResponseRedirect(reverse("routine_details", args=(routine.pk,)))
else:
print(form.errors)
print(form.errors)
else:
form = RoutineForm(instance=routine)
@ -270,9 +270,5 @@ def link_skill_to_routine(request, routineid, skillid, order):
link, created = RoutineSkill.objects.get_or_create(
routine=routine, skill=skill, rank=order
)
# context = {'link':link, 'created':created}
# return render(request, 'compose_routine.html', context)
return HttpResponse(200, (link, created))
# except:
# return False

View File

@ -1,8 +1,10 @@
from datetime import date
from django.db import models
from django.db.models import Q, Count, Min
from django.db.models import Count
import pendulum
from datetime import date
from ultron.location.models import Club
from ultron.objective.models import Skill
@ -36,7 +38,7 @@ class Gymnast(Markdownizable):
hours_by_week = models.PositiveSmallIntegerField(verbose_name="# Hours by week")
def __str__(self):
return u"%s %s" % (self.first_name, self.last_name)
return "%s %s" % (self.first_name, self.last_name)
@property
def next_birthday(self):
@ -152,8 +154,9 @@ class Gymnast(Markdownizable):
def unknown_skill_lte_level(self, max_level_skill):
"""
Renvoie la liste des skill inférieurs ou égaux au niveau max que le gymnaste ne sait *pas* faire.
Liste des Skill que le gymnaste ne sait PAS faire, classé par niveau (ayant un niveau inférieur ou égal au niveau max du gym)
Liste des Skill que le gymnaste ne sait PAS faire/
Ces skills sont classé par niveau.
"""
return Skill.objects.filter(level__lte=max_level_skill).exclude(
known_by__gymnast=self.id
@ -161,8 +164,8 @@ class Gymnast(Markdownizable):
def unknown_skill_gt_level(self, max_level_skill):
"""
Renvoie la liste des skill inférieurs ou égaux au niveau max que le gymnaste ne sait *pas* faire.
Liste des Skill que le gymnaste ne sait PAS faire, classé par niveau (ayant un niveau inférieur ou égal au niveau max du gym)
Liste des Skill que le gymnaste ne sait PAS faire,
classé par niveau (ayant un niveau inférieur ou égal au niveau max du gym)
"""
return Skill.objects.filter(level__gt=max_level_skill).exclude(
known_by__gymnast=self.id
@ -177,7 +180,8 @@ class Gymnast(Markdownizable):
def unknown_skill_gt_rank(self, max_rank_skill):
"""
Liste des Skill que le gymnaste ne sais PAS faire (ayant un niveau plus grand que le niveau max du gym)
Liste des Skill que le gymnaste ne sais PAS faire
(ayant un niveau plus grand que le niveau max du gym)
"""
return Skill.objects.filter(level__gt=max_rank_skill).exclude(
known_by__gymnast=self.id
@ -272,15 +276,33 @@ class Gymnast(Markdownizable):
1. on va chercher le niveau maximum de skill que le gymnast sait faire
2. on va chercher le nombre de skill par niveau que le gymnast sait faire
nb_known_skill_by_level = [{'level': 1, 'nb_known_skill': 1}, {'level': 2, 'nb_known_skill': 2}]
nb_known_skill_by_level = [
{
'level': 1,
'nb_known_skill': 1
},
{
'level': 2,
'nb_known_skill': 2
}
]
3. si le niveau max est supérieur à 0
OUI:
a. on va chercher le nombre total des skills dont le niveau est inférieur ou égale au niveau max (cf. 1.)
a. on va chercher le nombre total des skills dont le niveau
est inférieur ou égale au niveau max (cf. 1.)
b. on va chercher le nombre de skill qu'il y a par niveau :
[{'level': 1, 'nb_skill': 1}, {'level': 2, 'nb_skill': 1}]
[
{
'level': 1, 'nb_skill': 1
},
{
'level': 2, 'nb_skill': 1
}
]
c. Pour chaque élément da la liste obtenue en b :
- si le niveau du skill est le même que le niveau courant ... je sais pas, je comprends plus...
- si le niveau du skill est le même que le niveau courant ...
je sais pas, je comprends plus...
- on incrémente j
NON:
@ -317,7 +339,7 @@ class Gymnast(Markdownizable):
"""
context = {}
min_rank_skill = self.min_rank_skill()
# min_rank_skill = self.min_rank_skill()
max_rank_skill = self.max_rank_skill()
context["max_rank_skill"] = max_rank_skill
nb_known_skill_by_rank = self.known_skill_by_rank()

View File

@ -13,7 +13,7 @@ def generate_level_chart_bar(gymnast_id):
"""
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
gymnast_known_skills = gymnast.known_skills.count()
# gymnast_known_skills = gymnast.known_skills.count()
context = gymnast.get_informations_from_level()
return context
return context

View File

@ -35,11 +35,17 @@ def generate_skill_doughnut(gymnast_id):
.distinct()
.count()
)
nb_skill = Skill.objects.all().count()
gymnast_nb_known_skills = (
LearnedSkill.objects.filter(gymnast=gymnast_id).distinct("skill").count()
)
nb_unknown_skill = nb_skill - gymnast_nb_known_skills
return {"nb_skill_masterised": nb_skill_masterised, "nb_skill_chained": nb_skill_chained, "nb_skill_without_help": nb_skill_without_help, "nb_skill_whith_help": nb_skill_whith_help, "nb_unknown_skill": nb_unknown_skill}
return {
"nb_skill_masterised": nb_skill_masterised,
"nb_skill_chained": nb_skill_chained,
"nb_skill_without_help": nb_skill_without_help,
"nb_skill_whith_help": nb_skill_whith_help,
"nb_unknown_skill": nb_unknown_skill,
}

View File

@ -1,49 +1,48 @@
from datetime import datetime
from django.test import TestCase
from django.urls import reverse
from ultron.people.models import Gymnast
class GymnastTestCase(TestCase):
def test_gymnast_tostring(self):
g = Gymnast(last_name="Pauchou", first_name="Fred")
self.assertEqual(str(g), "Fred Pauchou")
gymnast = Gymnast(last_name="Pauchou", first_name="Fred")
self.assertEqual(str(gymnast), "Fred Pauchou")
def test_gymnaste_get_age(self):
g = Gymnast(
gymnast = Gymnast(
last_name="Pauchou",
first_name="Fred",
birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
)
self.assertEqual(g.age, 36)
self.assertEqual(gymnast.age, 36)
def test_gymnaste_get_next_age(self):
g = Gymnast(
gymnast = Gymnast(
last_name="Pauchou",
first_name="Fred",
birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
)
self.assertEqual(g.next_age, 37)
self.assertEqual(gymnast.next_age, 37)
def test_gymnaste_next_birthday(self):
g = Gymnast(
gymnast = Gymnast(
last_name="Pauchou",
first_name="Fred",
birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
)
self.assertEqual(g.next_birthday, datetime.strptime("03/07/2022", "%d/%m/%Y"))
self.assertEqual(gymnast.next_birthday, datetime.strptime("03/07/2022", "%d/%m/%Y"))
def test_next_birthday_in_days(self):
g = Gymnast(
gymnast = Gymnast(
last_name="Pauchou",
first_name="Fred",
birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
)
self.assertEqual(g.next_birthday_in_days, 196)
self.assertEqual(gymnast.next_birthday_in_days, 196)
def test_min_rank_skill(self):
pass

View File

@ -1,4 +1,4 @@
from django.urls import path, re_path
from django.urls import path
from . import views

View File

@ -1,15 +1,14 @@
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
from django.http import HttpResponse, HttpResponseRedirect
from django.db.models import Q, F, Count, Min
from django.contrib import messages
from .models import Gymnast
from .forms import GymnastForm
from django.contrib.auth.decorators import login_required
from django.db.models import Q, F
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views.decorators.http import require_http_methods
import simplejson
import pendulum
from ultron.followup.models import Event
from ultron.objective.models import Educative
from ultron.followup.forms import GymnastHasRoutineForm
from ultron.followup.models import (
Chrono,
@ -20,11 +19,10 @@ from ultron.followup.models import (
Accident,
HeightWeight,
NumberOfRoutineDone,
Plan
)
import simplejson
import pendulum
from .models import Gymnast
from .forms import GymnastForm
@login_required
@ -80,16 +78,22 @@ def gymnast_details(request, gymnast_id, tab=None):
percentage_known_skill = (nb_known_skill / nb_skill) * 100
chronos_list = Chrono.objects.filter(gymnast=gymnast_id).order_by("-date")[:10]
straightjump_score = (
Chrono.objects.filter(gymnast=gymnast_id).filter(chrono_type=0).order_by("-date")
Chrono.objects.filter(gymnast=gymnast_id)
.filter(chrono_type=0)
.order_by("-date")
)
best_straightjump = (
Chrono.objects.filter(gymnast=gymnast_id).filter(chrono_type=0).order_by("-score")[:1]
Chrono.objects.filter(gymnast=gymnast_id)
.filter(chrono_type=0)
.order_by("-score")[:1]
)
best_routine = (
Chrono.objects.filter(gymnast=gymnast_id).filter(chrono_type=1).order_by("-score")[:1]
Chrono.objects.filter(gymnast=gymnast_id)
.filter(chrono_type=1)
.order_by("-score")[:1]
)
nb_unknown_skill = nb_skill - gymnast_nb_known_skills
# nb_unknown_skill = nb_skill - gymnast_nb_known_skills
context = {
"gymnast": gymnast,
@ -217,10 +221,18 @@ def gymnast_display_routines(request, gymnast_id):
Tag affichant les séries d'un gymnaste.
"""
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
ghr_list = gymnast.has_routine.prefetch_related("routine").filter(dateend__isnull=True)
routine_done_list = NumberOfRoutineDone.objects.filter(gymnast = gymnast_id).order_by("-date")[:8]
ghr_list = gymnast.has_routine.prefetch_related("routine").filter(
dateend__isnull=True
)
routine_done_list = NumberOfRoutineDone.objects.filter(gymnast=gymnast_id).order_by(
"-date"
)[:8]
context = {"ghr_list": ghr_list, "routine_done_list": routine_done_list, "gymnast_id": gymnast_id}
context = {
"ghr_list": ghr_list,
"routine_done_list": routine_done_list,
"gymnast_id": gymnast_id,
}
return render(request, "people/gymnasts/list_routine.html", context)
@ -243,9 +255,8 @@ def link_routine_to_gymnast(request, gymnast_id=None):
form.save()
if gymnast_id is not None:
return HttpResponseRedirect("/gymnast/details/" + str(gymnast_id) + "/")
else:
return HttpResponseRedirect("/gymnast/")
return HttpResponseRedirect("/gymnast/")
else:
form = GymnastHasRoutineForm(instance=gymnast, initial=data)
@ -273,8 +284,8 @@ def gymnast_create_or_update(request, gymnast_id=None):
if gymnast_form.is_valid():
gymnast = gymnast_form.save()
return HttpResponseRedirect("/gymnast/details/" + str(gymnast.id))
else:
print(gymnast_form.errors)
print(gymnast_form.errors)
form = GymnastForm(instance=gymnast, initial=data)
@ -285,9 +296,9 @@ def gymnast_create_or_update(request, gymnast_id=None):
@login_required
@require_http_methods(["GET"])
def gymnast_display_skill(request, gymnast_id):
"""
Tag affichant les statistiques de skill d'un gymnaste : le nombre de saut qu'il sait faire (total,
par niveau, par rank, ), calcule la complétude,
"""Tag affichant les statistiques de skill d'un gymnaste
Le nombre de saut qu'il sait faire (total, par niveau, par rank, …), calcule la complétude, …
.. todo:: Générer UNE fois la liste de skill que le gymnaste ne sait pas faire (1 query)
et les counts puis, dans le template on parcourt plusieurs fois cette même liste mais on

View File

@ -45,7 +45,7 @@ class EventAdmin(ForeignKeyAutocompleteAdmin):
# filter_horizontal = ('gymnasts',)
class Event_ParticipationAdmin(admin.ModelAdmin):
class EventParticipationAdmin(admin.ModelAdmin):
model = Event_Participation
fields = ("event", "gymnast", "rank")
@ -54,4 +54,4 @@ class Event_ParticipationAdmin(admin.ModelAdmin):
admin.site.register(EventType, EventTypeAdmin)
admin.site.register(Event, EventAdmin)
admin.site.register(Event_Participation, Event_ParticipationAdmin)
admin.site.register(Event_Participation, EventParticipationAdmin)

View File

@ -1,15 +1,14 @@
from datetime import date
from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
from ultron.people.models import Gymnast
from .models import Event
class EventForm(forms.ModelForm):
# gymnasts = forms.ModelMultipleChoiceField(queryset=Gymnast.objects.all(), widget=FilteredSelectMultiple('Gymnast(s)', is_stacked=False))
# gymnasts = forms.ModelMultipleChoiceField(queryset=Gymnast.objects.all(),
# widget=FilteredSelectMultiple('Gymnast(s)', is_stacked=False))
class Meta:
model = Event

View File

@ -1,6 +1,5 @@
from datetime import datetime, time
from django.contrib.auth import get_user_model
from django.db import models
import pendulum

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,4 +1,4 @@
from django.urls import path, re_path
from django.urls import path
from . import views

View File

@ -1,9 +1,10 @@
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render, get_object_or_404
from django.utils import timezone
from django.views.decorators.http import require_http_methods
import simplejson
# from followup.models import Chrono, Skill
from ultron.people.models import Gymnast
@ -17,7 +18,7 @@ from .forms import EventForm
# import pendulum
import simplejson
# import collections
# import locale
@ -64,8 +65,8 @@ def event_create_or_update(request, eventid=None):
if event_form.is_valid():
event = event_form.save()
return HttpResponseRedirect("/event/" + str(event.id) + "/")
else:
print(event_form.errors)
print(event_form.errors)
form = EventForm(instance=event, initial=data)
@ -89,7 +90,7 @@ def link_gymnast_to_event(request, eventid, gymnastid):
try:
gymnast = get_object_or_404(Gymnast, pk=gymnastid)
event = get_object_or_404(Event, pk=eventid)
link = Event_Participation.objects.create(gymnast=gymnast, event=event)
Event_Participation.objects.create(gymnast=gymnast, event=event)
except:
return HttpResponse(409)
@ -173,8 +174,8 @@ def event_detail(request, eventid=None):
event = Event.objects.get(pk=eventid)
gymnast_list = []
today = timezone.now().date()
tohour = timezone.now().time()
# today = timezone.now().date()
# tohour = timezone.now().time()
# if event.datebegin.date() > today:
# for gymnast in event.gymnasts.all():

View File

@ -1,7 +1,6 @@
# coding=UTF-8
from django import forms
from datetime import date
from .models import Profile

View File

@ -9,7 +9,7 @@ Les profils peuvent enregistrer les informations suivantes:
from django.contrib.auth import get_user_model
from django.db import models
from django.dispatch import receiver
User = get_user_model()

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,6 +1,6 @@
"""URLs définissant la gestion des profils utilisateurs."""
from django.urls import path, re_path
from django.urls import path
from . import views

View File

@ -2,14 +2,14 @@
from django.contrib.auth.decorators import login_required
from django.contrib.auth import get_user_model
from django.db.models import Q
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.views.decorators.http import require_http_methods
from .forms import ProfileForm
from .models import Profile
User = get_user_model()

View File

@ -1,7 +1,6 @@
"""Ensemble des classes d'utilité publique :-)"""
from django.db import models
from datetime import datetime, date, time, timedelta
from django.utils import timezone
import markdown
@ -135,8 +134,8 @@ class Temporizable(models.Model):
"""
if rest:
return get_number_of_weeks_between(the_date, self.dateend.date())
else:
return get_number_of_weeks_between(self.datebegin.date(), the_date)
return get_number_of_weeks_between(self.datebegin.date(), the_date)
class Markdownizable(models.Model):

View File

@ -1,6 +1,6 @@
from django import template
from django.utils.html import format_html
from django.urls import resolve, reverse
from django.urls import reverse
register = template.Library()
@ -19,33 +19,32 @@ def menuitem(context, url, css_class, title):
css_class,
title,
)
else:
if url == "/admin/":
return format_html(
'<li><a href="{}" target="_blank"><i class="{}"></i><p>{}</p></a></li>',
url,
css_class,
title,
)
else:
return format_html(
'<li><a href="{}"><i class="{}"></i><p>{}</p></a></li>',
url,
css_class,
title,
)
else: # si le contexte est "/"
if context.request.path == url:
if url == "/admin/":
return format_html(
'<li class="active"><a href="{}"><i class="{}"></i><p>{}</p></a></li>',
'<li><a href="{}" target="_blank"><i class="{}"></i><p>{}</p></a></li>',
url,
css_class,
title,
)
else:
return format_html(
return format_html(
'<li><a href="{}"><i class="{}"></i><p>{}</p></a></li>',
url,
css_class,
title,
)
if context.request.path == url: # si le contexte est "/"
return format_html(
'<li class="active"><a href="{}"><i class="{}"></i><p>{}</p></a></li>',
url,
css_class,
title,
)
return format_html(
'<li><a href="{}"><i class="{}"></i><p>{}</p></a></li>',
url,
css_class,
title,
)