zoukankan      html  css  js  c++  java
  • Django

           用户的注册登录是一个网站应该具有的最基本的功能,所以我们这个个人博客的开发第一个功能就是用户的登录和注册,这个是基于Django2.0来重写用户的登录注册公告,利用Django里面的Auth认证模块,但是改写user模型表使用前面表结构里面的自定义UserInfo模型表,方便用户添加更多的信息。

    总体开发思路:

    用Django开发一个app, 来实现下面的内容,本文只介绍用户登录注册部分

    • 用户注册:注册完成后转到登录页面
    • 用户登录:登录后转到首页面
    • 首页面:导航条(注册登录),网站里面发表的内容,左右侧边广告栏
    • 用户资料页面:查看用户注册的信息,并且提供编辑资料的按钮
    • 用户资料编辑页面: 用户资料编辑完成后转到用户资料页面查看信息
    • 用户密码重置
    • 用户注销

    第一步 创建名叫user的APP,并且修改setting.py

    假设我们已经有了一个名字为BBS的项目, 我们可可以在终端cmd窗口cd进入这个目录,然后输入以下命令,创建一个名为users 的App:

    python manage.py startapp users
    

    然后在setting.py 文件中奖users加入到INSTALL_APPS:

    INSTALLED_APPS = [    'reg.apps.RegConfig',    'django.contrib.admin',    'django.contrib.auth',    'django.contrib.contenttypes',    'django.contrib.sessions',    'django.contrib.messages',    'django.contrib.staticfiles',    'users',
    ]
    

    第二步 配置URL

    个人习惯自上而下的思考,所以习惯先编写url,然后在写view里面的函数逻辑

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^register/', views.register),
        url(r'^login/', views.login),
    
        url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
    ]

    第三步 编写视图view

    我们需要register和logi你两个视图,让用户通过ajax向我们提交数据,并处理这些数据,我们用到了forms组件部分

    所以需要新建myform.py文件,创建一个Myform用于register功能,代码如下

    from django import forms
    from django.forms import widgets
    from app01 import models
    
    class MyForm(forms.Form):
        username = forms.CharField(max_length=16, min_length=3,label='用户名', error_messages={
            'required': '用户名不能为空',
            'min_length': '用户名不能低于3位',
            'max_length': '用户名不能多于16位',
        }, widget=widgets.TextInput(attrs={'class': 'form-control'}))
        password = forms.CharField(max_length=16, min_length=3, label='密码', error_messages={
            'required': '密码不能为空',
            'min_length': '密码不能低于3位',
            'max_length': '密码不能多于16位',
        }, widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
        re_password = forms.CharField(max_length=16, min_length=3, label='确认密码',error_messages={
            'required': '确认密码不能为空',
            'min_length': '确认密码不能低于3位',
            'max_length': '确认密码不能多于16位',
        }, widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
        email = forms.EmailField(label='邮箱', error_messages={
            'required': '邮箱不能为空',
            'invalid': '邮箱格式错误'
        },widget=widgets.EmailInput(attrs={'class': 'form-control'}))
    
    
        def clean_username(self):
            username = self.cleaned_data.get('username')
            user_obj = models.UserInfo.objects.filter(username='username')
            if user_obj :
                self.add_error('username','用户名已存在')
            return username
    
        def clean(self):
            password = self.cleaned_data.get('password')
            re_password = self.cleaned_data.get('re_password')
            if not password == re_password:
                self.add_error('re_password','两次密码不一致')
            return self.cleaned_data
    MyForm

    以上代码长,我们不但做了数据格式的校验, 另外我们添加了clean的用法,用来验证用户是否已经存在和两次密码是否一致。

    我们单独新建一个myform.py 可以方便我们后期的维护,添加修改字段。clean可以自定义表单验证,非常便捷,不需要再view.py中进行表单的验证(用户名检查、密码检查等),这样整个的逻辑就会很清楚

    from django.shortcuts import render, redirect, reverse, HttpResponse
    from app01.myform import MyForm
    from app01 import models
    from django.http import JsonResponse
    from django.contrib import auth
    import random
    from PIL import ImageFont, Image, ImageDraw
    from io import BytesIO
    
    需要的模块
    def register(request):
        back_dic = {
            'code': 100,
            'msg': ''
        }
        form_obj = MyForm()
        if request.method == "POST":
            form_obj = MyForm(request.POST)
            if form_obj.is_valid():
                data = form_obj.cleaned_data
                # 去除re_password
                data.pop('re_password')
                # 获取用户上传的头像文件
                file_obj = request.FILES.get('myfile')
                print(file_obj)
                if file_obj:
                    data['avatar'] = file_obj
                models.UserInfo.objects.create(**data)
                back_dic['msg'] = '注册成功'
                back_dic['url'] = '/login/'
            else:
                back_dic['code'] = 101
                back_dic['msg'] = form_obj.errors
            return JsonResponse(back_dic)
        return render(request, 'register.html', locals())
    register
    def login(request):
        back_dic = {
            'code': 100,
            'msg': ''
        }
        if request.POST:
            username = request.POST.get('username')
            password = request.POST.get('password')
            code = request.POST.get('code')
            # 先验证验证码是否一致
            if request.session.get('code').upper() == code.upper(0):
                user_obj = auth.authenticate(username=username, password=password)
                if user_obj:
                    auth.login(user_obj)
                    back_dic['msg'] = '登录成功'
                else:
                    back_dic['code'] = 202
                    back_dic['msg'] = '用户名或者密码错误'
            else:
                back_dic['code'] = 201
                back_dic['msg'] = '验证码错误'
    
        return render(request, 'login.html', locals())
    login

    我们先看register函数是怎么工作的:

    • 先生成一个 空的forms组件,渲染到注册页面
    • 当用户通过post方法提交表单,我先验证Myforms里面的数据是否有效。如果有效,所有的数据都在forms组件自带的cleaned_data中,而我们的模型表里面并没有re_password字段,所以我们需要删除re_password字段来,然后把存入到数据库中。
    • 如果注册成功,需要转到登录页面,所以需要在back_dic里面添加一个url字段,
    • 如果没有提交表单或者不是通过post方法提交表单,我们就转入到注册页面

    再来看看login的功能是怎么工作的:

    • 用户提交数据后,先验证验证码是否一致
    • request.session.get('code').upper() == code.upper(0
    • 如果用户提交的数据一致的话就可以通过auth认证模块来实现验证用户是否存在
    • auth.authenticate(username=username, password=password)
    • 如果用户存在的,记录用户的登录状态auth.login(request, user_obj),
    • 这样在其他地方我们都可以通过request.user来获取用户对象,这样方便我们调用用户的其他属性。
    • 如果用户登录成功返到主页米
    • 如果不是通过post来提交数据,我们可以通过转到登录页面

    第四步 编写temlate里面的html文件

    下面是register的代码:

    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1 class="text-center">注册页面</h1>
                <hr>
                <form id="my_form">
                {% csrf_token %}
                    {% for form in form_obj %}
                        <div class="form-group">
                            <label for="{{ form.auto_id }}">{{ form.label }}</label>
                            {{ form }}
                            <span class="errors pull-right" style="color: red"></span>
                        </div>
                    {% endfor %}
                </form>
                <div class="form-group">
                    <label for="id_myfile">头像
                        <img src="/static/img/default.png" id="id_img" alt="" width="80" height="90"
                             style="margin-left:15px"></label>
                    <input type="file" id="id_myfile" name="myfile" style="display: none">
                </div>
                <button class="btn-success btn pull-right" id="id_submit">确认</button>
            </div>
        </div>
    </div>
    

    这是register的js代码

    // 头像处理
    $('#id_myfile').change(function () {
        // 获取文件对象
        let file_obj = this.files[0];
        // 新建一个内置对象
        let fileReader = new FileReader();
        // 将文件传递给内文件
        fileReader.readAsDataURL(file_obj);
        // 将获取到的文件渲染出来
        fileReader.onload = function () {
            $('#id_img').attr('src', fileReader.result)
        }
    });
    
    // ajax处理数据
    $('#id_submit').click(function () {
        let formData = new FormData();
        console.log($('#my_form').serializeArray());
        $.each($('#my_form').serializeArray(), function (index, obj) {
            formData.append(obj.name, obj.value)
        });
        // 手动添加文件
        formData.append('myfile',$('#id_myfile')[0].files[0]);
        $.ajax({
            url: '',
            type: 'post',
            data: formData,
            processData: false,
            contentType: false,
    
            success: function (data) {
                if (data.code == 100) {
                    location.href = data.url
                } else {
                    $.each(data.msg, function (index, obj) {
                        let targetId = '#id_' + index;
                        // 渲染错信息
                        $(targetId).next().html(obj[0]).parent().addClass('has-error')
    
                    })
                }
            }
    
        })
    });
    $('input').focus(function () {
        $(this).next().html('').parent().removeClass('has-error')
    });
    

    login的HTML代码

    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h2 class="text-center">登录</h2>
                {% csrf_token %}
                <div class="form-group">
                    <label for="id_username">用户名</label>
                    <input type="text" name="username" id="id_username" class="form-control">
                </div>
                <div class="form-group">
                    <label for="id_password">密码</label>
                    <input type="password" name="password" id="id_password" class="form-control">
                </div>
                <div class="form-group">
                    <label for="id_code">验证码</label>
                    <div class="row">
                        <div class="col-md-6">
                            <input type="text" name="code" id="id_code" class="form-control">
                        </div>
                        <div class="col-md-6">
                            <img src="/get_code/" alt="" width="310" height="35" id="id_img">
                        </div>
                    </div>
                </div>
                <button class="btn btn-success" id="id_button">登录</button>
                <span class="errors" style="color: red" id="id_error"></span>
            </div>
        </div>
    </div>

    js代码

     $('#id_img').click(function () {
            // 获取图片src旧的路径
            let oldPath = $(this).attr('src');
            // 修改图片的src属性
            $(this).attr('src',oldPath += '?')
        });
    
        // ajax发送数据
        $('#id_button').click(function () {
            $.ajax({
                url:'',
                type:'post',
                data:{
                    'username':$('#id_username').val(),
                    'password':$('#id_password').val(),
                    'code':$('#id_code').val(),
                    // 'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val(),
                    'csrfmiddlewaretoken':'{{ csrf_token }}',
                },
                success:function (data) {
                    if(data.code == 100){
                        location.href = data.url
                    }else{
                        $('#id_error').html(data.msg)
                    }
                }
            })
        })
    

    总结:

    本文主要写的是注册和登录,扩展了Django自带的User的模型表和auth认证模块,forms组件。

  • 相关阅读:
    redis info命令中各个参数的含义
    mogndb 慢查询
    一分钟看懂Docker的网络模式和跨主机通信
    解决Nginx出现403 forbidden (13: Permission denied)报错的四种方法
    dva学习---effects异步中通过select获取当前的state
    golang json数组拼接
    golang mongodb查找find demo
    React从入门到精通系列之(14)refs和DOM元素
    选择——ERP信息系统选型
    企业库存资产的帐实管理思考
  • 原文地址:https://www.cnblogs.com/king-home/p/11111562.html
Copyright © 2011-2022 走看看