在任務管理中,我們增加一個添加附件的功能,方便用戶將相應的資料上傳至服務器。Django提供了方便的upload方法,具體可參閱https://docs.djangoproject.com/en/1.9/topics/http/file-uploads/
#建立上傳附件的FORM
class UploadFileForm(forms.Form):
#提供一個上傳附件的FORM
file = forms.FileField()
Models.py:
#上傳附件
class Upload(models.Model):
#與task表格是一對多的關係,依附於task之上
task = models.ForeignKey(Task)
#上傳附件名稱
upload_title = models.CharField(max_length=255)
#上傳附件路徑
upload_path = models.CharField(max_length=255)
#上傳附件時間
upload_signtime = models.DateTimeField(auto_now_add=True,null=True)
def __unicode__(self):
return self.upload_title
3 .建立一個echo目錄下建立一個upload.py文件用來處理上傳文件
通常會使用下面的兩個個方法來訪問被上傳的內容:
UploadedFile.read():從文件中讀取整個上傳的數據。小心整個方法:如果這個文件很大,你把它讀到內存中會弄慢你的系統。
UploadedFile.multiple_chunks():如果上傳的文件足夠大需要分塊就返回真。默認的這個值是2.5兆,當然這個值是可以調節的,看下面的UploadedFile.chunks():一個產生器,返回文件的塊。如果multiple_chunks()是真的話,你應該在一個循環中使用這個方法,而不是使用read();
我們使用第二種方法來進行處理
Upload.py:
# -*- coding: UTF-8 -*-
import os,sys
reload(sys)
sys.setdefaultencoding('utf8')
#定義一個處理上傳文件的函數
def handle_uploaded_file(f):
#獲取項目的基本路徑
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
try:
#將上傳文件放於media路徑下
#注意: media前面的'/'與否取決於windows或linux平臺
path = os.path.join(BASE_DIR, 'media/')
#如果沒有這個路徑則建立
if not os.path.exists(path):
os.makedirs(path)
else:
file_name = str(path + f.name)
#以二進制寫方式打開,可以讀、寫文件, 如果文件不存在,創建該文件;如果文件已存在,先清空,再打開文件
destination = open(file_name, 'wb+')
#在UploadedFile.chunks()上循環而不是用read(),保證大文件不會大量使用你的系統內存。
for chunk in f.chunks():
destination.write(chunk)
destination.close()
except Exception, e:
print e
#返回文件名稱及路徑
return f.name, path
3. 在views.py中建立一個上傳文件的函數:
#上傳附件函數
def upload_file(request, pk):
#獲得一個任務的實例
task_ins = get_object_or_404(Task, pk=pk)
#如果獲取到了POST的提交
if request.method == 'POST':
#獲取form表單,request.FILES是存放文件的地方
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
#通過處理上傳文件函數來獲得返回值
uf = handle_uploaded_file(request.FILES['file'])
#獲取上傳文件的實例,並補充相應信息至數據庫中
upload_ins = Upload()
#綁定相應的task id
upload_ins.task_id = task_ins.id
#記錄相應的文件名
upload_ins.upload_title = uf[0]
#記錄相應的上傳路徑
upload_ins.upload_path = uf[1]
#保存upload的實例
upload_ins.save()
return redirect('task_edit', pk=task_ins.id)
else:
form = UploadFileForm()
#構建相應的context,傳遞至上傳文件頁面
context = {
'form': form,
'sub_title': '上傳文件',
}
return render(request, 'upload.html', context)
4. 建立一個上傳文件的html頁面,用於上傳文件:
Upload.html:
{% extends "index.html" %}
{% block page_title %}
上傳文件
{% endblock %}
{% block container %}
{% load staticfiles %}
<form enctype="multipart/form-data" method="POST" action="">{% csrf_token %}
{{ form }}
<input type="submit" value="上傳文件" />
</form>
{% endblock %}
5. 在原有任務表單中,增加上傳附件的鏈接:
<!-----附件上傳頁面 BEGIN----->
<div id="div_id_task_attachment" class="form-group">
<label for="div_id_task_attachment" class="control-label"><strong>附件</strong></label>
</div>
<div>
<!--通過數據庫,將upload中附件的數據取出,並展示-->
{% for data in task.upload_set.all %}
<!--get_media_prefix 在settings.py中定義,獲取相關路徑,並顯示相應文件名-->
<a href="{% get_media_prefix %}{{ data.upload_title }}">{{ data.upload_title }}</a><br/>
{% endfor %}
<br/><br/>
</div>
<!---附件上傳頁面 end---->
<!--如果任務的狀態是處理中,那麼以下按鈕正常出現,如果是其他狀態,那麼這些按鈕不出現-->
{% if task.task_status == '處理中' %}
<div>
<a href="{% url 'upload_file' task.id %} "><input class='btn btn-purple' type='button' value='添加附件' /></a>
</div>
{% endif %}
<br/><br/>
6. 增加urls.py中的信息:
#上傳附件
urlpatterns = [
…
url(r'^upload_file/(?P<pk>\d+)/$', echo.views.upload_file, name='upload_file'),
…
]
7. 調整urls.py關於靜態文件的配置
在生產環境中, 靜態文件交由Web服務器處理,Django本身不處理靜態文件。爲了便於開發,Django提供了在開發環境的對靜態文件的處理機制。
1)在INSTALLED_APPS裏面加入'django.contrib.staticfiles',
2)在urls.py裏面加入
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
MEDIA:指用戶上傳的文件,比如在Model裏面的FileFIeld,ImageField上傳的文件。
STATIC主要指的是如css,js,images這樣文件
8. 驗證上傳附件功能