转载请注明来源地址和原做者(CFishHome)正则表达式
上一节的学前准备工做和第一个小牛试刀的Django项目学习,让咱们对Django开发愈来愈感兴趣了。正所谓趁热打铁,让咱们继续来学习网站开发必备的视图函数和URL映射等知识,跟着步伐一块儿学习,我相信你会收获不少。噔~噔,新闻播报时间:9月12-9月16有两个超强台风在广东湛江登录,沿途影响众多城市,包括深圳!!因此很遗憾,前几天打算和舍友去深圳游玩的计划泡汤了,也只能推迟几天前往深圳度中秋、看月亮了~算法
不管是使用命令行仍是Pycharm建立Django项目工程,settings.py文件的DEBUG都默认设置为True,因此默认是开启了DEBUG模式。以下图所示:
开启DEBUG模式有如下好处:
1.咱们能够发现,在Django开发时,频繁修改文件代码,而后要关闭项目,再重启项目才能测试咱们修改的代码。可是若是开启了DEBUG模式,那么之后咱们修改了Django项目的代码,而后按下了ctrl+s,那么Django就会自动的给咱们重启项目,不须要手动关闭再重启。
2.若是开启了DEBUG模式,那么之后Django项目中的代码出现bug了,那么在浏览器和控制台会打印出错信息。
3.在实际将项目发布到网上给其余用户使用时,禁止开启DEBUG模式,由于前面说了入宫出现bug会在浏览器和控制台打印出错信息,这无疑把代码泄露在网上,会有很大的安全隐患。
4.若是DEBUG设置为False,那么必须设置ALLOWED_HOSTS。前一篇说过,若是将host设置为0.0.0.0,那么只能经过ALLOWED_HOSTS设置的IP地址进行访问该项目,也能够设置多个IP地址。ALLOWED_HOSTS字段以下图位置:数据库
咱们在学习前先回顾下咱们上一篇作了什么。上一篇咱们首先在Pycharm建立了一个名为first_project的Django项目,而后在CMD使用命令建立了一个名为my_app的app应用。注意,上篇因测试须要修改了IP地址和端口号,因此这里我将项目的IP地址和端口号修改回127.0.0.1:8000,说明访问这个IP就能够访问咱们的项目了。总体框架以下图所示:django
视图其实就是视图函数,它通常都写在 app 的 views.py 文件中,也就是咱们my_app包里的views.py文件。而且视图函数的第一个参数永远都是 request (一个HttpRequest)对象。这个对象存储了请求过来的全部信息,包括携带的参数以及一些头部信息等。在视图中,通常是完成逻辑相关的操做。好比这个请求是添加一篇博客,那么在视图函数能够经过request来接收到这些数据,而后存储到数据库中,最后再把函数执行的结果返回给浏览器。视图函数的返回结果必须是 HttpResponseBase 对象或者子类的对象。
咱们打开my_app的views.py文件,添加如下代码:编程
from django.http import HttpResponse # book_list是咱们定义的一个视图函数,第一个参数必须是request对象,而且该函数返回必须是 HttpResponseBase 对象或者子类的对象。 def book_list(request): return HttpResponse("书籍列表!")
上面视图函数返回的 HttpResponse("书籍列表!")只是单纯的在网页上输出"书籍列表!"文本内容。浏览器
视图函数写完后,咱们怎么实现让用户在浏览器中输入一个URL就能够访问到咱们刚才写的视图函数,即用户在浏览器一输入某URL,网页就显示"书籍列表!"文本内容。安全
URL映射原理:用户在浏览器输入了某个 URL ,请求到咱们的网站的时候, django 会从项目的 urls.py 文件中寻找对应的视图。为何会是在urls.py文件中寻找映射呢?这是由于在"settings.py"文件中配置了"ROT_URLCONF"为"urls.py"。在 urls.py 文件中有一个 urlpatterns 变量,之后 django 就会从这个变量中读取全部的匹配规则。匹配规则须要使用 django.urls.path 函数进行包裹,这个函数会根据传入的参数返回 URLPattern 或者是 URLResolver 的对象。app
修改first_project项目的 urls.py 文件代码,示例代码以下:框架
from django.contrib import admin from django.urls import path from my_app import views # 导入my_app包的views.py模块 urlpatterns = [ path('admin/', admin.site.urls), path('book/', views.book_list) ]
运行first_project项目,在浏览器输入127.0.0.1:8000/book,访问成功!以下图所示(图片左下角显示了"书籍列表!"文本内容):
到了这里朋友们可能会好奇若是输入127.0.0.1:8000会怎么样?知足你的好奇心,结果以下:
个人天!我按照上一篇的流程能够访问的啊,怎么如今不彳亍了。其实当新添加了第一个URL映射以后须要注意的是主网页127.0.0.1:8000的网页404丢失了,这是由于若是刚开始建立的项目,若还未添加过URL映射,那么默认Django的底层提供一个就是那个火箭??页面来映射,但若添加了,那么就没法继续映射那个火箭??页面了,由于看urlpatterns变量其实都没有映射空URL,即127.0.0.1:8000为空URL。编程语言
为URL传递参数有三种方式:
1.URL中添加参数
2.查询字符串传递参数
3.指定默认的参数
有时候, url 中包含了一些参数须要动态调整。好比简书某篇文章的详情页的url,是 https://www.jianshu.com/p/a5aab9c4978e 后面的 a5aab9c4978e 就是这篇文章的 id ,那么简书的文章详情页面的url就能够写成 https://www.jianshu.com/p/<id>; ,其中id就是文章的id。那么如何在 django 中实现这种需求呢。这时候咱们能够在 path 函数中,使用尖括号的形式来定义一个参数,也能够多个参数。好比我如今想要获取一本书籍的详细信息,那么应该在 url 中指定这个参数。first_project项目urls.py文件的示例代码以下:
from django.contrib import admin from django.urls import path from book import views urlpatterns = [ path('admin/', admin.site.urls), path('book/',views.book_list), path('book/<book_id>/',views.book_detail) # <book_id>就是参数 ]
采用在URL中使用变量的方式,在path函数的第一个参数中,使用“<参数名>”的方式能够传递参数,而后在视图函数中也要写一个函数来进行映射,视图函数中的参数必须和URL中的参数名称保持一致,否则就找不到这个参数(视图函数第一个参数是request,那么第二个参数就是book_id)。
而my_app包的views.py 中的代码以下:
# 该视图函数与'book/<book_id>/'进行URL映射,而且视图函数第二个参数必须同名 def book_detail(request,book_id): text = "您输入的书籍的id是:%s" % book_id return HttpResponse(text)
运行结果以下:
对于多个参数也一样相似,这里再也不测试。只不过在URL中添加多个参数,而后视图函数添加多个同名参数来接收。
另外一种方式是经过查询字符串的方式传递一个参数过去。在设置URL时,不须要单独的匹配查询字符串的部分,只须要在视图函数中使用request.GET.get('参数名称')的方式来获取。由于查询字符串使用的是“GET”请求,因此咱们经过“request.GET”来获取参数。
first_project项目的urls.py文件的示例代码以下:
urlpatterns = [ path('admin/', admin.site.urls), path('book/',views.book_list), path('book/<int:book_id>/',views.book_detail), # <book_id>就是参数,注意book_id前面还添加了个int转换器,这里只要咱们知道这是限制输入的id只能是整型便可,后面会详细讲解转换器的做用。 path('book/pub/',views.book_pub) ]
在 my_app包中的views.py 后面添加以下代码:
def book_pub(request): pub_id = request.GET.get("id") text = "您输入的出版社id是:%s" % pub_id return HttpResponse(text)
之后在浏览器输入127.0.0.1:8000/book/pub/?id=1 便可将参数传递过去。
运行结果以下:
咱们作个小测试,若是将转换器Int去掉的话,咱们还能成功访问到嘛?将urls.py文件代码修改以下:
urlpatterns = [ path('admin/', admin.site.urls), path('book/',views.book_list), path('book/<book_id>/',views.book_detail), path('book/pub/',views.book_pub) ]
运行结果以下:
经过上图能够发现,跟咱们预期的不太同样,咱们在浏览器输入的URL(http://127.0.0.1:8000/book/pub/?id=200) 被book_detail视图函数捕获了,这说明pub后面的全部字符串都被认为是传递到book_detail视图函数。
使用 path 后,在path的第一个参数能够包含参数,而有时候想指定默认的参数,这时候能够经过如下方式来完成,如下代码仅供理解默认参数的使用,在咱们的实际项目中没有此代码。
from django.urls import path from . import views urlpatterns = [ path('blog/', views.page), path('blog/page<int:num>/', views.page), ] # View (in blog/views.py) def page(request, num=1): # Output the appropriate page of blog entries, according to num.
上面'blog/page<int:num>/',参数前面多了个page,表明输入URL时须要添加page,例如:’127.0.0.1:8000/blog/page100‘。所欲,若是你只写’127.0.0.1:8000/blog/page',那么将使用默认参数,num值为1。
默认参数的使用规则以下:
1.当用户访问一个URL不含有变量的时候,映射到视图函数
而且视图函数的形参有一个默认参数含有值,视图函数就直
接使用这个默认参数。
2.当用户访问一个URL含有变量的时候,映射到视图函数并
且视图函数的形参有一个默认参数含有值,视图函数就不使
用默认参数的值,而是采用URL匹配规则传进来的值。
总结:其实上面的默认函数使用规则和编程语言函数的默认
参数使用规则相似。
前一节咱们简单使用了int转换器将同级的两种传递参数的方式区分开来,否则查询字符串方式会被第一种传递参数方式所捕获。
咱们的转换器是用在path函数中,因此有必要简单介绍下path函数,这里只简单介绍第一个参数,下一篇文章会详细讲path函数的使用方法。
path函数签名以下:
path(route,view,name=None,kwargs=None)
route 参数: url 的匹配规则。这个参数中能够指定 url 中须要传递的参数,好比在访问文章详情页的时候,能够传递一个 id 。传递参数是经过 <> 尖括号来进行指定的。而且在传递参数的时候,能够指定这个参数的数据类型,好比文章的 id 都是 int 类型,那么能够这样写 <int:id> ,之后匹配的时候,就只会匹配到 id 为 int 类型的 url ,而不会匹配其余的 url ,而且在视图函数中获取这个参数的时候,就已经被转换成一个 int 类型了。
其中还有几种经常使用的转换器类型:
1.str:非空的字符串类型。默认的转换器。可是不能包含斜杠。
2.int:匹配任意的零或者正数的×××。到视图函数中就是一个int类型。
3.slug:由英文中的横杠 - ,或者下划线 _ 链接英文字符或者数字而成的字符串。
4.uuid:匹配 uuid 字符串。
5.path:匹配非空的英文字符串,能够包含斜杠。
Tips:经过from django.urls import converters能够导入定义转换器的模块。
下面重点介绍int、str、uuid转换器,而slug和path转换器再也不解释。
str转换器是默认的转换器,表明若是在参数前面不添加任何东西,那么将默认采用str转换器。
在converters模块中对str转换器的定义以下图:
其实说白了也就是一个类,而后定义了一个正则表达式,对传递的参数进行正则匹配。
在converters模块中对int转换器的定义以下图:
从类的定义中能够看出,它是匹配一个0-9的任意一个或多个以上的数字。
UUID 是 通用惟一识别码(Universally Unique Identifier)的缩写,每一个人均可以建立不与其它人冲突的UUID。在这样的状况下,就不需考虑数据库建立时的名称重复问题。目前最普遍应用的UUID,是微软公司的全局惟一标识符(GUID)。全局惟一标识符(GUID,Globally Unique Identifier)是一种由算法生成的二进制长度为128位的数字标识符。GUID的总数达到32^128个,因此随机生成两个相同GUID的可能性极小,但并不为0。GUID的格式为:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",其中每一个 x 是 0-9 或 a-f 范围内的一个4位十六进制数,因此每一个x表明4个二进制位,因此4*32=128个二进制位,即GUID的总数达到32^128个。例如:6F9619FF-8B86-D011-B42D-00C04FC964FF 即为有效的 GUID 值。
在converters模块中对uuidt转换器的定义以下图:
在咱们的项目中,不可能只有一个 app ,若是把全部的 app 的 views 中的视图都放在 first_project项目的urls.py 中进行映射,确定会让代码显得很是乱。
就像咱们目前的项目同样显得十分混乱,多个book的视图映射都放在一块儿,以下图:
所以 django 给咱们提供了一个方法,能够在 app 内部包含本身的 url 匹配规则,而在项目的 urls.py 中再统一包含这个 app 的 urls 。使用这个技术须要借助 include 函数,对include函数的使用下一篇会有详细讲解,这里只要知道它的做用便可。
好,如今my_app包里添加一个urls.py文件,代码修改以下:
from django.urls import path from my_app import views from django.urls import converters urlpatterns = [ path('', views.book_list), path('<int:book_id>/', views.book_detail), # <book_id>就是参数 path('pub/', views.book_pub) ]
而后将first_project项目的urls.py代码修改以下:
from django.contrib import admin from django.urls import path,include from my_app import views from django.urls import converters urlpatterns = [ path('admin/', admin.site.urls), path('book/', include("my_app.urls")) ]
从上面两个文件代码的修改咱们能够这样理解:如今first_project项目的urls.py文件,将’book/‘本来的映射交给了my_app包里的urls.py文件进行内部映射。其实这两个文件之间的映射关系就至关于字符串的拼接,例如:'book/'拼接my_app的urls.py文件的'pub/'组合成’book/pub/‘,而后再映射到book_pub视图函数。
运行结果以下,彻底没有问题,跟分离前如出一辙: