zoukankan      html  css  js  c++  java
  • 头像的上传的实现

      上传头像跟上传文件一样,但是平时的应用中,我们都是直接点击一张图片,就会跳出类似于input标签中type为file的样式,这个实现就用到了label标签的特性,通过label标签的关联特性,我们可以将一张图片包在label标签中,并且将input标签隐藏掉,就可以实现点击图片,打开的是input的标签。

    具体代码的实现:(基于bootstrap的实现)

    <div>
    <label class="col-sm-2 control-label">头像</label>
    <
    div class="col-sm-8"> <label for="id_avatar"><img src="/static/avatars/default.png" alt="图像加载失败"></label> <input type="file" id="id_avatar" name="file" style="display:none"> </div>
    </div>

    实现了这个替换后,我们在使用时,就会发现,选择了图片后,不能显示,所以我们就要针对这个来实现预览功能

    预览功能的实现:

     <div class="form-group">
                   <label
                                class="col-sm-2 control-label">头像</label>
                        <div class="col-sm-8">
                            <label for="id_avatar"><img id="avatar-img" src="/static/img/default.png" alt=""></label>
                            <input accept="image/*" type="file" name="avatar" id="id_avatar" style="display: none">
                            <span class="help-block"></span>
                        </div>
     </div>
    
                 
    <script src="/static/jquery-3.3.1.js"></script>
    <script src="/static/bootstrap/js/bootstrap.min.js"></script>
    <script>
        // 找到头像的input标签绑定change事件
        $("#id_avatar").change(function () {
            // 1. 创建一个读取文件的对象
            var fileReader = new FileReader();
            // 取到当前选中的头像文件
            // console.log(this.files[0]);
            // 读取你选中的那个文件
            fileReader.readAsDataURL(this.files[0]);  // 读取文件是需要时间的
            fileReader.onload = function () {
                // 2. 等上一步读完文件之后才 把图片加载到img标签中
                $("#avatar-img").attr("src", fileReader.result);
            };
        });

    备注:

      文件的读取是需要时间的,所以必须使用onload方法进行等待文件的读取完成

      此外,使用this.files得到的是一个对象,取0得到的是这个文件。

      我们也可以在输入文件的那个input框中添加一个属性:accept 比如accept="image/png",表示一个默认的格式。

    预览功能实现后,当用户确认选择,进行上传时,就需要进行后端的存储操作

    备注:使用form表单进行向后端的提交带文件的数据时,需要指定form表单的提交属性  在form表单中加上enctype属性 enctype=multipart/form-data,同样的使用ajax向后端提交带文件的数据时也需要类似的属性:1.添加两个属性processData:false,contentType:false   2.data必须是FormData()类型

    以Django为例,使用ajax实现向后端的提交

    ajax代码实现:

     // AJAX提交注册的数据
        $("#reg-submit").click(function () {
            // 取到用户填写的注册数据,向后端发送AJAX请求
            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("avatar", $("#id_avatar")[0].files[0]);
            formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
    
            $.ajax({
                url: "/reg/",
                type: "post",
                processData: false,
                contentType: false,
                data: formData,
                success:function (data) {
                    if (data.status){
                        // 有错误就展示错误
                        // console.log(data.msg);
                        // 将报错信息填写到页面上
                        $.each(data.msg, function (k,v) {
                            // console.log("id_"+k, v[0]);
                            // console.log($("#id_"+k));
                            $("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error");
                        })
    
                    }else {
                        // 没有错误就跳转到指定页面
                        location.href = data.msg;
                    }
                }
            })
        });
    
        // 将所有的input框绑定获取焦点的事件,将所有的错误信息清空
        $("form input").focus(function () {
            $(this).next().text("").parent().parent().removeClass("has-error");
        })

    视图函数部分的实现:

    # 注册的视图函数
    def register(request):
        if request.method == "POST":
            ret = {"status": 0, "msg": ""}
            form_obj = forms.RegForm(request.POST)
            print(request.POST)
            # 帮我做校验
            if form_obj.is_valid():
                # 校验通过,去数据库创建一个新的用户
                form_obj.cleaned_data.pop("re_password")
                avatar_img = request.FILES.get("avatar")
                models.UserInfo.objects.create_user(**form_obj.cleaned_data, avatar=avatar_img)
                ret["msg"] = "/index/"
                return JsonResponse(ret)
            else:
                print(form_obj.errors)
                ret["status"] = 1
                ret["msg"] = form_obj.errors
                print(ret)
                print("=" * 120)
                return JsonResponse(ret)
        # 生成一个form对象
        form_obj = forms.RegForm()
        print(form_obj.fields)
        return render(request, "register.html", {"form_obj": form_obj})

     备注:上传的文件名有重复时,Django内部会自动在文件名后加一个随机的字符串做区分,并在数据库存储。

    另外,在Django中我们用到了form组件的一些用法

    from django import forms
    from blog import models
    from django.core.exceptions import ValidationError
    
    # from django.core.validators import RegexValidator
    # mobile = forms.CharField(validators=[RegexValidator('regex','哈哈哈')])
    class RegForm(forms.Form):
        username=forms.CharField(label='用户名',max_length=12,error_messages={'required':'不能为空'},widget=forms.widgets.TextInput(attrs={'class':'form-control','placeholder':'请输入用户名'}))
        password = forms.CharField(label='密码',min_length=6,error_messages={'min_length':'密码最少为六位','required':'不能为空'},widget=forms.widgets.PasswordInput(attrs={'class':'form-control','placeholder':'请输入密码'}))
        re_password = forms.CharField(label='确认密码',min_length=6,error_messages={'min_length':'确认密码最少为六位','required':'不能为空'},widget=forms.widgets.PasswordInput(attrs={'class':'form-control','placeholder':'请输入确认密码'}))
        email = forms.EmailField(label='邮箱',error_messages={'required':'不能为空','invalid':'格式错误'},widget=forms.widgets.EmailInput(attrs={'class':'form-control','placeholder':'请输入邮箱'}))
        def clean(self):
            password = self.cleaned_data.get('password')
            re_password = self.cleaned_data.get('re_password')
            if re_password:
                if password !=re_password:
                    self.add_error('re_password',ValidationError('两次密码不一致'))
                else:
                    self.cleaned_data.pop('re_password')
            return self.cleaned_data
        def clean_username(self):
            username = self.cleaned_data.get('username')
            is_exists = models.UserInfo.objects.filter(username=username)
            if is_exists:
                self.add_error('username',ValidationError('用户名已存在'))
            return username
    
        def clean_email(self):
            email = self.cleaned_data.get('email')
            is_exist = models.UserInfo.objects.filter(email=email)
            if is_exist:
                self.add_error('email',ValidationError('邮箱已存在'))
            else:
                return email

    备注:label标签的特殊用法:

    <!--label的两种用法-->
    
    <!--用法一:正常用法  实现关联-->
    <label for="d1">用户:</label>
    <input type="text" id="d1">
    
    <!--用法二:将input标签包到label标签里面也可以实现联动效果-->
    <label>用户名 <input type="text"></label>

     用户上传的文件,Django都叫media文件

    如果要在页面中展示出头像,如果上传文件的路径在static目录下,就会在页面展示出来,否则,就无法展示,因为settings.py 文件中没有设置文件访问路径。

    如下图:这样配置上传文件的路径,就可以直接在页面中展示出来

    如果放在了其他路径下,就要一些相应的配置

    Django给我们提供了这种功能,只需要配置好media就可以

    1. settings.py中:

    #BASE_DIR是Django中的项目的绝对路径
    #只需要在settings中添加这些就可以
    MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR,'media')

    2.路由  urls.py 中的配置:

    from django.views.static import serve
    from django.conf import settings
    
    
    #在路由中添加路径
    
    url(r'^media/(?P<path>.*)$', serve, {"document_root": settings.MEDIA_ROOT}),
  • 相关阅读:
    ajax的优缺点
    Service层事务不能回滚的解决方式
    java---springMVC与strutsMVC的区别
    java----监听器的作用
    ActionContextCleanUp
    Struts2请求处理流程及源码分析
    Struts2的拦截器是如何使用AOP工作的
    SSH三大框架的知识题
    java--Struts中请求的过程
    java----Servlet的生命周期
  • 原文地址:https://www.cnblogs.com/zhaopanpan/p/9080278.html
Copyright © 2011-2022 走看看