django-短信登录

1.前端代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.css">
</head>
<body>
<style>
    .box {
        width: 480px;
        border: 1px solid silver;
        margin-left: auto;
        margin-right: auto;
        margin-top: 100px;
        padding: 40px 80px 40px 80px;
        box-shadow: 10px 10px 10px rgb(0 0 0 /5%);

    }

    .sms {
        float: right;
    }

    .text {
        text-align: center;
    }

    .error-message {
        color: red;
        position: absolute;
    }
</style>
<div class="box">
    <h1 class="text">短信登录</h1>
    <form method="post" id="sms_form" novalidate>
        {% csrf_token %}
        {% for field in form %}
            {% if field.name == "code" %}
                <div class="form-group" style="position:relative; margin-bottom: 20px">
                    <label for="username">{{ field.label }}</label>
                    <div class="row">
                        <div class="col-xs-7">
                            {{ field }}
                            <span class="error-message">{{ filed.errors.0 }}</span>
                        </div>

                        <div class="col-xs-5">
                            <input type="button" class="btn btn-default" id="sendBtn" value="点击获取验证码">
                        </div>
                    </div>
                </div>
            {% else %}
                <div class="form-group" style="position:relative; margin-bottom: 20px">
                    <label>{{ field.label }}</label>
                    {{ field }}
                    <span class="error-message">{{ filed.errors.0 }}</span>
                </div>
            {% endif %}

        {% endfor %}

        <button type="button" id="LoginBtn" class="btn btn-primary">登录</button>
        <a href="{% url 'login' %}" class="sms">用户登录</a>
    </form>
</div>
<script src="/static/js/jquery-3.4.1.js"></script>
<script src="/static/js/csrf.js"></script>
<script>

    $(function () {
        bindSendSmsEvent()
        BindLoginEvent()
    })

    function BindLoginEvent() {
        $("#LoginBtn").click(function () {
            $(".error-message").empty();
            $.ajax({
                url:{% url 'sms_login' %},
                type: "POST",
                data: $("#sms_form").serialize(),
                dataType: "JSON",
                success: function (res) {
                    if (res.status) {
                        location.href = res.data
                    } else {
                        $.each(res.msg, function (k, v) {
                            $("#id_" + k).next().text(v[0])
                        })
                    }
                }
            })
        })
    }

    function bindSendSmsEvent() {
        // 按钮绑定点击事件
        $("#sendBtn").click(function () {
            // 1.获取手机号, 向后台发送请求【先不写】
            // 清楚所有的错误
            $(".error-message").empty();

            $.ajax({
                url:{% url 'sms_send' %},
                type: "POST",
                data: {
                    mobile: $("#id_mobile").val(),
                    role: $("#id_role").val()
                },
                dataType: "JSON",
                success: function (res) {
                    console.log(res);
                    if (res.status) {
                         sendSmsRemind()
                    } else {
                        $.each(res.msg, function (k, v) {
                            $("#id_" + k).next().text(v[0])
                        })
                    }
                }
            })

        });
    }

    function sendSmsRemind() {
        var $smsBtn = $("#sendBtn");
        // 2.1 禁用
        $smsBtn.prop("disabled", true);

        // 2.2 改内容
        var time = 60;
        var remind = setInterval(function () {
            $smsBtn.val(time + "秒重新发送");
            time = time - 1;
            if (time < 1) {
                clearInterval(remind);

                $smsBtn.val("点击获取验证码");
                $smsBtn.prop("disabled", false);
            }
        }, 1000);
    }
</script>
</body>
</html>

2.后端代码

2.2.1视图函数

sms_login函数是短信登录的逻辑。

sms_send函数是获取点击短信验证码,校验我表单中手机号是否填的正确,后调用第三方的sdk(腾讯云或者阿里云)来发送短信,获取了短信在Redis中缓存等待用户输入校验。

python 复制代码
def sms_login(request):
    res = BaseRespone()
    if request.method == 'GET':
        form = SmsLoginForm()
        return render(request, 'sms_login.html', {"form": form})
    print(request.POST)
    form = SmsLoginForm(request.POST)
    if not form.is_valid():
        res.msg = form.errors
        return JsonResponse(res.dirt)
    mobile = form.cleaned_data['mobile']
    code = form.cleaned_data['code']
    role = form.cleaned_data['role']

    # 验证redis缓存的code跟我输入的code一不一样
    conn = get_redis_connection("default")
    cache_code = conn.get(mobile)
    if not cache_code:
        res.msg = {"code": ["短信验证码错误"]}
        return JsonResponse(res.dirt)
    res.status = True
    if code != cache_code.decode("utf-8"):
        res.msg = {"code": ["短信验证码错误"]}
        return JsonResponse(res.dirt)

    if role == "1":
        user_object = models.Administrator.objects.filter(active=1, mobile=mobile).first()
    else:
        user_object = models.Customer.objects.filter(active=1, mobile=mobile).first()

    if not user_object:
        res.msg = {"mobile": ["手机号不存在"]}
        return JsonResponse(res.dirt)

    mapping = {"1": "ADMIN", "2": "CUSTOMER"}
    request.session['user_info'] = {'role': mapping[role], 'name': user_object.username, 'id': user_object.id}
    res.status = True
    res.data = settings.LOGIN_HOME
    return JsonResponse(res.dirt)


def sms_send(request):
    res = BaseRespone()
    form = MobileForm(data=request.POST)
    if not form.is_valid():
        res.msg = form.errors
        return JsonResponse(res.dirt, json_dumps_params={"ensure_ascii": False})

    mobile = form.cleaned_data['mobile']
    # 调用腾讯云的SDK要用到手机号

    # 假短信验证码
    sms_code = random.randint(1000, 9999)
    conn = redis.Redis(host='192.168.110.131', port=6379, password='', encoding='utf-8')
    conn.set('18888888889', sms_code, ex=60)
    value = conn.get('18888888889')
    if value:
        res.status = True
        return JsonResponse(res.dirt, json_dumps_params={"ensure_ascii": False})

2.2.2 froms组件

python 复制代码
class SmsLoginForm(forms.Form):
    role = forms.ChoiceField(
        label="角色",
        choices=(("2", "客户"), ("1", "管理员")),
        widget=forms.Select(attrs={"class": "form-control"})
    )
    mobile = forms.CharField(
        label="手机号",
        validators=[RegexValidator(r'^1[358]\d{9}$', '手机格式错误'), ],
        widget=forms.TextInput(attrs={"class": 'form-control', "placeholder": "手机号"})
    )
    code = forms.CharField(
        label="短信验证码",
        validators=[RegexValidator(r'^[0-9]{4}$', '验证码格式错误'), ],
        widget=forms.TextInput(attrs={"class": 'form-control', "placeholder": "短信验证码"})
    )


class MobileForm(forms.Form):
    role = forms.ChoiceField(
        label="角色",
        required=True,
        choices=(("2", "客户"), ("1", "管理员")),
        widget=forms.Select(attrs={"class": "form-control"})
    )

    mobile = forms.CharField(
        label="手机号",
        required=True,
        validators=[RegexValidator(r'^1[358]\d{9}$', '手机格式错误'), ]
    )

    def clean_mobile(self):
        role = self.cleaned_data['role']
        mobile = self.cleaned_data['mobile']
        if not role:
            return mobile

        if role == '1':
            exist = models.Administrator.objects.filter(active=1, mobile=mobile).exists()
        else:
            exist = models.Customer.objects.filter(active=1, mobile=mobile).exists()

        if not exist:
            raise ValidationError("手机号不存在")
        return mobile
相关推荐
小码的头发丝、7 小时前
Django中ListView 和 DetailView类的区别
数据库·python·django
知识的宝藏8 小时前
Django中间件应该怎么使用
中间件·django
千澜空8 小时前
celery在django项目中实现并发任务和定时任务
python·django·celery·定时任务·异步任务
竹笋常青8 小时前
《流星落凡尘》
django·numpy
coberup14 小时前
django Forbidden (403)错误解决方法
python·django·403错误
过期动态1 天前
详解Python面向对象程序设计
开发语言·python·pycharm·django
阿乾之铭1 天前
通过Django 与 PostgreSQL 进行WEB开发详细流程
python·postgresql·django
春天的菠菜1 天前
【django】Django REST Framework (DRF) 项目中实现 JWT
后端·python·django·jwt
千里码aicood1 天前
[含文档+PPT+源码等]精品基于Python实现的django房屋出租系统的设计与实现
开发语言·python·django
啧不应该啊1 天前
Django替换现有用户模型(auth_user)
后端·python·django