Как создать несколько типов пользователей с помощью google OAuth в Django

Я работаю на Django и делаю систему управления школой, где я даю возможность ученикам и учителям входить и регистрироваться через Google OAuth .

Вот мои модели

from django.db import models 

class Student(models.Model):
    first= models.CharField(max_length = 100 , blank = False , null = False)
    last = models.CharField(max_length = 100 , blank = False , null = False)
    user = models.OneToOneField(User , on_delete = models.CASCADE)
    class_studying = models.ForeignKey("SchoolClass")
    ...

class Teacher(models.Model):
    first= models.CharField(max_length = 100 , blank = False , null = False)
    last = models.CharField(max_length = 100 , blank = False , null = False)
    user = models.OneToOneField(User , on_delete = models.CASCADE)
    classes_teaching = models.ManyToManyField("SchoolClass")
    salary = models.DecimalField(max_digits =6 , decimal_places = 2)
    ...

Я использую google Oauth с пакетом django-allauth для регистрации, входа пользователей через google OAuth .

Здесь у меня есть возможность создать только один тип пользователя через Google OAuth с помощью сигналов. Либо я могу создать ученика, либо учителя. Но я хочу создать способ, чтобы я мог зарегистрировать как учителя, так и ученика через тот же OAuth. Я пробовал различные способы и применял несколько логических схем, чтобы понять это, но я не могу получить полноценное решение .

Signals.py

from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save , sender = User )
def save_student(sender , instance , created , *args , **kwargs):
    if created : 
        student = Student(user = instance)
        student.save()
        ...

Я пытаюсь найти различные решения для решения этой проблемы, но не могу создать полноценное решение .

После создания пользователя. Он сохраняется в базе данных в модели пользователя. Я хочу создать связанное лицо в соответствии с потребностью.

Если учитель хочет создать учетную запись, ему должна быть предоставлена какая-то другая ссылка или форма регистрации через Google OAuth, а для ученика - другая. Мне это тоже не помогает.

Любая помощь была бы очень кстати. Спасибо.

Вам необходимо удалить сигнал и создать собственный поток аутентификации.

Идеальный способ - переопределить метод auth и создать свою собственную функцию. В функции auth мы получим тип пользователя (студент, преподаватель) и создадим студента или преподавателя на основе типа пользователя.

class GoogleSocialAuthView(GenericAPIView):
serializer_class = GoogleSocialAuthSerializer

def post(self, request):
    serializer = self.serializer_class(data=request.data)
    serializer.is_valid(raise_exception=True)
    data = (serializer.validated_data['auth_token'])
    return Response(data, status=status.HTTP_200_OK)

Класс Серилаизер:

class GoogleSocialAuthSerializer(serializers.Serializer):
auth_token = serializers.CharField()

def validate_auth_token(self, auth_token):
    user_data = google.Google.validate(auth_token)
    try:
        user_data['sub']
    except:
        raise serializers.ValidationError(
            'The token is invalid or expired. Please login again.'
        )

    if user_data['aud'] != os.environ.get('GOOGLE_CLIENT_ID'):
        raise AuthenticationFailed('oops, who are you?')

    user_id = user_data['sub']
    email = user_data['email']
    provider = 'google'
    name = email.split("@")[0]
    return register_social_user(
        provider=provider, user_id=user_id, email=email, name=name
    )

Функция регистрации:

def register_social_user(provider, user_id, email, name):
filtered_user_by_email = BenjiUser.objects.filter(email=email)
data = {}
if filtered_user_by_email.exists():
    if provider == filtered_user_by_email[0].auth_provider:
        registered_user = authenticate(
            username=name, password=os.environ.get('SOCIAL_SECRET')
        )
        refresh = RefreshToken.for_user(registered_user)
        data['token'] = str(refresh.access_token)
        user = CustomUser.objects.get(username=registered_user.username)
        data['user'] = BenjiUserSerializer(instance=user).data
        return data
    else:
        raise AuthenticationFailed(
            detail='Please continue your login using ' + filtered_user_by_email[0].auth_provider)

else:
    user = {
        'username': generate_username(name), 'email': email,
        'password': os.environ.get('SOCIAL_SECRET')
    }
    # TODO: Check user type and based on it create object.
    user = CustomUser.objects.create_user(**user)
    user.is_verified = True
    user.save()
    new_user = authenticate(
        username=name, password=os.environ.get('SOCIAL_SECRET')
    )
    refresh = RefreshToken.for_user(new_user)
    data['token'] = str(refresh.access_token)
    from tenants.serializers import BenjiUserSerializer
    data['user'] = CustomUserSerializer(instance=user).data
    return data
Вернуться на верх