蒋振飞的博客 - 网站搭建 (第15天) 用户注册登录   
正在加载蒋振飞的博客...
V3.0
蒋振飞的博客

网站搭建 (第15天) 用户注册登录

发布时间: 2018年09月02日 发布人: 蒋振飞 热度: 678 ℃ 评论数: 0

一、前言

这几天正好学了Flask的用户注册登录功能设计,发现与Django的使用特别类似,所以学习Flask的同时也加强了我对Django表单的印象。正好网站搭建也差不多更新到用户操作部分了,就索性把Django表单相关知识再推进一下。其实要加入用户操作功能,也可以直接在模板页面中加上form标签,然后在视图中利用requets.POST.get来接收键值,最后保存在数据库中,所以不是非要使用Django的表单功能才能设计。使用表单是因为表单的确能简化用户在提交用户信息的相关处理,如输入内容不能为空,邮箱必须带有@字符等,这些验证表单的合法性最后都可以交给Django的表单来执行。

    因为在Django中,有比较全的用户模块,所以我没有另外去创建models.py来定义用户的模型,这已经在Django中实现了。我只创建了forms.py用来加入表单字段,另外引用了Django自带的User类。用户的注册登录功能可以比较好的涵盖form表单的相关知识点,常用的form字段定义在官方文档都有说明:表格字段

二、用户注册

我在注册表单中,需要用户名,邮箱,密码等输入。

from django import forms  # django表单功能
from django.contrib.auth.models import User

class RegForm(forms.Form):
    """
    用户注册表单
    """
    # 用户名
    username = forms.CharField(label='用户名',
        max_length=30,
        min_length=3,
        widget=forms.TextInput(
            attrs={'class': 'form-control', 'placeholder': '请输入用户名'}))

    # 邮箱
    email = forms.EmailField(label='邮箱',
        widget=forms.EmailInput(
            attrs={'class': 'form-control', 'placeholder': '请输入邮箱'}))

    # 密码
    password = forms.CharField(label='密码',
        min_length=6,
        widget=forms.PasswordInput(
            attrs={'class': 'form-control', 'placeholder': '请输入密码'}))

    # 再次输入密码
    password_again = forms.CharField(label='再输入一次密码',
        min_length=6,
        widget=forms.PasswordInput(
            attrs={'class': 'form-control', 'placeholder': '再输入依次密码'}))

其中包含了一些属性设置,用来规范表单的显示。定义好表单之后,除了表单自动验证的部分外,还需要另外手动添加对字段的验证,如用户名,邮箱是否会与数据库已有的用户重复,还有第二次输入的密码与第一次输入的密码是否一致,以确保用户输入了正确的密码,所以还需在RegForm类中加入一些方法。

def clean_username(self):
    """
    清洗输入的用户名
    :return: 清洗后的用户名
    """
    username = self.cleaned_data['username']
    if User.objects.filter(username=username).exists():
        raise forms.ValidationError('用户名已存在')
    return username

def clean_email(self):
    """
    清洗输入的邮箱
    :return: 清洗后的邮箱
    """
    email = self.cleaned_data['email']
    if User.objects.filter(email=email).exists():
        raise forms.ValidationError('邮箱已存在')
    return email

def clean_password_again(self):
    """
    清洗第二次输入的密码
    :return: 输入一致的密码
    """
    password = self.cleaned_data['password']
    password_again = self.cleaned_data['password_again']

    if password != password_again:
        raise forms.ValidationError('两次输入的密码不一致')
    return password

其中forms.ValidationError是抛出表单错误的信息。在views.py中添加用户注册的处理,常用的Forms API:Working with forms

from django.shortcuts import redirect, render
from django.contrib import auth  # auth模块是Django提供的标准权限管理系统,可以提供用户身份认证, 用户组和权限管理。
from django.urls import reverse    # 反向解析
from django.contrib.auth.models import User
from .forms import LoginForm, RegForm

def register(request):
    """
    用户注册功能相关处理
    :param request: 请求对象
    :return: 注册成功返回首页,失败返回注册表单
    """
    if request.method == 'POST':
        reg_form = RegForm(request.POST)
        # 判断是否有效
        # 验证通过
        if reg_form.is_valid():
            # 第一种注册方法
            username = reg_form.cleaned_data['username']
            email = reg_form.cleaned_data['email']
            password = reg_form.cleaned_data['password']
            # 创建用户
            user = User.objects.create_user(username, email, password)
            user.save()
            # 登录用户
            user = auth.authenticate(username=username, password=password)
            auth.login(request, user)
            return redirect(request.GET.get('from', reverse('blog:home')))

        '''
            # 第二种注册方法
            user = User()
            user.username = username
            user.email = email
            user.set_password(password)
            user.save()

        '''

    # 验证失败
    else:
        # login_form对象会自动创建表单
        reg_form = RegForm()

    context = {'reg_form': reg_form}
    return render(request, 'user/register.html', context)

注册页面如下

<div class="col-xs-11 col-sm-5 col-lg-4 col-sm-offset-4 blog-border side-info">
    <h4>欢迎注册</h4>
    <form action="" method="POST">{% csrf_token %}

        {% for field in reg_form %}
            {# label去冒号 #}
            <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                {{ field }}
            <p class="text-danger">{{ field.errors.as_text }}</p>
        {% endfor %}
            {# 错误信息标红 #}
            <span class="pull-left text-danger">{{ login_form.non_field_errors }}</span>
            {# <span>用户名:</span> #}
            {# <input type="text" name="username"> #}
            {# <span>密码:</span> #}
            {# <input type="password" name="password"> #}
            <span style="font-weight: bold;">已有帐号?<a style="color: #337ab7;" href="{% url 'user:login' %}">点击登录</a></span>
        <input class="btn btn-primary pull-right" style="margin-bottom: 0.5em" type="submit" value="注册">
    </form>
    {% if user.is_authenticated %}
        <script type="text/javascript">
            window.location.href = '/';
        </script>
    {% else %}

    {% endif %}
</div>

最后在urls.py添加

url(r'^register/', views.register, name='register'),

三、用户登录

与RegForm类似,需要用户名和密码,少了一些验证,只要判断在用户表中是否含有这个用户名。

from django import forms  # django表单功能
from django.contrib import auth
from django.contrib.auth.models import User

class LoginForm(forms.Form):
    """
    用户登录表单
    """
    # 用户名
    username = forms.CharField(label='用户名',
                               widget=forms.TextInput(
                                   attrs={'class': 'form-control', 'placeholder': '请输入用户名'}))

    # 密码
    password = forms.CharField(label='密码',
                               widget=forms.PasswordInput(
                                   attrs={'class': 'form-control', 'placeholder': '请输入密码'}))

    def clean(self):
        """
        清洗输入不合格的表单
        :return: 清洗后的数据
        """
        username = self.cleaned_data['username']
        password = self.cleaned_data['password']
        user = auth.authenticate(username=username, password=password)
        # 判断用户是否存在
        if user is None:
            raise forms.ValidationError('用户名或密码不正确')
        else:
            self.cleaned_data['user'] = user
        return self.cleaned_data

用户登录的视图处理

from django.shortcuts import redirect, render
from django.contrib import auth  # auth模块是Django提供的标准权限管理系统,可以提供用户身份认证, 用户组和权限管理。
from django.urls import reverse    # 反向解析
from .forms import LoginForm

def login(request):
    """
    用户登录逻辑处理
    :param request:
    :return: 登录视图
    """
    if request.method == 'POST':
        login_form = LoginForm(request.POST)
        # 判断是否有效
        # 验证通过
        if login_form.is_valid():
            # cleaned_data是一个字典,包含了字段的信息
            # 表示清理过或者整理过的数据,比较干净的数据
            # username = login_form.cleaned_data['username']
            # password = login_form.cleaned_data['password']
            # user = auth.authenticate(username=username, password=password)
            # 判断用户是否存在
            # if user is not None:
            user = login_form.cleaned_data['user']
            auth.login(request, user)
            # 如果没有获取到源页面就返回到首页
            referer = request.GET.get('from', reverse('blog:blog'))
            return redirect(referer)

    # 验证失败
    else:
        # login_form对象会自动创建表单
        login_form = LoginForm()

    context = {'login_form': login_form}
    return render(request, 'user/login.html', context)

创建视图模板

<div class="col-xs-11 col-sm-5 col-lg-4 col-sm-offset-4 blog-border side-info">
    <h4>用户登录</h4>

     <form action="" method="POST">
         {% csrf_token %}
         {% for field in login_form %}
             <label for="{{ field.id_for_label }}">{{ field.label }}</label>
             {{ field }}
             <p class="text-danger">{{ field.errors.as_text }}</p>
         {% endfor %}
            {# 错误信息标红 #}
            <span class="pull-left text-danger">{{ login_form.non_field_errors }}</span>
            {# <span>用户名:</span> #}
            {# <input type="text" name="username"> #}
            {# <span>密码:</span> #}
            {# <input type="password" name="password"> #}
            <span style="font-weight: bold;">没有帐号?<a style="color: #337ab7;" href="{% url 'user:register' %}">点击注册</a></span>
            <input class="btn btn-primary pull-right" style="margin-bottom: 0.5em" type="submit" value="登录">
     </form>

    {% if user.is_authenticated %}
        <script type="text/javascript">
            window.location.href = '/';
        </script>
    {% else %}
    {% endif %}
</div>

在url.py添加

url(r'^login/', views.login, name='login'),

还可以使用如下方法显示用户信息

<p>加入时间:{{ user.date_joined }}</p>
<p>上次登录时间:{{ user.last_login}}</p>

打赏 蒋振飞

取消

感谢您的支持,我会继续努力的!

扫码支持
一分也是爱     一块不嫌多

点击 支付宝 或 微信 打赏蒋振飞

打开支付宝扫一扫,即可进行扫码打赏哦

评论列表