使用Django框架—Python编程从入门到精通(11)

发表于:2019-1-02 11:31

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:叶维忠    来源:51Testing软件测试网原创

#
Python
分享:
  19.3、使用Django框架
  Django是由Python语言开发的一个免费的开源网站框架,可以用于快速搭建高性能并优雅的网站。本节将详细讲解使用Django框架开发Web程序的知识。
  19.3.1、搭建Django环境
  在当今技术环境下,有多种安装Django框架的方法。下面对这些安装方法按难易程度进行排序,其中越靠前的越简单。
  "Python包管理器。
  "操作系统包管理器。
  "官方发布的压缩包。
  "源码库。
  最简单的下载和安装方式是使用Python包管理工具,建议读者使用这种安装方式。例如可以使用Setuptools中的easy_install或pip。目前在所有的操作系统平台上都可使用这两个工具。对于Windows用户来说,在使用Setuptools时需要将easy_install.exe文件存放在Python安装目录下的Scripts文件夹中。此时只须在DOS命令行窗口中使用一条命令就可以安装Django。其中可以使用如下"easy_install"命令进行安装。
  easy_install django
  也可以使用如下"pip"命令进行安装。
  pip install django
  本书使用的Django版本是1.10.4,控制台安装界面如图19-12所示。
  
  19.3.2、常用的Django命令
  接下来将要讲解一些Django框架中常用的基本的命令,读者需要打开Linux操作系统或Mac OS的Terminal(终端)并直接在终端中输入这些命令(不是Python的shell中)。如果读者使用的是Windows系统,则在CMD控制台中输入操作命令。
  (1)新建一个Django工程。
  django-admin.py startproject project-name
  "project-name"表示项目名字。在Windows系统中需要使用如下命令创建项目。
  django-admin startproject project-name
  (2)新建app(应用程序)。
  python manage.py startapp app-name
  或者
  django-admin.py startapp app-name
  通常一个项目有多个app。当然,通用的app也可以在多个项目中使用。
  (3)同步数据库
  python manage.py syncdb
  注意,在Django 1.7.1及以上的版本中需要用以下命令。
  python manage.py makemigrations
  python manage.py migrate
  这种方法可以创建表,当在models.py中新增类时,运行它就可以自动在数据库中创建表,不用手动创建。
  (4)使用开发服务器。
  开发服务器(即在开发时使用的服务器),在修改代码后会自动重启,这会方便程序的调试和开发。但是由于性能问题,建议只用来测试,不要用在生产环境中。
python manage.py runserver
#当提示端口被占用的时候,可以用其他端口
python manage.py runserver 8001
python manage.py runserver 9999
(当然也可以终止占用端口的进程)
#监听所有可用的IP(计算机可能有一个或多个内网IP,一个或多个外网IP,即有多个IP地址)
python manage.py runserver 0.0.0.0:8000
#如果在外网或者局域网计算机上可以用其他计算机查看开发服务器
#访问对应的IP与端口,比如 http://172.16.20.*:8000
  (5)清空数据库。
  python manage.py flush
  此命令会询问是yes还是no,选择yes会把数据全部清空掉,只留下空表。
  (6)创建超级管理员。
python manage.py createsuperuser
# 按照提示输入用户名和对应的密码就好了,邮箱可以留空,用户名和密码必填
# 修改用户密码可以用:
python manage.py changepassword username
  (7)导出数据,导入数据。
  python manage.py dumpdata appname > appname.json
  python manage.py loaddata appname.json
  (8)Django项目环境终端。
  python manage.py shell
  如果安装了bpython或ipython,会自动调用它们的界面,推荐安装bpython。这个命令和直接运行Python或bpython进入shell的区别是:可以在这个shell里面调用当前项目的models.py中的API。
  (9)数据库命令行。
  python manage.py dbshell
  Django会自动进入在settings.py中设置的数据库,如果是MySQL或PostgreSQL,会要求输入数据库用户密码。在这个终端可以执行数据库的SQL语句。如果对SQL比较熟悉,可能喜欢这种方式。
  19.3.3、第一个Django工程
  下面的实例代码演示了创建并运行第一个Django项目的过程。
  实例19-8 创建并运行第一个Django项目
  源码路径 daima\19\19-8
  (1)在CMD控制台中定位到"H"盘,然后通过如下命令创建一个mysite目录作为项目。
  django-admin startproject mysite
  创建成功后会看到如下所示的目录样式。
  mysite
  ├── manage.py
  └── mysite
  ├── __init__.py
  ├── settings.py
  ├── urls.py
  └── wsgi.py
  也就是说,在"H"盘中新建了一个mysite目录,其中还有一个mysite子目录。这个子目录mysite中是一些项目的设置settings.py文件,总的urls配置文件urls.py,以及部署服务器时用到的wsgi.py文件,还有文件__init__.py(它是Python包的目录结构必需的,与调用有关)。
  "mysite:项目的容器,保存整个项目。
  "manage.py:一个实用的命令行工具,可让你以各种方式与该Django项目进行交互。
  "mysite/__init__.py:一个空文件,告诉Python该目录是一个Python包。
  "mysite/settings.py:该Django项目的设置/配置。
  "mysite/urls.py:该Django项目的URL声明,一份由Django驱动的网站"目录"。
  "mysite/wsgi.py:一个WSGI兼容的Web服务器的入口,以便运行你的项目。
  (2)在CMD控制台中定位到mysite目录下(注意,不是mysite中的mysite目录),然后通过如下命令新建一个应用(app),名称叫learn。
  H:\mysite>python manage.py startapp learn
  此时可以看到在主mysite目录中多出了一个learn文件夹,在里面有如下所示的文件。
  learn/
  ├── __init__.py
  ├── admin.py
  ├── apps.py
  ├── models.py
  ├── tests.py
  └── views.py
  (3)为了将新定义的app添加到settings.py文件的INSTALLED_APPS中,需要对文件mysite/mysite/settings.py进行如下修改。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'learn',
]
  这一步的目的是将新建的程序"learn"添加到INSTALLED_APPS中。如果不这样做,django就不能自动找到app中的模板文件(app-name/templates/下的文件)和静态文件(app-name/static/中的文件)。
  (4)定义视图函数,用于显示访问页面时的内容。在learn目录中打开文件views.py,然后进行如下所示的修改。
#coding:utf-8
from django.http import HttpResponse
def index(request):
return HttpResponse(u"欢迎光临,浪潮软件欢迎您!")
  对上述代码的具体说明如下所示。
  "第1行:声明编码格式为utf-8,因为我们在代码中用到了中文。如果不声明,就会报错。
  "第2行:引入HttpResponse,用来向网页返回内容。就像Python中的print函数一样,只不过HttpResponse是把内容显示到网页上。
  "第3~4行:定义一个index()函数,第一个参数必须是request,与网页发来的请求有关。在request变量里面包含get/post的内容、用户浏览器和系统等信息。函数index()返回一个HttpResponse对象,它可以经过一些处理,最终显示几个字到网页上。
  现在问题来了,用户应该访问什么网址才能看到刚才写的这个函数呢?怎么让网址和函数关联起来呢?接下来,需要定义和视图函数相关的URL网址。
  (5)定义视图函数相关的URL网址,对文件mysite/mysite/urls.py进行如下所示的修改。
from django.conf.urls import url
from django.contrib import admin
from learn import views as learn_views     #新修改的
urlpatterns = [
url(r'^$', learn_views.index),         #新修改的
url(r'^admin/', admin.site.urls),
]
  (6)在终端上运行如下命令进行测试:
  python manage.py runserver
  测试成功后显示如图19-13所示的界面效果。
  在浏览器中的执行效果如图19-14所示。
 
  19.3.4、在URL中传递参数
  和前面学习的Tornado框架一样,使用Django框架也可以实现对URL参数的处理。下面的实例代码演示了使用Django框架实现参数相加功能的过程。
  实例19-9 实现参数相加功能
  源码路径 daima\19\19-9
  (1)在CMD控制台中定位到"H"盘,然后通过如下命令创建一个"zqxt_views"目录作为项目。
  django-admin startproject zqxt_views
  也就是说,在"H"盘中新建了一个zqxt_views目录,其中还有一个zqxt_views子目录。这个子目录中是一些项目的设置settings.py文件,总的urls配置文件urls.py,以及部署服务器时用到的wsgi.py文件,还有文件__init__.py(它是Python包的目录结构必需的,与调用有关)。
  (2)在CMD控制台中定位到zqxt_views目录下(注意,不是zqxt_views中的zqxt_views目录),然后通过如下命令新建一个应用(app),名称叫calc。
  cd zqxt_views
  python manage.py startapp calc
  此时自动生成目录的结构大致如下所示。
  zqxt_views/
  ├── calc
  │    ├── __init__.py
  │    ├── admin.py
  │    ├── apps.py
  │    ├── models.py
  │    ├── tests.py
  │    └── views.py
  ├── manage.py
  └── zqxt_views
  ├── __init__.py
  ├── settings.py
  ├── urls.py
  └── wsgi.py
  (3)为了将新定义的app添加到settings.py文件的INSTALLED_APPS中,需要对文件zqxt_views/zqxt_views/settings.py进行如下修改。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'calc',
]
  这一步的目的是将新建的程序"calc"添加到INSTALLED_APPS中,如果不这样做,django就不能自动找到app中的模板文件(app-name/templates/下的文件)和静态文件(app-name/static/中的文件)。
  (4)定义视图函数,用于显示访问页面时的内容。对文件calc/views.py进行如下所示的修改。
from django.shortcuts import render
from django.http import HttpResponse
def add(request):
a = request.GET['a']
b = request.GET['b']
c = int(a)+int(b)
return HttpResponse(str(c))
  在上述代码中,request.GET类似于一个字典,当没有为传递的a设置值时,a的默认值为0。
  (5)定义视图函数相关的URL网址,添加一个网址来对应刚才新建的视图函数。对文件zqxt_views/zqxt_views/urls.py进行如下所示的修改。
from django.conf.urls import url
from django.contrib import admin
from learn import views as learn_views    #新修改的
urlpatterns = [
url(r'^$', learn_views.index),        #新修改的
url(r'^admin/', admin.site.urls),
]
  (6)在终端上运行如下命令进行测试。
  python manage.py runserver
  在浏览器中输入"http://localhost:8000/add/"后的执行效果如图19-15所示。
  如果在URL中输入数字参数,例如在浏览器中输入"http://localhost:8000/add/ ?a=4&b=5",执行后会显示这两个数字(4和5)的和。执行效果如图19-16所示。
  在Python程序中,也可以采用"/add/3/4/"这样的方式对URL中的参数进行求和处理。这时需要修改文件calc/views.py的代码,在里面新定义一个求和函数add2()。具体代码如下所示。
def add2(request, a, b):
c = int(a) + int(b)
return HttpResponse(str(c))
 
  接着修改文件zqxt_views/urls.py的代码,再添加一个新的URL。具体代码如下所示。
  url(r'^add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
  此时可以看到网址中多了"\d+",正则表达式中的"\d"代表一个数字,"+"代表一个或多个前面的字符,写在一起的"\d+"就表示一个或多个数字,用括号括起来的意思是另存为一个子组(更多知识参见Python正则表达式)。每一个子组将作为一个参数,被文件views.py中的对应视图函数接收。此时,输入如下网址执行后,就可以看到同样的执行效果。
  http://localhost:8000/add/?add/4/5/
  19.3.5、使用模板
  在Django框架中,模板是一个文本,用于分离文档的表现形式和具体内容。为了方便开发者进行开发,Django框架提供了很多模板标签,具体说明如下所示。
  (1)autoescape:控制当前自动转义的行为,有on和off两个选项,例如以下代码。
{% autoescape on %}
{{ body }}
{% endautoescape %}
  (2)block:定义一个子模板可以覆盖的块。
  (3)comment:注释,例如{% comment %}和{% endcomment %}之间的内容被视为注释。
  (4)csrf_token:一个防止CSRF攻击(跨站点请求伪造)的标签。
  (5)cycle:循环给出的字符串或者变量,可以混用。例如以下代码。
{% for o in some_list %}
<tr class="{% cycle 'row1' rowvalue2 'row3' %}">
...
</tr>
{% endfor %}
  值得注意的是,这里变量的值默认不是自动转义的,要么相信变量,要么使用强制转义的方法。例如以下代码。
{% for o in some_list %}
<tr class="{% filter force_escape %}{% cycle rowvalue1 rowvalue2 %}{% endfilter %}">
...
</tr>
{% endfor %}
  在某些情况下,可能想在循环外部引用循环中的下一个值,这时需要用as给cycle标签设置一个名字,这个名字代表的是当前循环的值。但是在cycle标签里面,可以用这个变量来获得循环中的下一个值。例如以下代码。
<tr>
<td class="{% cycle 'row1' 'row2' as rowcolors %}">...</td>
<td class="{{ rowcolors }}">...</td>
</tr>
<tr>
<td class="{% cycle rowcolors %}">...</td>
<td class="{{ rowcolors }}">...</td>
</tr>
  对应的渲染结果如下所示。
<tr>
<td class="row1">...</td>
<td class="row1">...</td>
</tr>
<tr>
<td class="row2">...</td>
<td class="row2">...</td>
</tr>
  但是一旦定义了cycle标签,默认就会使用循环中的第一个值。当你仅仅想定义一个循环而不想输出循环的值时(比如在父模板定义变量以方便继承),可以用cycle的silent参数(必须保证silent是cycle的最后一个参数),并且silent也具有继承的特点。尽管下面第2行中的cycle没有silent参数,但是因为rowcolors是前面定义的且包含silent参数,所以第2个cycle也具有silent循环的特点。
  {% cycle 'row1' 'row2' as rowcolors silent %}
  {% cycle rowcolors %}
  (6)debug:输出所有的调试信息,包括当前上下文和导入的模块。
  (7)extends:表示当前模板继承了一个父模板,接受一个包含父模板名字的变量或者字符串常量。
  (8)filter:通过可用的过滤器过滤内容,过滤器之间还可以相互(调用)。例如以下代码。
  {% filter force_escape|lower %}
  This text will be HTML-escaped, and will appear in all lowercase.
  {% endfilter %}
  (9)firstof:返回列表中第一个可用(非False)的变量或者字符串,注意,firstof中的变量不是自动转义的。例如以下代码。
 {% firstof var1 var2 var3 "fallback value" %}
  (10)for:for循环,可以在后面加入reversed参数遍历逆序的列表。例如以下代码。
  {% for obj in list reversed %}
  还可以根据列表的数据来写for语句,例如下面是对于字典类型数据的for循环。
  {% for key, value in data.items %}
  {{ key }}: {{ value }}
  {% endfor %}
  另外,在for循环中还有一系列有用的变量,具体说明如表19-1所示。
  (11)for...empty:如果for循环中的参数列表为空,则执行empty里面的内容。例如下面的代码
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athlete in this list!</li>
{% endfor %}
</ul>
  (12)if:这是一个条件语句,例如下面的代码。
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}
  (13)布尔操作符:在if标签中只可以使用and、or和not三个布尔操作符,以及==、!=、<、>、<=、>=、in、not in等操作符。在if标签里面,通过这些操作符可以开发出复杂的表达式。
  (14)ifchanged:检测一个值在循环的最后有没有改变。这个标签是在循环里面使用的,有如下所示的两种用法。
  "当没有接受参数时,比较的是ifchange标签里面的内容相比以前是否有变化,当有变化时标签生效。
  "当接受一个或一个以上的参数时,如果有一个或者以上的参数发生变化,标签生效。
  在ifchanged中可以有else标签。例如下面的代码。
{% for match in matches %}
<div style="background-color:
{% ifchanged match.ballot_id %}
{% cycle "red" "blue" %}
{% else %}
grey
{% endifchanged %}
">{{ match }}</div>
{% endfor %}
  (15)ifequal:仅当两个参数相等时输出块中的内容,可以配合else输出。例如下面的代码。
{% ifequal user.username "adrian" %}
...
{% endifequal %}
  (16)ifnotequal:功能和用法与ifequal标签类似。
  (17)include:用于加载一个模板并用当前上下文(include该模板的模板的上下文)渲染它,接受一个变量或者字符串参数,也可以在include中传递一些参数进来。例如下面的代码。
  {% include "name_snippet.html" with person="Jane" greeting="Hello" %}
  如果只想接受传递的参数,不接受当前模板的上下文,可以使用only参数。例如:
  {% include "name_snippet.html" with greeting="Hi" only %}
  (18)load:加载一个自定义的模板标签集合。
  (19)now:显示当前的时间日期,接受格式化字符串的参数。例如下面的代码。
  It is {% now "jS F Y H:i" %}
  在现实中已经定义好了一些格式化字符串参数,具体如下所示:
  "DATE_FORMAT(月日年);
  "DATETIME_FORMAT(月日年时);
  "SHORT_DATE_FORMAT(月/日/年);
  "SHORT_DATETIME_FORMAT(月/日/年/时)。
  (20)regroup:通过共同的属性对一个列表的相似对象重新分组,假如存在如下一个cities列表。
cities = [
{'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
{'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
{'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
{'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
{'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
]
  如果想按照country属性来重新分组,目的是得到下面的分组结果。
  India
  Mumbai: 19,000,000
  Calcutta: 15,000,000
  USA
  New York: 20,000,000
  Chicago: 7,000,000
  Japan
  Tokyo: 33,000,000
  则可以通过如下代码实现上述要求的分组功能。
{% regroup cities by country as country_list %}
<ul>
{% for country in country_list %}
<li>{{ country.grouper }}
<ul>
{% for item in country.list %}
<li>{{ item.name }}: {{ item.population }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
  值得注意的是,regroup并不会重新排序,所以必须确保cities在regroup之前已经按country排好序。否则,将得不到预期想要的结果。如果不确定cities在regroup之前已经按country排好序,可以用dictsort进行过滤器排序。例如下面的代码
  {% regroup cities|dictsort:"country" by country as country_list %}
  (21)spaceless:移除html标签之间的空格,需要注意的是标签之间的空格,标签与内容之间的空格不会被删除。例如下面的代码
{% spaceless %}
<p>
<a href="foo/">Foo</a>
</p>
{% endspaceless %}
  运行结果如下。
  <p><a href="foo/">Foo</a></p>
  (22)ssi:在页面上输出给定文件的内容。例如下面的代码。
  {% ssi /home/html/ljworld.com/includes/right_generic.html %}
  使用参数parsed可以使得输入的内容作为一个模板,从而可以使用当前模板的上下文。例如下面的代码。
  {% ssi /home/html/ljworld.com/includes/right_generic.html parsed %}
  (23)url:返回一个绝对路径的引用(没有域名的url),接受的第一个参数是一个视图函数的名字,然后从urls配置文件里面找到那个视图函数对应的url。
  (24)widthratio:计算给定值与最大值的比率,然后把这个比率与一个常数相乘,返回最终的结果。例如下面的代码。
  <img src="bar.gif" height="10" width="{% widthratio this_value max_value 100 %}" />
  (25)with:用更简单的变量名缓存复杂的变量名,例如下面的代码。
  {% with total=business.employees.count %}
  {{ total }} employee{{ total|pluralize }}
  {% endwith %}
  下面的实例代码演示了在Django框架中使用模板的过程。
  实例19-10 在Django框架中使用模板
  源码路径 daima\19\19-10
  (1)分别创建一个名为"zqxt_tmpl"的项目和一个名称为"learn"的应用。
  (2)将"learn"应用加入到settings.INSTALLED_ APPS中。具体实现代码如下所示。
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'learn',
)
  (3)打开文件learn/views.py编写一个首页的视图。具体实现代码如下所示。
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
  (4)在learn目录下新建一个templates文件夹用于保存模板文件,然后在里面新建一个home.html文件作为模板。文件home.html的具体实现代码如下所示。
<!DOCTYPE html>
<html>
<head>
<title>欢迎光临</title>
</head>
<body>
欢迎选择浪潮产品!
</body>
</html>
  (5)为了将视图函数对应到网址,对文件zqxt_tmpl/urls.py的代码进行如下所示的修改。
from django.conf.urls import include, url
from django.contrib import admin
from learn import views as learn_views
urlpatterns = [
url(r'^$', learn_views.home, name='home'),
url(r'^admin/', admin.site.urls),
]
  (6)输入如下命令启动服务器。
  python manage.py runserver
  执行后将显示模板的内容,执行效果如图19-17所示。
  19.3.6、使用表单
  在动态 Web 应用中,表单是实现动态网页效果的核心。下面的实例代码演示了在Django框架中使用表单计算数字之和的过程。
  实例19-11 使用表单计算数字之和
  源码路径 daima\19\19-11
  (1)新建一个名为"zqxt_form2"的项目,然后进入"zqxt_form2"文件夹中,并新建一个名为"tools"的app。
django-admin startproject zqxt_form2
python manage.py startapp tools
  (2)在"tools"文件夹中新建文件forms.py。具体实现代码如下所示。
from django import forms
class AddForm(forms.Form):
a = forms.IntegerField()
b = forms.IntegerField()
  (3)编写视图文件views.py,实现两个数字的求和操作。具体实现代码如下所示。
#coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse
#引入创建的表单类
from .forms import AddForm
def index(request):
if request.method == 'POST':# 当提交表单时
form = AddForm(request.POST)
#form 包含提交的数据
if form.is_valid():# 如果提交的数据合法
a = form.cleaned_data['a']
b = form.cleaned_data['b']
return HttpResponse(str(int(a) +
int(b)))
else:# 当正常访问时
form = AddForm()
return render(request, 'index.html', {'form': form})
  (4)编写模板文件index.html,实现一个简单的表单效果。具体实现代码如下所示。
<form method='post'>
{% csrf_token %}
{{ form }}
<input type="submit" value="提交">
</form>
  (5)在文件urls.py中设置将视图函数对应到网址。具体实现代码如下所示。
from django.conf.urls import include, url
from django.contrib import admin
from tools import views as tools_views
urlpatterns = [
url(r'^$', tools_views.index, name='home'),
url(r'^admin/', admin.site.urls),
]
  在浏览器中运行后会显示一个表单效果,在表单中可以输入两个数字。执行效果如图 19-18所示。
  单击"提交"按钮后会计算这两个数字的和,并显示求和结果。执行效果如图19-19所示。
 

相关阅读:
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号