基於django的視頻點播網站開發-step3-註冊登錄功能

用戶註冊登錄是一個網站的基本功能,django對這部分進行了很好的封裝,我們只需要在django的基礎上做些簡單的修改就可以達到我們想要的效果。在本講中,我們會用到user中的用戶授權方面的一些函數,還會對django中的user進行擴展,以及django中的form驗證。

效果展示

註冊頁面
基於django的視頻點播網站開發-step3-註冊登錄功能

登錄頁面
基於django的視頻點播網站開發-step3-註冊登錄功能

創建users應用

django的設計哲學是,一個應用只提供一種功能,比如users應用只提供用戶相關功能,comment應用只提供評論相關功能,這能提高代碼的重複利用率。

在django中,只需要下面一條命令,即可建立users應用

python3 manage.py startapp users

建表

我們需要一個用戶表,用來實現登錄註冊功能,雖然django已經自帶來用戶登錄註冊功能,也有相應的表,但是不符合中國人習慣,需要我們對user模型進行自定義。實現自定義User模型最簡單的方式就是繼承AbstractBaseUser,AbstractBaseUser實現了User的核心功能,我們只需加一些額外的字段進行補充即可。

User模型原有的字段有:

  • username
  • password
  • last_login
  • is_superuser
  • first_name
  • last_name
  • email
  • is_staff
  • is_active
  • date_joined

這些都是最基本的字段,並不能滿足我們的需求。

根據網站自身業務,我們又添加了下面的字段

  • nickname(暱稱)
  • avatar(頭像)
  • mobile(手機號)
  • gender(性別)
  • subscribe(是否訂閱)

我們只需在users/models.py中寫入代碼

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

class User(AbstractUser):
    GENDER_CHOICES = (
        ('M', '男'),
        ('F', '女'),
    )
    nickname = models.CharField(blank=True, null=True, max_length=20)
    avatar = models.FileField(upload_to='avatar/')
    mobile = models.CharField(blank=True, null=True, max_length=13)
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES,blank=True, null=True)
    subscribe = models.BooleanField(default=False)

    class Meta:
        db_table = "v_user"

gender是性別字段,其中用到了choices=GENDER_CHOICES。這種方式常常用在下拉框或單多選框,例如 M對應男 F對應女。

url配置

在user文件夾下面,新建url.py文件,寫入登錄、註冊和退出的url信息。app_name是命名空間,我們命名爲'users'。

from django.urls import path
from . import views

app_name = 'users'
urlpatterns = [
    path('login/', views.login, name='login'),
    path('signup/', views.signup, name='signup'),
    path('logout/', views.logout, name='logout'),
]

url路由配置好了,我們下面就開始寫視圖函數代碼了

註冊函數

我們先來寫註冊函數,寫註冊,當然得有註冊表單了,幸運的是,在django中,可以用代碼來生成表單。我們只需在users下新建forms.py文件,然後寫入註冊表單的代碼。

class SignUpForm(UserCreationForm):
    username = forms.CharField(min_length=4,max_length=30,
                               error_messages={
                                   'min_length': '用戶名不少於4個字符',
                                   'max_length': '用戶名不能多於30個字符',
                                   'required': '用戶名不能爲空',
                               },
                               widget=forms.TextInput(attrs={'placeholder': '請輸入用戶名'}))
    password1 = forms.CharField(min_length=8, max_length=30,
                                error_messages={
                                    'min_length': '密碼不少於8個字符',
                                    'max_length': '密碼不能多於30個字符',
                                    'required': '密碼不能爲空',
                                },
                                widget=forms.PasswordInput(attrs={'placeholder': '請輸入密碼'}))
    password2 = forms.CharField(min_length=8,max_length=30,
                                error_messages={
                                    'min_length': '密碼不少於8個字符',
                                    'max_length': '密碼不能多於30個字符',
                                    'required': '密碼不能爲空',
                                },
                                widget=forms.PasswordInput(attrs={'placeholder': '請確認密碼'}))

    class Meta:
        model = User
        fields = ('username', 'password1', 'password2',)

    error_messages = {'password_mismatch': '兩次密碼不一致', }

我們的表單一共有三個字段:username、password1、password2,它們都是CharField類型,widget分別是TextInput和PasswordInput。而且django是自帶驗證的,只需要我們配置好error_messages字典,當form驗證的時候,就會顯示我們自定義的錯誤信息。
有了註冊表單後,就可以在前端模板和視圖函數中使用它。

下面是註冊視圖函數。

...
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout

def signup(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            raw_password1 = form.cleaned_data.get('password1')
            user = authenticate(username=username, password=raw_password1)
            auth_login(request, user)
            return redirect('home')
        else:
            print(form.errors)
    else:
        form = SignUpForm()
    return render(request, 'registration/signup.html', {'form': form})

在signup函數中,我們通過form = SignUpForm初始化一個表單,並在render函數中傳遞給模板。

註冊模板文件寫在了templates/registration/signup.html

關鍵代碼是

<form class="ui large form" novalidate method="post" action="{% url 'users:signup' %}" enctype="multipart/form-data" >
            {% csrf_token %}
            <div class="ui stacked segment">
                <div class="field"> 
                    {{form.username}} 
                </div>
                <div class="field"> 
                    {{form.password1}} 
                </div>
                <div class="field"> 
                    {{form.password2}} 
                </div>
                <button class="ui submit button" type="submit">註冊</button>
            </div>
            {% include "base/form_errors.html" %}
        </form>

form的action爲

{% url 'users:signup' %}

即在url.py中定義的signup函數。
通過post請求傳遞給signup,在signup中,通過如下四行代碼來實現註冊,並自動登錄的。

username = form.cleaned_data.get('username')
raw_password1 = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password1)
auth_login(request, user)

登錄函數

登錄函數與註冊函數的模式是一樣的,都是先寫form,寫模板,最後寫視圖函數。
由於form和模板的代碼和註冊功能類似,這裏就不貼了,大家可以上github查看。

重點講一下login視圖函數

def login(request):
    if request.method == 'POST':
        next = request.POST.get('next', '/')
        form = UserLoginForm(request=request, data=request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            user = authenticate(username=username, password=password)
            if user is not None:
                auth_login(request, user)
                return redirect(next)
        else:
            print(form.errors)
    else:
        next = request.GET.get('next', '/')
        form = UserLoginForm()
    print(next)
    return render(request, 'registration/login.html', {'form': form, 'next':next})

在login函數中,我們多了一個next變量,next對應的是登錄後要跳轉的url,其實這是一種場景,假如你在購物網站買東西,最後付款的時候,會跳轉到付款頁,假如你沒有登錄,網站會提示你登錄,登錄後,會再次跳轉到付款頁。

當然了,跳轉到登錄頁的時候,需要你在url後追加next參數,如 aaa. com/login/?next=bbb. com
這樣用戶登錄後就會跳到bbb. com

退出函數

from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout

def logout(request):
    auth_logout(request)
    return redirect('home')

退出功能,僅需要一行代碼 auth_logout(request) 就ok了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章