django 搭建上傳文件系統——細說Form Validation(二)


我學習django的主要途徑是http://djangobook.com, 作者的書好像也出版了。作者的思路很清爽,講解淺顯易懂,該深入的地方深入,我很喜歡,比django官方文檔感覺好多了,官方文檔講解的太晦澀。這些隨筆是結合一些例子來細說django的學習要點與本人的學習心得。

有些中文博客也講解了用django做一些小的項目,但是沒有細講django的原理,即為什么要這樣做,我就個人的理解會細致地講解各個部分的知識點。希望能幫助更多人,也希望與更多人一起進步。

本人配置環境:(2017.6.20)

注意: 在windows中的文件系統是用反斜杠'\'來表示,但是即使是在windows系統下的django,在表示文件路徑時依然用unix 風格的斜杠'/'

OS: win7

python:3.6.2

Django: 1.11.2


創建項目與應用

 

每個項目的前部分:創建項目與應用,把應用添加到settings.py 的'INSTALLED_APP'里,在settings.py里設置默認的數據庫,並同步數據庫數據的操作都是一樣的,就不具體敘述,可以參考我前面的例子。

我把這個上傳文件的項目命名為disk, 項目名稱為mysite,創建完成后的結構如下:(disk/templates, disk/uploads, disk/forms.py 是我本人創建的,不是系統創建的。請忽略除mysite, disk以外的部分,與此例無關。)

# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'disk',
)

 

創建Form類實例

 

為了簡單起見,在這個文件上傳系統中,我們只設計兩個變量:上傳文件的用戶改名,及上傳的文件。Django中為用戶定義了一個django.forms庫,這個庫可以方便地進行form類的數據顯示及數據驗證,省去了很多用戶的代碼。django.forms庫用起來也方便,只需要在HTML文件中需要增加<form> tag時,定義相應的 Form 類就可以。在以下的示例中我們最終的頁面上只有一個<form> tag, 所以我們只需要定義一個Form類即可。Django 社區的慣例是把Form類單獨放在一個forms.py文件中,我們最好也遵循這個規則。創建disk\forms.py文件,並寫入:

# mysite\disk\forms.py

from django import forms

class UserForm(forms.Form):
    userName = forms.CharField(max_length = 20)
    uploadFile = forms.FileField()

可以看出Form類的語法與定義Model時的語法很像,對於每個變量都要定義它的域的屬性,這個我在下面的Model章節中會仔細再講。在UserForm中,我們定義了userName,它是字符屬性,還定義了uploadFile,它是文件屬性。默認情況下這兩個變量都是不能為空的,如果為空,則會在html頁面中顯示出相應的錯誤。

 

創建Models(數據庫層)

 

我們需要把用戶名和上傳的文件路徑放到數據庫中, 所以在設計數據庫時需要兩個字段:userName and uploadFile。在disk\models.py文件中寫入:

# disk\models.py

from django.db import models

# Create your models here.
class User(models.Model):
    userName = models.CharField(max_length = 30)
    uploadFile = models.FileField(upload_to = 'disk/upload/')

    def __str__(self):
        return self.userName

對於models的定義,要講的東西很多。

  • 每個變量都要定義成某種類型的域(field),django會根據不同的域來決定某些事情。比如,域的類型會決定數據庫中該變量的數據類型(比如INTERGER, VARCHAR)。對於每個變量,在html顯示層,django把它定義成一個單獨的widget。最終是以什么widget顯示變量也是與該域的類型有關的,比如一個CharField變量最終會以<input type= 'text'>的形式顯現。
  • 以下是每種域類型變量的定義,來自http://www.djangobook.com/model-definition-reference/。為了保證釋義的完整性與准確性,我就不翻譯成中文了:

 

下張表是所有域通用的可選參數:

  • FileFiled 說明:此類變量不支持primary_key, unique參數(見上表)。有兩個可選參數:upload_tostorage'upload_to'定義的是一個本地的文件路徑,這個路徑可以是個相對路徑,它會自動加到settings.py文件中 BASE_DIR 目錄的后面。一般情況下,即使文件上傳成功也不會保存到數據庫中,除非顯性的調用save()函數。從性能上考慮,不會把上傳的文件存儲到數據庫中,而是把文件的路徑存儲到數據庫中(如果調用了save()函數)。
  • 在定義完models后,要把它同步到數據庫中,主要用兩個命令python manage.py makemigrations,   python manage.py migrate

 

創建Views (邏輯層)

 

視圖views決定的是按照怎樣的邏輯收集處理數據,並把用戶的數據呈現給用戶;可以把它理解成用戶數據(數據庫)到最終呈現頁面(web頁面)的中間人。這部分一般就是純粹的python代碼。打開mysite\disk\views.py文件並寫入:

# mysite\disk\views.py

from django.shortcuts import render
from disk.forms import UserForm
from disk.models import User


def uploads(request):
    if request.method == 'POST':
        userform = UserForm(request.POST, request.FILES)
        if userform.isValid():
              user = User()
              user.userName = userform.cleaned_data['userName']
              user.uploadFile = userform.cleaned_data['uploadFile']
              user.save()
              return render(request, 'uploadOK.html')
    else:
        userform = UserForm(initial ={'userName': 'sunshore'})
    return render(request, 'upload.html', {'userform': userform})

 views.py文件就把上文定義的UserForm和User (models文件)引用了過來。

  • 對於HttpRequest.POST對象,我們在上一節中講過,這里不再敘述。
  • HttpRequest.FILES對象也是一個“類字典”對象,它的'key'是文件名,與html文件中<input type = "file" name = "" />中的內容相同;'key'所對應的'value' 是上傳的文件。注意: 這個對象必須是在HttpRequest method = 'POST' 並且<form> tag中包含 enctype="multipart/form-data"時才會有值,否則會返回一個空的類字典對象。
  • django中Form類實例化后,可以通過isValid()函數來檢查數據是否有效;如果有效,則該實例就會有cleaned_data屬性,這是一個字典對象,包含的是Form類數據。
  • 我們首先檢查HttpRequest是一個POST 方法,然后實例化Form類,如果實例化成功,就把數據存儲到數據庫中去。(當然最終存儲到數據庫中不是文件本身,而是文件路徑,上部分提到過)。如果HttpRequest不是POST方法,則把用戶名初始化成'sunshore'

 

創建Templates(顯示層)

 

我們需要創建templates來定制數據的顯示。Django中將數據的處理與顯示分開了,數據的處理是在views.py中,數據的顯示是在templates里。 默認情況下,mysite/mysite/settings.py文件中的TEMPLATES定義'APP_DIRS' = True, 也就是說django會到各個應用的文件下尋找templates文件夾,使用里面定義的html文件。

我們需要在mysite/disk/templates創建兩個html文件:upload.htmluploadOK.html,並寫入:

# mysite\disk\templates\upload.html

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<style type="text/css">

     ul.errorlist{
     margin:0;
     padding:0;
    }
    .errorlist li{
    background-color: blue;
    color: white;
    display: block;
    font-size: 1.0em;
    margin: 0 0 1px;
    padding: 0 10px;
   }
</style>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Upload File</title>
</head>
<body>
     <h1>User Upload Files</h1>
     <form action="" method="post" enctype="multipart/form-data" >
      {{userform.as_p}}
      {% csrf_token %}
      <input type="submit" value="ok"/>
     </form>
</body>
</html>
# mysite\disk\templates\uploadOK.html

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Upload OK</title>
</head>
<body>
         <p > Uploading Files Successfully </p>
         <a href= 'upload'>Back to upload file page </a>

</body>
</html>
  •  Form類會自動生成頁面的錯誤信息,並以errorlist的形式返回結果。在html文件中我們可以對errorlist進行CSS的定制,使得error信息更為突出。這就是<style> ....</style>那段代碼的作用。
  • 默認情況下,Form類顯示成員的排版格式有form.as_p, form.as_table, form.as_ul這三種形式,不同形式下成員的排列是不同的。比如本示例中userform.as_p會顯示如下

userform.as_table 顯示結果:

 

userform.as_ul 顯示結果:

我們可以根據自己的喜好來選擇成員的顯示形式。當然django也支持自己定制所有成員的顯示形式。感興趣的讀者可以參考:http://djangobook.com/tying-forms-views.

 

設置urlconf 文件

 

這個是用正則表達式的方式定義了HttpRequest.url和views的對應關系。在mysite\urls.py文件中輸入:

# mysite\urls.py

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

from disk import views as disk_views

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'mysite2.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^admin/', include(admin.site.urls)),
    url(r'^upload/$', disk_views.upload),
)

 

啟動服務

 

mysite文件夾下,終端命令行輸入: python manage.py runserver 80

 

在用戶正確地上傳了文件后,我們可以在mysite\disk\upload文件夾下看到此文件,這個是在models.py里定義的,讀者們可以試一下。


免責聲明!

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



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