使用Django构建个人网站(十)——注册内容追加,前端知识大应用

这篇博客算是一个十分庞大的实践了,之前的每个功能实现都是很简单的——调用调用框架,自己写一些简单的视图函数。
今天我将完成对博客系统注册内容的追加,博客前端页面的完善两个部分。重点在于前端页面的完善了(要用很多js)
我的前端水平不高,jquery学过之后就忘记了,因此我用原生js代码来实现我想要的功能。

技术概要

  • 构建django模板,追加User的内容
  • 构建前端页面
  • 使用js完成用户注册页面信息的验证
    • 验证用户名是否合法
    • 验证密码是否符合要求
    • 引入发送短信模块,给注册手机发送短信验证码
    • 引入邮件发送模块,发送注册成功提示
    • 表单的处理,把表单内容写入模型

下面我将一一实现这些功能

构建django模板,追加User内容

模型构造

之前我用的用户模型,直接就是from django.contrib.auth.models import User这个用户模型,它的自定义字段有很多是不符合实际需求的,在这里,我对它进行一个扩展。
打开/account/models.py,编辑这个模板文件,代码如下所示

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

# Create your models here.


class UserProfile(models.Model):
    mobile = models.CharField(max_length=11, verbose_name="手机号码")
    email = models.EmailField(default='', verbose_name="电子邮箱")
    nickname = models.CharField(max_length=30, verbose_name="昵称")
    username = models.OneToOneField(User, on_delete=models.CASCADE, default=None, verbose_name="用户名")
    QQ = models.CharField(max_length=10, verbose_name="QQ号码")

内容还是比较易于理解的,在这里其实是创建了一个一对一的用户模型,把它和User紧密相连,其他的都是正常的字段创建,没有什么好介绍的。

后台管理

后台管理都是在admin.py中完成,这个应用也不例外,打开/account/admin.py,写如下代码即可:

from django.contrib import admin
from .models import UserProfile
# Register your models here.
admin.site.register(UserProfile)

我没有去实现高级后台管理功能,因为我的目的是先把网站上线,后续功能可以慢慢追加。其实也不一定有必要了,把所有的东西如果前台都能展示,其实不要这个后台管理界面也是没有问题的。

构建前端页面

表单构建

所有的表单都是在form.py中完成的,代码如下

from django import forms
from .models import UserProfile
class LoginForm(forms.Form):
    username = forms.CharField()
    password = forms.CharField(widget=forms.PasswordInput)

class SignUpForm(forms.ModelForm):
    username = forms.CharField()
    password = forms.CharField(widget=forms.PasswordInput)
    class Meta:
        model = UserProfile
        fields = ['username', 'password', 'mobile', 'email', 'nickname', 'QQ']

前端页面

前端页面这里,我没有用django自带的表单转页面功能,你问我为什么,因为我弄了很久都不知道怎么给它自动生成的表单加样式,丑的一批比较不雅观,因此自定义了表单。
表单这里要注意的就是表单的name属性,这个是最后传给后台由后台接收的

{% extends "base_cn.html" %}
{% block title %}
注册界面
{% endblock %}
{% block content %}
<div class="container">
    <h1 class="text-center" style="margin-bottom: 15px;">&nbsp;&nbsp;&nbsp;</h1>
    <!-- 表单样式非常难看,用JS来重写样式(因为以我的水平没法给生成的表单加属性,只能用js -->
    <form onsubmit="return checkForm();" class="form-horizontal" action="/account/signup/" method="POST">
        {% csrf_token %}
        <div class="form-group">
            <label for="username" class="col-sm-2 control-label">用户名</label>
            <div class=" col-sm-5">
                <input type="text" name="username" id="username" class="form-control">
            </div>
            <div class="col-sm-5" style="height: 34px;line-height: 34px;"><span
                    class="glyphicon glyphicon-remove"></span>&nbsp;请输入你的用户名,用户名长度应在5位以上</div>
        </div>
        <div class="form-group">
            <label for="password" class="col-sm-2 control-label">密码</label>
            <div class="col-sm-5">
                <input type="password" name="password" id="password" class="form-control">
            </div>
            <div class="col-sm-5" style="height: 34px;line-height: 34px;"><span
                    class="glyphicon glyphicon-remove"></span>&nbsp;请输入密码,密码长度应在8位以上</div>
        </div>
        <div class="form-group">
            <label for="password_repeat" class="col-sm-2 control-label">确认密码</label>
            <div class="col-sm-5">
                <input type="password" name="password_repeat" id="password_repeat" class="form-control">
            </div>
            <div class="col-sm-5" style="height: 34px;line-height: 34px;"><span
                    class="glyphicon glyphicon-remove"></span>&nbsp;请确认密码,密码长度应在8位以上</div>
        </div>
        <div class="form-group">
            <label for="mobile" class="col-sm-2 control-label">手机号码</label>
            <div class="col-sm-5">
                <input type="text" name="mobile" id="moblie" class="form-control">
            </div>
            <div class="col-sm-5" style="height: 34px;line-height: 34px;"><span
                    class="glyphicon glyphicon-remove"></span>&nbsp;请输入你的手机号码</div>
        </div>
        <div class="form-group">
            <label for="mobile_identy" class="col-sm-2 control-label">短信验证</label>
            <div class="col-sm-3">
                <input type="text" name="mobile_identy" id="mobile_identy" class="form-control">
            </div>
            <div class="col-sm-2">
                <button type="button" class="btn btn-info">发送短信验证</button>
            </div>
            <!-- <div class="col-sm-5" style="height: 34px;line-height: 34px;"><span
                    class="glyphicon glyphicon-remove"></span>简介性的字,可用AJAX进行动态刷新</div> -->
        </div>
        <div class="form-group">
            <label for="email" class="col-sm-2 control-label">电子邮件</label>
            <div class="col-sm-5">
                <input type="email" name="email" id="email" class="form-control">
            </div>
            <div class="col-sm-5" style="height: 34px;line-height: 34px;"><span
                    class="glyphicon glyphicon-remove"></span>&nbsp;请输入你的电子邮箱</div>
        </div>
        <div class="form-group">
            <label for="nickname" class="col-sm-2 control-label">昵称</label>
            <div class="col-sm-5">
                <input type="text" class="form-control" name="nickname" id="nickname">
            </div>
            <div class="col-sm-5" style="height: 34px;line-height: 34px;"><span
                    class="glyphicon glyphicon-remove"></span>&nbsp;输入昵称,这是你展示给其他用户的名称</div>
        </div>
        <div class="form-group">
            <label for="QQ" class="col-sm-2 control-label">QQ号码</label>
            <div class="col-sm-5">
                <input type="text" name="QQ" id="QQ" class="form-control">
            </div>
            <div class="col-sm-5" style="height: 34px;line-height: 34px;"><span
                    class="glyphicon glyphicon-remove"></span>&nbsp;留下你的QQ吧,让我可以联系到你</div>
        </div>
        <div class="form-group">
            <label for="nickname" class="col-sm-2 control-label"></label>
            <div class="col-sm-5">
                <button class="btn btn-primary btn-lg">提交注册</button>
            </div>
        </div>
    </form>
</div>
<script src="/static/js/signUp.js"></script>
{% endblock %}

视图函数

下面那个函数就是表单的注册视图函数了,可以看到我注释掉了后台的表单生成,我自己写前端页面并构建联系,当请求是request时候,后台打印前端传来的数据,看下有没有问题即可。

from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
from .forms import LoginForm, SignUpForm

# Create your views here.
def user_login(request):
    if request.method == 'GET':
        # 自动生成表单
        login_form = LoginForm()
        context = {}
        context['form'] = login_form
        return render(request, "account/login.html", context=context)
    if request.method == 'POST':
        #用POST请求来初始化表单
        login_form = LoginForm(request.POST)
        # 判断用户输入是否合法
        if login_form.is_valid():
            # 用键值对存储了表单中的数据
            data = login_form.cleaned_data
            user = authenticate(username=data['username'], password=data['password'])
            if user:
                login(request, user)
                request.session['username'] = data['username']
                return redirect('/')
            else:
                return HttpResponse('账号或密码错误')
        else:
            return HttpResponse('登录内容有误')

def user_signup(request):
    if request.method == 'GET':
        # signup_form = SignUpForm()
        # context = {}
        # context['form'] = signup_form
        return render(request, 'account/signUp.html'\
            # , context=context
        )
    else:
        print(request.POST)
        return HttpResponse("提交成功")

现在执行服务,在前台注册页面随便填点数据,提交一下,会看到后台打印如下内容:

<QueryDict: {‘csrfmiddlewaretoken’: [‘anZbYCNJ0XjxN1QJARrjLMEen7i6OPRtoX3JVBYnIxWXhfGbbIDPSE6rVGXAwzGT’], ‘username’: [‘wangxiong’], ‘password’: [‘931225’], ‘password_repeat’: [‘ewfwef’], ‘mobile’: [‘威风威风’], ‘mobile_identy’: [‘威锋网’], ‘email’: [‘13961252501@139.com’], ‘nickname’: [‘87527’], ‘QQ’: [‘74745’]}>
前端则会显示

提交成功

说明数据处理没问题,既然如此,就把所有的验证工作交给前端由AJAX完成吧!完成js部分后,我再进行后台的数据处理,把表单内容提交进数据库。

使用js完成用户注册页面信息的验证

因为我的前端js学的也不是很好,只是勉强应用阶段,所以我就不把那些函数封装的那么好了,直接一步一步来了,毕竟我的主要任务也不是玩前端的,GO!

在前端界面的最后我已经引入了script文件,现在开始编写/static/js/signUp.js文件,由于js我也不熟悉,所以我很有必要把注释写的清楚一些,也方便自己日后回顾。

先把用户名验证补上,后面的抽时间再增加,其实原理都是一样的,用js查元素的值,根据不同的情况再返回不同的值
要注意的就是这里面的正则表达式了,确实只要有一段时间不用,正则就忘得很快了,心累,都是现用现查现写的

var username = document.getElementById("username");
var password = document.getElementById("password");
var password_repeat = document.getElementById("password_repeat");
var mobile = document.getElementById("mobile");
var mobile_identy = document.getElementById("mobile_identy");
var email = document.getElementById("email");
var nickname = document.getElementById("nickname");
var QQ = document.getElementById("QQ");
var check1 = 0, //验证用户名
    check2 = 0, //验证密码
    check3 = 0, //确认密码
    check4 = 0, //手机号码
    check5 = 0, //短信验证码
    check6 = 0, //电子邮箱
    check7 = 0, //昵称
    check8 = 0; //QQ号码

window.onload = function () {
    //验证用户名函数
    username.onblur = function () {
        //js的正则表达式,很有必要
        var patrn = /^[a-zA-Z0-9._/]{5,20}$/;
        var usr = username.value;
        check1 = patrn.test(usr);
        if (check1 == true) {
            document.getElementsByClassName("check")[0].innerHTML = "<span></span>&nbsp;该用户名合法";
            document.getElementsByClassName("check")[0].children[0].setAttribute("class", "glyphicon glyphicon-ok");
            document.getElementsByClassName("check")[0].children[0].setAttribute("style", "color:green;");
        }
        if (check1 == false) {
            document.getElementsByClassName("check")[0].innerHTML = "<span></span>&nbsp;长度应在5到20位;可以是字母、数字、下划线";
            document.getElementsByClassName("check")[0].children[0].setAttribute("class", "glyphicon glyphicon-remove");
            document.getElementsByClassName("check")[0].children[0].setAttribute("style", "color:red;");
        }
    }
    //验证密码函数
    password.onblur = function () {
        var patrn = /^[a-zA-Z0-9._/]{8,20}$/;
        var pwd = password.value;
        check2 = patrn.test(pwd);
        if (check2 == true) {
            document.getElementsByClassName("check")[1].innerHTML = "<span></span>&nbsp;该密码符合要求";
            document.getElementsByClassName("check")[1].children[0].setAttribute("class", "glyphicon glyphicon-ok");
            document.getElementsByClassName("check")[1].children[0].setAttribute("style", "color:green;");
        }
        if (check2 == false) {
            document.getElementsByClassName("check")[1].innerHTML = "<span></span>&nbsp;请输入密码,密码长度应在8位以上";
            document.getElementsByClassName("check")[1].children[0].setAttribute("class", "glyphicon glyphicon-remove");
            document.getElementsByClassName("check")[1].children[0].setAttribute("style", "color:red;");
        }
    }
    //验证密码确认函数
    password_repeat.onblur = function () {
        check3 = (password.value == password_repeat.value && check2);
        if (check3 == true) {
            document.getElementsByClassName("check")[2].innerHTML = "<span></span>&nbsp;密码验证成功";
            document.getElementsByClassName("check")[2].children[0].setAttribute("class", "glyphicon glyphicon-ok");
            document.getElementsByClassName("check")[2].children[0].setAttribute("style", "color:green;");
        }
        if (check3 == false) {
            document.getElementsByClassName("check")[2].innerHTML = "<span></span>&nbsp;两次密码不一致,请重新来过";
            document.getElementsByClassName("check")[2].children[0].setAttribute("class", "glyphicon glyphicon-remove");
            document.getElementsByClassName("check")[2].children[0].setAttribute("style", "color:red;");
        }
    }
    //验证手机号码函数,手机设置为11位的纯数字,在模型中手机号码是以字符串存储的,还算比较方便
    mobile.onblur = function () {
        var patrn = /^1[0-9]{10}$/;
        var num = mobile.value;
        check4 = patrn.test(num);
        if (check4 == true) {
            document.getElementsByClassName("check")[3].innerHTML = "<span></span>&nbsp;手机号暂且是对的";
            document.getElementsByClassName("check")[3].children[0].setAttribute("class", "glyphicon glyphicon-ok");
            document.getElementsByClassName("check")[3].children[0].setAttribute("style", "color:green;");
        }
        if (check4 == false) {
            document.getElementsByClassName("check")[3].innerHTML = "<span></span>&nbsp;手机号最起码是11位吧?";
            document.getElementsByClassName("check")[3].children[0].setAttribute("class", "glyphicon glyphicon-remove");
            document.getElementsByClassName("check")[3].children[0].setAttribute("style", "color:red;");
        }
    }
    email.onblur = function () {
        var patrn = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
        var Edress = email.value;
        check6 = patrn.test(Edress);
        if (check6 == true) {
            document.getElementsByClassName("check")[5].innerHTML = "<span></span>&nbsp;是合法邮箱";
            document.getElementsByClassName("check")[5].children[0].setAttribute("class", "glyphicon glyphicon-ok");
            document.getElementsByClassName("check")[5].children[0].setAttribute("style", "color:green;");
        }
        if (check6 == false) {
            document.getElementsByClassName("check")[5].innerHTML = "<span></span>&nbsp;请填写正确的邮箱";
            document.getElementsByClassName("check")[5].children[0].setAttribute("class", "glyphicon glyphicon-remove");
            document.getElementsByClassName("check")[5].children[0].setAttribute("style", "color:red;");
        }
    }
}


function checkForm() {
    alert(check1);
    return false;
}

后台发送短信验证码

我用的是腾讯云的发送短信服务(不是打广告哈),他的接口文档是这样的

'''
以下为初始设置
'''
# 短信应用 SDK AppID
appid = 1400009099  # SDK AppID 以1400开头
# 短信应用 SDK AppKey
appkey = "9ff91d87c2cd7cd0ea762f141975d1df37481d48700d70ac37470aefc60f9bad"
# 需要发送短信的手机号码
phone_numbers = ["21212313123", "12345678902", "12345678903"]
# 短信模板ID,需要在短信控制台中申请
template_id = 7839  # NOTE: 这里的模板 ID`7839`只是示例,真实的模板 ID 需要在短信控制台中申请
# 签名
sms_sign = "腾讯云"  # NOTE: 签名参数使用的是`签名内容`,而不是`签名ID`。这里的签名"腾讯云"只是示例,真实的签名需要在短信控制台中申请

# 主要程序
from qcloudsms_py import SmsSingleSender
from qcloudsms_py.httpclient import HTTPError
ssender = SmsSingleSender(appid, appkey)
params = ["5678"]  # 当模板没有参数时,`params = []`
try:
  result = ssender.send_with_param(86, phone_numbers[0],
      template_id, params, sign=sms_sign, extend="", ext="")  # 签名参数未提供或者为空时,会使用默认签名发送短信
except HTTPError as e:
  print(e)
except Exception as e:
  print(e)
print(result)

作为一个比较低端的APIcaller,只要看懂这些代码,然后修改成自己适用的即可。接着和前端ajax衔接上就行了。

创建一个app名叫ajax,专用来处理ajax请求(之前有一个地方是用ajax请求的,就算了——先实现项目,后期再改)

python manage.py startapp ajax
输入这段代码,生成一个新的应用,这几步已经形成肌肉习惯

  • settings.py增加应用名称
  • 设置url
  • 设置视图函数

视图函数是重点了,因为我要在视图函数里生成随机验证码发送给前端,在这里还得调用一下腾讯云的发短信服务。
params的构造很简单,构造一个六位的随机数出来,发送短信模块腾讯云有sdk文档,我就不打广告了,自己可以去看,最终把验证码以Httpresponse的形式传回给前端

from django.shortcuts import render
from django.http import HttpResponse
from qcloudsms_py.httpclient import HTTPError
from qcloudsms_py import SmsSingleSender
from .message import appid, appkey, template_id, sms_sign
import random


def message(request):
    phone_numbers = [request.GET['num']]
    print(phone_numbers)
    params = [''.join([str(random.randrange(0, 10)) for i in range(6)])]
    print(params)
    ssender = SmsSingleSender(appid, appkey)
    ssender.send_with_param(86, phone_numbers[0],
                            template_id, params, sign=sms_sign, extend="", ext="")
    return HttpResponse(params[0])

发短信的js代码是这样的

    mobile_button.onclick = function () {
        var num = mobile.value;
        if (check4 == true) {
            alert("已发送验证码到" + num);
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    idendy = xhr.responseText;
                }
            }
            xhr.open("get", "/ajax/message?num=" + num, true);
            xhr.send(null);
        } else {
            alert("手机号码不对是不能发送验证码的");
        }
    }

最后的最后来个form表单验证

function checkForm() {
    if (check1 && check2 && check3 && check4 && check5 && check6 && check7 && check8) {
        return true;
    } else {
        return false;
    }
}

总结

验证依旧不完整,你问我少了哪块,我只能说少了用户名查重这块我还没验证,这块也是要发送ajax请求的。后续我就自己完善了,不必再发博客里了,毕竟这东西都是相通的

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值