在django中實現文件上傳有三種方法可以實現:
- 自己手動寫
- 使用Form組件
- 使用ModelForm組件
其中使用ModelForm組件實現是最簡單的。
1、自己手寫
先寫一個上傳的頁面 upload_file.html
enctype="multipart/form-data 一定要加這個,不然只會上傳文件名,不會上傳文件內容。
{% extends 'layout.html' %}{% block content %}<div class="container"><form method="post" enctype="multipart/form-data">{% csrf_token %}<input type="text" name="username"><input type="file" name="avatar"><input type="submit" value="提交"></form></div>{% endblock %}
在寫一個視圖函數:
在這個視圖函數中如果是get 請求就展示上傳的頁面,如果是post 請求,就將獲取到的文件對象在項目跟目錄創建一個相同的文件名保存起來。
from django.shortcuts import render, HttpResponsedef upload_list(request):if request.method == 'GET':return render(request,'upload_file.html')print(request.POST) # 請求體中的數據print(request.FILES) # 請求發過來的文件 {}file_object = request.FILES.get("avatar")f = open(file_object.name,mode='wb')for chunk in file_object.chunks():f.write(chunk)f.close()return HttpResponse('上傳成功')
簡單的頁面效果:
2、使用Form組件
提交頁面時: 用戶輸入數據 + 文件(輸入不能為空,報錯)
- Form生成HTML標簽 :type=file
- 表單的驗證
- form.cleaned_data 獲取數據 + 文件對象
將上傳的圖片保存到static目錄,并且在數據庫保存文件存儲的路徑
models.py 中創建一個數據庫
class Boss(models.Model):"""保存圖片"""name = models.CharField(verbose_name="姓名",max_length=32)age = models.IntegerField(verbose_name="年齡")img = models.CharField(verbose_name="圖片",max_length=128)
視圖函數
from django.shortcuts import render, HttpResponse
from django import forms
import os
from app01 import modelsclass UpForm(forms.Form):name = forms.CharField(label='姓名')age = forms.IntegerField(label='年齡')img = forms.FileField(label='頭像')def upload_form(request):if request.method == 'GET':form = UpForm()return render(request,'upload_form.html',{'form':form})form = UpForm(data=request.POST,files=request.FILES)if form.is_valid():# 1、讀取圖片內容,寫入文件夾中并獲取文件的路徑image_object = form.cleaned_data.get('img')# 創建文件路徑db_file_path = os.path.join('static','img',image_object.name)file_path = os.path.join('app01',db_file_path)f = open(file_path,mode='wb')for chunk in image_object.chunks():f.write(chunk)f.close()# 2、 將圖片文件路徑寫入到數據庫models.Boss.objects.create(name=form.cleaned_data['name'],age = form.cleaned_data['age'],img = db_file_path,)return HttpResponse('上傳成功')return render(request,'upload_form.html',{'form':form})
upload_form.html 文件內容:
{% extends 'layout.html' %}{% block content %}<div class="container"><div class="panel panel-default"><div class="panel-heading">圖片上傳</div><div class="panel-body"><form method="post" enctype="multipart/form-data" novalidate>{% csrf_token %}{% for field in form %}<div class="form-group"><label >{{ field.label }}</label>{{ field }}<span style="color:red">{{ field.errors.0 }}</span></div>{% endfor %}<button type="submit" class="btn btn-primary">提交</button></form></div></div></div>
{% endblock %}
頁面效果:
3、使用ModelForm組件
使用ModelForm的前提條件要設置好media 目錄
啟用media 目錄
在django的開發中有兩個特殊的文件夾:
- static , 存放靜態文件的路徑,包括: css、js 、項目圖片。
- media , 用戶上傳的數據目錄。
1、在urls.py中的配置
from django.urls import path,re_path
from django.views.static import serve
from django.conf import settingsurlpatterns = [re_path(r'^media/(?P<path>.*)$', serve, {'document_root':settings.MEDIA_ROOT},name='media'),]
2、在settings.py中配置:
import osMEDIA_ROOT = os.path.join(BASE_DIR,"media")
MEDIA_URL = "/media/"
models.py 重新創建一個表來存儲文件路徑
class City(models.Model):"""城市"""name = models.CharField(verbose_name="名稱",max_length=32)count = models.IntegerField(verbose_name="人口")# 本質上數據庫也是charField ,自動保存數據,upload_to 表示會保存到media目錄下的cityimg = models.FileField(verbose_name='Logo',max_length=128,upload_to='city/')
視圖函數:
通過 form.save() django 自動將文件存儲到media目錄下的city目錄,并且把文件路徑保存到數據庫
from django.shortcuts import render, HttpResponse
from app01 import models
from app01.utils.bootstrap import BootStrapModelFormclass UploadModelForm(BootStrapModelForm):bootstrap_exclude_name = ['img']class Meta:model = models.Cityfields = "__all__"def upload_modelform(request):if request.method == 'GET':form = UploadModelForm()return render(request,'upload_form.html',{'form':form})form = UploadModelForm(data=request.POST,files=request.FILES)if form.is_valid():form.save()return HttpResponse('上傳成功')return render(request, 'upload_form.html', {'form': form})
upload_form.html
{% extends 'layout.html' %}{% block content %}<div class="container"><div class="panel panel-default"><div class="panel-heading">圖片上傳</div><div class="panel-body"><form method="post" enctype="multipart/form-data" novalidate>{% csrf_token %}{% for field in form %}<div class="form-group"><label >{{ field.label }}</label>{{ field }}<span style="color:red">{{ field.errors.0 }}</span></div>{% endfor %}<button type="submit" class="btn btn-primary">提交</button></form></div></div></div>
{% endblock %}
效果:
數據庫存儲的: