如何在使用基于 class 的视图注册后立即登录用户?

How to logged a user just after Sign up with class based views?

我在一个销售图片的网站上工作,我正在尝试找到一种方法,让用户在注册后可以 login 使用基于 class 的视图,我已经做到了使用基于函数的视图,但我想基于 class 来做,因为它需要更少的代码。

以下是基于 function 的视图:

我的models.py:

from django.db import models
from django.contrib.auth.models import User


class JobType(models.Model):
    job_name = models.CharField(max_length=50)

    def __str__(self):
        return self.job_name


class Country(models.Model):
    country_name = models.CharField(max_length=50)

    def __str__(self):
        return self.country_name


class IndianState(models.Model):
    state_name = models.CharField(max_length=30)

    def __str__(self):
        return self.state_name


class SignUpModel(User):
    company_name = models.CharField(max_length=80)
    job = models.ForeignKey(JobType, on_delete=models.CASCADE)
    mobile_no = models.PositiveIntegerField()
    country = models.ForeignKey(
        Country, on_delete=models.CASCADE, blank=True)
    state = models.ForeignKey(IndianState, on_delete=models.CASCADE)

forms.py

from django import forms
from django.contrib.auth.forms import AuthenticationForm, UsernameField
from django.utils.translation import gettext, gettext_lazy as _
from django.core import validators
from .models import JobType, SignUpModel


class MyAuthenticationForm(AuthenticationForm):
    username = UsernameField(widget=forms.TextInput(attrs={'autofocus': True}))
    password = forms.CharField(
        label=_("Password"),
        strip=False,
        widget=forms.PasswordInput(attrs={'autocomplete': 'current-password'}),
    )

    error_messages = {
        'invalid_login': _(
            "Please enter a correct %(username)s and password."
        ),
        'inactive': _("This account is inactive."),
    }


class LoginForm(MyAuthenticationForm):
    username = UsernameField(widget=forms.TextInput(
        attrs={"autofocus": True, "class": 'form-control', 'placeholder': 'Enter Username'}), error_messages={'required': 'Enter Username'})
    password = forms.CharField(
        strip=False,
        widget=forms.PasswordInput(
            attrs={'placeholder': "Enter Password", 'class': 'form-control', 'auto-complete': 'current-password'}),
        error_messages={'required': 'Enter Password'}
    )


class SignUpForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['job'].empty_label = 'Select Job Description'
        self.fields['country'].empty_label = 'Select Country'
        self.fields['state'].empty_label = 'Select State'

    first_name = forms.CharField(widget=forms.TextInput(
        attrs={'placeholder': 'First Name', 'class': 'form-control'}), required=True, error_messages={'required': 'First Name is required'})
    last_name = forms.CharField(widget=forms.TextInput(
        attrs={'placeholder': 'Last Name', 'class': 'form-control'}), required=True, error_messages={'required': 'Last Name is required'})
    email = forms.EmailField(widget=forms.EmailInput(
        attrs={'placeholder': 'Email Address', 'class': 'form-control'}), required=True, error_messages={'required': 'Email Address is required'})
    mobile_no = forms.CharField(widget=forms.NumberInput(
        attrs={'placeholder': 'Mobile Number', 'class': 'form-control'}), validators=[validators.MinLengthValidator(10), validators.MaxLengthValidator(10)])
    password = forms.CharField(widget=forms.PasswordInput(
        attrs={'placeholder': 'Enter Password', 'class': 'form-control'}), validators=[validators.MinLengthValidator(8)], error_messages={'required': 'Enter Password'})

    class Meta:
        model = SignUpModel
        fields = ['username', 'first_name', 'last_name', 'email', 'password',
                  'company_name', 'job', 'mobile_no', 'country', 'state']
        widgets = {
            'company_name': forms.TextInput(attrs={'placeholder': 'Company Name', 'class': 'form-control'}),
            'mobile_no': forms.NumberInput(attrs={'placeholder': 'Mobile Number', 'class': 'form-control'}),
            'username': forms.TextInput(attrs={'placeholder': 'Your Username', 'class': 'form-control'}),
            'job': forms.Select(attrs={'class': 'form-control'}),
            'country': forms.Select(attrs={'class': 'form-control'}),
            'state': forms.Select(attrs={'class': 'form-control'})

        }
        error_messages = {
            'username': {
                'required': _('Username must be given')
            },
            'password': {
                'required': _('password is required')
            },
            'mobile_no': {
                'required': _('Mobile Number is required')
            },
            'company_name': {
                'required': _('Company Name is required')
            },
            'job': {
                'required': _('Job description must be selected')
            },
            'state': {
                'required': _('State Name is required')
            }
        }

记住: 在这里,为了我的目的,我已经覆盖了 django's 表格。

views.py

from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from about.models import SignUpModel
from . forms import LoginForm
from django.views.generic.base import TemplateView
from django.contrib.auth.views import LoginView, LogoutView
from . forms import SignUpForm
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login
from django.contrib import messages
from django.contrib.auth.hashers import make_password
from django.contrib.auth import login, authenticate

# @cache_page(60*60*24)


def about_first_page(request):
    return render(request, 'aboutus/home.html')


# @cache_page(60*60*24)
def pricing(request):
    return render(request, 'aboutus/pricing.html')


class MyLoginView(LoginView):
    template_name = 'aboutus/registration.html'
    authentication_form = LoginForm


class MyLogoutView(LogoutView):
    template_name = 'aboutus/logout.html'


@method_decorator(login_required(login_url='/about/registration/'), name='dispatch')
class UserMyAccounts(TemplateView):
    def get(self, request, *args, **kwargs):
        return super().get(request, *args, **kwargs)
    template_name = 'aboutus/myaccounts.html'


def sign_up(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            un = form.cleaned_data['username']
            pword = make_password(form.cleaned_data['password'])

            fname = form.cleaned_data['first_name']
            lname = form.cleaned_data['last_name']
            em = form.cleaned_data['email']
            compname = form.cleaned_data['company_name']
            job = form.cleaned_data['job']
            mobno = form.cleaned_data['mobile_no']
            country = form.cleaned_data['country']
            state = form.cleaned_data['state']
            sign_up_prop = SignUpModel(first_name=fname, last_name=lname,
                                       username=un, password=pword, email=em,
                                       company_name=compname, job=job, mobile_no=mobno, country=country, state=state)
            sign_up_prop.save()

            """username and password from request"""
            un_request = request.POST.get('username')
            pass_request = request.POST.get('password')

            authen = authenticate(
                request, username=un_request, password=pass_request)
            if authen is not None:
                login(request, authen)
                return HttpResponseRedirect('/about/myaccounts/')

    else:
        form = SignUpForm()
    return render(request, 'aboutus/sign-up.html', {'form': form})

urls.py

from django import views
from django.urls import path
from about import views
from django.contrib.auth import views as auth_views
from django.views.generic.base import TemplateView
from .forms import LoginForm
urlpatterns = [
    path('', views.about_first_page, name='about_first_page'),
    path('pricing', views.pricing, name='pricing'),
    path('registration/', views.MyLoginView.as_view(), name='login'),
    path('logout/', views.MyLogoutView.as_view(), name='logout'),
    path('sign-up/', views.sign_up, name='sign-up'),
    path('myaccounts/', views.UserMyAccounts.as_view(), name='myaccounts')
]

上面基于 function 的视图,它工作正常,但是当我开始使用基于 class 的视图时,我卡在了这一点上:

所有其他 files 相同。

这是 views.py,基于 class 的视图:

class SignUpView(CreateView):
    form_class = SignUpForm
    template_name = 'aboutus/sign-up.html'
    success_url = '/about/myaccounts/'

那么,我怎样才能对 class 做同样的事情呢?

可以使用form_valid[Django-doc]方法

class SignUpView(CreateView):
  form_class = SignUpForm
  template_name = 'aboutus/sign-up.html'
  success_url = '/about/myaccounts/'
  
  def form_valid(self, form):
      response = super().form_valid(form)
      user = form.save()
      login(self.request, user, backend='django.contrib.auth.backends.ModelBackend')
      return response

更新

更新你的forms.py

from django.contrib.auth.forms import UserCreationForm

class SignUpForm(UserCreationForm):
    ....

如果上述解决方案对您不起作用,那么您可以通过覆盖它来散列表单保存方法中的密码

from django.contrib.auth.hashers import make_password

    class SignUpForm(forms.ModelForm):
        ....
        def save(self, commit=True):
            user = super(SignUpForm, self).save(commit=False)
            raw_password = make_password(
              self.cleaned_data["password"]
            )
            if commit:
               user.save()
            return user