Compare commits

...

25 Commits

Author SHA1 Message Date
Trullemans Gregory e61279b75b Migration to new device (part 2) 2022-01-14 11:54:10 +01:00
Trullemans Gregory 796ccc3f09 Migration to new device (part 2) 2022-01-14 11:42:39 +01:00
Trullemans Gregory c38c72d637 Migration to new device 2022-01-14 10:58:58 +01:00
Trullemans Gregory 16486064ce Minor improvement 2021-12-05 12:43:30 +01:00
Trullemans Gregory 0cb1a81215 Dump database 2021-10-29 09:24:41 +02:00
Trullemans Gregory 3b1862f9f6 Renaming ageBoy/ageGirl to age_boy/age_girl 2021-10-26 19:08:23 +02:00
Fred Pauchet 8b9e61ed2d Begin moving templates to their own subdirectory 2021-10-20 21:50:47 +02:00
Fred Pauchet 359c215924 Add a 'cancel' button on the places form 2021-10-20 21:47:24 +02:00
Fred Pauchet 76eb02585b Fix spelling (again) 2021-10-20 21:42:09 +02:00
Fred Pauchet 4d095fab31 Fixing spelling 2021-10-20 21:34:57 +02:00
Fred Pauchet 9381ebc593 Allow to set related user from the admin 2021-10-20 21:18:17 +02:00
Fred Pauchet f409ce4cc5 Fixing small bugs that prevent using the application
* Profiles do not exist when accessing settings
* Impossibility to change the sidebar color
* `verbose_name` on EventParticipation
* Fix CourseAdmin
* Fix PlanningLineAdmin
2021-10-19 20:56:38 +02:00
Fred Pauchet f057380fdb Enable whitenoise to serve static files 2021-10-14 21:51:50 +02:00
Fred Pauchet 3d919c7edf Clean up settings.py (a little bit) 2021-10-14 21:46:45 +02:00
Fred Pauchet fe4d2c620e Add psycopg2 as production requirement 2021-10-08 22:10:25 +02:00
Fred Pauchet 046755d987 Make it work on Heroku
Add gunicorn as requirements
Change khana.settings to config.settings
2021-10-08 22:04:44 +02:00
Fred Pauchet 54695787de Add requirements.txt to make buildpack compatible 2021-10-08 21:51:09 +02:00
Fred Pauchet 7bba598ab0 Building for heroku 2021-10-08 21:49:47 +02:00
Fred Pauchet ee2608d820 Add a Procfile for heroku to run correctly 2021-10-08 19:58:39 +02:00
Fred Pauchet dcb5cd0e9d Fix renamed fields (but not everywhere) 2021-10-05 21:28:23 +02:00
Fred Pauchet b700ca8b10 Except bare exception (instead of expression) 2021-10-05 21:16:51 +02:00
Fred Pauchet f278d4befa manage.py runserver and manage.py check say it's OK 2021-10-05 19:31:33 +02:00
Fred Pauchet 91ee5cdc65 pylint khana --errors-only says it's OK 2021-10-05 19:25:57 +02:00
Fred Pauchet 8e9b4b8aa7 Rewrite templatetags 2021-10-04 21:46:09 +02:00
Fred Pauchet e56660e626 Here we go again... 2021-10-04 21:39:37 +02:00
372 changed files with 2165 additions and 8961 deletions

View File

@ -232,7 +232,7 @@ single-line-if-stmt=no
[VARIABLES]
django-settings-module=khana.settings
django-settings-module=config.settings
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.

14
Makefile Normal file
View File

@ -0,0 +1,14 @@
# Makefile for khana
ifeq ($(shell which coverage >/dev/null 2>&1; echo $$?), 1)
$(error The 'coverage' command was not found. Make sure you have coverage installed)
endif
.PHONY: help coverage
help:
@echo " coverage to run coverage check of the source files."
coverage:
coverage run --source='.' manage.py test; coverage report; coverage html;
@echo "Testing of coverage in the sources finished."

1
Procfile Normal file
View File

@ -0,0 +1 @@
web: gunicorn config.wsgi

View File

@ -1,6 +1,6 @@
# Gestion de Gymnastes
Le but de cette application est de permettre une gestion des gymnastes tout au long de leur carrière : de leur premier cours à leur ultime compétition.
Le but de cette application est de permettre une gestion des gymnastes tout au long de leur carrière : de leur premier cours à leur ultime compétition.
(plus d'information à venir)
@ -63,4 +63,4 @@ Ce module permet de gérer les compétitions. (plus d'informations à venir)
## Personnes
Ce module permet de gérer les personnes. (plus d'informations à venir)
Ce module permet de gérer les personnes. (plus d'informations à venir)

View File

@ -1,94 +0,0 @@
-- phpMyAdmin SQL Dump
-- version 4.4.12
-- http://www.phpmyadmin.net
--
-- Client : localhost
-- Généré le : Mer 18 Juillet 2018 à 14:32
-- Version du serveur : 5.6.26
-- Version de PHP : 7.1.16
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Base de données : `ffg_judging`
--
-- --------------------------------------------------------
--
-- Structure de la table `competition_availablecategory`
--
CREATE TABLE IF NOT EXISTS `competition_availablecategory` (
`id` int(11) NOT NULL,
`is_active` tinyint(1) NOT NULL,
`category_id` int(11) DEFAULT NULL,
`division_id` int(11) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;
--
-- Contenu de la table `competition_availablecategory`
--
INSERT INTO `competition_availablecategory` (`id`, `is_active`, `category_id`, `division_id`) VALUES
(1, 1, 1, 5),
(2, 1, 2, 5),
(3, 1, 3, 5),
(4, 1, 4, 1),
(5, 1, 5, 1),
(6, 1, 6, 1),
(7, 1, 7, 1),
(8, 1, 8, 1),
(9, 1, 4, 2),
(10, 1, 5, 2),
(11, 1, 6, 2),
(12, 1, 7, 2),
(13, 1, 8, 2),
(14, 1, 9, 3),
(15, 1, 10, 3),
(16, 1, 11, 3),
(17, 1, 12, 3),
(18, 1, 13, 4);
--
-- Index pour les tables exportées
--
--
-- Index pour la table `competition_availablecategory`
--
ALTER TABLE `competition_availablecategory`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `competition_availablecat_division_id_category_id_7cbea8cc_uniq` (`division_id`,`category_id`),
ADD KEY `competition_availabl_category_id_d9b4ab8c_fk_competiti` (`category_id`);
--
-- AUTO_INCREMENT pour les tables exportées
--
--
-- AUTO_INCREMENT pour la table `competition_availablecategory`
--
ALTER TABLE `competition_availablecategory`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=19;
--
-- Contraintes pour les tables exportées
--
--
-- Contraintes pour la table `competition_availablecategory`
--
ALTER TABLE `competition_availablecategory`
ADD CONSTRAINT `competition_availabl_category_id_d9b4ab8c_fk_competiti` FOREIGN KEY (`category_id`) REFERENCES `competition_category` (`id`),
ADD CONSTRAINT `competition_availabl_division_id_88e96c01_fk_competiti` FOREIGN KEY (`division_id`) REFERENCES `competition_division` (`id`);
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

View File

@ -1,76 +0,0 @@
-- phpMyAdmin SQL Dump
-- version 4.4.12
-- http://www.phpmyadmin.net
--
-- Client : localhost
-- Généré le : Mer 18 Juillet 2018 à 14:31
-- Version du serveur : 5.6.26
-- Version de PHP : 7.1.16
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Base de données : `ffg_judging`
--
-- --------------------------------------------------------
--
-- Structure de la table `competition_category`
--
CREATE TABLE IF NOT EXISTS `competition_category` (
`id` int(11) NOT NULL,
`label` varchar(25) NOT NULL,
`acronym` varchar(7) NOT NULL,
`is_active` tinyint(1) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
--
-- Contenu de la table `competition_category`
--
INSERT INTO `competition_category` (`id`, `label`, `acronym`, `is_active`) VALUES
(1, '-8 ans', '-8', 1),
(2, '-9 ans', '-9', 1),
(3, '-10 ans', '-10', 1),
(4, '11 ans', '11', 1),
(5, '12 ans', '12', 1),
(6, '13-14 ans', '13-14', 1),
(7, 'Juniors', 'Ju', 1),
(8, 'Seniors', 'Se', 1),
(9, 'Niveau 1', 'N1', 1),
(10, 'Niveau 2', 'N2', 1),
(11, 'Niveau 3', 'N3', 1),
(12, 'Niveau 4', 'N4', 1),
(13, 'Bronze', 'Bronze', 1);
--
-- Index pour les tables exportées
--
--
-- Index pour la table `competition_category`
--
ALTER TABLE `competition_category`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT pour les tables exportées
--
--
-- AUTO_INCREMENT pour la table `competition_category`
--
ALTER TABLE `competition_category`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=14;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

View File

@ -1,62 +0,0 @@
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Base de données : `ffg_judging`
--
-- --------------------------------------------------------
--
-- Structure de la table `competition_division`
--
CREATE TABLE IF NOT EXISTS `competition_division` (
`id` int(11) NOT NULL,
`label` varchar(25) NOT NULL,
`acronym` varchar(5) NOT NULL,
`is_active` tinyint(1) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
--
-- Contenu de la table `competition_division`
--
INSERT INTO `competition_division` (`id`, `label`, `acronym`, `is_active`) VALUES
(1, 'Division 1', 'D1', 1),
(2, 'Division 2', 'D2', 1),
(3, 'Division 3', 'D3', 1),
(4, 'Division 4', 'D4', 1),
(5, 'Division Préparatoire', 'Prépa', 1);
--
-- Index pour les tables exportées
--
--
-- Index pour la table `competition_division`
--
ALTER TABLE `competition_division`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT pour les tables exportées
--
--
-- AUTO_INCREMENT pour la table `competition_division`
--
ALTER TABLE `competition_division`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=6;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

File diff suppressed because one or more lines are too long

View File

@ -1,66 +0,0 @@
"1","Delginiesse","Lou","Acrotramp Blocry","2007-05-30","F","121510","1","64","17"
"2","Delginiesse","Léa","Acrotramp Blocry","2004-04-01","F","121509","1","24","17"
"3","Gatelier","Léa","Acrotramp Blocry","2005-09-22","F","141305","1","51","17"
"4","Henry","Océane","Acrotramp Blocry","2003-05-26","F","99539","1","20","17"
"5","Herlant","Pénéline","Acrotramp Blocry","2006-08-30","F","122578","1","40","17"
"6","Reynaert","Sara","Acrotramp Blocry","2006-02-22","F","122573","1","61","17"
"7","Trejo","Metzli","Acrotramp Blocry","2004-06-17","F","141308","1","18","17"
"8","Beauclercq","Nathan","Acrotramp Blocry","2005-01-22","M","141301","1","17","17"
"9","De Mesmaeker","Adrien","Acrotramp Blocry","2004-04-09","M","122585","1","33","17"
"10","Detalle","Mattéo","Acrotramp Blocry","2006-10-25","M","122588","1","26","17"
"11","Garcia Moreau","Matéo","Acrotramp Blocry","2005-08-24","M","99555","1","37","17"
"12","Jarman","Joshua","Acrotramp Blocry","2006-01-10","M","141315","1","11","17"
"13","Pablos Martin","Hugo","Acrotramp Blocry","2004-08-12","M","141313","1","34","17"
"14","Van Poucke Cotton","Nelson","Acrotramp Blocry","2007-01-23","M","141306","1","57","17"
"15","Vanhuffel","Trystan","Acrotramp Blocry","2005-04-03","M","141303","1","21","17"
"16","Ingels","Cedric","CGOM ASBL","2007-06-08","M","82832","1","44","17"
"17","Charles","Angelique","Acrotramp Blocry","1992-08-10","F","10900","1","5","16"
"18","Leblanc","Olivia","Acrotramp Blocry","2000-12-19","F","112449","1","59","16"
"19","Luyten","Clara","Acrotramp Blocry","2003-07-23","F","112450","1","56","16"
"20","Tombeux","Juliette","Acrotramp Blocry","2005-12-28","F","99545","1","14","16"
"21","Eglem","Elisa","Aquilon Lillois","2005-02-24","F","133827","1","27","16"
"22","Geirnaert","Marine","Aquilon Lillois","2002-11-12","F","74759","1","13","16"
"23","Kraled","Anyssa","Aquilon Lillois","2004-10-18","F","96489","1","1","16"
"24","Catteau","Marine","CGOM ASBL","2004-02-05","F","135223","1","36","16"
"25","Gaeremynck","Laurine","CGOM ASBL","2002-03-01","F","10012","1","31","16"
"26","Ernaelsten","Perrine","TRAMPO NAMUR CLUB","2004-12-09","F","54365","1","4","16"
"27","Brodzinski","Barthélemy","Acrotramp Blocry","2002-06-24","M","58261","1","49","16"
"28","Goens","François","Acrotramp Blocry","2001-08-27","M","141309","1","29","16"
"29","Le Grelle","Jérémie","Acrotramp Blocry","2000-10-24","M","96217","1","39","16"
"30","Simon","Matthias","Acrotramp Blocry","2003-02-24","M","122574","1","60","16"
"31","Devos","Hugo","CGOM ASBL","2006-05-22","M","133688","1","28","16"
"32","Dhulst","Louis","CGOM ASBL","2006-09-27","M","127026","1","54","16"
"33","Jeunehomme","Nathan","TRAMPO NAMUR CLUB","2003-03-05","M","126730","1","23","16"
"34","Breugelmans","Baptiste","Acrotramp Blocry","2002-10-21","M","122559","1","53","15"
"35","Huwaerts","Leslie","Acrotramp Blocry","2001-12-08","F","71725","1","48","15"
"36","Gheysens","Julie","CGOM ASBL","2005-06-01","F","42242","1","2","15"
"37","Herpoel","Cyrielle","CGOM ASBL","2005-10-28","F","69829","1","43","15"
"38","Platteau Holvoet","Raphael","CGOM ASBL","2005-02-25","M","120509","1","45","15"
"39","Roussel","Leina","CGOM ASBL","2004-03-17","F","80890","1","3","18"
"40","Vanbiervliet","Zoë","CGOM ASBL","2000-12-11","F","10216","1","47","14"
"41","Vandenberghe","Zélie","CGOM ASBL","2003-08-07","F","42230","1","41","14"
"42","Jacquet","Quentin","Acrotramp Blocry","2004-10-19","M","99547","1","66","14"
"43","Moens","Aymeric","Acrotramp Blocry","2001-02-26","M","58294","1","65","12"
"44","Debusschere","Tom","CGOM ASBL","2003-02-11","M","91937","1","8","14"
"45","Jaillet","Robin","CGOM ASBL","2001-06-29","M","97949","1","25","14"
"46","Scokart","Romain","Flying Acrobatics Trampoline Club","2001-12-30","M","103263","1","42","14"
"47","Herlant","Ophéliane","Acrotramp Blocry","2008-11-03","F","122577","1","15","3"
"48","Lannoye","Cédric","Acrotramp Blocry","2008-06-30","M","141316","1","38","3"
"49","May","boris","Acrotramp Blocry","2008-06-17","M","144052","1","12","3"
"50","Mean","Juliette","Acrotramp Blocry","2008-02-05","F","54451","1","35","3"
"51","Reynart","Flore","Acrotramp Blocry","2008-07-15","F","141297","1","46","3"
"52","Romain","Mathis","Acrotramp Blocry","2008-02-28","M","141307","1","50","3"
"53","Cordier","Jeanne","Acrotramp Blocry","2010-01-10","F","144055","1","58","2"
"54","Demaret","Louise","Acrotramp Blocry","2009-09-27","F","96169","1","6","2"
"55","Ebertitan","Kenza","Acrotramp Blocry","2009-06-26","F","141304","1","55","2"
"56","Halin","Axel","Acrotramp Blocry","2009-02-13","M","141310","1","9","2"
"57","Renette","Zebulon","Acrotramp Blocry","2009-02-14","M","141317","1","63","2"
"58","Mertens","Déborah","Flying Acrobatics Trampoline Club","2009-11-04","F","119801","1","16","2"
"59","Salhi","Safwane","Flying Acrobatics Trampoline Club","2001-05-30","M","4283","1","30","7"
"60","Pesesse","Lucas","Flying Acrobatics Trampoline Club","2007-07-19","M","70414","1","32","4"
"61","Carlini","Gabriel","Flying Acrobatics Trampoline Club","2006-08-11","M","103673","1","22","5"
"62","Demacker","Naomy","CGOM ASBL","2004-04-14","F","123439","1","10","11"
"63","Damri","Neila","TRAMPO NAMUR CLUB","2004-06-14","F","25026","1","62","11"
"64","Granda Martinez","Noelia","Flying Acrobatics Trampoline Club","2003-01-28","F","66196","1","52","12"
"65","Vanholder","Noah","Flying Acrobatics Trampoline Club","2003-05-21","M","101994","1","7","12"
"66","Pirson","Maxime","TRAMPO NAMUR CLUB","2000-11-08","M","24332","1","19","13"
1 1 Delginiesse Lou Acrotramp Blocry 2007-05-30 F 121510 1 64 17
2 2 Delginiesse Léa Acrotramp Blocry 2004-04-01 F 121509 1 24 17
3 3 Gatelier Léa Acrotramp Blocry 2005-09-22 F 141305 1 51 17
4 4 Henry Océane Acrotramp Blocry 2003-05-26 F 99539 1 20 17
5 5 Herlant Pénéline Acrotramp Blocry 2006-08-30 F 122578 1 40 17
6 6 Reynaert Sara Acrotramp Blocry 2006-02-22 F 122573 1 61 17
7 7 Trejo Metzli Acrotramp Blocry 2004-06-17 F 141308 1 18 17
8 8 Beauclercq Nathan Acrotramp Blocry 2005-01-22 M 141301 1 17 17
9 9 De Mesmaeker Adrien Acrotramp Blocry 2004-04-09 M 122585 1 33 17
10 10 Detalle Mattéo Acrotramp Blocry 2006-10-25 M 122588 1 26 17
11 11 Garcia Moreau Matéo Acrotramp Blocry 2005-08-24 M 99555 1 37 17
12 12 Jarman Joshua Acrotramp Blocry 2006-01-10 M 141315 1 11 17
13 13 Pablos Martin Hugo Acrotramp Blocry 2004-08-12 M 141313 1 34 17
14 14 Van Poucke Cotton Nelson Acrotramp Blocry 2007-01-23 M 141306 1 57 17
15 15 Vanhuffel Trystan Acrotramp Blocry 2005-04-03 M 141303 1 21 17
16 16 Ingels Cedric CGOM ASBL 2007-06-08 M 82832 1 44 17
17 17 Charles Angelique Acrotramp Blocry 1992-08-10 F 10900 1 5 16
18 18 Leblanc Olivia Acrotramp Blocry 2000-12-19 F 112449 1 59 16
19 19 Luyten Clara Acrotramp Blocry 2003-07-23 F 112450 1 56 16
20 20 Tombeux Juliette Acrotramp Blocry 2005-12-28 F 99545 1 14 16
21 21 Eglem Elisa Aquilon Lillois 2005-02-24 F 133827 1 27 16
22 22 Geirnaert Marine Aquilon Lillois 2002-11-12 F 74759 1 13 16
23 23 Kraled Anyssa Aquilon Lillois 2004-10-18 F 96489 1 1 16
24 24 Catteau Marine CGOM ASBL 2004-02-05 F 135223 1 36 16
25 25 Gaeremynck Laurine CGOM ASBL 2002-03-01 F 10012 1 31 16
26 26 Ernaelsten Perrine TRAMPO NAMUR CLUB 2004-12-09 F 54365 1 4 16
27 27 Brodzinski Barthélemy Acrotramp Blocry 2002-06-24 M 58261 1 49 16
28 28 Goens François Acrotramp Blocry 2001-08-27 M 141309 1 29 16
29 29 Le Grelle Jérémie Acrotramp Blocry 2000-10-24 M 96217 1 39 16
30 30 Simon Matthias Acrotramp Blocry 2003-02-24 M 122574 1 60 16
31 31 Devos Hugo CGOM ASBL 2006-05-22 M 133688 1 28 16
32 32 Dhulst Louis CGOM ASBL 2006-09-27 M 127026 1 54 16
33 33 Jeunehomme Nathan TRAMPO NAMUR CLUB 2003-03-05 M 126730 1 23 16
34 34 Breugelmans Baptiste Acrotramp Blocry 2002-10-21 M 122559 1 53 15
35 35 Huwaerts Leslie Acrotramp Blocry 2001-12-08 F 71725 1 48 15
36 36 Gheysens Julie CGOM ASBL 2005-06-01 F 42242 1 2 15
37 37 Herpoel Cyrielle CGOM ASBL 2005-10-28 F 69829 1 43 15
38 38 Platteau Holvoet Raphael CGOM ASBL 2005-02-25 M 120509 1 45 15
39 39 Roussel Leina CGOM ASBL 2004-03-17 F 80890 1 3 18
40 40 Vanbiervliet Zoë CGOM ASBL 2000-12-11 F 10216 1 47 14
41 41 Vandenberghe Zélie CGOM ASBL 2003-08-07 F 42230 1 41 14
42 42 Jacquet Quentin Acrotramp Blocry 2004-10-19 M 99547 1 66 14
43 43 Moens Aymeric Acrotramp Blocry 2001-02-26 M 58294 1 65 12
44 44 Debusschere Tom CGOM ASBL 2003-02-11 M 91937 1 8 14
45 45 Jaillet Robin CGOM ASBL 2001-06-29 M 97949 1 25 14
46 46 Scokart Romain Flying Acrobatics Trampoline Club 2001-12-30 M 103263 1 42 14
47 47 Herlant Ophéliane Acrotramp Blocry 2008-11-03 F 122577 1 15 3
48 48 Lannoye Cédric Acrotramp Blocry 2008-06-30 M 141316 1 38 3
49 49 May boris Acrotramp Blocry 2008-06-17 M 144052 1 12 3
50 50 Mean Juliette Acrotramp Blocry 2008-02-05 F 54451 1 35 3
51 51 Reynart Flore Acrotramp Blocry 2008-07-15 F 141297 1 46 3
52 52 Romain Mathis Acrotramp Blocry 2008-02-28 M 141307 1 50 3
53 53 Cordier Jeanne Acrotramp Blocry 2010-01-10 F 144055 1 58 2
54 54 Demaret Louise Acrotramp Blocry 2009-09-27 F 96169 1 6 2
55 55 Ebertitan Kenza Acrotramp Blocry 2009-06-26 F 141304 1 55 2
56 56 Halin Axel Acrotramp Blocry 2009-02-13 M 141310 1 9 2
57 57 Renette Zebulon Acrotramp Blocry 2009-02-14 M 141317 1 63 2
58 58 Mertens Déborah Flying Acrobatics Trampoline Club 2009-11-04 F 119801 1 16 2
59 59 Salhi Safwane Flying Acrobatics Trampoline Club 2001-05-30 M 4283 1 30 7
60 60 Pesesse Lucas Flying Acrobatics Trampoline Club 2007-07-19 M 70414 1 32 4
61 61 Carlini Gabriel Flying Acrobatics Trampoline Club 2006-08-11 M 103673 1 22 5
62 62 Demacker Naomy CGOM ASBL 2004-04-14 F 123439 1 10 11
63 63 Damri Neila TRAMPO NAMUR CLUB 2004-06-14 F 25026 1 62 11
64 64 Granda Martinez Noelia Flying Acrobatics Trampoline Club 2003-01-28 F 66196 1 52 12
65 65 Vanholder Noah Flying Acrobatics Trampoline Club 2003-05-21 M 101994 1 7 12
66 66 Pirson Maxime TRAMPO NAMUR CLUB 2000-11-08 M 24332 1 19 13

View File

@ -1,146 +0,0 @@
-- phpMyAdmin SQL Dump
-- version 4.4.12
-- http://www.phpmyadmin.net
--
-- Client : localhost
-- Généré le : Mar 24 Juillet 2018 à 21:42
-- Version du serveur : 5.6.26
-- Version de PHP : 7.1.16
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Base de données : `ffg_judging`
--
-- --------------------------------------------------------
--
-- Structure de la table `person_gymnast`
--
CREATE TABLE IF NOT EXISTS `person_gymnast` (
`id` int(11) NOT NULL,
`lastname` varchar(255) NOT NULL,
`firstname` varchar(255) NOT NULL,
`club` varchar(255) NOT NULL,
`birthdate` date NOT NULL,
`gender` varchar(1) NOT NULL,
`licence` int(11) DEFAULT NULL,
`is_present` tinyint(1) NOT NULL,
`bib` int(11) DEFAULT NULL,
`category_id` int(11) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8;
--
-- Contenu de la table `person_gymnast`
--
INSERT INTO `person_gymnast` (`id`, `lastname`, `firstname`, `club`, `birthdate`, `gender`, `licence`, `is_present`, `bib`, `category_id`) VALUES
(1, 'Delginiesse', 'Lou', 'Acrotramp Blocry', '2007-05-30', 'F', 121510, 1, 64, 17),
(2, 'Delginiesse', 'Léa', 'Acrotramp Blocry', '2004-04-01', 'F', 121509, 1, 24, 17),
(3, 'Gatelier', 'Léa', 'Acrotramp Blocry', '2005-09-22', 'F', 141305, 1, 51, 17),
(4, 'Henry', 'Océane', 'Acrotramp Blocry', '2003-05-26', 'F', 99539, 1, 20, 17),
(5, 'Herlant', 'Pénéline', 'Acrotramp Blocry', '2006-08-30', 'F', 122578, 1, 40, 17),
(6, 'Reynaert', 'Sara', 'Acrotramp Blocry', '2006-02-22', 'F', 122573, 1, 61, 17),
(7, 'Trejo', 'Metzli', 'Acrotramp Blocry', '2004-06-17', 'F', 141308, 1, 18, 17),
(8, 'Beauclercq', 'Nathan', 'Acrotramp Blocry', '2005-01-22', 'M', 141301, 1, 17, 17),
(9, 'De Mesmaeker', 'Adrien', 'Acrotramp Blocry', '2004-04-09', 'M', 122585, 1, 33, 17),
(10, 'Detalle', 'Mattéo', 'Acrotramp Blocry', '2006-10-25', 'M', 122588, 1, 26, 17),
(11, 'Garcia Moreau', 'Matéo', 'Acrotramp Blocry', '2005-08-24', 'M', 99555, 1, 37, 17),
(12, 'Jarman', 'Joshua', 'Acrotramp Blocry', '2006-01-10', 'M', 141315, 1, 11, 17),
(13, 'Pablos Martin', 'Hugo', 'Acrotramp Blocry', '2004-08-12', 'M', 141313, 1, 34, 17),
(14, 'Van Poucke Cotton', 'Nelson', 'Acrotramp Blocry', '2007-01-23', 'M', 141306, 1, 57, 17),
(15, 'Vanhuffel', 'Trystan', 'Acrotramp Blocry', '2005-04-03', 'M', 141303, 1, 21, 17),
(16, 'Ingels', 'Cedric', 'CGOM ASBL', '2007-06-08', 'M', 82832, 1, 44, 17),
(17, 'Charles', 'Angelique', 'Acrotramp Blocry', '1992-08-10', 'F', 10900, 1, 5, 16),
(18, 'Leblanc', 'Olivia', 'Acrotramp Blocry', '2000-12-19', 'F', 112449, 1, 59, 16),
(19, 'Luyten', 'Clara', 'Acrotramp Blocry', '2003-07-23', 'F', 112450, 1, 56, 16),
(20, 'Tombeux', 'Juliette', 'Acrotramp Blocry', '2005-12-28', 'F', 99545, 1, 14, 16),
(21, 'Eglem', 'Elisa', 'Aquilon Lillois', '2005-02-24', 'F', 133827, 1, 27, 16),
(22, 'Geirnaert', 'Marine', 'Aquilon Lillois', '2002-11-12', 'F', 74759, 1, 13, 16),
(23, 'Kraled', 'Anyssa', 'Aquilon Lillois', '2004-10-18', 'F', 96489, 1, 1, 16),
(24, 'Catteau', 'Marine', 'CGOM ASBL', '2004-02-05', 'F', 135223, 1, 36, 16),
(25, 'Gaeremynck', 'Laurine', 'CGOM ASBL', '2002-03-01', 'F', 10012, 1, 31, 16),
(26, 'Ernaelsten', 'Perrine', 'TRAMPO NAMUR CLUB', '2004-12-09', 'F', 54365, 1, 4, 16),
(27, 'Brodzinski', 'Barthélemy', 'Acrotramp Blocry', '2002-06-24', 'M', 58261, 1, 49, 16),
(28, 'Goens', 'François', 'Acrotramp Blocry', '2001-08-27', 'M', 141309, 1, 29, 16),
(29, 'Le Grelle', 'Jérémie', 'Acrotramp Blocry', '2000-10-24', 'M', 96217, 1, 39, 16),
(30, 'Simon', 'Matthias', 'Acrotramp Blocry', '2003-02-24', 'M', 122574, 1, 60, 16),
(31, 'Devos', 'Hugo', 'CGOM ASBL', '2006-05-22', 'M', 133688, 1, 28, 16),
(32, 'Dhulst', 'Louis', 'CGOM ASBL', '2006-09-27', 'M', 127026, 1, 54, 16),
(33, 'Jeunehomme', 'Nathan', 'TRAMPO NAMUR CLUB', '2003-03-05', 'M', 126730, 1, 23, 16),
(34, 'Breugelmans', 'Baptiste', 'Acrotramp Blocry', '2002-10-21', 'M', 122559, 1, 53, 15),
(35, 'Huwaerts', 'Leslie', 'Acrotramp Blocry', '2001-12-08', 'F', 71725, 1, 48, 15),
(36, 'Gheysens', 'Julie', 'CGOM ASBL', '2005-06-01', 'F', 42242, 1, 2, 15),
(37, 'Herpoel', 'Cyrielle', 'CGOM ASBL', '2005-10-28', 'F', 69829, 1, 43, 15),
(38, 'Platteau Holvoet', 'Raphael', 'CGOM ASBL', '2005-02-25', 'M', 120509, 1, 45, 15),
(39, 'Roussel', 'Leina', 'CGOM ASBL', '2004-03-17', 'F', 80890, 1, 3, 18),
(40, 'Vanbiervliet', 'Zoë', 'CGOM ASBL', '2000-12-11', 'F', 10216, 1, 47, 14),
(41, 'Vandenberghe', 'Zélie', 'CGOM ASBL', '2003-08-07', 'F', 42230, 1, 41, 14),
(42, 'Jacquet', 'Quentin', 'Acrotramp Blocry', '2004-10-19', 'M', 99547, 1, 66, 14),
(43, 'Moens', 'Aymeric', 'Acrotramp Blocry', '2001-02-26', 'M', 58294, 1, 65, 12),
(44, 'Debusschere', 'Tom', 'CGOM ASBL', '2003-02-11', 'M', 91937, 1, 8, 14),
(45, 'Jaillet', 'Robin', 'CGOM ASBL', '2001-06-29', 'M', 97949, 1, 25, 14),
(46, 'Scokart', 'Romain', 'Flying Acrobatics Trampoline Club', '2001-12-30', 'M', 103263, 1, 42, 14),
(47, 'Herlant', 'Ophéliane', 'Acrotramp Blocry', '2008-11-03', 'F', 122577, 1, 15, 3),
(48, 'Lannoye', 'Cédric', 'Acrotramp Blocry', '2008-06-30', 'M', 141316, 1, 38, 3),
(49, 'May', 'boris', 'Acrotramp Blocry', '2008-06-17', 'M', 144052, 1, 12, 3),
(50, 'Mean', 'Juliette', 'Acrotramp Blocry', '2008-02-05', 'F', 54451, 1, 35, 3),
(51, 'Reynart', 'Flore', 'Acrotramp Blocry', '2008-07-15', 'F', 141297, 1, 46, 3),
(52, 'Romain', 'Mathis', 'Acrotramp Blocry', '2008-02-28', 'M', 141307, 1, 50, 3),
(53, 'Cordier', 'Jeanne', 'Acrotramp Blocry', '2010-01-10', 'F', 144055, 1, 58, 2),
(54, 'Demaret', 'Louise', 'Acrotramp Blocry', '2009-09-27', 'F', 96169, 1, 6, 2),
(55, 'Ebertitan', 'Kenza', 'Acrotramp Blocry', '2009-06-26', 'F', 141304, 1, 55, 2),
(56, 'Halin', 'Axel', 'Acrotramp Blocry', '2009-02-13', 'M', 141310, 1, 9, 2),
(57, 'Renette', 'Zebulon', 'Acrotramp Blocry', '2009-02-14', 'M', 141317, 1, 63, 2),
(58, 'Mertens', 'Déborah', 'Flying Acrobatics Trampoline Club', '2009-11-04', 'F', 119801, 1, 16, 2),
(59, 'Salhi', 'Safwane', 'Flying Acrobatics Trampoline Club', '2001-05-30', 'M', 4283, 1, 30, 7),
(60, 'Pesesse', 'Lucas', 'Flying Acrobatics Trampoline Club', '2007-07-19', 'M', 70414, 1, 32, 4),
(61, 'Carlini', 'Gabriel', 'Flying Acrobatics Trampoline Club', '2006-08-11', 'M', 103673, 1, 22, 5),
(62, 'Demacker', 'Naomy', 'CGOM ASBL', '2004-04-14', 'F', 123439, 1, 10, 11),
(63, 'Damri', 'Neila', 'TRAMPO NAMUR CLUB', '2004-06-14', 'F', 25026, 1, 62, 11),
(64, 'Granda Martinez', 'Noelia', 'Flying Acrobatics Trampoline Club', '2003-01-28', 'F', 66196, 1, 52, 12),
(65, 'Vanholder', 'Noah', 'Flying Acrobatics Trampoline Club', '2003-05-21', 'M', 101994, 1, 7, 12),
(66, 'Pirson', 'Maxime', 'TRAMPO NAMUR CLUB', '2000-11-08', 'M', 24332, 1, 19, 13);
--
-- Index pour les tables exportées
--
--
-- Index pour la table `person_gymnast`
--
ALTER TABLE `person_gymnast`
ADD PRIMARY KEY (`id`),
ADD KEY `person_gymnast_category_id_f8d57860_fk_technic_a` (`category_id`);
--
-- AUTO_INCREMENT pour les tables exportées
--
--
-- AUTO_INCREMENT pour la table `person_gymnast`
--
ALTER TABLE `person_gymnast`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=67;
--
-- Contraintes pour les tables exportées
--
--
-- Contraintes pour la table `person_gymnast`
--
ALTER TABLE `person_gymnast`
ADD CONSTRAINT `person_gymnast_category_id_f8d57860_fk_technic_a` FOREIGN KEY (`category_id`) REFERENCES `technic_availablecategory` (`id`);
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

View File

@ -10,54 +10,51 @@ For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
import environ
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
from pathlib import Path
env = environ.Env(
DEBUG=(bool, False)
)
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
env = environ.Env(DEBUG=(bool, False))
environ.Env.read_env()
DEBUG = env('DEBUG', default=True)
DEBUG = env("DEBUG", default=True)
SECRET_KEY = env('SECRET_KEY', default="6@9p0g-5ebcttbt$^*s4rda5!piezt6b7wj35g(+$mgz52k#d=")
SECRET_KEY = env(
"SECRET_KEY", default="6@9p0g-5ebcttbt$^*s4rda5!piezt6b7wj35g(+$mgz52k#d="
)
DATABASES = {
'default': env.db('DATABASE_URL', default='sqlite:///db.sqlite3')
}
DATABASES = {"default": env.db("DATABASE_URL", default="sqlite:///db.sqlite3")}
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
ALLOWED_HOSTS = ["*"]
# Application definition
INSTALLED_APPS = (
"django.contrib.contenttypes",
"django.contrib.admin",
# 'django.contrib.admindocs',
"django.contrib.auth",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"django_extensions",
"people",
"location",
"planning",
"objective",
"competition",
"profile",
"tools",
"communication",
"khana.people",
"khana.location",
"khana.planning",
"khana.objective",
"khana.competition",
"khana.profile",
"khana.tools",
"khana.communication",
"rest_framework",
)
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
#'django.middleware.csrf.CsrfViewMiddleware',
@ -66,7 +63,7 @@ MIDDLEWARE = [
#'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = "khana.urls"
ROOT_URLCONF = "config.urls"
TEMPLATES = [
{
@ -107,19 +104,20 @@ LOGIN_URL = "/login/"
LOGOUT_URL = "/logout/"
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
MEDIA_URL = "/media/" # https://media.khana.be
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
STATIC_URL = "/static/"
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
MEDIA_URL = "/media/" # https://media.khana.be
STATIC_ROOT = BASE_DIR / 'staticfiles'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
DEBUG_TOOLBAR_CONFIG = {
"JQUERY_URL": STATIC_URL + "js/jquery-2.1.4.min.js",
}
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

View File

@ -17,21 +17,22 @@ Including another URLconf
from django.urls import include, path
from django.conf.urls.static import static
from django.contrib import admin
from khana import settings
import khana.views
import planning.views
import people.views
import objective.views
import location.views
from config import settings
import location.urls
import people.urls
import objective.urls
import planning.urls
import competition.urls
import profile.urls
import communication.urls
import config.views
import khana.planning.views
import khana.people.views
import khana.objective.views
import khana.location.views
import khana.location.urls
import khana.people.urls
import khana.objective.urls
import khana.planning.urls
import khana.competition.urls
import khana.profile.urls
import khana.communication.urls
# import planningline_urlpatterns
@ -45,45 +46,45 @@ urlpatterns = [
path(r"admin/", admin.site.urls),
# url(r'^admin/jsi18n/$', include('django.views.i18n.javascript_catalog')), # pour le "ModelMultipleChoiceField" de event.forms
# Profile list
path(r"profile/", include(profile.urls.profile_urlpatterns)),
path(r"profile/", include(khana.profile.urls.profile_urlpatterns)),
# Attendance list
path(r"attendance/", include(planning.urls.attendance_urlpatterns)),
path(r"attendance/", include(khana.planning.urls.attendance_urlpatterns)),
# About competition
path(r"score/", include(competition.urls.score_urlpatterns)),
path(r"score/", include(khana.competition.urls.score_urlpatterns)),
# About gymnast
path(r"gymnast/", include(people.urls.people_urlpatterns)),
path(r"gymnast/", include(khana.people.urls.people_urlpatterns)),
# About event
path(r"event/", include(planning.urls.event_urlpatterns)),
path(r"event/", include(khana.planning.urls.event_urlpatterns)),
# About skill
path(r"skill/", include(objective.urls.skill_urlpatterns)),
path(r"skill/", include(khana.objective.urls.skill_urlpatterns)),
# About chrono
path(r"chrono/", include(objective.urls.chrono_urlpatterns)),
path(r"chrono/", include(khana.objective.urls.chrono_urlpatterns)),
# About skill
path(r"training/", include(planning.urls.training_urlpatterns)),
path(r"training/", include(khana.planning.urls.training_urlpatterns)),
# About routine
path(r"routine/", include(objective.urls.routine_urlpatterns)),
path(r"routine/", include(khana.objective.urls.routine_urlpatterns)),
# About accident
path(r"accident/", include(people.urls.accident_urlpatterns)),
path(r"accident/", include(khana.people.urls.accident_urlpatterns)),
# About unavailability
path(r"unavailability/", include(planning.urls.unavailability_urlpatterns)),
path(r"unavailability/", include(khana.planning.urls.unavailability_urlpatterns)),
# About planningline
path(r"program/", include(planning.urls.planningline_urlpatterns)),
path(r"program/", include(khana.planning.urls.planningline_urlpatterns)),
# About course
path(r"course/", include(planning.urls.course_urlpatterns)),
path(r"messages/", include(communication.urls.message_urlpatterns)),
path(r"course/", include(khana.planning.urls.course_urlpatterns)),
path(r"messages/", include(khana.communication.urls.message_urlpatterns)),
# About Location
path(r"place/", include(location.urls.place_urlpatterns)),
path(r"country/", include(location.urls.country_urlpatterns)),
path(r"club/", include(location.urls.club_urlpatterns)),
path(r"place/", include(khana.location.urls.place_urlpatterns)),
path(r"country/", include(khana.location.urls.country_urlpatterns)),
path(r"club/", include(khana.location.urls.club_urlpatterns)),
# url(r'^club/', location.views.chooseStatistics),
# url(r'^club/(?P<clubid>[0-9]+)', location.views.club_statistics),
# Global search
path(r"search/", khana.views.search, name="global_search"),
path(r"search/", config.views.search, name="global_search"),
# login & logout
path(r"login/", khana.views.login, name="login"),
path(r"logout/", khana.views.logout, name="logout"),
path(r"login/", config.views.login, name="login"),
path(r"logout/", config.views.logout, name="logout"),
# Home page
path(r"", khana.views.home, name="home"),
path(r"", config.views.home, name="home"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# if settings.DEBUG:

View File

@ -1,4 +1,8 @@
# coding=UTF-8
from datetime import datetime, timedelta, date
from functools import reduce
import operator
from django.db.models import Q
from django.shortcuts import render
from django.template import RequestContext
@ -9,23 +13,20 @@ from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
from datetime import datetime, timedelta, date
from functools import reduce
import operator
import pendulum
from planning.models import (
from khana.planning.models import (
Season,
Event,
Unavailability,
Course,
get_number_of_weeks_between,
)
from people.models import Gymnast, Accident # people model
from location.models import Club # location model
from objective.models import Skill, Routine # objective model
from profile.models import Profile
from communication.views import get_number_of_unread_message
import pendulum
from khana.people.models import Gymnast, Accident # people model
from khana.location.models import Club # location model
from khana.objective.models import Skill, Routine # objective model
from khana.profile.models import Profile
from khana.communication.views import get_number_of_unread_message
def login(request):
@ -49,7 +50,7 @@ def login(request):
request.session["template"] = profile.template_color
request.session["sidebar"] = profile.sidebar_color
request.session["is_sidebar_minified"] = profile.is_sidebar_minified
except expression as identifier:
except Exception:
pass
request.session["clubid"] = request.POST.get("clubid", None)
return HttpResponseRedirect("/")
@ -159,10 +160,10 @@ def home(request):
try:
season = Season.objects.get(datebegin__lte=today, dateend__gte=today)
except Season.DoesNotExist:
context = {"error": "No season founded."}
context = {"error": "No season found."}
return render(request, "index.html", context)
except Season.MultipleObjectsReturned:
context = {"error": "Multiple season founded."}
context = {"error": "Multiple season found."}
return render(request, "index.html", context)
week_number = season.week_number_from_begin(today)
@ -246,7 +247,8 @@ def search(request):
name__icontains=pattern
) # ou gymnaste qui y participe !
gymnast_list = Gymnast.objects.filter(
Q(user__last_name__icontains=pattern) | Q(user__first_name__icontains=pattern)
Q(user__last_name__icontains=pattern)
| Q(user__first_name__icontains=pattern)
)
accident_list = Accident.objects.filter(
Q(gymnast__user__last_name__icontains=pattern)

View File

@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "khana.settings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
application = get_wsgi_application()

1
db.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -9,6 +9,7 @@ from .models import Message
class MessageAdmin(admin.ModelAdmin):
"""La classe `MessageAdmin` contrôle la gestion des messages
"""
list_display = ("sender", "recipient", "written_at", "is_read", "read_at")
ordering = ("written_at", "sender")
search_fields = ("sender", "recipient", "message_title")

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class CommunicationConfig(AppConfig):
name = "communication"
name = "khana.communication"

View File

@ -8,6 +8,7 @@ from .models import Message
class MessageForm(forms.ModelForm):
"""Formulaire de base pour la création et la modification de messages
"""
class Meta:
model = Message
fields = (

View File

@ -0,0 +1,63 @@
# Generated by Django 3.2.2 on 2021-05-13 10:58
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("communication", "0002_auto_20190413_1028"),
]
operations = [
migrations.RenameField(
model_name="message", old_name="message_body", new_name="body",
),
migrations.RenameField(
model_name="message", old_name="date_of_reading", new_name="read_at",
),
migrations.RenameField(
model_name="message", old_name="message_title", new_name="title",
),
migrations.RenameField(
model_name="message", old_name="date_of_writing", new_name="written_at",
),
migrations.RemoveField(model_name="message", name="is_read",),
migrations.RemoveField(model_name="message", name="reader",),
migrations.RemoveField(model_name="message", name="writer",),
migrations.AddField(
model_name="message",
name="content",
field=models.TextField(
blank=True,
help_text="Seul le MarkDown simple est accepté",
null=True,
verbose_name="Comments",
),
),
migrations.AddField(
model_name="message",
name="recipient",
field=models.ForeignKey(
default=1,
on_delete=django.db.models.deletion.CASCADE,
related_name="received_messages",
to="auth.user",
),
preserve_default=False,
),
migrations.AddField(
model_name="message",
name="sender",
field=models.ForeignKey(
default=1,
on_delete=django.db.models.deletion.CASCADE,
related_name="sent_messages",
to="auth.user",
),
preserve_default=False,
),
]

View File

@ -12,7 +12,7 @@ from datetime import datetime
from django.db import models
from django.contrib.auth import get_user_model
from base.models import Markdownizable
from khana.base.models import Markdownizable
User = get_user_model()
@ -33,13 +33,11 @@ class Message(Markdownizable):
sender = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="sent_messages"
)
written_at = models.DateTimeField(
auto_now_add=True, verbose_name="Date of writing"
)
recipient = models.ForeignKey(User, on_delete=models.CASCADE, related_name="received_messages")
read_at = models.DateTimeField(
auto_now=True, verbose_name="Date of reading"
written_at = models.DateTimeField(auto_now_add=True, verbose_name="Date of writing")
recipient = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="received_messages"
)
read_at = models.DateTimeField(auto_now=True, verbose_name="Date of reading")
title = models.CharField(max_length=255, verbose_name="Title")
body = models.TextField(null=True, blank=True, verbose_name="Message")

View File

@ -14,6 +14,6 @@ def test_message_to_string():
"""Vérifie la représentation textuelle d'un message
"""
timing = datetime.now()
user = User(username='fred', password='fredpassword')
user = User(username="fred", password="fredpassword")
message = Message(sender=user, written_at=timing, title="test")
assert str(message) == "fred - " + str(timing) + " : test"

View File

@ -0,0 +1,92 @@
"""Vues et fonctions pour tout ce qui touche à la communication entre plusieurs utilisateurs."""
from datetime import datetime
from django.contrib.auth.decorators import login_required
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 .forms import MessageForm
from .models import Message
@login_required
def get_number_of_unread_message(request):
"""Récupère le nombre de messages non lus associés à l'utilisateur en session.
"""
return (
Message.objects.filter(recipient=request.user)
.filter(read_at__isnull=True)
.count()
)
@login_required
@require_http_methods(["GET"])
def get_received_messages(request):
"""Récupère des messages recus pour l'utilisateur connecté.
"""
return request.user.received_messages.all()
@login_required
@require_http_methods(["GET"])
def get_sent_messages(request):
"""Récupère des messages envoyés par l'utilisateur connecté.
"""
return request.user.sent_messages.all()
@login_required
@require_http_methods(["GET"])
def get_message_details(request, messageid):
"""Récupère les détails (l'affichage ?) d'un message.
"""
message = get_object_or_404(Message, pk=messageid)
if not message.read_at and message.recipient == request.user.id:
message.read_at = datetime.now()
message.save()
context = {"message": message, "type": None}
return render(request, "message_details.html", context)
@login_required
@require_http_methods(["POST"])
def delete_message(request, messageid):
"""Supprime le message dont la clé est passée en paramètre.
"""
try:
message = Message.objects.get(pk=messageid)
if message.sender == request.user or message.recipient == request.user:
message.delete()
else:
return HttpResponse(401)
except:
return HttpResponse(400)
return HttpResponse(200)
@login_required
@require_http_methods(["GET", "POST"])
def compose_message(request):
"""Permet à l'utilisateur connecté de rédiger un nouveau message.
"""
if request.method == "POST":
form = MessageForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("sent_messages"))
print("Invalid form")
else:
form = MessageForm()
context = {"form": form, "writer": request.user.id}
return render(request, "message_create.html", context)

View File

@ -15,7 +15,6 @@ class PointAdmin(admin.ModelAdmin):
"total",
)
ordering = ("gymnast",)
# search_fields = ('longLabel', 'shortLabel')
list_filter = ("gymnast", "event", "routine_type")

View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class CompetitionConfig(AppConfig):
name = "khana.competition"

View File

@ -1,4 +1,3 @@
# coding=UTF-8
from django.db import models
@ -14,7 +13,6 @@ class Point(models.Model):
"people.Gymnast", on_delete=models.CASCADE, default=None
)
event = models.ForeignKey("planning.Event", on_delete=models.CASCADE, default=None)
# routine=models.ForeignKey('objective.Routine')
routine_type = models.PositiveSmallIntegerField(choices=ROUTINETYPE_CHOICE)
point_execution = models.DecimalField(max_digits=5, decimal_places=3)
point_difficulty = models.DecimalField(max_digits=3, decimal_places=1)
@ -24,9 +22,8 @@ class Point(models.Model):
total = models.DecimalField(max_digits=6, decimal_places=3)
def __str__(self):
return "%s, %s - %s" % (
self.gymnast.lastname,
self.gymnast.firstname,
return "%s - %s" % (
self.gymnast,
self.total,
)

View File

@ -1,12 +1,7 @@
# coding=UTF-8
import pytest
from .models import (
Point,
Competition,
Division,
Level
)
from .models import Point, Competition, Division, Level
# class TestModelCompetition(TestCase):
@ -14,6 +9,7 @@ from .models import (
# Tests relatifs à la classe `Compétition`.
# """
def test_competition_str_():
""" Vérifie la représentation textuelle de la classe. """
competition = Competition(name="Belgian Open Trampoline", acronym="BOT")
@ -25,6 +21,7 @@ def test_competition_str_():
# Tests relatifs à la classe `Division`.
# """
def test_division_str_():
""" Vérifie la représentation textuelle de la classe. """
competition = Competition(name="Belgian Open Trampoline", acronym="BOT")
@ -37,6 +34,7 @@ def test_division_str_():
# Tests relatifs à la classe `Level`.
# """
def test_level_str_():
""" Vérifie la représentation textuelle de la classe. """
competition = Competition(name="Belgian Open Trampoline", acronym="BOT")

View File

@ -1,4 +1,3 @@
# coding=UTF-8
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
@ -6,9 +5,10 @@ from django.http import HttpResponse, HttpResponseRedirect
from django.views.decorators.http import require_http_methods
from django.db.models import Q
from khana.people.models import Gymnast
from .forms import ScoreForm
from .models import Point
from people.models import Gymnast
@login_required

5
khana/location/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class LocationConfig(AppConfig):
name = "khana.location"

View File

@ -8,10 +8,7 @@ from ..models import Club, Country, Place
class TestCountry(TestCase):
def test_str_should_contain_name_and_iso2(self):
country = Country.objects.create(
nameus="Belgium",
namefr="Belgique",
isonum=56,
iso2="BE"
nameus="Belgium", namefr="Belgique", isonum=56, iso2="BE"
)
self.assertEqual(str(country), "Belgique (BE)")
@ -23,11 +20,8 @@ class TestPlace(TestCase):
name="Heaven",
postal=1080,
country=Country.objects.create(
nameus="Belgium",
namefr="Belgique",
isonum=56,
iso2="BE"
)
nameus="Belgium", namefr="Belgique", isonum=56, iso2="BE"
),
)
self.assertEqual(str(place), "Heaven (?)")
@ -41,12 +35,9 @@ class TestClub(TestCase):
name="Heaven",
postal=1080,
country=Country.objects.create(
nameus="Belgium",
namefr="Belgique",
isonum=56,
iso2="BE"
)
)
nameus="Belgium", namefr="Belgique", isonum=56, iso2="BE"
),
),
)
self.assertEqual(str(club), "RSCA (à ?)")
self.assertEqual(str(club), "RSCA (à ?)")

View File

@ -1,10 +1,6 @@
# coding=UTF-8
from .models import (
Club,
Place,
Country
)
from .models import Club, Place, Country
import pytest
# class GymnastTestCase():
@ -12,11 +8,13 @@ def test_country_tostring():
c = Country(namefr="Belgique", iso2="56")
assert str(c) == "Belgique (56)"
def test_place_tostring():
p = Place(name="FATC", city="Lillois")
assert str(p) == "FATC (Lillois)"
def test_club_tostring():
p = Place(name="FATC", city="Lillois")
club = Club(place=p, name="FATC2")
assert str(club) == "FATC2 (à Lillois)"
assert str(club) == "FATC2 (à Lillois)"

View File

@ -1,34 +1,35 @@
# coding=UTF-8
from django.db.models import Q, Count
from django.shortcuts import render, get_object_or_404
from django.template import RequestContext
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 HttpResponse, HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
from datetime import datetime, timedelta, date
from functools import reduce
import operator
import simplejson
from planning.models import (
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.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 khana.planning.models import (
Event,
Unavailability,
Course,
Subgroup,
Training,
) # planning model
from people.models import Gymnast, Accident # people model
)
from khana.objective.models import Skill, Routine
from khana.people.models import Gymnast, Accident
from .models import (
Club,
Place,
Country,
)
from .forms import PlaceForm
from objective.models import Skill, Routine # objective model
def __diffTime(end, start):
@ -87,7 +88,7 @@ def place_listing(request):
"""
place_list = Place.objects.all()
context = {"place_list": place_list}
return render(request, "place_list.html", context)
return render(request, "places/list.html", context)
@login_required
@ -115,7 +116,7 @@ def place_create_or_update(request, placeid=None):
form = PlaceForm(instance=place, initial=data)
context = {"form": form, "placeid": placeid}
return render(request, "place_create.html", context)
return render(request, "places/create.html", context)
@login_required
@ -126,7 +127,7 @@ def place_details(request, placeid):
"""
place = get_object_or_404(Place, pk=placeid)
context = {"place": place}
return render(request, "place_details.html", context)
return render(request, "places/details.html", context)
@login_required

View File

@ -1,7 +1,8 @@
import math
from people.models import Gymnast
from objectives.models import Skill
from khana.people.models import Gymnast
from khana.objective.models import Skill
def suggest_routine(
@ -22,7 +23,7 @@ def suggest_routine(
logic (bool): indique si la série doit suivre certaines règles de logique (sportive).
gymnast (gymnast): gymnaste.
last_jump (skill): dernier saut sélectionné pour la série.
Returns:
??? (list): liste des séries correspondantes aux criètres.
"""
@ -58,16 +59,17 @@ def suggest_routine(
for skill in skill_list:
current_routine.append(skill)
current_routine.append(
self.suggest_routine(
request,
total_difficulty_score - skill.difficulty,
max_difficulty_score,
routine_length - 1,
competition,
logic,
gymnast,
skill,
)
None
# suggest_routine()
# request,
# total_difficulty_score - skill.difficulty,
# max_difficulty_score,
# routine_length - 1,
# competition,
# logic,
# gymnast,
# skill,
# )
)
current_routine.pop()
# def knapSack(W, wt, val, n):

View File

@ -1,6 +1,6 @@
from django.contrib import admin
# Register your models here.
from .models import (
Educative,
TouchPosition,
@ -30,12 +30,8 @@ def duplicate_skill(self, SkillAdmin, request, queryset):
class SkillAdmin(ForeignKeyAutocompleteAdmin):
model = Skill
# related_search_fields = {
# 'departure': ('label', 'short_label'),
# 'landing': ('label', 'short_label')
# }
fields = (
"label",
"long_label",
"short_label",
"information",
"departure",
@ -57,7 +53,7 @@ class SkillAdmin(ForeignKeyAutocompleteAdmin):
)
list_display = (
"label",
"long_label",
"difficulty",
"is_competitive",
"level",
@ -66,9 +62,9 @@ class SkillAdmin(ForeignKeyAutocompleteAdmin):
"age_boy",
"age_girl",
)
# list_display = ('label', 'short_label', 'prerequisite')
ordering = ("label", "short_label")
search_fields = ("rank", "label", "short_label")
ordering = ("long_label", "short_label")
search_fields = ("rank", "long_label", "short_label")
list_filter = (
"is_competitive",
"departure",
@ -94,7 +90,7 @@ class RoutineAdmin(admin.ModelAdmin):
model = Routine
fields = (
"label",
"long_label",
"short_label",
"difficulty",
"level",
@ -107,7 +103,7 @@ class RoutineAdmin(admin.ModelAdmin):
"is_competitive",
)
list_display = (
"label",
"long_label",
"short_label",
"is_competitive",
"active",
@ -117,7 +113,7 @@ class RoutineAdmin(admin.ModelAdmin):
)
list_filter = ("level", "difficulty", "is_competitive", "active")
search_fields = (
"label",
"long_label",
"short_label",
)
@ -127,10 +123,10 @@ class RoutineAdmin(admin.ModelAdmin):
js = ("js/routine.js",)
# TODO: ne proposer QUE les SKILL comme educatif
def get_related_filter(self, model, request):
# print('boum')
if not issubclass(model, Educative):
return super(Skill, self).get_related_filter(model, request)
# def get_related_filter(self, model, request):
# # print('boum')
# if not issubclass(model, Educative):
# return super(Skill, self).get_related_filter(model, request)
class RoutineSkillAdmin(admin.ModelAdmin):

5
khana/objective/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class ObjectiveConfig(AppConfig):
name = "khana.objective"

View File

@ -8,13 +8,13 @@ from .models import Routine, RoutineSkill, Chrono
class RoutineForm(forms.ModelForm):
class Meta:
model = Routine
fields = ("label", "label", "difficulty", "level", "active")
fields = ("long_label", "short_label", "difficulty", "level", "active")
widgets = {
# Champs obligatoires de la classe mère.
"label": forms.TextInput(
"long_label": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Routine's long name"}
),
"label": forms.TextInput(
"short_label": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Routine's short name"}
),
"difficulty": forms.HiddenInput(),

View File

@ -2,7 +2,7 @@
from django.db import migrations, models
import django.db.models.deletion
import objective.models
import khana.objective.models
class Migration(migrations.Migration):
@ -28,7 +28,7 @@ class Migration(migrations.Migration):
model_name="skill",
name="departure",
field=models.ForeignKey(
default=objective.models.get_default_position,
default=khana.objective.models.get_default_position,
on_delete=django.db.models.deletion.CASCADE,
related_name="depart_of",
to="objective.TouchPosition",
@ -39,7 +39,7 @@ class Migration(migrations.Migration):
model_name="skill",
name="landing",
field=models.ForeignKey(
default=objective.models.get_default_position,
default=khana.objective.models.get_default_position,
on_delete=django.db.models.deletion.CASCADE,
related_name="landing_of",
to="objective.TouchPosition",

View File

@ -6,13 +6,11 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('objective', '0015_auto_20190524_1211'),
("objective", "0015_auto_20190524_1211"),
]
operations = [
migrations.RenameField(
model_name='educative',
old_name='information',
new_name='content',
model_name="educative", old_name="information", new_name="content",
),
]

View File

@ -0,0 +1,75 @@
# Generated by Django 3.2.2 on 2021-06-20 16:18
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("objective", "0016_rename_information_educative_content"),
]
operations = [
migrations.RenameModel(old_name="Routine_Skill", new_name="RoutineSkill",),
migrations.AlterModelOptions(
name="educative",
options={
"ordering": ["label", "short_label"],
"verbose_name": "Educatif",
"verbose_name_plural": "Educatifs",
},
),
migrations.AlterModelOptions(
name="touchposition",
options={
"ordering": [
"label",
"short_label",
"is_default",
"allowed_in_competition",
],
"verbose_name": "Landing",
"verbose_name_plural": "Landings",
},
),
migrations.RenameField(
model_name="educative", old_name="ageBoy", new_name="age_boy",
),
migrations.RenameField(
model_name="educative", old_name="ageGirl", new_name="age_girl",
),
migrations.RenameField(
model_name="educative", old_name="educative", new_name="educatives",
),
migrations.RenameField(
model_name="educative", old_name="longLabel", new_name="label",
),
migrations.RenameField(
model_name="educative", old_name="prerequisite", new_name="prerequisites",
),
migrations.RenameField(
model_name="educative", old_name="shortLabel", new_name="short_label",
),
migrations.RenameField(
model_name="skill", old_name="rotationType", new_name="rotation_type",
),
migrations.RenameField(
model_name="skill",
old_name="simplyNotation",
new_name="simplified_notation",
),
migrations.RenameField(
model_name="touchposition",
old_name="competition",
new_name="allowed_in_competition",
),
migrations.RenameField(
model_name="touchposition", old_name="default", new_name="is_default",
),
migrations.RenameField(
model_name="touchposition", old_name="longLabel", new_name="label",
),
migrations.RenameField(
model_name="touchposition", old_name="shortLabel", new_name="short_label",
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 3.2.8 on 2021-12-05 11:33
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('objective', '0017_auto_20210620_1618'),
]
operations = [
migrations.AlterModelOptions(
name='educative',
options={'ordering': ['long_label', 'short_label'], 'verbose_name': 'Educatif', 'verbose_name_plural': 'Educatifs'},
),
migrations.RenameField(
model_name='educative',
old_name='label',
new_name='long_label',
),
]

View File

@ -0,0 +1,53 @@
# Generated by Django 4.0.1 on 2022-01-13 21:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('objective', '0018_auto_20211205_1133'),
]
operations = [
migrations.AddField(
model_name='educative',
name='age_boy_chained',
field=models.PositiveSmallIntegerField(choices=[(6, '6-7'), (7, '7-8'), (8, '8-9'), (9, '9-10'), (10, '10-11'), (11, '11-12'), (12, '12-13'), (13, '13-14'), (14, '14-15'), (15, '15-16'), (16, '16-17'), (17, '17+')], default=6, verbose_name="Boy's age chained"),
),
migrations.AddField(
model_name='educative',
name='age_boy_masterised',
field=models.PositiveSmallIntegerField(choices=[(6, '6-7'), (7, '7-8'), (8, '8-9'), (9, '9-10'), (10, '10-11'), (11, '11-12'), (12, '12-13'), (13, '13-14'), (14, '14-15'), (15, '15-16'), (16, '16-17'), (17, '17+')], default=6, verbose_name="Boy's age masterised"),
),
migrations.AddField(
model_name='educative',
name='age_boy_with_help',
field=models.PositiveSmallIntegerField(choices=[(6, '6-7'), (7, '7-8'), (8, '8-9'), (9, '9-10'), (10, '10-11'), (11, '11-12'), (12, '12-13'), (13, '13-14'), (14, '14-15'), (15, '15-16'), (16, '16-17'), (17, '17+')], default=6, verbose_name="Boy's age with help"),
),
migrations.AddField(
model_name='educative',
name='age_boy_without_help',
field=models.PositiveSmallIntegerField(choices=[(6, '6-7'), (7, '7-8'), (8, '8-9'), (9, '9-10'), (10, '10-11'), (11, '11-12'), (12, '12-13'), (13, '13-14'), (14, '14-15'), (15, '15-16'), (16, '16-17'), (17, '17+')], default=6, verbose_name="Boy's age without help"),
),
migrations.AddField(
model_name='educative',
name='age_girl_chained',
field=models.PositiveSmallIntegerField(choices=[(6, '6-7'), (7, '7-8'), (8, '8-9'), (9, '9-10'), (10, '10-11'), (11, '11-12'), (12, '12-13'), (13, '13-14'), (14, '14-15'), (15, '15-16'), (16, '16-17'), (17, '17+')], default=6, verbose_name="Girl's age chained"),
),
migrations.AddField(
model_name='educative',
name='age_girl_masterised',
field=models.PositiveSmallIntegerField(choices=[(6, '6-7'), (7, '7-8'), (8, '8-9'), (9, '9-10'), (10, '10-11'), (11, '11-12'), (12, '12-13'), (13, '13-14'), (14, '14-15'), (15, '15-16'), (16, '16-17'), (17, '17+')], default=6, verbose_name="Girl's age masterised"),
),
migrations.AddField(
model_name='educative',
name='age_girl_with_help',
field=models.PositiveSmallIntegerField(choices=[(6, '6-7'), (7, '7-8'), (8, '8-9'), (9, '9-10'), (10, '10-11'), (11, '11-12'), (12, '12-13'), (13, '13-14'), (14, '14-15'), (15, '15-16'), (16, '16-17'), (17, '17+')], default=6, verbose_name="Girl's age with help"),
),
migrations.AddField(
model_name='educative',
name='age_girl_without_help',
field=models.PositiveSmallIntegerField(choices=[(6, '6-7'), (7, '7-8'), (8, '8-9'), (9, '9-10'), (10, '10-11'), (11, '11-12'), (12, '12-13'), (13, '13-14'), (14, '14-15'), (15, '15-16'), (16, '16-17'), (17, '17+')], default=6, verbose_name="Girl's age without help"),
),
]

View File

@ -1,10 +1,13 @@
# coding=UTF-8
from datetime import date
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models import Q
from base.models import Markdownizable
from django.contrib.auth.models import User
from khana.base.models import Markdownizable
User = get_user_model()
class Educative(Markdownizable):
@ -12,35 +15,76 @@ class Educative(Markdownizable):
Classe `mère`.
"""
AGE_CHOICES = (
(6, "6-7"),
(7, "7-8"),
(8, "8-9"),
(9, "9-10"),
(10, "10-11"),
(11, "11-12"),
(12, "12-13"),
(13, "13-14"),
(14, "14-15"),
(15, "15-16"),
(16, "16-17"),
(17, "17+"),
)
class Meta:
verbose_name = "Educatif"
verbose_name_plural = "Educatifs"
ordering = ["label", "short_label"] # 'level',
ordering = ["long_label", "short_label"] # 'level',
label = models.CharField(max_length = 255, verbose_name = "Long Name")
short_label = models.CharField(max_length = 255, verbose_name = "Short Name")
long_label = models.CharField(max_length=255, verbose_name="Long Name")
short_label = models.CharField(max_length=255, verbose_name="Short Name")
difficulty = models.DecimalField(
max_digits = 3, decimal_places = 1, verbose_name = "Difficulty"
max_digits=3, decimal_places=1, verbose_name="Difficulty"
)
level = models.PositiveSmallIntegerField(verbose_name = "Level", default = 0)
rank = models.PositiveSmallIntegerField(verbose_name = "Rank", default = 0)
level = models.PositiveSmallIntegerField(verbose_name="Level", default=0)
rank = models.PositiveSmallIntegerField(verbose_name="Rank", default=0)
educatives = models.ManyToManyField(
"self", related_name = "educativeOf", blank = True, symmetrical = False
"self", related_name="educativeOf", blank=True, symmetrical=False
)
prerequisites = models.ManyToManyField(
"self", related_name = "prerequisiteOf", blank = True, symmetrical = False
"self", related_name="prerequisiteOf", blank=True, symmetrical=False
)
age_boy = models.PositiveSmallIntegerField(
blank = True, null = True, verbose_name = "Boy's age"
blank=True, null=True, verbose_name="Boy's age"
)
age_girl = models.PositiveSmallIntegerField(
blank = True, null = True, verbose_name = "Girl's age"
blank=True, null=True, verbose_name="Girl's age"
)
age_boy_with_help = models.PositiveSmallIntegerField(
choices=AGE_CHOICES, verbose_name="Boy's age with help", default=6
)
age_boy_without_help = models.PositiveSmallIntegerField(
choices=AGE_CHOICES, verbose_name="Boy's age without help", default=6
)
age_boy_chained = models.PositiveSmallIntegerField(
choices=AGE_CHOICES, verbose_name="Boy's age chained", default=6
)
age_boy_masterised = models.PositiveSmallIntegerField(
choices=AGE_CHOICES, verbose_name="Boy's age masterised", default=6
)
age_girl_with_help = models.PositiveSmallIntegerField(
choices=AGE_CHOICES, verbose_name="Girl's age with help", default=6
)
age_girl_without_help = models.PositiveSmallIntegerField(
choices=AGE_CHOICES, verbose_name="Girl's age without help", default=6
)
age_girl_chained = models.PositiveSmallIntegerField(
choices=AGE_CHOICES, verbose_name="Girl's age chained", default=6
)
age_girl_masterised = models.PositiveSmallIntegerField(
choices=AGE_CHOICES, verbose_name="Girl's age masterised", default=6
)
def __str__(self):
return "%s - %s (level: %s | diff: %s)" % (
self.rank,
self.longLabel,
self.label,
self.level,
self.difficulty,
)
@ -56,13 +100,13 @@ class TouchPosition(models.Model):
verbose_name_plural = "Landings"
ordering = ["label", "short_label", "is_default", "allowed_in_competition"]
label = models.CharField(max_length = 30, verbose_name = "Nom long")
short_label = models.CharField(max_length = 15, verbose_name = "Nom court")
allowed_in_competition = models.BooleanField(verbose_name = "Compétition")
is_default = models.BooleanField(verbose_name = "Défaut")
label = models.CharField(max_length=30, verbose_name="Nom long")
short_label = models.CharField(max_length=15, verbose_name="Nom court")
allowed_in_competition = models.BooleanField(verbose_name="Compétition")
is_default = models.BooleanField(verbose_name="Défaut")
def __str__(self):
return "%s" % (self.longLabel)
return "%s" % (self.label)
def get_default_position():
@ -104,29 +148,31 @@ class Skill(Educative):
(2, "Backward"),
)
position = models.CharField(max_length = 2, choices = POSITION_CHOICES)
position = models.CharField(max_length=2, choices=POSITION_CHOICES)
departure = models.ForeignKey(
TouchPosition,
related_name = "depart_of",
default = get_default_position,
verbose_name = "Take-off position",
on_delete = models.CASCADE,
related_name="depart_of",
default=get_default_position,
verbose_name="Take-off position",
on_delete=models.CASCADE,
)
landing = models.ForeignKey(
TouchPosition,
related_name = "landing_of",
default = get_default_position,
verbose_name = "Landing position",
on_delete = models.CASCADE,
related_name="landing_of",
default=get_default_position,
verbose_name="Landing position",
on_delete=models.CASCADE,
)
rotation_type = models.PositiveSmallIntegerField(
choices = ROTATION_CHOICES, verbose_name = "Type de rotation"
choices=ROTATION_CHOICES, verbose_name="Type de rotation"
)
rotation = models.PositiveSmallIntegerField(verbose_name = "1/4 de rotation")
twist = models.PositiveSmallIntegerField(verbose_name = "1/2 Vrille")
notation = models.CharField(max_length = 25)
simplified_notation = models.CharField(max_length = 25, verbose_name = "Notation simplifiée")
is_competitive = models.BooleanField(default = False)
rotation = models.PositiveSmallIntegerField(verbose_name="1/4 de rotation")
twist = models.PositiveSmallIntegerField(verbose_name="1/2 Vrille")
notation = models.CharField(max_length=25)
simplified_notation = models.CharField(
max_length=25, verbose_name="Notation simplifiée"
)
is_competitive = models.BooleanField(default=False)
# importance = models.PositiveSmallIntegerField(default = 1)
def __str__(self):
@ -144,12 +190,12 @@ class Routine(Educative):
active = models.BooleanField()
jumps = models.ManyToManyField(
Skill, through = "RoutineSkill", verbose_name = "routine"
Skill, through="RoutineSkill", verbose_name="routine"
) # ceci n'est pas un vrai champ
is_competitive = models.BooleanField(default = False)
is_competitive = models.BooleanField(default=False)
def __str__(self):
return "%s (%s)" % (self.label, self.short_label)
return "%s (%s)" % (self.long_label, self.short_label)
def contains_basic_jumps(self):
"""
@ -216,10 +262,10 @@ class RoutineSkill(models.Model):
ordering = ("rank",)
routine = models.ForeignKey(
Routine, on_delete = models.CASCADE, default = None, related_name = "skill_links"
Routine, on_delete=models.CASCADE, default=None, related_name="skill_links"
)
skill = models.ForeignKey(
Skill, on_delete = models.CASCADE, default = None, related_name = "routine_links"
Skill, on_delete=models.CASCADE, default=None, related_name="routine_links"
)
rank = models.PositiveSmallIntegerField()
@ -247,13 +293,13 @@ class Chrono(models.Model):
(99, "Other"),
)
routine = models.ForeignKey(Routine, on_delete = models.CASCADE, default = None)
routine_type = models.PositiveSmallIntegerField(choices = ROUTINETYPE_CHOICE)
routine = models.ForeignKey(Routine, on_delete=models.CASCADE, default=None)
routine_type = models.PositiveSmallIntegerField(choices=ROUTINETYPE_CHOICE)
gymnast = models.ForeignKey(
"people.gymnast", on_delete = models.CASCADE, default = None
"people.gymnast", on_delete=models.CASCADE, default=None
)
date = models.DateField(default = date.today, verbose_name = "Date")
score = models.DecimalField(max_digits = 5, decimal_places = 2)
date = models.DateField(default=date.today, verbose_name="Date")
score = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return "%s le %s : %s pour %s" % (
@ -278,13 +324,13 @@ class Evaluation(models.Model):
Classe permettant l'évaluation des éducatifs.
"""
date = models.DateField(default = date.today, verbose_name = "Date")
value = models.PositiveSmallIntegerField(default = 0)
date = models.DateField(default=date.today, verbose_name="Date")
value = models.PositiveSmallIntegerField(default=0)
educative = models.ForeignKey(
Educative,
related_name = "depart_of",
verbose_name = "Take-off position",
on_delete = models.CASCADE,
related_name="depart_of",
verbose_name="Take-off position",
on_delete=models.CASCADE,
)
type_of_evaluator = models.BooleanField(default = 0)
evaluator = models.ForeignKey(User, null = True, on_delete = models.SET_NULL)
type_of_evaluator = models.BooleanField(default=0)
evaluator = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)

View File

@ -1,9 +1,8 @@
# coding=UTF-8
from django.urls import reverse
from django.test import TestCase, Client
from django.urls import reverse
from .models import Routine_Skill, Routine, Skill, TouchPosition
from .models import RoutineSkill, Routine, Skill, TouchPosition
from .views import link_skill_to_routine
@ -51,4 +50,4 @@ class RoutineTest(TestCase):
# print(response)
self.assertEquals(response.status_code, 200)
self.assertTrue(Routine_Skill.objects.exists())
self.assertTrue(RoutineSkill.objects.exists())

View File

@ -7,7 +7,7 @@ from . import views
# Skills
skill_urlpatterns = [
re_path(
r"^(?P<field>(level|rank|difficulty|landing|rotation|departure|twist))/(?P<expression>[\w]+)/(?P<value>[\w]+)$",
r"^(?P<field>(level|rank|difficulty))/(?P<expression>[\w]+)/(?P<value>[\w]+)$",
views.skill_listing,
name="skill_listing_by_key",
),
@ -42,11 +42,7 @@ routine_urlpatterns = [
views.delete_skill_from_routine,
name="delete_skill_from_routine",
),
path(
r"suggest/",
views.suggest_routine,
name="suggest_routine",
)
path(r"suggest/", views.suggest_routine, name="suggest_routine",),
]
# Chrono

View File

@ -1,26 +1,24 @@
# coding=UTF-8
from django.db.models import Q
from django.shortcuts import render, get_object_or_404
from django.template import RequestContext
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
from django.urls import reverse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.views.decorators.clickjacking import xframe_options_exempt
from datetime import datetime
import math
import random
import simplejson
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
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.urls import reverse
from django.views.decorators.http import require_http_methods
from django.views.decorators.clickjacking import xframe_options_exempt
from khana.people.models import Gymnast, CanDoRelation
from .models import Skill, Educative, Routine, Chrono, RoutineSkill
from .forms import RoutineForm, ChronoForm
from people.models import Gymnast, CanDoRelation
from datetime import datetime
import random
import math
def __lookup(lookup_class, lookup_value):
@ -30,7 +28,7 @@ def __lookup(lookup_class, lookup_value):
:param lookup_class: classe fille dans laquelle la recherche doit être
faite.
:type lookup_class: string (`skill` ou `routine`).
:type lookup_class: string (`skill` ou `routine`).ùpdem
:param lookup_value: pattern de recherche.
:type lookup_value: string.
@ -261,11 +259,11 @@ def routine_details(request, routineid):
if not skill_link.skill.is_competitive:
is_competitive = False
if skill_link.skill.ageBoy is not None and skill_link.skill.ageBoy > age_boy:
age_boy = skill_link.skill.ageBoy
if skill_link.skill.age_boy is not None and skill_link.skill.age_boy > age_boy:
age_boy = skill_link.skill.age_boy
if skill_link.skill.ageGirl is not None and skill_link.skill.ageGirl > age_girl:
age_girl = skill_link.skill.ageGirl
if skill_link.skill.age_girl is not None and skill_link.skill.age_girl > age_girl:
age_girl = skill_link.skill.age_girl
if routine.skill_links.all().count() != 10:
is_competitive = False
@ -278,11 +276,11 @@ def routine_details(request, routineid):
if routine.rank is None or routine.rank < rank:
routine.rank = rank
if routine.ageBoy is None or routine.ageBoy < age_boy:
routine.ageBoy = age_boy
if routine.age_boy is None or routine.age_boy < age_boy:
routine.age_boy = age_boy
if routine.ageGirl is None or routine.ageGirl < age_girl:
routine.ageGirl = age_girl
if routine.age_girl is None or routine.age_girl < age_girl:
routine.age_girl = age_girl
routine.is_competitive = is_competitive
@ -338,7 +336,9 @@ def random_skill(request, skill_quantity=20, is_competitive=True):
number_of_skill = skillid_list.count()
selected_skillid_list = [
skillid_list[x]["id"]
for x in [random.randrange(0, number_of_skill, 1) for i in range(skill_quantity)]
for x in [
random.randrange(0, number_of_skill, 1) for i in range(skill_quantity)
]
]
skill_list = Skill.objects.filter(id__in=selected_skillid_list)
@ -370,7 +370,7 @@ def __construct_routine(
competition (bool): indique si la série doit respecter les règles de compétition.
logic (bool): indique si la série doit suivre les règles de logique (sportive).
gymnast (gymnast): gymnaste.
Returns:
??? (list ?): liste des séries correspondantes aux criètres.
"""
@ -387,12 +387,14 @@ def __construct_routine(
if current_routine:
skill_list = Skill.objects.filter(
departure = current_routine[-1].landing
) # , difficulty__lte = total_difficulty_score
departure=current_routine[-1].landing
) # , difficulty__lte = total_difficulty_score
if len(current_routine) == (max_routine_length - 1):
skill_list = skill_list.filter(landing__longLabel="Debout")
if logic and current_routine[-1].landing.longLabel == "Debout":
skill_list = skill_list.exclude(rotationType = current_routine[-1].rotationType)
skill_list = skill_list.exclude(
rotationType=current_routine[-1].rotationType
)
else:
skill_list = Skill.objects.filter(departure__longLabel="Debout")
@ -404,23 +406,31 @@ def __construct_routine(
min_diff_skill = total_difficulty_score
max_diff_skill = total_difficulty_score + 3
else:
if math.ceil(total_difficulty_score / max_routine_length) <= max_skill_difficulty:
min_diff_skill = math.ceil(max((total_difficulty_score / max_routine_length) - 5, 0))
if (
math.ceil(total_difficulty_score / max_routine_length)
<= max_skill_difficulty
):
min_diff_skill = math.ceil(
max((total_difficulty_score / max_routine_length) - 5, 0)
)
else:
return
if (math.ceil(total_difficulty_score / max_routine_length) + 2) <= max_skill_difficulty:
max_diff_skill = math.ceil(total_difficulty_score / max_routine_length) + 2
if (
math.ceil(total_difficulty_score / max_routine_length) + 2
) <= max_skill_difficulty:
max_diff_skill = (
math.ceil(total_difficulty_score / max_routine_length) + 2
)
else:
return
skill_list = skill_list.filter(
difficulty__gte = (min_diff_skill / 10),
difficulty__lte = (max_diff_skill / 10)
difficulty__gte=(min_diff_skill / 10), difficulty__lte=(max_diff_skill / 10)
)
if gymnast:
skill_list = skill_list.filter(cando__gymnast = gymnast)
skill_list = skill_list.filter(cando__gymnast=gymnast)
for skill in skill_list:
current_routine.append(skill)
@ -429,7 +439,9 @@ def __construct_routine(
current_routine,
max_routine_length,
max_skill_difficulty,
total_difficulty_score - (skill.difficulty * 10) if total_difficulty_score is not None else None,
total_difficulty_score - (skill.difficulty * 10)
if total_difficulty_score is not None
else None,
competition,
logic,
gymnast,
@ -442,7 +454,7 @@ def __construct_routine(
def suggest_routine(
request,
max_routine_length = 2,
max_routine_length=2,
total_difficulty_score=None,
competition=True,
logic=True,
@ -457,7 +469,7 @@ def suggest_routine(
logic (bool): indique si la série doit suivre les règles de logique (sportive).
gymnast (gymnast): gymnaste.
last_jump (skill): dernier saut sélectionné pour la série.
Returns:
??? (list): liste des séries correspondantes aux criètres.
@ -471,24 +483,32 @@ def suggest_routine(
total_difficulty_score = 26
if gymnast:
max_skill_difficulty = Educative.objects.values('difficulty').filter(cando__gymnast=gymnast).order_by(
"-difficulty"
)[:1][0]["difficulty"] * 10
max_skill_difficulty = (
Educative.objects.values("difficulty")
.filter(cando__gymnast=gymnast)
.order_by("-difficulty")[:1][0]["difficulty"]
* 10
)
else:
max_skill_difficulty = Skill.objects.values('difficulty').order_by("-difficulty")[:1][0]["difficulty"] * 10
max_skill_difficulty = (
Skill.objects.values("difficulty").order_by("-difficulty")[:1][0][
"difficulty"
]
* 10
)
# difficulty_scores = range(5, 45, 5)
# for total_difficulty_score in difficulty_scores:
# print("===============================================================================================")
__construct_routine(
routine,
max_routine_length,
max_skill_difficulty,
total_difficulty_score,
competition,
logic,
gymnast,
)
routine,
max_routine_length,
max_skill_difficulty,
total_difficulty_score,
competition,
logic,
gymnast,
)
# print(routines)

124
khana/people/admin.py Normal file
View File

@ -0,0 +1,124 @@
"""Administration des gymnastes et des personnes.
Remarks:
* Je ne pense pas qu'il faille encore passer par `ForeignKeyAutocompleteAdmin`.
https://docs.djangoproject.com/fr/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields
"""
from django.contrib import admin
from django_extensions.admin import ForeignKeyAutocompleteAdmin
from .models import (
Gymnast,
Accident,
CanDoRelation,
ToDoRelation,
GymnastHasRoutine,
)
class CanDoRelationAdmin(ForeignKeyAutocompleteAdmin):
model = CanDoRelation
list_display = ("date", "gymnast", "educative")
list_filter = ("gymnast",)
search_fields = ("gymnast", "educative")
autocomplete_fields = ("gymnast",)
# related_search_fields = {
# 'gymnast': ('lastname', 'firstname'),
# }
class InlineCanDoRelation(admin.TabularInline):
model = CanDoRelation
class ToDoRelationAdmin(ForeignKeyAutocompleteAdmin):
model = ToDoRelation
list_display = ("date", "gymnast", "educative")
list_filter = ("gymnast",)
search_fields = ("gymnast", "educative")
autocomplete_fields = ("gymnast",)
# related_search_fields = {
# 'gymnast': ('lastname', 'firstname'),
# # 'educative': ('longLabel', 'shortLabel'), # TO_FRED : Pq ca marche pas ca ?
# }
class GymnastHasRoutineAdmin(ForeignKeyAutocompleteAdmin):
model = GymnastHasRoutine
list_display = ("gymnast", "routine", "routine_type", "datebegin", "dateend")
list_filter = ("gymnast", "routine_type")
search_fields = ("gymnast", "routine")
autocomplete_fields = ("gymnast", "routine")
class InlineToDoRelation(admin.TabularInline):
model = ToDoRelation
class GymnastAdmin(admin.ModelAdmin):
model = Gymnast
def lastname(self, obj):
return obj.user.last_name
def firstname(self, obj):
return obj.user.first_name
def email(self, obj):
return obj.user.email
def is_active(self, obj):
return obj.user.is_active
fields = (
"user",
"birthdate",
"gender",
"club",
"niss",
"address",
"postal",
"city",
"phone",
"gsm",
"federation_id",
"year_of_practice",
"gsm_main_responsible",
"email_main_responsible",
"gsm_second_responsible",
"email_second_responsible",
"orientation",
"trainer",
"picture",
"content",
)
list_display = ("lastname", "firstname", "birthdate", "age", "is_active")
list_filter = ("gender", "user__is_active")
search_fields = ("lastname", "firstname", "email")
inlines = [InlineToDoRelation, InlineCanDoRelation]
autocomplete_fields = ("club",)
class AccidentAdmin(admin.ModelAdmin):
model = Accident
fields = ("date", "gymnast", "educative", "information")
list_display = ("date", "gymnast", "educative")
list_filter = ("date",)
search_fields = ("date", "gymnast", "educative")
autocomplete_fields = ["gymnast", "educative"]
admin.site.register(Gymnast, GymnastAdmin)
admin.site.register(Accident, AccidentAdmin)
admin.site.register(CanDoRelation, CanDoRelationAdmin)
admin.site.register(ToDoRelation, ToDoRelationAdmin)
admin.site.register(GymnastHasRoutine, GymnastHasRoutineAdmin)

5
khana/people/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class PeopleConfig(AppConfig):
name = "khana.people"

175
khana/people/forms.py Normal file
View File

@ -0,0 +1,175 @@
"""Formulaires de gestion des données entrantes pour les gymnastes et accidents."""
from django import forms
from django.contrib.auth import get_user_model
from .models import (
Accident,
Gymnast,
GymnastHasRoutine,
)
User = get_user_model()
class AccidentForm(forms.ModelForm):
class Meta:
model = Accident
fields = ("gymnast", "educative", "date", "content")
widgets = {
"date": forms.DateInput(
attrs={
"class": "form-control datepicker",
# "value": date.today().strftime("%Y-%m-%d"),
}
),
"gymnast": forms.HiddenInput(),
"educative": forms.HiddenInput(),
"content": forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Informations about accident: context (why, where, …), consequencies, …",
}
),
}
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
"class": "form-control",
"placeholder": "Searching gymnast…",
"data-ref": "#id_gymnast",
}
)
)
educative_related = forms.CharField(
widget=forms.TextInput(
attrs={
"class": "form-control",
"placeholder": "Searching skill…",
"data-ref": "#id_educative",
}
)
)
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = (
"last_name",
"first_name",
"email",
"is_active",
"username",
)
class GymnastForm(forms.ModelForm):
lastname = forms.CharField(
widget=forms.TextInput(
attrs={"class": "form-control", "placeholder": "Lastname"}
)
)
firstname = forms.CharField(
widget=forms.TextInput(
attrs={"class": "form-control", "placeholder": "Firstname"}
)
)
email = forms.EmailField()
# is_active = forms.CheckboxInput()
class Meta:
model = Gymnast
fields = (
"id",
"birthdate",
"gender",
"address",
"postal",
"city",
"phone",
"gsm",
"gsm_main_responsible",
"email_main_responsible",
"gsm_second_responsible",
"email_second_responsible",
"orientation",
"picture",
"content",
)
widgets = {
"id": forms.HiddenInput(),
"lastname": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Lastname"}
),
"firstname": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Firstname"}
),
"birthdate": forms.DateInput(attrs={"class": "form-control datepicker"}),
"gender": forms.Select(attrs={"class": "form-control"}),
"address": forms.TextInput(attrs={"class": "form-control"}),
"postal": forms.TextInput(attrs={"class": "form-control"}),
"city": forms.TextInput(attrs={"class": "form-control"}),
"phone": forms.TextInput(attrs={"class": "form-control"}),
"gsm": forms.TextInput(attrs={"class": "form-control"}),
"email": forms.EmailInput(attrs={"class": "form-control"}),
"gsm_main_responsible": forms.TextInput(attrs={"class": "form-control"}),
"email_main_responsible": forms.EmailInput(attrs={"class": "form-control"}),
"gsm_second_responsible": forms.TextInput(attrs={"class": "form-control"}),
"email_second_responsible": forms.EmailInput(
attrs={"class": "form-control"}
),
# "is_active": forms.CheckboxInput(
# attrs={
# "class": "bootstrap-switch mt-0",
# "data-on-label": "<i class='tim-icons icon-check-2 text-success'></i>",
# "data-off-label": "<i class='tim-icons icon-simple-remove text-danger'></i>",
# }
# ),
"orientation": forms.Select(attrs={"class": "form-control"}),
"picture": forms.Select(attrs={"class": "form-control"}),
"content": forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Informations about the gymnast.",
}
),
}
class GymnastHasRoutineForm(forms.ModelForm):
"""
"""
class Meta:
model = GymnastHasRoutine
fields = ("gymnast", "routine", "routine_type", "datebegin", "dateend")
widgets = {
"gymnast": forms.HiddenInput(),
"routine": forms.HiddenInput(),
"routine_type": forms.Select(attrs={"class": "form-control"}),
"datebegin": forms.DateInput(attrs={"class": "form-control datepicker",}),
"dateend": forms.DateInput(attrs={"class": "form-control datepicker",}),
}
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
"class": "form-control",
"placeholder": "Searching gymnast…",
"data-ref": "#id_gymnast",
}
)
)
routine_related = forms.CharField(
widget=forms.TextInput(
attrs={
"class": "form-control",
"placeholder": "Searching routine…",
"data-ref": "#id_routine",
}
)
)

Some files were not shown because too many files have changed in this diff Show More