注册 登录
  • 欢迎访问"运维那点事",推荐使用Google浏览器访问,可以扫码关注本站的"微信公众号"。
  • 如果您觉得本站对你有帮助,那么可以扫码捐助以帮助本站更好地发展。

Django视图与URL

Python框架 彭东稳 142次浏览 未收录 0个评论

一、Django新建项目

安装Django之后,你现在应该已经有了可用的管理工具django-admin.py。我们可以使用django-admin.py来创建一个项目:

注意:project_name是自己的项目名称,需要为合法的Python包名,如不能为1a或a-b。

创建完成后我们可以查看下项目的目录结构:

manage.py:一个实用的命令行工具,可让你以各种方式与该Django项目进行交互。

project_name:项目的容器,此名称一旦创建后就不能更改了。

__init__.py:一个空文件,告诉Python该目录是一个Python模块。

settings.py:该Django项目的设置/配置文件,比如设置数据库,开启DEBUG,设置允许访问主机,设置入口URL,设置时区等。

urls.py:该Django项目的URL入口文件,用户访问入口,其他所有都是通过此处路由跳转过去的,通过settings文件设定的。

wsgi.py:一个WSGI兼容的Web服务器的入口,以便运行你的项目,开发者不需要关注。

接下来我们进入项目目录输入以下命令,启动Django web服务器:

其中0.0.0.0让其它电脑可连接到开发服务器,8000为端口号。如果不说明,那么端口号默认为8000。对于新版本Django,启动Django后,不能访问,报400错误。原因是服务端没有开启允许访问,编辑project_name目录下setting.py ,把其中的ALLOWED_HOSTS=[]改成ALLOWED_HOSTS=[‘*’],表示任意地址。在浏览器输入你服务器的IP及端口号,如果正常启动,在浏览器访问地址会出现“It worked!”就表示成功了。

Django内置的webserver,仅仅用于开发测试,当我们更改配置文件后,内置webserver会自动reload,方便开发。线上使用还是需要用nginx这种高性能web服务器。

二、视图与URL配置

了解完创建一个项目之后,来写一个Hello World项目返回。我们先直接在项目下的urls.py文件中写views跟urls,先不分开写了,虽然在Django把views、urls、models、templates都分别分开来写,其实我们知道这些东西再Django里面都是函数、对象等,其实都写到一个文件里面也是可以的。但是真正写项目时应遵循规范,这样写的代码别人也能马上看得懂,容易协作。

重点分析:

  • HttpResponse模块,它是用来向网页返回内容的,就像Python中的print一样,只不过HttpResponse是把内容显示到网页上。
  • 函数的第一个参数必须是request,与网页发来的请求有关,request变量里面包含get或post的内容,用户浏览器,系统等信息在里面(后面会讲,先了解一下就可以)。
  • urlpatterns是一个url列表,变量名是固定的,不可更改,Django会匹配这个变量来找URL。可以去settings文件看到ROOT_URLCONF参数,已经标明了入口URL是那个。
  • url(regex, view, **kwargs, name)可以接收四个参数,分别是两个必选参数:regex、view;以及两个可选参数:kwargs、name,接下来详细介绍这四个参数。regex:正则表达式,与之匹配的URL会执行对应的第二个参数view。view:用于执行与正则表达式匹配的URL请求,注意这里是一个对象而不是执行函数。kwargs:视图使用的字典类型的参数。name:用来定义URL别名的,可以通过这个别名反解析URL。
  • regex匹配时的前后/号,比如“r^hello/$”不能写成“r^/hello/$”这样的,前面的/必须不能写,不然会报错,因为Django默认已经帮我们带有。而后面的/就有点逻辑了,带上/时,如果我们访问“http://url/hello/”可以正常访问,但如果访问“http://url/hello”会自动跳转到“http://url/hello/”进行访问,这是Django帮我们做的。如果不带/时,我们访问“http://url/hello/”就会报错,而访问“http://url/hello”正常。一般都带上即可。

三、Django创建应用

  • 新建App

要先进入项目目录下,cd project_name然后执行下面的命令。

一般一个项目有多个app,当然通用的app也可以在多个项目中使用。与项目名类似app name也需要为合法的Python包名,如blog,news, aboutus等都是合法的 app名称。

__init__.py:用于说明app_name目录是一个python模块。

admin.py:新建App时会自动创建admin,当需要使用后台来管理这个App时就可以在这个文件中设置。

apps.py:这个模块是新版本才添加的,就是一个App的配置文件,里面内容不多。

migrations:这个模块是新版才添加的,用来做数据库迁移的,当我们使用ORM创建了表结构之后,就会应用到数据库的,但是当我们对表结构做变更之后,在Django1.6之前是没法再次应用的。有了这个模块之后,当我们对表结构做更改之后,执行几个命令就可以把新的结构应用到数据库,老数据不会丢失。

models.py:包含一系列的模型类,每个模型类对应数据库中的一个表,这之间的映射由Django来做,有关数据库的配置在project_name/settings.py中,另外只有App才能使用model,而项目不行。

tests.py:可以用来写单元测试使用。

views.py:包含的是对各个请求的处理逻辑,前面说的URL Dispacher即将URL请求映射到这个文件中的函数或类方法上。同时可以在polls目录下创建template目录,然后将前台的html,css,script等内容放置在这个目录下,并在setttings.py文件添加相应的配置信息。所以,我们其实可以看到App相当于一个相对独立的功能模块,其遵循的设计理念是MVT(类似MVC);在一个大型的项目中,可以包含很多App,而且每个App可以在不同的项目中复用,这也符合Django的编程理念,即:不要做重复的事情。

综上所述,Project和App的区别已经很明显了,Project包含一些全局配置,这些配置构成一个全局的运行平台,各个App都运行在这个全局的运行平台上,而App代表的是一个相对独立的功能模块,所以程序的逻辑都在App中。一个Project一般包含多个App,一个App也可以用在多个Project中。

App的设计是可插拔的,其不一定非得在Project目录下,但是需要在settings文件中设置好,如下:

上面的admin、auth、sessions等应用都是内置定义好的,如果有新的应用只需要添加即可。

  • 配置Project导入App

官方推荐写“polls.apps.PollsConfig”这种格式,直接写“polls”也是可以的。

  • 编写App View

前面我们写了一个Hello world项目,是在Project下面编写的,并且都写在了urls.py文件中。下面我们就按照Django规范写法,把各个模块都分开写,业务逻辑都应该在App中views.py中实现(注意把urls.py文件还原)。

  • 编写URL

在App中把view写好之后,就可以回到Project中编写url了。

然后可以使用curl访问了,结果如下:

但是这样有一个缺点,就是当App多了的时候,Project里面的配置就会让你眼花缭乱,并且如果不同项目有同名函数,在import时可能都需要使用as关键字做个别名才可以运行。对于这个问题Django也给出了处理办法,就是各自App的url自行处理,然后只需要使用include包含进Project的urls.py文件即可。这样,Project只管项目配置,不管App。

此时,更改Project的urls.py文件,如下:

然后,我们需要在App目录下创建urls.py文件,如下:

需要注意的一点是,经过Project匹配之后的URL转到App中之后,App中的url正则写成“^$”了,而不是“^polls/$”,因为App的url匹配的是Project中匹配到的路径之后的。比如你访问路径是“http://URL/polls/new”,那么经过Project的“^polls/”匹配之后,到App后只能去匹配“new”了,而不是“/polls/new”。一定不要搞混这里,这也是Django的设计理念,就是在Project层已经匹配过了,再到App层如果匹配同样的路径也没有意义。

四、视图与URL进阶

上面已经简单演示了视图与URL相关操作,但都是静态的。下面再学习一下带参数的视图与URL,在网页上做加减法。

首先采用 /polls/?a=100&b=200这样的GET方法进行加法操作,各个文件配置如下:

注:request.GET获取到的是一个QueryDict,类似于一个字典,更好的办法是用request.GET.get(‘a’, 0) ,当a不存在时给一个默认值0。这里我们打印出了GET获取到的类字典,后面可以看到。

都修改完成后,可以选择重启webserver,正常运行的情况下,就可以访问了。

如果直接访问: http://10.10.0.109:8000/polls/ ,就会出现MultiValueDictKeyError错误。这是因为我们并没有传值进去,我们在后面加上 ?a=100&b=200 ,即访问 http://10.10.0.109:8000/polls/?a=100&b=200

Django视图与URL

网页显示就是a+b的结果,对于a和b可以随意改变其值。其实request对象传递进来的,因为我们是GET请求,所以通过request.GET方法获取到了一个类字典。类型如下:

所以我们使用GET对象request.GET[‘a’]直接可以获取到值,但最好使用request.GET.get(‘a’, 0)标准方式,通过GET对象的get方法获取列表中的第一个值。关于request对象可以看Django写一个简单投票系统

另外,也可以采用 /polls/100/200/这样的URL方式,前面介绍的时候就说过Django支持优雅的URL。接着修改文件,再新定义一个add1函数:

我们可以看到url函数中多了“(\d+)”,正则表达式中“\d”代表一个数字,“+”代表一个或多个前面的字符,写在一起“\d+”就是一个或多个数字,用括号括起来的意思是保存为一个子组(更多知识请参见Python正则表达式),每一个子组将作为一个参数,被views.py中的对应视图函数接收。多个数字使用“([0-9]+)”表示也一样。

另外需要说明一点的是,Django从URL中捕获到的参数永远是string类型的,不管你输入的是数值还是字符。所以如果需要其它类型,需要自己接收时转换,比如上面我们把接收到的参数转换为int类型。

我们再访问 http://10.10.0.109:8000/polls/100/200/就可以看到和刚才同样的效果,但是这回网址更优雅了。

Django视图与URL

五、URL反解析

在上面的urls.py文件中我们使用到了url函数的name参数,如下:

这里的name=’plus’是用来干什么的呢?

简单说,name可以用于在templates, models, views ……中得到对应的网址,相当于“给网址取了个名字”,只要这个名字不变,网址变了也能通过名字获取到。我们称之为“URL反解析”。

比如我们在开发的时候,刚开始想用的是 /polls/100/200/ ,后台发现这样不好,比如我们又想改成 /plus/100/200/这样的形式,但是我们在网页中,代码中很多地方都写的是 /polls/100/200/这样的形式,这样就导致我们在每个地方都要改,修改网址的代价很大。

有没有更优雅的方式来解决这个问题呢?当然答案是肯定的。我们先说一下如何用Python代码获取对应的网址:

reverse函数接收url中的name值作为第一个参数,后面可以通过args=(参数1,参数2)来传入参数,拼装成一个URL。我们在代码中就可以通过reverse()来获取对应的网址(这个网址可以用来跳转,也可以用来计算相关页面的地址),只要对应的url的name不改,就不用改代码中的网址。

在Django模板中使用也是一样,可以很方便的使用:

不带参数的:{% url ‘name’ %}

带参数的,参数可以是变量名:{% url ‘name’ 参数 %}

例如:<a href=”{% url ‘plus’ 100 200 %}”>link</a>,这样就可以通过{% url ‘plus’ 100 200 %} 获取到对应的网址/plus/100/200/。

开始可能觉得直接写网址简单,但是用多了你一定会发现,用“死网址”的方法很糟糕。

六、URL命名空间

知道了URL反解析之后,又可以考虑另外一个问题了,那就是如果多个App使用同样的一个name值怎么办呢?此时反解析时就不知道找哪个name。所以Django又为我们设计了URL命名空间的概念。

对于URL命名空间有两种级别,一种是App级别的命名空间,一种是Instance级别的命名空间。这里就简单说一下App级别的命名空间,处理方法也很简单,在urls.py文件中定义一个变量即可:

或者写成下面这种形式:

那么在使用反解析时就得带上命名空间了,不然就会报错的:

同理,在模板中也得改,所以最好一开始都定义好App namespace,免得日后需要更改。

对于instance namespace一般用的不多,只有在你的App有多个include时则使用instance namespace(在urls中同一个App默认只能由一个include)。设置方法如下:

完结。。。


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (0)or分享 (0)
关于作者:

您必须 登录 才能发表评论!