您的位置:首页 > 编程语言 > Go语言

django 搭建上传文件系统——细说Form Validation(二)

2017-06-20 18:32 323 查看
我学习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_to和storage。'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.html和uploadOK.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里定义的,读者们可以试一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: