基于django的视频点播网站开发-step3-注册登录功能

用户注册登录是一个网站的基本功能,django对这部分进行了很好的封装,我们只需要在django的基础上做些简单的修改就可以达到我们想要的效果。在本讲中,我们会用到user中的用户授权方面的一些函数,还会对django中的user进行扩展,以及django中的form验证。

效果展示

注册页面

image

登录页面

image

创建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了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,639评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,277评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,221评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,474评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,570评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,816评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,957评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,718评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,176评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,511评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,646评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,322评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,934评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,755评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,987评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,358评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,514评论 2 348

推荐阅读更多精彩内容