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组件。

猜你喜欢

转载自www.cnblogs.com/king-home/p/11111562.html