url route distribution of learning

Video explain Continued

Configure a URL

Django 1.11 version URLConf official documents

  URL configuration (URLconf) as the Django directory site support. Its essence is a mapping table between the URL and the URL you want to call that view function. You're in such a way to tell Django, call the code for this URL, call that code for that URL.

The basic format  

from django.conf.urls import url

#循环urlpatterns,找到对应的函数执行,匹配上一个路径就找到对应的函数执行,就不再往下循环了,并给函数传一个参数request,和wsgiref的environ类似,就是请求信息的所有内容
urlpatterns = [
     url(正则表达式, views视图函数,参数,别名),
]

  note:

  Django version 2.0 of the routing system has been replaced with the following wording, but django2.0 is backward compatible with version 1.x syntax ( official documents ):

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),
]

Parameter Description 

  • Regular Expressions: A regular expression string
  • views view function: a callable object, typically a string path view function is designated as a view or function
  • Parameters: The optional parameters to be passed to the default view function (a dictionary)
  • Alias: An optional parameter name

Di-n-expression Detailed

basic configuration

from django.conf.urls import url

from app01 import views#从app01导入视图

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003), #思考:如果用户想看2004、2005、2006....等,你要写一堆的url吗,是不是在articles后面写一个正则表达式/d{4}/就行啦,网址里面输入127.0.0.1:8000/articles/1999/试一下看看
    
   
    url(r'^articles/([0-9]{4})/$',views.year_archive), 
    
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), 
    #思考,如果你想拿到用户输入的什么年份,并通过这个年份去数据库里面匹配对应年份的文章,你怎么办?怎么获取用户输入的年份啊,分组/(\d{4})/,一个小括号搞定
    
   url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

  views.py view function in the wording:

第一个参数必须是request,后面的参数是对应着上面 分组正则匹配的每个参数的

from django.shortcuts import render,HttpResponse
# Create your views here.

def special_case_2003(request,):
    return HttpResponse(2003)

def year_archive(request,year,):
    return HttpResponse(year+'年')


def month_archive(request,year,month,):
    return HttpResponse(year+'年'+month+'月')

def article_detail(request,year,month,day):
    return HttpResponse(year+'年'+month+'月'+day+'日')

ps注意 url匹配出来的参数 对与的视图函数 要一一对应 不能多 也不能少

Precautions

  1. urlpatterns elements in the writing order from the top one by matching a regular expression, once the match is successful discontinued.
  2. To capture a value from the URL, only to place a pair of parentheses (packet matches) around it.
  3. No need to add a leading backslash (that is written on the front of the regular /), because each URL has. For example, it should be ^ articles, not ^ / articles.
  4. Each regular expression in front of the 'r' is optional, but suggested adding.
  5. ^ Articles & in what end, beginning with what, strictly limited path

  

Supplement

# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
APPEND_SLASH=True

  Django settings.py file in the default configuration does not APPEND_SLASH this parameter, but Django default this parameter is APPEND_SLASH = True. Its role is automatically added at the end of the URL '/'. The effect is this: we define urls.py:

from django.conf.urls import url
from app01 import views

urlpatterns = [
        url(r'^blog/$', views.blog),
]

  Access http://www.example.com/blog , the default URL will automatically be converted to HTTP: //www.example/com/blog/ .

  If you set in settings.py in APPEND_SLASH = False , this time we'll request http://www.example.com/blog will be prompted to find the page when.

Three group matches Name (famous grouping)

  The above example uses simple regular expression match to capture the value of the packet in the URL (by the parentheses) in the view position and passed to the argument.

  In more advanced usage, you can use the packet matches the name of a regular expression groups to capture value in the URL and keyword parameters passed to the view form.

  In Python regular expressions, the group named regular expression syntax group is (?P<name>pattern), which nameis the name of the group, patternis the pattern to match.

  Here are used the above named group URLconf rewritten:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003), #注意正则匹配出来的内容是字符串,即便是你在url里面写的是2003数字,匹配出来之后也是字符串
    
   url(r'^articles/(\d{4})/$', views.year_archive),#year_archive(request,n),小括号为分组,有分组,那么这个分组得到的用户输入的内容,就会作为对应函数的位置参数传进去,别忘了形参要写两个了,明白了吗?
    
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),#某年的,(?P<year>[0-9]{4})这是命名参数(正则命名匹配还记得吗?),那么函数year_archive(request,year),形参名称必须是year这个名字。而且注意如果你这个正则后面没有写$符号,即便是输入了月份路径,也会被它拦截下拉,因为它的正则也能匹配上
    
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),#某年某月的
    
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), #某年某月某日的
]

  This implementation is identical to the previous example, only a subtle difference: the captured value as a key instead of the position parameter transfer function parameters to view.

  For example, for a url / articles / 2017/12 / corresponding to the view function calls in the following manner:

views.month_archive(request, year="2017", month="12"),year和month的位置可以换,没所谓了,因为是按照名字来取数据的,还记得关键字参数吗?

  In practice, the use of grouping named match the way you can make your URLconf more clear and not prone to error parameter order problem, but some developers think that grouping named group syntax ugly and too cumbersome.

  As for exactly what kind should be used, you can decide according to their preferences.

  

URLconf matching position

    URLconf look at the URL request, it will be treated as a normal Python string. It does not include GET and POST parameters, and domain name.

    For example, http://www.example.com/myapp/ request, URLconf looks myapp /.

    In http://www.example.com/myapp/?page=3 request, URLconf will look myapp/.

    URLconf request method does not check. In other words, all requests method - the same URL POST, GET, HEADetc. - will be routed to the same function.

Capture parameters are always strings

  Each captured in the URLconf parameters as a normal Python string passed to view, regardless of regular expressions to match what way. For example, in the following line URLconf:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

  View to the transfer function of views.year_archive()the yearparameters always be a string type.

The default value specified in the function view

# urls.py中
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# views.py中,可以为num指定默认值
def page(request, num="1"):
    pass

  In the above example, the two point to the same URL pattern view - views.page - but the first pattern does not capture anything from the URL.

  If the first pattern matches, page () function will use its default parameters if num = the second pattern matching, page will capture a regular expression to the num value "1", ().

include other URLconfs (also called URL distribution)

  Ask you a question, views and models are not all files on every app application inside ah, but urls.py on which this document, is not in the project folder inside, what explanation, indicating that not all the app are using it, if you have a project 10 applications, each with 100 url, that means you have to write how many correspondence between the url in urls file inside, and all of the app are written in the url this is a file inside the urls ah, that all right, of course, no problem, but the degree of coupling is too high, so in django url here to provide you with a distribution interface is called include

url wording

#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.

#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:


from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
    
   url(r'^blog/', include('blog.urls')),  # 可以包含其他的URLconfs文件
    
   url(r'^app01/',include('app01.urls')),  #别忘了要去app01这个应用下创建一个urls.py的文件,现在的意思是凡是以app01开头的路径请求,都让它去找app01下的urls文件中去找对应的视图函数,还要注意一点,此时这个文件里面的那个app01路径不能用$结尾,因为如果写了$,就没办法比配上app01/后面的路径了

]

:( urls.py content of app01 the fact that the global urls.py copy the contents inside it, put the urls.py file you created under app01 folder, not the app01 the application to delete the url on the line)

from django.conf.urls import url
#from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^articles/2003/', views.special_case_2003,{'foo':'xxxxx'}), #{'foo':'xxxxx'}那么你的视图函数里面必须有个形参叫做foo来接收这种传参
    url(r'^articles/(\d{4})/(\d{2})/', views.year_archive),

]

At this point directory structure:

  img

    img

    When articles related URL path before we visit again this time, we need to write the beginning of the app01

    img

    Enter the correct way:

    img

    In fact, it is equivalent to what has been done, the URL http://127.0.0.1:8000/app01/articles/2003/, the inside portion of the path app01 / articles / 2003 /, the project urls.py inside, the matching to the app01 /, then took the path remaining part articles / 2003 / urls.py inside to app01 document which match, find the corresponding function is executed.

    Also note that, see below the $ symbol:

    img

    img

    img

    

    Let's look: if we want to enter http://127.0.0.1:8000/app01/, see app01 this home application, how to do? As I now enter a http://127.0.0.1:8000 to view the site's home page, how to do, that is to say without any path behind me, to see your home page URL, how do the root path of all general site the site's home page, right

    img

    Can you see the following written in this way:

    img

    

    img

    views.py which I wrote such a function

    img

    Enter the URL:

    img

    The index found that all went inside to perform a function, that is to say, all this is not to obtain the rule url to match, right

    Therefore, the correct wording, matching the root path wording:

url(r'^$', views.index),#以空开头,还要以空结尾,写在项目的urls.py文件里面就是项目的首页,写在应用文件夹里面的urls.py文件中,那就是app01的首页

    img

    img

    img

    img

    app01 function of content:

    img

    

  Also note that when the app is added, needs to be configured:

  img

Passing additional parameters to the view function (learn)

    URLconfs has a hook that allows you to pass a Python dictionary as an additional parameter passed to the view function.

    django.conf.urls.url() Function takes an optional third argument, it is a dictionary, represent additional keyword arguments want to pass to the view function.

    E.g: 

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),#注意,这就像一个命名分组一样,你的函数里面的必须有一个形参,形参必须叫做foo才行,如果是命名分组的url,那么foo参数写在函数的哪个位置都行,如果不是命名分组,那么都是将这个形参写在参数的最后。
]

  在这个例子中,对于/blog/2005/请求,Django 将调用views.year_archive(request, year='2005', foo='bar')。
    这个技术在Syndication 框架中使用,来传递元数据和选项给视图。

四 命名URL(别名)和URL的反向解析

你想,我们自己写的url里面的路径有没有可能会更改,如果路径更改了,那么我们前端访问这个路径的标签(a标签,form表单等等)里面的属性值是不是也要自己手动去改啊,这样我们拓展起来就不方便了,你想是不是?尤其是前端可能不是你写的,那你是不是要进行部门沟通啊,想一想怎么办?

  在使用Django 项目时,一个常见的需求是获得URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。
  人们强烈希望不要硬编码(其实就是在标签里面写死了路径,凡是写死了的代码就是硬编码)这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 毫不相关的专门的URL 生成机制,因为这样容易导致一定程度上产生过期的URL。
  换句话讲,需要的是一个DRY 机制。除了其它有点,它还允许设计的URL 可以自动更新而不用遍历项目的源代码来搜索并替换过期的URL。
  获取一个URL 最开始想到的信息是处理它视图的标识(例如名字),查找正确的URL 的其它必要的信息有视图参数的类型(位置参数、关键字参数)和值。
  Django 提供一个办法是让URL 映射是URL 设计唯一的地方。你填充你的URLconf,然后可以双向使用它:

  • 根据用户/浏览器发起的URL 请求,它调用正确的Django 视图,并从URL 中提取它的参数需要的值。
  • 根据Django 视图的标识和将要传递给它的参数的值,获取与之关联的URL。

  第一种方式是我们在前面的章节中一直讨论的用法。第二种方式叫做反向解析URL、反向URL 匹配、反向URL 查询或者简单的URL 反查。
  在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:

  • 在模板中:使用url模板标签。
  • 在Python 代码中:使用django.core.urlresolvers.reverse() 函数。
  • 在更高层的与处理Django 模型实例相关的代码中:使用get_absolute_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' %}  #模板渲染的时候,被django解析成了这个名字对应的那个url,这个过程叫做反向解析

在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,))) #或者直接return redirect('news-year-archive',year) redirect内部会自动调用reverse来进行反向解析

  如果出于某种原因决定按年归档文章发布的URL应该调整一下,那么你将只需要修改URLconf 中的内容。

  在某些场景中,一个视图是通用的,所以在URL 和视图之间存在多对一的关系。对于这些情况,当反查URL 时,只有视图的名字还不够。

  注意:

  为了完成上面例子中的URL 反查,你将需要使用命名的URL 模式。URL 的名称使用的字符串可以包含任何你喜欢的字符。不只限制在合法的Python 名称。

  当命名你的URL 模式时,请确保使用的名称不会与其它应用中名称冲突。如果你的URL 模式叫做comment,而另外一个应用中也有一个同样的名称,当你在模板中使用这个名称的时候不能保证将插入哪个URL。

  在URL 名称中加上一个前缀,比如应用的名称,将减少冲突的可能。我们建议使用myapp-comment 而不是comment

  

五 命名空间模式

​ 即使不同的APP使用相同的URL名称,URL的命名空间模式也可以让你唯一反转命名的URL。

  举个例子:

  项目的urls.py写法:

from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls')),
    url(r'^app02/', include('app02.urls')),

]

  app01下的urls.py写法

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index,name='index'),

]

  app02下的urls.py的写法

from django.conf.urls import url
from django.contrib import admin
from app02 import views
# app_name = 'app02'
urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index,name='index'),
]

  app01下的views.py的写法

from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
# Create your views here.

def index(request):
    print(reverse('index'))
    return HttpResponse('ok')

  app02下的views.py的写法

from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
# Create your views here.
def index(request):

    print(reverse('index'))
    return HttpResponse('ok2')

  你会发现,不管你是访问app01下的index还是app02下的index,打印的结果都是/app02/index/,也就是打印的是最后一个index别名对应的url路径。所以别名冲突了的话就需要我们的命名空间来保证别名对应的url的唯一性了。

  project中的urls.py

from django.conf.urls import url, include
 
urlpatterns = [
    url(r'^app01/', include('app01.urls', namespace='app01')),
    url(r'^app02/', include('app02.urls', namespace='app02')),
]

  app01中的urls.py

from django.conf.urls import url
from app01 import views
 
urlpatterns = [
    url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
]

  app02中的urls.py

from django.conf.urls import url
from app02 import views
 
urlpatterns = [
    url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
]

  现在,我的两个app中 url名称重复了,我反转URL的时候就可以通过命名空间的名称得到我当前的URL。

  语法:

  '命名空间名称:URL名称'

  模板中使用:

{% url 'app01:detail' pk=12 pp=99 %}

  views中的函数中使用

v = reverse('app01:detail', kwargs={'pk':11})

  这样即使app中URL的命名相同,我也可以反转得到正确的URL了。

第二种写法:就是在每个app下的urls.py文件中指定app名称,同样是命名空间。

from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # url(r'^app01/', include('app01.urls',namespace='app01')),
    url(r'^app01/', include('app01.urls')),
    # url(r'^app02/', include('app02.urls',namespace='app02')),
    url(r'^app02/', include('app02.urls')),

]

app01下的urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views
app_name = 'app01'
urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index,name='index'),

]

app02下的urls.py

from django.conf.urls import url
from django.contrib import admin
from app02 import views
app_name = 'app02'
urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index,name='index'),
]

app01下的view视图中反向解析

def index(request):
    print(reverse('app01:index'))
    return HttpResponse('ok')

app02下的view视图中反向解析

def index(request):

    print(reverse('app02:index'))
    return HttpResponse('ok2')

第三种写法:

项目的urls.py中的写法:

from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # url(r'^app01/', include('app01.urls',namespace='app01')),
    url(r'^app01/', include(('app01.urls','app01'),namespace='app01')),
    # url(r'^app02/', include('app02.urls',namespace='app02')),
    url(r'^app02/', include(('app02.urls','app02'),namespace='app02')),

]

那么其他的app中的urls.py中就不需要写app_name='应用名'了,看app01下urls.py的写法:

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index,name='index'),

]

app02 under urls.py wording:

from django.conf.urls import url
from django.contrib import admin
from app02 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index,name='index'),
]

View wording:

#app01
def index(request):
    print(reverse('app01:index'))
    return HttpResponse('ok')

#app02
def index(request):
    print(reverse('app02:index'))
    return HttpResponse('ok2')

Guess you like

Origin www.cnblogs.com/saoqiang/p/12381762.html