Django-allauth: Перенаправление пользователей после регистрации/входа на определенную страницу в зависимости от того, с какой страницы они пришли

Проблема

  1. I have an invite system in my django app that allow users to invite other people (using their email) to join their team.
  2. When an invited user clicks on an invitation, they are redirected to an url that carries informations about the specific team the user was invited to.
  3. Such url calls a view called accept_invitation that handles the following use-cases:
  • a) Если пользователь уже вошел в систему И он также является приглашенным пользователем (я проверяю электронную почту приглашенного), я добавляю пользователя в команду и перенаправляю его на страницу команды.

  • b) Если пользователь уже вошел в систему, но не является приглашенным пользователем, я перенаправляю его на страницу, где предлагаю ему войти в систему под другим аккаунтом.

  • c) Если пользователь вышел из системы, я перенаправляю его на страницу, где предлагаю ему войти в систему и/или зарегистрироваться для продолжения.

В случае использования a) все работает отлично, но в случаях использования b) и c) мне нужно было придумать, как распространить информацию о приглашении на следующие экраны и после логина.

Моя первоначальная идея заключалась в том, чтобы добавить параметры приглашения в request.session, чтобы после входа в систему я мог получить информацию из запроса в адаптере MyAccountAdapter(DefaultAccountAdapter), а затем отправить пользователей туда, куда им нужно.

Однако я делаю что-то не так, и MyAccountAdapter не вызывается. Я не уверен, почему. Я думаю это из-за другого адаптера MySocialAccountAdapter, который я сделал и который, возможно, все портит (и я даже не уверен, что он делает то, что должен делать).

В любом случае, я заблудился, поэтому любая помощь будет очень признательна.

Настройка

Мое accept_invitation мнение

def accept_invitation(request, invitation_id):
    invitation = TeamMemberInvitation.objects.get(id=invitation_id)
    print('I am entering here, yes')
    print(request)

    context = {
        'project': invitation.project,
        'invitation': invitation
    }

    if invitation.key_expired():
        print('expired do something')
        return render(request, 'action/team_and_permission/invitation_expired.html', context)

    if request.user.is_authenticated:
        print('user is logged in')
        if request.user.email == invitation.invitee.email:
            print('the logged in user is also the one invited!')
            if TeamMember.objects.filter(project=invitation.project,user=request.user).exists():
                print('the logged in user is the one invited and is already a member!')
                return redirect('action:project_team', project_id=invitation.project.id)
            else:
                print('the logged in user is the one invited but is not a member, yet!')
                #accept invitation
                invitation.status = INVITATION_STATUS[1][0]
                #add to team member
                invitation.accept_invitation(request.user)
                #send him to the project
                return redirect('action:project_team', project_id=invitation.project.id)

        else:
            print('the invited user is not the user that is currently logged in, do something!')
            # accept invitation
            invitation.status = INVITATION_STATUS[1][0]
            # add to team member
            invitation.accept_invitation(request.user)
            # send him to the project
            return redirect('action:project_team', project_id=invitation.project.id)

    # if user is logged out
    else:
        print('user is logged out')
        request.session['team_membership_project_id'] = str(invitation.project.id)
        request.session['invitation_id'] = str(invitation.id)


        return redirect('myusermodel:sign_in')

    return render(request, 'action/team_and_permission/accept_invitation.html', context)

Мои адаптеры, которые, как я надеялся, решат мою проблему, но не решили (значит, я сделал что-то не так в них)


class MyAccountAdapter(DefaultAccountAdapter):

    def get_login_redirect_url(self, request):
        print('I am entering here')
        print(request)
        if 'team_membership_project_id' in request.session:
            parameters = {}
            #parameters['project_id'] = request.session['team_membership_project_id']
            parameters['invitation_id'] = request.session['invitation_id']

            path = reverse('action:accept_invitation', urlconf=None, args=None, kwargs=parameters)

            return path

        path = '/'

        return path

    def is_open_for_signup(self, request):
        """
        Checks whether or not the site is open for signups.Next to simply returning True/False you can also intervene the
        regular flow by raising an ImmediateHttpResponse. (Comment reproduced from the overridden method.)
        """
        return True


class MySocialAccountAdapter(DefaultSocialAccountAdapter):
    def pre_social_login(self, request, sociallogin):
        user = sociallogin.user
        if user.id:
            return
        try:
            # if user exists, connect the account to the existing account and login
            customer = CustomUser.objects.get(email=user.email)
            sociallogin.state['process'] = 'connect'
            #sociallogin.connect(request, user)
            perform_login(request, customer, 'none')
        except CustomUser.DoesNotExist:
            pass


мои настройки

...

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.sites',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.google',
    'whitenoise.runserver_nostatic',  # new
]

MIDDLEWARE = [
    #'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]


...


AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]



AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
    'guardian.backends.ObjectPermissionBackend',
]

SITE_ID = 3
LOGIN_REDIRECT_URL = '/'
ACCOUNT_ADAPTER = 'myusermodel.adapter.MyAccountAdapter'



# Additional configuration settings
SOCIALACCOUNT_QUERY_EMAIL = True
ACCOUNT_LOGOUT_ON_GET = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
AUTH_USER_MODEL = 'myusermodel.CustomUser'



SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': [
            'profile',
            'email',
        ],
        'AUTH_PARAMS': {
            'access_type': 'online',
        }
    }
}

...

И моя пользовательская модель пользователя, на случай, если она тоже делает что-то не так (я так не думаю)

from django.contrib.auth.base_user import BaseUserManager
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _


class CustomUserManager(BaseUserManager):
    """
    Custom user model manager where email is the unique identifiers
    for authentication instead of usernames.
    """
    def create_user(self, email, password, **extra_fields):
        """
        Create and save a User with the given email and password.
        """
        if not email:
            raise ValueError(_('The Email must be set'))
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, password, **extra_fields):
        """
        Create and save a SuperUser with the given email and password.
        """
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError(_('Superuser must have is_staff=True.'))
        if extra_fields.get('is_superuser') is not True:
            raise ValueError(_('Superuser must have is_superuser=True.'))
        return self.create_user(email, password, **extra_fields)


class CustomUser(AbstractUser):
    username = None
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

    def __str__(self):
        return self.email

Представление, которое я построил, на самом деле было правильным. Исправив эту проблему, исчезла и эта (Django-allauth: Мой поток перенаправления после регистрации с Google Auth сломан, и я не могу понять почему)

Вернуться на верх