頭像的上傳的實現


  上傳頭像跟上傳文件一樣,但是平時的應用中,我們都是直接點擊一張圖片,就會跳出類似於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}),

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM