Browse Source

Nouvelle orientation du projet, redéfinition des structures de données.

master
Hugo LEVY-FALK 8 years ago
parent
commit
b5a51e1bec
  1. 7
      content/migrations/0001_initial.py
  2. 22
      content/migrations/0002_content_school_owner.py
  3. 32
      content/models.py
  4. 12
      settings/migrations/0001_initial.py
  5. 28
      settings/migrations/0002_auto_20180301_1047.py
  6. 23
      settings/migrations/0003_auto_20180301_1109.py
  7. 16
      settings/models.py
  8. 4
      settings/views.py
  9. 18
      site_tps/wsgi.py
  10. 44
      users/admin.py
  11. 27
      users/migrations/0001_initial.py
  12. 20
      users/migrations/0002_schoolprofile_admins.py
  13. 19
      users/migrations/0003_auto_20180301_0933.py
  14. 19
      users/migrations/0004_auto_20180301_0952.py
  15. 19
      users/migrations/0005_auto_20180301_1029.py
  16. 18
      users/migrations/0006_schoolprofile_phone.py
  17. 118
      users/models.py
  18. 6
      users/urls.py
  19. 31
      users/views.py

7
content/migrations/0001_initial.py

@ -1,5 +1,6 @@
# Generated by Django 2.0.1 on 2018-02-28 18:43
# Generated by Django 2.0.1 on 2018-03-08 22:03
import content.models
from django.db import migrations, models
import django.db.models.deletion
@ -9,6 +10,7 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('users', '0001_initial'),
]
operations = [
@ -26,8 +28,9 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Nom du contenu')),
('file', models.FileField(upload_to='', verbose_name='Fichier')),
('file', models.FileField(upload_to=content.models.get_upload_to, validators=[content.models.validate_file_extension], verbose_name='Fichier')),
('category', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='content.Category', verbose_name='Catégorie')),
('school_owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.School')),
],
),
]

22
content/migrations/0002_content_school_owner.py

@ -1,22 +0,0 @@
# Generated by Django 2.0.1 on 2018-02-28 18:43
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('content', '0001_initial'),
('users', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='content',
name='school_owner',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.SchoolProfile'),
),
]

32
content/models.py

@ -1,9 +1,11 @@
import os
from django.db import models
from django.core.exceptions import ValidationError
from django.urls import reverse
from django.contrib.auth.models import Group
from django.conf import settings
from users.models import SchoolProfile
from users.models import School
class Category(models.Model):
"""Une catégorie de contenu."""
@ -19,13 +21,26 @@ class Category(models.Model):
verbose_name="Illustration de la catégorie",
null=True,
)
def get_absolute_url(self):
return reverse('content:category-list', kwargs={'pk':self.pk})
return reverse('content:category-list', kwargs={'pk': self.pk})
def __str__(self):
return self.name
def get_upload_to(instance, filename):
extension = filename.split('.')[-1]
return "static/media/"+instance.school.name+"/"+instance.category.name+'.'+extension
def validate_file_extension(value):
ext = os.path.splitext(value.name)[1] # [0] returns path+filename
valid_extensions = ['mp4', 'avi', 'mov']
if not ext.lower() in valid_extensions:
raise ValidationError(u'Unsupported file extension.')
class Content(models.Model):
"""Un contenu du site (vidéo)."""
name = models.CharField(
@ -33,7 +48,7 @@ class Content(models.Model):
verbose_name="Nom du contenu"
)
school_owner = models.ForeignKey(
SchoolProfile,
School,
on_delete=models.CASCADE,
)
category = models.ForeignKey(
@ -43,11 +58,10 @@ class Content(models.Model):
null=True
)
file = models.FileField(
verbose_name="Fichier"
verbose_name="Fichier",
validators=[validate_file_extension],
upload_to=get_upload_to
)
def __str__(self):
return self.name
def manager_right(self):
return 'users.manage_' + str(self.school_owner.group.pk)

12
settings/migrations/0001_initial.py

@ -1,4 +1,4 @@
# Generated by Django 2.0.1 on 2018-02-28 18:43
# Generated by Django 2.0.1 on 2018-03-08 22:03
from django.db import migrations, models
@ -17,6 +17,16 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('allow_upload', models.BooleanField(default=False, verbose_name="Autoriser l'upload de vidéos.")),
('home_message', models.TextField(default='', verbose_name="Message de la page d'accueil")),
('site_logo', models.ImageField(blank=True, null=True, upload_to='', verbose_name='Logo du site')),
('event_poster', models.ImageField(blank=True, null=True, upload_to='', verbose_name="Affiche de l'événement")),
],
),
migrations.CreateModel(
name='StaticPage',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Titre de la catégorie')),
('text', models.TextField(verbose_name='Texte de la catégorie')),
],
),
]

28
settings/migrations/0002_auto_20180301_1047.py

@ -1,28 +0,0 @@
# Generated by Django 2.0.1 on 2018-03-01 10:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('settings', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='sitesettings',
name='event_poster',
field=models.ImageField(null=True, upload_to='', verbose_name="Affiche de l'événement"),
),
migrations.AddField(
model_name='sitesettings',
name='min_number_of_categories',
field=models.PositiveIntegerField(default=0, verbose_name='Nombre minimal de catégories dans laquelle participer'),
),
migrations.AddField(
model_name='sitesettings',
name='site_logo',
field=models.ImageField(null=True, upload_to='', verbose_name='Logo du site'),
),
]

23
settings/migrations/0003_auto_20180301_1109.py

@ -1,23 +0,0 @@
# Generated by Django 2.0.1 on 2018-03-01 11:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('settings', '0002_auto_20180301_1047'),
]
operations = [
migrations.AlterField(
model_name='sitesettings',
name='event_poster',
field=models.ImageField(blank=True, null=True, upload_to='', verbose_name="Affiche de l'événement"),
),
migrations.AlterField(
model_name='sitesettings',
name='site_logo',
field=models.ImageField(blank=True, null=True, upload_to='', verbose_name='Logo du site'),
),
]

16
settings/models.py

@ -1,7 +1,5 @@
from django.db import models
from .aes_field import AESEncryptedField
class SiteSettings(models.Model):
PRETTY_NAME = "Réglages du site"
@ -23,11 +21,17 @@ class SiteSettings(models.Model):
null=True,
blank=True
)
min_number_of_categories = models.PositiveIntegerField(
verbose_name="Nombre minimal de catégories dans laquelle participer",
default=0,
)
@classmethod
def get_settings(cls):
return cls.objects.get_or_create()[0]
class StaticPage(models.Model):
name = models.CharField(
max_length=255,
verbose_name="Titre de la catégorie",
)
text = models.TextField(
verbose_name="Texte de la catégorie"
)

4
settings/views.py

@ -7,7 +7,7 @@ from django.shortcuts import get_object_or_404, redirect, render
from django.contrib import messages
from content.models import Category
from users.models import SchoolProfile
from users.models import School
from .models import SiteSettings
from .forms import SelectUserForm
@ -20,7 +20,7 @@ class SettingsView(LoginRequiredMixin, PermissionRequiredMixin, TemplateView):
context = super().get_context_data(**kwargs)
context['categories'] = Category.objects.all()
context['site_settings'], _ = SiteSettings.objects.get_or_create()
context['schools'] = SchoolProfile.objects.all()
context['schools'] = School.objects.all()
context['settings'] = True
context['administrators'] = Group.objects.get(name='admins').user_set.all()
return context

18
site_tps/wsgi.py

@ -1,16 +1,18 @@
"""
WSGI config for site_tps project.
import os
import sys
It exposes the WSGI callable as a module-level variable named ``application``.
VIRTUALENV_LOC = '/var/www/site_tps/env_site'
For more information on this file, see
https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
"""
# Activation de l'environnement virtuel
activate_env=os.path.join(VIRTUALENV_LOC, 'bin/activate_this.py')
exec(compile(open(activate_env, "rb").read(), activate_env, 'exec'), {'__file__':activate_env})
import os
# Ajout du répertoire du site au PATH
sys.path.append('/var/www/site_tps')
sys.path.append('/var/www/site_tps/site_tps')
# Les trucs par défaut de Django
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "site_tps.settings")
application = get_wsgi_application()

44
users/admin.py

@ -1,44 +0,0 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
from django.contrib.auth.models import User, Group
from .models import UserProfile, SchoolProfile
# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class UserInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'user profiles'
# Define a new User admin
class UserAdmin(BaseUserAdmin):
inlines = (UserInline, )
# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class SchoolInline(admin.StackedInline):
model = SchoolProfile
can_delete = False
verbose_name_plural = 'schools'
fk_name = 'admins'
# Define a new User admin
class GroupAdmin(BaseGroupAdmin):
inlines = (SchoolInline, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
admin.site.unregister(Group)
admin.site.register(Group, GroupAdmin)

27
users/migrations/0001_initial.py

@ -1,8 +1,10 @@
# Generated by Django 2.0.1 on 2018-02-28 18:43
# Generated by Django 2.0.1 on 2018-03-08 22:03
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import users.models
class Migration(migrations.Migration):
@ -10,24 +12,25 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0009_alter_user_last_name_max_length'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='SchoolProfile',
name='School',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='students', to='auth.Group')),
],
),
migrations.CreateModel(
name='UserProfile',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('school', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.SchoolProfile')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('phone', models.CharField(help_text='Visible uniquement des administrateurs', max_length=10, null=True, validators=[django.core.validators.RegexValidator('^[0-9]{10}$', 'Veuillez entrer un numéro à 10 chiffres.')], verbose_name='Numéro de téléphone pour contacter le responsable des productions')),
('logo', models.ImageField(null=True, upload_to=users.models.get_upload_to, verbose_name="Logo à utiliser pour représenter l'école")),
('first_name_j1', models.CharField(max_length=255, verbose_name='Prénom juré n°1')),
('last_name_j1', models.CharField(max_length=255, verbose_name='Nom juré n°1')),
('phone_j1', models.CharField(help_text='Visible uniquement des administrateurs', max_length=10, null=True, validators=[django.core.validators.RegexValidator('^[0-9]{10}$', 'Veuillez entrer un numéro à 10 chiffres.')], verbose_name='Numéro de téléphone juré n°1')),
('mail_j1', models.EmailField(max_length=254, verbose_name='Email juré n°1')),
('first_name_j2', models.CharField(max_length=255, verbose_name='Prénom juré n°2')),
('last_name_j2', models.CharField(max_length=255, verbose_name='Nom juré n°2')),
('phone_j2', models.CharField(help_text='Visible uniquement des administrateurs', max_length=10, null=True, validators=[django.core.validators.RegexValidator('^[0-9]{10}$', 'Veuillez entrer un numéro à 10 chiffres.')], verbose_name='Numéro de téléphone juré n°2')),
('mail_j2', models.EmailField(max_length=254, verbose_name='Email juré n°2')),
('admin', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name="Administrateur de l'école")),
],
),
]

20
users/migrations/0002_schoolprofile_admins.py

@ -1,20 +0,0 @@
# Generated by Django 2.0.1 on 2018-03-01 07:16
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('auth', '0009_alter_user_last_name_max_length'),
('users', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='schoolprofile',
name='admins',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='admin_of', to='auth.Group'),
),
]

19
users/migrations/0003_auto_20180301_0933.py

@ -1,19 +0,0 @@
# Generated by Django 2.0.1 on 2018-03-01 09:33
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0002_schoolprofile_admins'),
]
operations = [
migrations.AlterField(
model_name='schoolprofile',
name='group',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='school', to='auth.Group'),
),
]

19
users/migrations/0004_auto_20180301_0952.py

@ -1,19 +0,0 @@
# Generated by Django 2.0.1 on 2018-03-01 09:52
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0003_auto_20180301_0933'),
]
operations = [
migrations.AlterField(
model_name='schoolprofile',
name='group',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='school', to='auth.Group'),
),
]

19
users/migrations/0005_auto_20180301_1029.py

@ -1,19 +0,0 @@
# Generated by Django 2.0.1 on 2018-03-01 10:29
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0004_auto_20180301_0952'),
]
operations = [
migrations.AlterField(
model_name='userprofile',
name='school',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.SchoolProfile'),
),
]

18
users/migrations/0006_schoolprofile_phone.py

@ -1,18 +0,0 @@
# Generated by Django 2.0.1 on 2018-03-01 23:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0005_auto_20180301_1029'),
]
operations = [
migrations.AddField(
model_name='schoolprofile',
name='phone',
field=models.CharField(help_text='Visible uniquement des administrateurs', max_length=10, null=True, verbose_name='Numéro de téléphone pour contacter le responsable des productions'),
),
]

118
users/models.py

@ -7,18 +7,17 @@ from django.dispatch import receiver
from django.core import validators
class SchoolProfile(models.Model):
def get_upload_to(instance, filename):
return "static/media/"+instance.name+"/"+filename
class School(models.Model):
"""Ajoute un champ pour distinguer les groupes écoles des autres."""
group = models.OneToOneField(
Group,
on_delete=models.CASCADE,
related_name="school",
)
admins = models.OneToOneField(
Group,
admin = models.OneToOneField(
User,
verbose_name="Administrateur de l'école",
null=True,
on_delete=models.SET_NULL,
related_name="admin_of",
null=True
)
phone = models.CharField(
max_length=10,
@ -31,6 +30,53 @@ class SchoolProfile(models.Model):
"Veuillez entrer un numéro à 10 chiffres."),
]
)
logo = models.ImageField(
upload_to=get_upload_to,
verbose_name="Logo à utiliser pour représenter l'école",
null=True,
blank=False,
)
first_name_j1 = models.CharField(
max_length=255,
verbose_name="Prénom juré n°1"
)
last_name_j1 = models.CharField(
max_length=255,
verbose_name="Nom juré n°1"
)
phone_j1 = models.CharField(
max_length=10,
help_text="Visible uniquement des administrateurs",
verbose_name="Numéro de téléphone juré n°1",
blank=False,
null=True,
validators=[
validators.RegexValidator('^[0-9]{10}$',
"Veuillez entrer un numéro à 10 chiffres."),
]
)
mail_j1 = models.EmailField(verbose_name="Email juré n°1")
first_name_j2 = models.CharField(
max_length=255,
verbose_name="Prénom juré n°2"
)
last_name_j2 = models.CharField(
max_length=255,
verbose_name="Nom juré n°2"
)
phone_j2 = models.CharField(
max_length=10,
help_text="Visible uniquement des administrateurs",
verbose_name="Numéro de téléphone juré n°2",
blank=False,
null=True,
validators=[
validators.RegexValidator('^[0-9]{10}$',
"Veuillez entrer un numéro à 10 chiffres."),
]
)
mail_j2 = models.EmailField(verbose_name="Email juré n°2")
def __str__(self):
return self.group.name
@ -41,55 +87,3 @@ class SchoolProfile(models.Model):
def number_of_categories(self):
return self.content_set.values('category').distinct().count()
def save(self, *args, **kwargs):
viewing_right, _ = Permission.objects.get_or_create(
codename='view_' + str(self.group.pk),
name='Peut voir ' + str(self.group.pk),
content_type=ContentType.objects.get_for_model(SchoolProfile)
)
if viewing_right not in self.group.permissions.all():
self.group.permissions.add(viewing_right)
self.group.save()
admins,_ = Group.objects.get_or_create(name='admins')
admins.permissions.add(viewing_right)
super().save(*args, **kwargs)
@receiver(post_save, sender=SchoolProfile)
def update_permissions_school(sender, instance, **kwargs):
instance.admins,admin_created = Group.objects.get_or_create(name=str(instance.group.pk)+'_admins')
admin_right,_ = Permission.objects.get_or_create(
codename='manage_' + str(instance.group.pk),
name="Administrateur de l'école " + str(instance.group.pk),
content_type=ContentType.objects.get_for_model(SchoolProfile)
)
admins,_ = Group.objects.get_or_create(name='admins')
admins.permissions.add(admin_right)
if admin_created:
instance.save(update_fields=['admins'])
instance.admins.permissions.add(admin_right)
instance.admins.save()
class UserProfile(models.Model):
"""Profil d'un utilisateur"""
school = models.ForeignKey(SchoolProfile, on_delete=models.SET_NULL, null=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
@receiver(post_save, sender=UserProfile)
def update_groups(sender, instance, **kwargs):
instance.user.groups.add(instance.school.group)
@receiver(post_save, sender=User)
def update_permission_user(sender, instance, **kwargs):
perm,_ = Permission.objects.get_or_create(
codename='manage_'+str(instance.pk),
name='Peut administrer ' + instance.username,
content_type=ContentType.objects.get_for_model(User)
)
instance.user_permissions.add(perm)
admins,_ = Group.objects.get_or_create(name='admins')
admins.permissions.add(perm)

6
users/urls.py

@ -1,7 +1,6 @@
from django.urls import path
from .views import (
CreateUser,
CreateUserProfile,
CreateSchool,
EditSchoolName,
EditSchoolPhone,
@ -37,11 +36,6 @@ urlpatterns = [
PasswordChange.as_view(),
name='change-password'
),
path(
'user/<int:pk>/set_school',
CreateUserProfile.as_view(),
name='create-userprofile'
),
path(
'user/<int:pk>',
Profile.as_view(),

31
users/views.py

@ -8,7 +8,7 @@ from django.contrib import messages
from django.urls import reverse, reverse_lazy
from django.shortcuts import get_object_or_404, redirect
from .models import UserProfile, SchoolProfile
from .models import School
from content.models import Content
@ -64,27 +64,9 @@ class Profile(LoginRequiredMixin, UpdateView):
)
class CreateUserProfile(CreateView):
model = UserProfile
fields = ['school']
template_name = 'edit.html'
success_url = reverse_lazy('home')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = "Choix de l'école"
context['validate'] = "Choisir"
return context
def form_valid(self, form):
form.instance.user = get_object_or_404(User, pk=self.kwargs['pk'])
return super(CreateUserProfile, self).form_valid(form)
class CreateSchool(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
permission_required = 'users.add_schoolprofile'
model = Group
model = School
fields = ['name']
template_name = 'edit.html'
success_url = reverse_lazy('settings:index')
@ -97,17 +79,16 @@ class CreateSchool(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
def form_valid(self, form):
response = super(CreateSchool, self).form_valid(form)
profile = SchoolProfile()
profile = School()
profile.group = form.instance
profile.save()
return response
class EditSchoolName(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
model = Group
model = School
fields = ['name']
template_name = 'edit.html'
queryset = Group.objects.filter(school__isnull=False)
def get_success_url(self):
return reverse('users:edit-school-phone', kwargs={'pk':self.object.school.pk})
@ -128,7 +109,7 @@ class EditSchoolName(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
class EditSchoolPhone(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
model = SchoolProfile
model = School
fields = ['phone']
template_name = 'edit.html'
@ -148,13 +129,11 @@ class EditSchoolPhone(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
class DeleteSchool(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
model = Group
permission_required = 'users.delete_schoolprofile'
queryset = Group.objects.filter(school__isnull=False)
class School(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
model = Group
template_name = "users/school.html"
queryset = Group.objects.filter(school__isnull=False)
def get_context_data(self, **kwargs):
context = super().get_context_data()

Loading…
Cancel
Save