一:前端使用ajax发送FormData信息,FormData组装文件对象,后端通过request.FILES.get("xxx")获取file_obj,保存时,保存图片的字段必须设置upload_to字段,如upload_to='./upload/avatar/',且必须在settings文件中指定 MEDIA_ROOT = os.path.join(BASE_DIR, "blog/media")
register.html:

{% load staticfiles %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Blog-Sing Up</title> <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.css' %}"> <script src="{% static 'js/jquery-3.2.1.js' %}"></script> <style> .my-register { margin-top: 3%; } .my-register #my-form-div { border: solid 1px lightgray; padding: 20px; border-radius: 10px; } .my-valid-img { width: 140px; height: 33px; } .my-btn-register { width: 90px; } .warn-msg { color: #a94442; font-size: 12px; text-align: right; margin-right: 3px; margin-bottom: 0; visibility: hidden; } .form-group { margin-bottom: 0 !important; } .my-btn-register { margin-top: 5px; } .file_choose_div{ width: 60px; height: 60px; position: relative; margin-bottom: 15px!important; } .full{ position: absolute; top:0; left: 35px; width: 60px; height: 60px; } #file_choose{ opacity: 0; } </style> </head> <body> <div class="row my-register"> <div class="col-md-6 col-md-offset-3"> {% csrf_token %} <div id="my-form-div"> {% csrf_token %} <div class="form-group"> <label for="id_username">用户名</label> {{ form_obj.username }} <p class="warn-msg warn-msg-username">有误有误有误有误有误有误有误有误</p> </div> <div class="form-group"> <label for="id_password">密码</label> {{ form_obj.password }} <p class="warn-msg warn-msg-password">有误有误有误</p> </div> <div class="form-group"> <label for="id_repeat_password">重复密码</label> {{ form_obj.repeat_password }} <p class="warn-msg warn-msg-repeat_password">有误有误有误</p> </div> <div class="form-group"> <label for="id_email">邮箱</label> {{ form_obj.email }} <p class="warn-msg warn-msg-email">有误有误有误</p> </div> <div class="form-group file_choose_div"> <label for="id_email">头像</label> <img src="{% static 'img/default.png' %}" alt="" class="full" id="file_img"> <input type="file" class="full" id="file_choose"> </div> <div class="form-group"> <label for="id_valid_code">验证码</label> <div class="row"> <div class="col-md-5"> {{ form_obj.valid_code }} <p class="warn-msg warn-msg-valid_code">有误有误有误</p> </div> <div class="col-md-4"> <img class="my-valid-img" src="/valid_code/" alt=""> </div> </div> </div> <div class="row"> <div class="col-md-3"> <button type="submit" onclick="register()" class="btn btn-default my-btn-register">注册</button> </div> </div> </div> </div> </div> <script> function register() { //通过FormData对象发送信息,可以发送任何类型的数据 var username = $("#id_username").val(); var password = $("#id_password").val(); var repeat_password = $("#id_repeat_password").val(); var email = $("#id_email").val(); var valid_code = $("#id_valid_code").val(); var csrf = $('[name="csrfmiddlewaretoken"]').val(); var formData = new FormData(); formData.append("username",username); formData.append("password",password); formData.append("repeat_password",repeat_password); formData.append("email",email); formData.append("valid_code",valid_code); formData.append("csrfmiddlewaretoken",csrf); //组装图片文件对象 //文件对象:$("#file_choose")[0].files[0] //File {name: "新射雕2.jpg", lastModified: 1498045582805, lastModifiedDate: Wed Jun 21 2017 19:46:22 GMT+0800 (中国标准时间), webkitRelativePath: "", size: 274931, …} formData.append("img",$("#file_choose")[0].files[0]); $.ajax({ url: "/register/", type: "POST", data: formData, //使用formdata,processData,contentType必须设置为false, //processData的意思是不使用编码,因为默认会使用urlencode processData:false, contentType:false, success: function (data) { $(".warn-msg").css("visibility", "hidden"); if (data === "register ok") { location.href = "/login/" } else { var data1 = JSON.parse(data); if (data1["__all__"] && !data1["repeat_password"]) { $(".warn-msg-repeat_password").text(data1["__all__"]).css("visibility", "visible") } for (var k in data1) { $(".warn-msg-" + k).text(data1[k]).css("visibility", "visible") } } }, error: function (jqXHR, textStatus, err) { alert("error:" + err); } }) } //点击切换验证码 $(".my-valid-img").click(function () { $(".my-valid-img")[0].src += "?" }); //头像预览 $("#file_choose").change(function () { var reader = new FileReader(); var first_file = $(this)[0].files[0]; reader.readAsDataURL(first_file); reader.onload=function () { $("#file_img")[0].src=this.result //this.result的值是图片的信息: //<img src="data:image/jpeg;base64,/9j/4Syxf4f6d4f6s46s......k=" alt="" class="full" id="file_img"> } }) </script> </body> </html>
view中的register函数:
def register(request):
if request.is_ajax():
form_obj = forms.RegForm(request, request.POST)
if form_obj.is_valid():
info = form_obj.cleaned_data
file_obj = request.FILES.get("img")
print(file_obj) # 2.png
print(type(file_obj)) # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
models.UserInfo.objects.create_user(username=info["username"],
password=info["password"], email=info['email'], avatar=file_obj)
return HttpResponse("register ok")
else:
return HttpResponse(json.dumps(form_obj.errors))
form_obj = forms.RegForm()
trans = {
"form_obj": form_obj,
}
return render(request, "register.html", trans)
avatar = models.FileField(verbose_name='头像', upload_to='./upload/avatar/')
MEDIA_ROOT = os.path.join(BASE_DIR, "blog/media")
MEDIA_URL = "/media/"
二:使用KindEditor实现,KindEditor的使用看下示例代码,添加上传的url: uploadJson: "/upload_file/",后端找到路由函数保存文件.
Html:

{% load staticfiles %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加文章</title> <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.css' %}"> <script src="{% static 'js/jquery-3.2.1.js' %}"></script> <script src="{% static 'kindeditor-4.1.10/kindeditor.js' %}"></script> <style> body { background-color: #DEE7DE; } .my-container { margin-top: 70px; } </style> </head> <body> <div class="container-fluid my-container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div> <div class="form-group"> <label for="article-title">标题</label> <input type="text" class="form-control" id="article-title"> </div> <div class="form-group"> <label for="my-textarea">内容</label> <textarea class="form-control" id="my-textarea"></textarea> </div> {% csrf_token %} <div class="form-group"> <label for="article-category">文章分类</label> <div> {% for category in categorys %} <label class="radio-inline"> <input type="radio" name="article-category" value ="{{ category.title }}">{{ category.title }} </label> {% endfor %} </div> </div> <div style="margin:0 0 100px 0"> <button onclick="submit_article()" class="btn btn-default">发布</button> </div> </div> </div> </div> </div> <script> myKindEditor=KindEditor.create("#my-textarea", { "100%", height: "400px", resizeType: 0,//不准移动 uploadJson: "/upload_file/", extraFileUploadParams: { "csrfmiddlewaretoken": "{{ csrf_token }}" } }); function submit_article() { $.ajax({ url:"article/add/", type:"POST", data:{ "title":$("#article-title").val(), "content":myKindEditor.html(), "category":$('input:radio:checked').val(), "csrfmiddlewaretoken":$('[name="csrfmiddlewaretoken"]').val() }, success:function (data) { console.log(data); location.href="/blog/i/manage/" }, error:function (jqXHR, textStatus, err) { alert(err) } }) } </script> </body> </html>
后端路由:url(r'^upload_file/', views.upload_file),
视图函数:
def upload_file(request):
"""处理上传文件--添加文章时"""
file_obj = request.FILES.get("imgFile")
filename = file_obj.name
with open('blog/media/upload/img/' + filename, "wb") as f:
for chunk in file_obj.chunks():
f.write(chunk)
response_put = {
"error": 0,
"url": '/media/upload/img/' + filename
}
return HttpResponse(json.dumps(response_put))