目录html
路由与视图函数对应关系 >>> 路由层前端
URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表。python
你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。nginx
基本格式:git
from django.conf.urls import url urlpatterns = [ url(正则表达式, views视图函数,参数,别名), ]
注意:正则表达式
Django 2.0版本中的路由系统已经替换成下面的写法(官方文档):django
from django.urls import path urlpatterns = [ path('articles/2003/', views.special_case_2003), path('articles/<int:year>/', views.year_archive), path('articles/<int:year>/<int:month>/', views.month_archive), path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail), ]
举例:后端
from django.conf.urls import url from django.contrib import admin from app02 import views urlpatterns = [ url(r'^book_list/', views.book_list), url(r'test', views.test), url(r'test_add', views.test_add), ]
参数说明浏览器
注意服务器
^articles
而不是 ^/articles
。示例:
''' 一些请求的例子: /articles/2005/03/ 请求将匹配列表中的第三个模式。Django 将调用函数views.month_archive(request, '2005', '03')。 /articles/2005/3/ 不匹配任何URL 模式,由于列表中的第三个模式要求月份应该是两个数字。 /articles/2003/ 将匹配列表中的第一个模式不是第二个,由于模式按顺序匹配,第一个会首先测试是否匹配。请像这样自由插入一些特殊的状况来探测匹配的次序。 /articles/2003 不匹配任何一个模式,由于每一个模式要求URL 以一个反斜线结尾。 /articles/2003/03/03/ 将匹配最后一个模式。Django 将调用函数views.article_detail(request, '2003', '03', '03')。 '''
APPEND_SLASH:是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项 APPEND_SLASH=True
Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其做用就是自动在网址结尾加'/'。
其效果就是:
咱们定义了urls.py:
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^blog/$', views.blog), ]
访问 http://www.example.com/blog 时,默认将网址自动转换为 http://www.example/com/blog/ 。
若是在settings.py中设置了 APPEND_SLASH=False,此时咱们再请求 http://www.example.com/blog 时就会提示找不到页面。
分组:给某一段正则表达式加括号
在使用Django 项目时,一个常见的需求是得到URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。
人们强烈但愿不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 绝不相关的专门的URL 生成机制,由于这样容易致使必定程度上产生过时的URL。
换句话讲,须要的是一个DRY 机制。除了其它有点,它还容许设计的URL 能够自动更新而不用遍历项目的源代码来搜索并替换过时的URL。
获取一个URL 最开始想到的信息是处理它视图的标识(例如名字),查找正确的URL 的其它必要的信息有视图参数的类型(位置参数、关键字参数)和值。
Django 提供一个办法是让URL 映射是URL 设计惟一的地方。你填充你的URLconf,而后能够双向使用它:
第一种方式是咱们在前面的章节中一直讨论的用法。第二种方式叫作反向解析URL、反向URL 匹配、反向URL 查询或者简单的URL 反查。
在须要URL 的地方,对于不一样层级,Django 提供不一样的工具用于URL 反查:
上面说了一大堆,你可能并无看懂。(那是官方文档的生硬翻译)。
我们简单来讲就是能够给咱们的URL匹配规则起个名字,一个URL匹配模式起一个名字。
这样咱们之后就不须要写死URL代码了,只须要经过名字来调用当前的URL。
举个简单的例子:
url(r'^home', views.home, name='home'), # 给个人url匹配模式起名为 home url(r'^index/(\d*)', views.index, name='index'), # 给个人url匹配模式起名为index
这样:
在模板里面能够这样引用:
{% url 'home' %}
在views函数中能够这样引用:
from django.urls import reverse reverse("index", args=("2018", ))
例子:
考虑下面的URLconf:
from django.conf.urls import url from . import views urlpatterns = [ # ... url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'), # ... ]
根据这里的设计,某一年nnnn对应的归档的URL是/articles/nnnn/
。
你能够在模板的代码中使用下面的方法得到它们:
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a> <ul> {% for yearvar in year_list %} <li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li> {% endfor %} </ul>
在Python 代码中,这样使用:
from django.urls import reverse from django.shortcuts import redirect def redirect_to_year(request): # ... year = 2006 # ... return redirect(reverse('news-year-archive', args=(year,)))
若是出于某种缘由决定按年归档文章发布的URL应该调整一下,那么你将只须要修改URLconf 中的内容。
在某些场景中,一个视图是通用的,因此在URL 和视图之间存在多对一的关系。对于这些状况,当反查URL 时,只有视图的名字还不够。
注意:
为了完成上面例子中的URL 反查,你将须要使用命名的URL 模式。URL 的名称使用的字符串能够包含任何你喜欢的字符。不仅限制在合法的Python 名称。
当命名你的URL 模式时,请确保使用的名称不会与其它应用中名称冲突。若是你的URL 模式叫作comment
,而另一个应用中也有一个一样的名称,当你在模板中使用这个名称的时候不能保证将插入哪一个URL。
在URL 名称中加上一个前缀,好比应用的名称,将减小冲突的可能。咱们建议使用myapp-comment
而不是comment
。
urlpatterns = [ url(r'^test/(\d+)', views.test), ]
会将括号内匹配到的内容当作 位置参数 传递给后面的视图函数
def test(request,args): print(args) return HttpResponse('test')
urlpatterns = [ url(r'^test/(?P<year>\d+)', views.test), ]
会将括号内匹配到的内容当作 关键字参数 传递给后面的视图函数
方式1 # def test(request,**kwargs): # print(kwargs) # return HttpResponse('test') 方式2 def test(request,year): print(year,1) return HttpResponse('test')
url(r'^test/(\d+)/(\d+)/', views.test), url(r'^test/(?P<xxx>\d+)/(?P<month>\d+)/', views.test),
在使用Django 项目时,一个常见的需求是得到URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。人们强烈但愿不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 绝不相关的专门的URL 生成机制,由于这样容易致使必定程度上产生过时的URL。
在须要URL 的地方,对于不一样层级,Django 提供不一样的工具用于URL 反查:
from django.urls import reverse()函数
根据某一个东西 动态解析出一个结果 该结果能够直接访问对应的url
url(r'^test_add/', views.testadd,name='xxx') 前端解析 {% url 'xxx' %} 后端解析 from django.shortcuts import render,HttpResponse,redirect,reverse url = reverse('xxx')
url(r'^test_addsajdsjkahdkjasjkdh/(\d+)/', views.testadd,name='xxx'),
前端解析 <a href="{% url 'xxx' 1 %}">222</a> 后端解析 url = reverse('xxx',args=(1,))
url(r'^test_addsajdsjkahdkjasjkdh/(?P<year>\d+)/', views.testadd,name='xxx')
前端解析 <a href="{% url 'xxx' 1 %}">222</a> <a href="{% url 'xxx' year=1 %}">222</a> 后端解析 url = reverse('xxx',args=(1,)) url = reverse('xxx',kwargs={'year':123})
注意 反向解析的别名 必定不要重复
django里面的app能够有本身的static文件,templates文件夹,urls.py(******) 项目名下面的urls.py再也不作路由与视图函数对应关系 而是作一个中转站 只负责将请求分发到不一样的app中 而后在app的urls.py完成路由与视图函数的对应关系 from django.conf.urls import url,include url(r'^app01/',include(app01_urls)), url(r'^app02/',include(app02_urls))
命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不一样命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,由于已有的定义都处于其它命名空间中。
因为name没有做用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,当即返回
咱们在开发项目时,会常用name属性反解出URL,当不当心在不一样的app的urls中定义相同的name时,可能会致使URL反解错误,为了不这种事情发生,引入了命名空间。
解决各个app之间命名的重复 ,django是分不清楚。
总路由
url(r'^app01/',include('app01.urls',namespace='app01'))
url(r'^app02/',include('app02.urls',namespace='app02'))
print(reverse('app01:index')) print(reverse('app02:index'))
一般状况下 起别名的时候 前面能够加上你的应用名
建立一个app02:python manage.py startapp app02
总urls.py
from django.urls import path,re_path,include urlpatterns = [ path('app01/', include('app01.urls')), path('app02/', include('app02.urls')) ]
app01 的urls.py
from django.urls import path,re_path from app01 import views urlpatterns = [ re_path(r'index/',views.index,name='index'), ]
app02 的urls.py
from django.urls import path, re_path, include from app02 import views urlpatterns = [ re_path(r'index/', views.index,name='index'), ]
app01的视图函数
def index(request): url=reverse('index') print(url) return HttpResponse('index app01')
app02的视图函数
def index(request): url=reverse('index') print(url) return HttpResponse('index app02')
这样都找index,app01和app02找到的都是app02的index
如何处理?在路由分发的时候指定名称空间
总urls.py在路由分发时,指定名称空间
path('app01/', include(('app01.urls','app01'))), path('app02/', include(('app02.urls','app02'))) url(r'app01/',include('app01.urls',namespace='app01')), url(r'app02/',include('app02.urls',namespace='app02')) url(r'app01/',include(('app01.urls','app01'))), url(r'app02/',include(('app02.urls','app02')))
在视图函数反向解析的时候,指定是那个名称空间下的
url=reverse('app02:index') print(url) url2=reverse('app01:index') print(url2)
在模版里:
<a href="{% url 'app02:index'%}">哈哈</a>
一般针对不一样的项目 只会安装该项目所用的模块 用不到的一律不装
虚拟环境
不一样的项目应该有各自独立的解释器环境 最大化节省资源
实际功能中针对不一样的项目 会有一个叫requestsments.txt文件
该文件中列出来是一个个该项目须要用的到模块名和版本号
eg:
django = 1.11.11
nginx = 1.21
后期经过命令直接会去下载该文件内全部的模块及对应版本
不一样的项目有专门的解释器环境与之对应
每建立一个虚拟环境 就相似于从新下载了一个纯净的python解释器
虚拟环境不要建立太多个
建议 你的机器上不要有态多的虚拟环境
当前咱们这个阶段 建议你全部的模块所有都安装在本机环境中
虚拟环境的后期用法(了解)
python中经过requirements.txt来记录项目全部的依赖包及其版本号,以便在其余的环境中部署
(venv) $ pip freeze >requirements.txt
若是在开发的时候升级了依赖包,记得更新此文件!
在其余环境部署项目以前先经过以下命令安装依赖包,也就是当须要建立这个虚拟环境的彻底副本,能够建立一个新的虚拟环境,并在其上运行如下命令:
(venv) $ pip install -r requirements.txt
pip的freeze命令保存了保存当前Python环境下全部类库包,其它包括那些你没有在当前项目中使用的类库。 (若是你没有的virtualenv)。
pip的freeze命令只保存与安装在您的环境python全部软件包。
但有时你只想将当前项目使用的类库导出生成为 requirements.txt;
使用方法:
$ pip install pipreqs $ pipreqs /path/to/project
django1.x
django2.x
区别1: urls.py中1.x用的是url,而2.x用的是path 而且2.x中的path第一个不支持正则表达式,写什么就匹配什么 若是你以为很差用,2.x里面还有re_path 这个re_path就是你1.x里面的url
django2.0的re_path和1.0的url同样
思考状况以下:
urlpatterns = [ re_path('articles/(?P<year>[0-9]{4})/', year_archive), re_path('article/(?P<article_id>[a-zA-Z0-9]+)/detail/', detail_view), re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/edit/', edit_view), re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/delete/', delete_view), ]
考虑下这样的两个问题:
第一个问题,函数 year_archive
中year参数是字符串类型的,所以须要先转化为整数类型的变量值,固然year=int(year)
不会有诸如如TypeError或者ValueError的异常。那么有没有一种方法,在url中,使得这一转化步骤能够由Django自动完成?
第二个问题,三个路由中article_id都是一样的正则表达式,可是你须要写三遍,当以后article_id规则改变后,须要同时修改三处代码,那么有没有一种方法,只需修改一处便可?
在Django2.0中,可使用 path
解决以上的两个问题。
这是一个简单的例子:
from django.urls import path from . import views urlpatterns = [ path('articles/2003/', views.special_case_2003), path('articles/<int:year>/', views.year_archive), path('articles/<int:year>/<int:month>/', views.month_archive), path('articles/<int:year>/<int:month>/<slug>/', views.article_detail), # path才支持,re_path不支持 path('order/<int:year>',views.order), ]
基本规则:
<>
)从url中捕获值。<int:name>
捕获一个整数变量。若果没有转化器,将匹配任何字符串,固然也包括了 /
字符。如下是根据 2.0官方文档 而整理的示例分析表:(跟上面url的匹配关系)
文档原文是Path converters,暂且翻译为转化器。
Django默认支持如下5个转化器:
/
)以外的非空字符串,这是默认的形式对于一些复杂或者复用的须要,能够定义本身的转化器。转化器是一个类或接口,它的要求有三点:
regex
类属性,字符串类型to_python(self, value)
方法,value是由类属性 regex
所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。to_url(self, value)
方法,和 to_python
相反,value是一个具体的Python变量值,返回其字符串,一般用于url反向引用。例子:
class FourDigitYearConverter: regex = '[0-9]{4}' def to_python(self, value): return int(value) def to_url(self, value): return '%04d' % value
使用register_converter
将其注册到URL配置中:
from django.urls import register_converter, path from . import converters, views register_converter(converters.FourDigitYearConverter, 'yyyy') urlpatterns = [ path('articles/2003/', views.special_case_2003), path('articles/<yyyy:year>/', views.year_archive), ... ]