Flask实战第44天:完成前台注册功能

注册功能后端逻辑

用户注册要把注册的表单提交上来,因此,我要先对表单进行验证,编辑front.forms

from apps.forms import BaseForm
from wtforms import StringField
from wtforms.validators import Regexp, Length, EqualTo, ValidationError
from utils import xcache
from .models import FrontUser


class SignUpForm(BaseForm):
    telephone = StringField(validators=[Regexp(r'1[35678]\d{9}', message='手机号码格式错误')])
    sms_captcha = StringField(validators=[Regexp(r'\w{6}', message='短信验证码错误')])
    username = StringField(validators=[Length(2,20, message='用户名格式错误')])
    password1 = StringField(validators=[Length(5, 30, message='密码格式错误')])
    password2 = StringField(validators=[EqualTo('password1', message='两次密码不一致')])
    graph_captcha = StringField(validators=[Regexp(r'\w{4}', message='图形验证码错误')])

    def validate_telephone(self, field):
        user = FrontUser.query.filter_by(telephone=field.data).first()
        if user:
            raise ValidationError('该手机号已被注册')

    def validate_sms_captcha(self, field):
        telephone = self.telephone.data
        sms_captcha = field.data
        xcache.set('13602219337', 'heboan')
        sms_captcha_mem = xcache.get(telephone)
        print('用户输入的验证码:{}'.format(sms_captcha))
        print( '服务器存储的验证码:{}'.format(sms_captcha_mem))
        if not sms_captcha_mem or sms_captcha_mem != sms_captcha:
            raise ValidationError(message='短信验证码错误')

    def validate_graph_captcha(self, field):
        graph_captcha = field.data
        #因为图形验证码存储的key和值都是一样的,所以我们只要判断key是否存在就行
        if not xcache.get(graph_captcha.lower()):
            raise ValidationError(message='图形验证码错误')
front.views.py

然后就是注册的视图处理POST请求了, 编辑front.views.py

class SignUpViews(views.MethodView):
    def get(self):
        return render_template('front/front_signup.html')

    def post(self):
        signup_form = SignUpForm(request.form)
        if signup_form.validate():
            telephone = signup_form.telephone.data
            username = signup_form.username.data
            password = signup_form.password1.data
            user = FrontUser(telephone=telephone, username=username, password=password)
            db.session.add(user)
            db.session.commit()
            return xjson.json_success('恭喜您,注册成功')
        else:
            return xjson.json_param_error(signup_form.get_error())

注册功能前端逻辑

前端我们通过ajax来请求,编辑front_signup.js

 

...
//注册
$(function () {
    $('#submit-btn').click(function (event) {
        event.preventDefault();
        var telephone_input = $("input[name='telephone']");
        var sms_captcha_input = $("input[name='sms_captcha']");
        var username_input = $("input[name='username']");
        var password1_input = $("input[name='password1']");
        var password2_input = $("input[name='password2']");
        var graph_captcha_input = $("input[name='graph_captcha']")

        var telephone = telephone_input.val();
        var sms_captcha = sms_captcha_input.val();
        var username = username_input.val();
        var password1 = password1_input.val();
        var password2 = password2_input.val();
        var graph_captcha = graph_captcha_input.val();

        bbsajax.post({
            'url': '/signup/',
            'data': {
                'telephone': telephone,
                'sms_captcha': sms_captcha,
                'username': username,
                'password1': password1,
                'password2': password2,
                'graph_captcha': graph_captcha
            },
            'success': function (data) {
                if (data['code'] === 200){
                    //注册成功跳转到首页
                    window.location = '/';
                }else{
                    xtalert.alertInfo(data['message']);
                }
            },
            'fail': function (error) {
                xtalert.alertNetworkError();
            }

        });
    })
});

这样注册功能就OK,注册成功后会跳转到首页。

注册完成跳转回上一个页面

现在我们的需求是,用户直接进入注册页面注册,则注册成功后跳到首页,如果从本站的其他页面访问到注册页面注册,则注册成功后跳转到上一个页面。

那么我们可以在注册的视图函数中的get请求获取到referrer(上个页面,也就是从哪个页面跳过来的url)

#写一个检测referre的函数放到safeutils.py中,该文件放到utils下面
from utils import safeutils


class SignUpViews(views.MethodView):
    def get(self):
        #获取上一个页面的url
        return_to = request.referrer
        #referrer不一定会存在,比如直接访问的登录页面
        #并且它不等于登录页面的url
        #并且这个referre是个安全的url,防止恶意者去伪造它,被跳转到其它恶意的网站
        if return_to and return_to !=request.url and safeutils.is_safe_url(return_to):
            #把这个url传入到模板中
            return render_template('front/front_signup.html', return_to=return_to)
        return render_template('front/front_signup.html')

    ...
from urllib.parse import urlparse,urljoin
from flask import request

def is_safe_url(target):
    ref_url = urlparse(request.host_url)
    test_url = urlparse(urljoin(request.host_url, target))
    return test_url.scheme in ('http', 'https') and \
           ref_url.netloc == test_url.netloc
safeutils.py

url传入到frony_signup.html,我在这个页面找个位置接收它

<span style="display:none;" id="return-to-span">{{ return_to }}</span>

然后我们的js就可以获取到这个值,编辑front_signup.js

 

posted @ 2018-08-19 15:21  sellsa  阅读(812)  评论(0编辑  收藏  举报