添加上传目录
# 如果不添加上传目录,仍然可以上传成功,默认为project目录,如果models.py定义了upload_to="目录名称",则会上传到"project/目录名称"这个目录,如果添加了如下配置,会上传到"project/media"目录或者project/media/upload_to="目录名称"/:
settings.py MEDIA_URL = "/media/" MEDIA_ROOT = os.path.join(BASE_DIR, "media")
后台注册页面
# ajax在提交图片到后台的时候,不能直接将图片作为字典传递,而是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()); // 这里传递的是文件对象,是为了能够定位文件,后台获取到这个文件对象后会通过models字段单中的upload_to="avator"参数传递到服务器目录。 formData.append("avatar", $("#id_avatar")[0].files[0]); formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>注册</title> </head> <body> <link rel="stylesheet" href="/static/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/backend.css"> <div class="container register"> <div class="row"> <div class="col-md-6 col-md-offset-3"> {# form添加novalidate参数,代表取消前端h5的验证,比如邮箱格式验证#} <form novalidate action="/register/" method="post" class="form-horizontal" enctype="multipart/form-data"> {% csrf_token %} <div class="form-group"> <label for="{{ form_obj.username.id_for_label }}" class="col-sm-2 control-label"> {{ form_obj.username.label }} </label> <div class="col-sm-8"> {{ form_obj.username }} <span class="help-block">{{ form_obj.username.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ form_obj.password.id_for_label }}" class="col-sm-2 control-label"> {{ form_obj.password.label }} </label> <div class="col-sm-8"> {{ form_obj.password }} <span class="help-block">{{ form_obj.password.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ form_obj.re_password.id_for_label }}" class="col-sm-2 control-label"> {{ form_obj.re_password.label }} </label> <div class="col-sm-8"> {{ form_obj.re_password }} <span class="help-block">{{ form_obj.re_password.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ form_obj.email.id_for_label }}" class="col-sm-2 control-label"> {{ form_obj.email.label }} </label> <div class="col-sm-8"> {{ form_obj.email }} <span class="help-block">{{ form_obj.email.errors.0 }}</span> </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"></label> <input type="file" id="id_avatar" style="display: none;" name="avatar" accept="image/*"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-8"> <button id="reg-submit" type="button" class="btn btn-success">注册</button> </div> </div> </form> </div> </div> </div> {# <script src="/static/js/bootstrap.min.js"></script>#} <script src="/static/js/jquery-1.12.4.js"></script> <script> $("#id_avatar").change(function () { // 创建一个文件读取对象 var fileReader = new FileReader; // 在更改前端图片之前,把文件内容读取完 fileReader.readAsDataURL(this.files[0]); // 读取文件是需要时间的 // 文件读取完后,重新加载到img当中 fileReader.onload = function () { $("#avatar-img").attr("src", fileReader.result); } }); $("#reg-submit").click(function () { 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()); // 这里传递的是文件对象,是为了能够定位文件,后台获取到这个文件对象后会通过models字段单中的upload_to="avator"参数传递到服务器目录。 formData.append("avatar", $("#id_avatar")[0].files[0]); formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); /* console.log($("#id_avatar")); // 获取到了是一个jquery对象 // jQuery.fn.init [input#id_avatar, context: document, selector: "#id_avatar"] console.log($("#id_avatar")[0]); // 获取到了input整个标签 // <input type="file" id="id_avatar" style="display:none" name="avatar"> console.log($("#id_avatar")[0].files); // 获取了input标签当中的type="file"类型中的内容 //FileList {0: File, length: 1} // 0: File {name: "风景.jpg", lastModified: 1553135747721, lastModifiedDate: Thu Mar 21 2019 10:35:47 GMT+0800 (中国标准时间), webkitRelativePath: "", size: 27556, …} // length: 1 // __proto__: FileList console.log($("#id_avatar")[0].files[0]); // 获取到了整个上传的文件内容 // File {name: "风景.jpg", lastModified: 1553135747721, lastModifiedDate: Thu Mar 21 2019 10:35:47 GMT+0800 (中国标准时间), webkitRelativePath: "", size: 27556, …} */ $.ajax({ url: "/register/", type: "post", // 当需要传输图片的时候,需要将processData和contentType设置为false processData: false, contentType: false, data: formData, success:function (data) { // 这里data是后端返回的一个字典ret = {"status": 0, "msg": "/reg/"} 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"); }) //console.log(123) }else { // 没有错误就跳转到指定页面,这里data是后端返回的一个字典ret = {"status": 0, "msg": "/reg/"} location.href = data.msg; } } }) }); // 当input获取焦点的事件,移除报错的样式,并且晴空报错信息。 $("form input").focus(function () { $(this).next().text("").parent().parent().removeClass("has-error"); }) $("#id_username").blur(function () { var username = $(this).val(); $.ajax({ url: "/check_username_exist/", type: "get", data: {"username": username}, success: function (data) { if (data.status){ //$("#id_username").next.text(data.msg).parentElement().parentElement().addClass("has-error"); // 上面为错误写法 $("#id_username").next().text(data.msg).parent().parent().addClass("has-error"); } } }) }) </script> </body> </html>
views.py
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(): # 数据库中没有re_password字段,需要从字典中剔除re_password字段 form_obj.cleaned_data.pop("re_password") # 接收从ajax发送过来的的图片数据 avatar_img = request.FILES.get("avatar") print(avatar_img) models.UserInfo.objects.create_user(**form_obj.cleaned_data, avatar=avatar_img) ret["msg"] = "/reg/" # ajax在接收到ret对象后,会将这个数据取出,并且将这个数据通过使用location.href作为跳转目录 return JsonResponse(ret) else: ret["status"] = 1 ret["msg"] = form_obj.errors print(ret) return JsonResponse(ret) form_obj = forms.RegForm() return render(request, 'register.html', {"form_obj": form_obj}) def reg(request): return render(request, 'index.html') # 这里直接回复HttpResponse即可
最后,也是最重要,添加url路由,切记切记
from django.views.static import serve from django.conf import settings urlpatterns = [ re_path(r'^media/(?P<path>.*)$', serve, {"document_root": settings.MEDIA_ROOT}), ]