text: from django.conf import settings
  from django.contrib.auth import get_user_model
  from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
  from django.contrib.auth.views import (
      LoginView, LogoutView, PasswordChangeView, PasswordChangeDoneView,
      PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView, PasswordResetCompleteView
  )
  from django.contrib.sites.shortcuts import get_current_site
  from django.core.mail import send_mail
  from django.core.signing import BadSignature, SignatureExpired, loads, dumps
  from django.http import HttpResponseBadRequest
  from django.shortcuts import redirect, resolve_url
  from django.template.loader import render_to_string
  from django.urls import reverse_lazy
  from django.views import generic
  from .forms import (
      LoginForm, UserCreateForm, UserUpdateForm, MyPasswordChangeForm,
      MyPasswordResetForm, MySetPasswordForm, EmailChangeForm
  )
  
  
  User = get_user_model()
  
  
  class Top(generic.TemplateView):
      template_name = 'register/top.html'
  
  
  class Login(LoginView):
      """Login page"""
      form_class = LoginForm
      template_name = 'register/login.html'
  
  
  class Logout(LoginRequiredMixin, LogoutView):
      """Logout page"""
      template_name = 'register/top.html'
  
  
  class UserCreate(generic.CreateView):
      """Temporary user registration"""
      template_name = 'register/user_create.html'
      form_class = UserCreateForm
  
      def form_valid(self, form):
          """Issuing provisional registration and full registration email."""
          # Switching between temporary registration and main registration is easy with the is_active attribute.
          # The withdrawal process will also improve if you only set is_active to False.
          user = form.save(commit=False)
          user.is_active = False
          user.save()
  
          # Send activation URL
          current_site = get_current_site(self.request)
          domain = current_site.domain
          context = {
              'protocol': 'https' if self.request.is_secure() else 'http',
              'domain': domain,
              'token': dumps(user.pk),
              'user': user,
          }
  
          subject = render_to_string('register/mail_template/create/subject.txt', context)
          message = render_to_string('register/mail_template/create/message.txt', context)
  
          user.email_user(subject, message)
          return redirect('register:user_create_done')
  
  
  class UserCreateDone(generic.TemplateView):
      """I temporarily registered as a user"""
      template_name = 'register/user_create_done.html'
  
  
  class UserCreateComplete(generic.TemplateView):
      """User registration after accessing URL in email"""
      template_name = 'register/user_create_complete.html'
      timeout_seconds = getattr(settings, 'ACTIVATION_TIMEOUT_SECONDS', 60*60*24)  # Within 1 day by default
  
      def get(self, request, **kwargs):
          """Register if token is correct."""
          token = kwargs.get('token')
          try:
              user_pk = loads(token, max_age=self.timeout_seconds)
  
          # Expired
          except SignatureExpired:
              return HttpResponseBadRequest()
  
          # token is wrong
          except BadSignature:
              return HttpResponseBadRequest()
  
          # token is no problem
          else:
              try:
                  user = User.objects.get(pk=user_pk)
              except User.DoesNotExist:
                  return HttpResponseBadRequest()
              else:
                  if not user.is_active:
                      # まだ仮登録で、他に問題なければ本登録とする
                      user.is_active = True
                      user.save()
                      return super().get(request, **kwargs)
  
          return HttpResponseBadRequest()
  
  
  class OnlyYouMixin(UserPassesTestMixin):
      """Allow only the user or superuser to access the user page"""
      raise_exception = True
  
      def test_func(self):
          user = self.request.user
          return user.pk == self.kwargs['pk'] or user.is_superuser
  
  
  class UserDetail(OnlyYouMixin, generic.DetailView):
      """User details page"""
      model = User
      template_name = 'register/user_detail.html'  # Write template name properly in case you use default user
  
  
  class UserUpdate(OnlyYouMixin, generic.UpdateView):
      """User information update page"""
      model = User
      form_class = UserUpdateForm
      template_name = 'register/user_form.html'  # Write the template name properly in case you want to use the default user
  
      def get_success_url(self):
          return resolve_url('register:user_detail', pk=self.kwargs['pk'])
  
  
  class PasswordChange(PasswordChangeView):
      """Change password view"""
      form_class = MyPasswordChangeForm
      success_url = reverse_lazy('register:password_change_done')
      template_name = 'register/password_change.html'
  
  
  class PasswordChangeDone(PasswordChangeDoneView):
      """I changed my password"""
      template_name = 'register/password_change_done.html'
  
  
  class PasswordReset(PasswordResetView):
      """Password change URL sending page"""
      subject_template_name = 'register/mail_template/password_reset/subject.txt'
      email_template_name = 'register/mail_template/password_reset/message.txt'
      template_name = 'register/password_reset_form.html'
      form_class = MyPasswordResetForm
      success_url = reverse_lazy('register:password_reset_done')
  
  
  class PasswordResetDone(PasswordResetDoneView):
      """Page that sent URL for password change"""
      template_name = 'register/password_reset_done.html'
  
  
  class PasswordResetConfirm(PasswordResetConfirmView):
      """New password entry page"""
      form_class = MySetPasswordForm
      success_url = reverse_lazy('register:password_reset_complete')
      template_name = 'register/password_reset_confirm.html'
  
  
  class PasswordResetComplete(PasswordResetCompleteView):
      """New password set page"""
      template_name = 'register/password_reset_complete.html'
  
  
  class EmailChange(LoginRequiredMixin, generic.FormView):
      """E-mail address change"""
      template_name = 'register/email_change_form.html'
      form_class = EmailChangeForm
  
      def form_valid(self, form):
          user = self.request.user
          new_email = form.cleaned_data['email']
  
          # Send URL
          current_site = get_current_site(self.request)
          domain = current_site.domain
          context = {
              'protocol': 'https' if self.request.is_secure() else 'http',
              'domain': domain,
              'token': dumps(new_email),
              'user': user,
          }
  
          subject = render_to_string('register/mail_template/email_change/subject.txt', context)
          message = render_to_string('register/mail_template/email_change/message.txt', context)
          send_mail(subject, message, None, [new_email])
  
          return redirect('register:email_change_done')
  
  
  class EmailChangeDone(LoginRequiredMixin, generic.TemplateView):
      """I sent an email to change my email address"""
      template_name = 'register/email_change_done.html'
  
  
  class EmailChangeComplete(LoginRequiredMixin, generic.TemplateView):
      """Mead change view called after stepping on a link"""
      template_name = 'register/email_change_complete.html'
      timeout_seconds = getattr(settings, 'ACTIVATION_TIMEOUT_SECONDS', 60*60*24)  # デフォルトでは1日以内
  
      def get(self, request, **kwargs):
          token = kwargs.get('token')
          try:
              new_email = loads(token, max_age=self.timeout_seconds)
  
          # Expired
          except SignatureExpired:
              return HttpResponseBadRequest()
  
          # token is wrong
          except BadSignature:
              return HttpResponseBadRequest()
  
          # token is no problem
          else:
              User.objects.filter(email=new_email, is_active=False).delete()
              request.user.email = new_email
              request.user.save()
              return super().get(request, **kwargs)
  