首先上一个html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css"> <script src="/static/js/jquery-3.2.1.min.js"></script> <style> #avatar_img { margin-left: 20px; } #avatar { display: none; } .error { color: red; } </style> </head> <body> <h3>注册页面</h3> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <form id="form"> {% csrf_token %} {% for field in form %} <div class="form-group"> <label for="{{ field.auto_id }}">{{ field.label }}</label> {{ field }} <span class="error pull-right"></span> </div> {% endfor %} <div class="form-group"> <label for="avatar"> 头像 <img id="avatar_img" width="60" height="60" src="/static/blog/img/default.png" alt=""> </label> <input type="file" id="avatar" name="avatar"> </div> <input type="button" class="btn btn-default reg_btn" value="submit"><span class="error"></span> </form> </div> </div> </div> <script> // 头像预览 $("#avatar").change(function () { // 获取用户选中的文件对象 var file_obj = $(this)[0].files[0]; // 获取文件对象的路径 var reader = new FileReader(); reader.readAsDataURL(file_obj); // 修改img的src属性 ,src=文件对象的路径 reader.onload = function () { $("#avatar_img").attr("src", reader.result) }; }); // 基于Ajax提交数据 $(".reg_btn").click(function () { //console.log($("#form").serializeArray()); var formdata = new FormData(); var request_data = $("#form").serializeArray(); $.each(request_data, function (index, data) { formdata.append(data.name, data.value) }); formdata.append("avatar", $("#avatar")[0].files[0]); $.ajax({ url: "", type: "post", contentType: false, processData: false, data: formdata, success: function (data) { //console.log(data); if (data.user) { // 注册成功 location.href="/login/" } else { // 注册失败 //console.log(data.msg) // 清空错误信息 $("span.error").html(""); $(".form-group").removeClass("has-error"); // 展此次提交的错误信息! $.each(data.msg, function (field, error_list) { console.log(field, error_list); if (field=="__all__"){ $("#id_re_pwd").next().html(error_list[0]).parent().addClass("has-error"); } $("#id_" + field).next().html(error_list[0]); $("#id_" + field).parent().addClass("has-error"); }) } } }) }) </script> </body> </html>
大家仔细观察上方代码,在点击头像上传图片的时候,我的做法并不是用什么css定位之类的东西,而是直接用label自带的属性得到点击头像就相当于上传文件的效果。
细节看图
仅仅如此!
那如何实现头像的实时预览呢?
猜想3步骤1,头像应该是改变了 2,上传文件之后应该拿到 该图片的URL 3,将原有图片src替换为新图片的src!
onload是等待加载完成之后再去执行的内容!
下面就是forms组件了
from django import forms from django.forms import widgets from blog.models import UserInfo from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class UserForm(forms.Form): user=forms.CharField(max_length=32, error_messages={"required":"该字段不能为空"}, label="用户名", widget=widgets.TextInput(attrs={"class":"form-control"},) ) pwd=forms.CharField(max_length=32, label="密码", widget=widgets.PasswordInput(attrs={"class":"form-control"},) ) re_pwd=forms.CharField(max_length=32, label="确认密码", widget=widgets.PasswordInput(attrs={"class":"form-control"},) ) email=forms.EmailField(max_length=32, label="邮箱", widget=widgets.EmailInput(attrs={"class":"form-control"},) ) def clean_user(self): val=self.cleaned_data.get("user") user=UserInfo.objects.filter(username=val).first() if not user: return val else: raise ValidationError("该用户已注册!") def clean(self): pwd=self.cleaned_data.get("pwd") re_pwd=self.cleaned_data.get("re_pwd") if pwd and re_pwd: if pwd==re_pwd: return self.cleaned_data else: raise ValidationError("两次密码不一致!") else: return self.cleaned_data
当文件上传的时候还需要在settings中配置静态文件的路径
# 与用户上传相关的配置 MEDIA_ROOT=os.path.join(BASE_DIR,"media") MEDIA_URL="/media/"
并且还需要在URL中写出,因为django没有默认加。
re_path(r"media/(?P<path>.*)$",serve,{"document_root":settings.MEDIA_ROOT}), re_path('^(?P<username>\w+)/articles/(?P<article_id>\d+)$', views.article_detail),
在这里需要注意
要先在URL中导入
from django.views.static import serve
在这里上传完整的URL配置
"""cnblog URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.0/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path,re_path from django.views.static import serve from blog import views from cnblog import settings from django.urls import include urlpatterns = [ path('admin/', admin.site.urls), path('login/', views.login), path('index/', views.index), path('logout/', views.logout), re_path('^$', views.index), path('get_validCode_img/', views.get_valid_code_img), path('register/', views.register), # 文本编辑器上传图片url path('upload/', views.upload), # 后台管理url re_path("cn_backend/$",views.cn_backend), re_path("cn_backend/add_article/$",views.add_article), # 点赞 path("digg/",views.digg), # 评论 path("comment/",views.comment), # 获取评论树相关数据 path("get_comment_tree/",views.get_comment_tree), # media配置: re_path(r"media/(?P<path>.*)$",serve,{"document_root":settings.MEDIA_ROOT}), re_path('^(?P<username>\w+)/articles/(?P<article_id>\d+)$', views.article_detail), # article_detail(request,username="yuan","article_id":article_id) # 个人站点的跳转 re_path('^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)/$', views.home_site), # home_site(reqeust,username="yuan",condition="tag",param="python") # 个人站点url re_path('^(?P<username>\w+)/$', views.home_site), # home_site(reqeust,username="yuan") ]
不能忘了导入,否则直接访问静态文件是找不到的
没有过不去的坎,只有没加够的油!