Bonjour à tous,

Je viens vers vous car actuellement je travaille sur un projet personnel en django et je souhaiterais mettre en place le système d'authentification de django. J'ai lu différents tutoriels et aussi la documentation de django sur le sujet et j'ai vu qu'il y avait énormément de possibilités. Mon but serait de réaliser un système d'authentification pour plusieurs types d'utilisateur avec authentification par email et non username. Je me suis donc tourné vers la classe AbtractBaseUser de django.
Cependant,
je ne sais pas encore quel est le choix le plus judicieux afin de définir mon système d'authentification.

Pour le moment, j'ai réalisé un système de la manière suivante :

models.py
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)
 
TYPE_USER = (
    ('student', _('Student')),
    ('employee', _('Employee')),
)
 
class MyuserManager(BaseUserManager):
    def create_user(self, email, last_name, first_name, date_of_birth, user_type, password=None):
        if not email:
            raise ValueError("users must have an email address")
 
        user = self.model(
            email         = self.normalize_email(email),
            last_name     = last_name,
            first_name    = first_name,
            date_of_birth = date_of_birth,
            user_type     = user_type,
        )
 
        user.set_password(password)
        user.save() #default database(can use 'using=' attribute to select db
        return user
 
    def create_superuser(self, email, password, last_name, first_name, date_of_birth, user_type):
        user = self.create_user(email,
            password      = password,
            date_of_birth = date_of_birth,
            last_name     = last_name,
            first_name    = first_name,
            user_type     = user_type,
        )
        user.is_admin = True
        user.is_staff = True
        user.save()
        return user
 
class MyUser(AbstractBaseUser):
    """Based model user"""
    email   = models.EmailField(
        verbose_name = 'email',
        max_length=255,
        unique=True,
    )
    last_name     = models.CharField(max_length=30)
    first_name    = models.CharField(max_length=30)
    date_of_birth = models.DateField()
    user_type     = models.CharField(_('Type'), choices=TYPE_USER, max_length=20, default='student')
    phone         = models.CharField(max_length=20, blank=True)
    friends       = models.ManyToManyField("self", blank=True)
    faculty       = models.ForeignKey(Faculty, null=True, blank=True)
    desk          = models.CharField(max_length=30, blank=True)
    campus        = models.ForeignKey(Campus, null=True, blank=True)
    job           = models.ForeignKey(Function, null=True, blank=True)
    cursus        = models.ForeignKey(Cursus, null=True, blank=True)
    year          = models.IntegerField(null=True, blank=True)
    is_active     = models.BooleanField(default=True)
    is_admin      = models.BooleanField(default=False)
    is_staff      = models.BooleanField(default=False)
 
    objects = MyuserManager()
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['last_name', 'first_name', 'date_of_birth', 'user_type']
 
 
    def get_full_name(self):
        return self.email
 
    def get_short_name(self):
        return self.email
 
    def __str__(self):
        return self.email
 
    def has_perm(self, perm, obj=None):
        return True
 
    def has_module_perms(self, app_label):
        return True

Pour ce modèle, ce que j'ai fait c'est regrouper tous les champs dont j'aurai besoin pour mes utilisateurs ainsi je n'ai qu'un seul modèle dans ma base et avec l'attribut user_type je peux définir mon type d'utilisateur.
Ici je ne sais pas si cela est la meilleur solution car j'ai vu qu'il était possible d'utiliser l'héritage ou encore l'utilisation de clé étrangère.

Ainsi mes autres solutions seraient

soit je définis un modèle comme ceci :

Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
class MyUser(abstractBaseUser):
#Ici les champs commun à tous les utilisateurs
 
class MyStudentUser(MyUser):
#ici les champs spécifiques à l'étudiant
 
class MyEmployeeUser(MyUser):
#ici les champs spécifiques à l'employée

ou alors comme cela:

Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
class MyUser(abstractBaseUser):
#Ici les champs commun à tous les utilisateurs
 
class MyStudentUser(models.Model):
user = models.ForeignKey(MyUser, unique=True)  (Ou bien un OneToOneField)
#ici les champs spécifiques à l'étudiant
 
class MyEmployeeUser(models.Model):
user = models.ForeignKey(MyUser, unique=True)
#ici les champs spécifiques à l'employée

Avec mon unique modèle, j'ai essayé de créer une vue qui permettrait à un utilisateur de se créer un profile comme ceci:

views.py
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class RegisterProfile(CreateView):
    model = MyUser
    template_name = 'fbLike/user_profile.html'
    form_class = StudentProfileForm
    second_form_class = EmployeeProfileForm
 
 
    def get_success_url(self):
        return reverse('login',)
 
    def get_context_data(self, **kwargs):
        context = super(RegisterProfile, self).get_context_data(**kwargs)
        if 'studenForm' not in context:
            context['studentForm'] = self.form_class
        if 'employeeForm' not in context:
            context['employeeForm'] = self.second_form_class
        return context
 
 
    def post(self, request, *args, **kwargs):
        if request.POST['profileType'] == 'student':
            studentForm = self.form_class(request.POST)
            employeeForm = self.second_form_class()
            studentForm.user_type = 'student'
            if studentForm.is_valid():
                newStudentUser = MyUser()
                newStudentUser.set_password(studentForm.cleaned_data['password'])
                newStudentUser.email         = studentForm.cleaned_data['email']
                newStudentUser.first_name    = studentForm.cleaned_data['first_name']
                newStudentUser.last_name     = studentForm.cleaned_data['last_name']
                newStudentUser.date_of_birth = studentForm.cleaned_data['date_of_birth']
                newStudentUser.save()
                return redirect('login')
        else:
            employeeForm = self.second_form_class(request.POST)
            studentForm = self.form_class()
            employeeForm.user_type = 'employee'
            if employeeForm.is_valid():
                newEmployeeUser = MyUser()
                newEmployeeUser.set_password(employeeForm.cleaned_data['password'])
                newEmployeeUser.email         = employeeForm.cleaned_data['email']
                newEmployeeUser.first_name    = employeeForm.cleaned_data['first_name']
                newEmployeeUser.last_name     = employeeForm.cleaned_data['last_name']
                newEmployeeUser.date_of_birth = employeeForm.cleaned_data['date_of_birth']
                newEmployeeUser.save()
                return redirect('login')
 
        return render(request, self.template_name, {'studentForm': studentForm, 'employeeForm': employeeForm})

N'étant pas encore à l'aise avec django, je ne sais pas si c'est une solution acceptable. D'autant plus qu'ici j'ai déjà un petit problème lors de la création en soumettant mon formulaire avec les champs remplis. Je me retrouve avec une erreur de champs obligatoires alors qu'ils sont remplis.

Ensuite, j'ai essayé de mettre en place les modèles utilisants la foreign key mais je ne vois pas comment faire pour créer la vue de création d'utilisateur, notamment comment afficher les champs de la foreign key dans mon formulaire de l'étudiant ou de l'employée. dois-je créer un utilisateur MyUser avant puis l'ajouter à mes autres models où bien est-il possible de le faire en même temps que dans le formulaire de l'étudiant ou de l'employée ?

Au vue de ce long récit, j'espère ne pas être trop vague dans mon propos. Et que cela correspond bien aux régles du forum (je suis nouveau).
Enfin, auriez-vous des conseils à me donner ou des pistes vers ou chercher afin de que je puisse comprendre comme marche le système.

Je vous remercie d'avance.