Python教程

学习python-Day61

本文主要是介绍学习python-Day61,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

今日学习内容

一、注册forms编写

创建一个文件关于forms的校验代码。

from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError
from blog.models import UserInfo  # d导入模块:相对导入和绝对导入


class RegisterForm(forms.Form):
    # 用户名 密码 确认密码 邮箱
    username = forms.CharField(max_length=8, min_length=3, required=True, label='用户名',
                               error_messages={
                                   'max_length': '用户名过长',
                                   'min_length': '用户名过短',
                                   'required': '这个必填哦!',
                               }, widget=widgets.TextInput(attrs={'class': 'form-control'}))
    password = forms.CharField(max_length=8, min_length=3, required=True, label='密码',
                               error_messages={
                                   'max_length': '用户名过长',
                                   'min_length': '用户名过短',
                                   'required': '这个必填哦!',
                               }, widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
    re_password = forms.CharField(max_length=8, min_length=3, required=True, label='确认密码',
                                  error_messages={
                                      'max_length': '用户名过长',
                                      'min_length': '用户名过短',
                                      'required': '这个必填哦!',
                                  }, widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
    email = forms.EmailField(label='邮箱', widget=widgets.EmailInput(attrs={'class': 'form-control'}))

    # 局部钩子校验

    def clean_username(self):
        username = self.cleaned_data.get('username')

        # 方案一:
        user = UserInfo.objects.filter(username=username).first()
        if user:
            #用户已存在,不合理
            raise ValidationError('用户已存在')
        else:
            #将校验后的用户返回出去
            return username

        # 方案二:
        # try:
        #     UserInfo.objects.get(username=username)  # 有且只有一条才行,否则就抛出异常。
        #     raise ValidationError('用户已存在!')
        # except Exception as e:
        #     return username
        #这是一个与问题的代码。

    # 全局钩子校验
    def clean(self):
        password = self.cleaned_data.get('password')
        re_password = self.cleaned_data.get('re_password')
        if password == re_password:
            # 如果合理,则返回结果
            return self.cleaned_data
        else:
            # 不合理,则主动抛出异常
            raise ValidationError('两次密码不一致!')

二、注册页面搭建

# bootstrap 搭建
	settings.py  中加入 static
    	STATIC_URL = '/static/'
        STATICFILES_DIRS=[
            os.path.join(BASE_DIR, 'static')
        ]
    把bootstrap的静态资源copy到static文件夹下。
#新建模板文件  register.html
<body>
<div>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1 class="text-center">注册功能</h1>
                <form id="id_form">
                {# 没写这串代码会出现403权限错误#}
                {% csrf_token %}
                    {% for item in form %}
                        <div class="form-group">
                            <label for="{{ item.id_for_label }}">{{ item.label }}</label>
                            {{ item }}
                            <span class="pull-right text-danger "></span>
                        </div>
                    {% endfor %}
                    <div calss="form-group">
                        <label for="id_file">头像
                            <img src="/static/img/default.png" alt="" id="id_img" height="80px" width="80px"
                                 style="margin-left: 10px">
                        </label>
                        <input type="file" id="id_file" accept="image/*" style="display: none">

                    </div>
                    <div class="form-group text-center">
                        {#如果input类型type为submit或者button标签,或者form表单中,如果点提交,触发form的提交,如果写了ajax提交,会触发两次提交#}
                        <input type="button" value="注册" class="btn btn-success" id="id_submit">
                        <span class="text-danger error"></span>
                    </div>

                </form>
            </div>
        </div>

    </div>

</div>
</body>

image

三、头像动态显示

1.首先读文件,然后将读取到文件的阅读器将其放置在标签上面。
 $("#id_file").change(function () {
        // 把当前图片,放到img标签中
        // 把图片地址放到img标签上,标签就显示了图片
        //$("#id_img")[0].src='https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg'

        // 1 id_file这个标签的图片读出来,借助于文件阅读器,js提供的一个类
        var reader = new FileReader()
        // 2 拿到文件对象,赋值给一个变量
        var file = $("#id_file")[0].files[0]
        // 3 把文件读到文件阅读器中
        reader.readAsDataURL(file)
        // 4 等读完后,把文件阅读器的内容写到img标签上
        //$("#id_img")[0].src=reader.result
        reader.onload = function () {
            //$("#id_img")[0].src=reader.result
            $('#id_img').attr('src', reader.result)
        }

    })

image

四、注册功能后端

2.在views.py
def register(request):
    if request.method == 'GET':
        register_form = RegisterForm()
        # context: 上下文
        return render(request, 'register.html', context={'form': register_form})
    else:  # post请求的时候
        res = {'code': 100, 'msg': '注册成功'}
        # 取出用户名密码,使用form校验数据,如果校验通过,存到数据库中,如果校验不通过,返回错误信息
        register_form = RegisterForm(data=request.POST)
        if register_form.is_valid():
            # 数据字段自己的规则,局部钩子,全局钩子都校验过后,通过了
            # 1  re_password字段,不存到数据库的,剔除
            register_data = register_form.cleaned_data
            register_data.pop('re_password')
            # 2 头像:如果携带了要存,头像是文件,在request.FILES中
            my_file = request.FILES.get('my_file')
            if my_file:
                register_data['avatar'] = my_file
            # 2 存到数据库
            UserInfo.objects.create_user(**register_data)
            # UserInfo.objects.create_user(username=register_data.get('username'),) 等同于上面,但是麻烦
            return JsonResponse(res)
        else:
            res['code'] = 101
            res['msg'] = '注册失败'
            res['errors'] = register_form.errors
            return JsonResponse(res)

五、头像上传路径问题

注意:
项目后台静资源中得到图片,一般放在static文件夹下,
用户上传的文件,图片一般放在media文件夹下。文件路径先是在avatar文件夹下再是media文件夹下面,
django中需要在配置文件中加一句话
MEDIA_ROOT = os.path.jojin(BASE_DIR, 'media')

六、注册错误信息渲染

//当点击注册按钮,发送ajax请求到后端的注册功能
    $("#id_submit").click(function () {
        //上传文件,借助formdata对象
        var formdata = new FormData()

        //方式一
        {#formdata.append('username',$('#id_username').val())#}
        {#formdata.append('password',$('#id_password'.val()))#}
        {#formdata.append('re_password',$('#id_re_password'.val()))#}
        {#formdata.append('email',$('#id_email').val())#}
        {#formdata.append('my_file',$('#id_file')[0].files[0])#}


        //方式二:借助form表单批量处理
        var data = $("#id_form").serializeArray()
        {#console.log(data)#}
        //使用for循环,把data中的数据,转存到formdata中   jquery的each循环
        $.each(data, function (i, v) {
            //i为索引值, v是每个数据值
            formdata.append(v.name, v.value)
        })
        //文件单独再放进去,不能循环文件放进去,不然会出错的。
        formdata.append('my_file', $('#id_file')[0].files[0])

        //使用ajax向后端发送请求
        //1.  三种编码格式:urlencoded, form-data,json
        //urlencoded 的默认格式:{name:xz, age;19}---》name=xz&age=19
        $.ajax({
            url: '/register/',
            type: 'post',
            processData: false,
            contentType: false,
            data: formdata,
            //view视图函数里面的JsonResponse的返回值
            success: function (data) {
                console.log(data)
                if (data.code == 100) {
                    //表示注册成功,跳转到登录页面
                    location.href = '/login/'
                } else {
                    //前端显示错误信息
                    console.log(data)
                    //两次密码不一致的错误渲染
                    {#if(data.errors['__all__']){#}
                    {#    $(".error").html(data.errors["__all__"])[0]#}
                    {##}
                }
                    //其他标签的错误渲染
                    $.each(data.errors, function (k,v){
                        console.log(k)
                        console.log(v)
                        if(k=="__all__"){ //两次密码不一致的错误信息
                            $(".error").html(v[0])
                        }else{
                            //链式调用,在对应的input后面的span中插入错误文字,把父div加入has-error类,整个框变红
                            $("#id_" + k).next().html(v[0]).parent().addClass('has-error')
                        }
                    })
                    //定时任务
                    setTimeout(function (){
                        //把所有span的文字去掉,把父类div中的has-error类去掉
                        $(".text-danger").html("").parent().removeClass('has-error')
                    },3000)
                }
        })

image

七、用户存在校验功能

# 前端通过get把用户传入,我们可以根据用户名查询数据库,如果用户名存在,返回存在。如果不存在,返回不存在
/check_username/?username=xzx

def check_username(request):
    res = {'code':100, 'msg': '用户存在'}
    username = request.GET.get('username')
    user = UserInfo.objects.filter(username=username).first()
    if user:
        #用户存在
        return JsonResponse(res)
    else:
        #用户不存在
        res['code'] = 101
        res['msg'] = '用户不存在'
        return JsonResponse(res)

八、前端校验功能

  $("#id_username").blur(function(){
            $.ajax({
                url:'/check_username/?username=' +$(this).val(),
                type: 'get',
                success:function (data){
                    if(data.code == 100){
                        //在span中插入错误信息
                        {# alter(data.msg) #}
                        $("#id_username").next().html(data.msg)
                    }
                }
            })
        })
这篇关于学习python-Day61的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!