Django之路由系统urls

1、URL配置

  本质:URL与要为该URL调用的视图函数之间的映射表。

# 基本格式:
from django.conf.urls import url

urlpatterns = [
     # url(正则表达式, views视图函数,参数,别名),
    url(r'^admin/', admin.site.urls),
    url(r'^author/', views.author),
]

  说明:

    1. 路由一旦匹配后就不再走后面的匹配关系了

    2. 先拿"127.0.0.1:8000/author"去匹配,如果找不到就拿"127.0.0.1:8000/author/"在去访问一次

    3. 精准匹配即全匹配使用"^"和"$",如"^author/$"

    4. 路由增加首页的方式:url(r"^$", views.home)

    5. 增加一个尾页url(r""):url(r"", views.error),

2、分组命名匹配

# 无名分组
# 格式:
    url(r'^author/([0-9]{4})/$', views.author),
# 在view.py 下
    def author(request, xxx):
        pass
# 说明:把括号内的值当作为位置参数传给author的xxx


# 有名分组
# 格式:
    url(r'^author/(?P<year>/d+)/$', views.author),
# 在view.py 下
    def author(request, year):
        pass
# 说明:author函数的形参名必须是year,把括号的值当作关键字参数传给year

# 强调:
有名分组和无名分组不能混着用
无名分组和有名分组都支持多个参数

  2.1 url匹配的位置

    url匹配不检查请求的方法和参数,如:

      "127.0.0.1:8080/login/?name=sun&pwd=123", 只匹配login/,后面的参数不匹配。

  2.2 分组得到的参数永远都是字符串

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

      访问网址:"127.0.0.1:8080/book/2016",得到的year=2016的格式是字符串形式

  2.3 视图函数指定默认值

# urls.py中
from django.conf.urls import url
from app01 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

# 结果:
# 当访问127.0.0.1:8080/page/,得到的num='1'
# 当访问127.0.0.1:8080/page/4,得到的num='4'

  2.4 传递额外的参数给视图函数

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

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.archive, {'foo': 'bar'}),
]

# views.py中,可以为num指定默认值
def archive(request, year, foo):
    pass

# 当访问127.0.0.1:8080/blog/2014
# 执行 archive(request, year='2014', foo="bar")

3、反向解析

  给匹配的URL起个别名,当后端或前端需要使用这个URL时,可以直接通过别名找到原URL。

  好处:当URL需要修改时,就不用再去修改前端和后端的代码里这个URL。

  3.1 一般解析

# url.py中
    url(r"^testadd213123/$", view.testadd, name="testadd")

# 在后端反向解析
# views.py中
    from django.shortcuts import reverse
    res = reverse("testadd") 
    # res结果就是"testadd123/"

# 在前端反向解析
<a href="{% url "testadd" %}"> 添加</a>
# 在网页上显示:<a href="testadd/"> 添加</a>
# 一定要加引号,不然报错
# django.urls.exceptions.NoReverseMatch: Reverse for '' not found. '' is not a valid view function or pattern name.

 3.2 无名分组的反向解析

# url.py中
    url(r"^testadd213123/(\d+)$", view.testadd, name="testadd")

# 在后端反向解析
# views.py中
    from django.shortcuts import reverse
    def testadd(request, id):
        res = reverse("testadd", arg(id, ))
    # res结果就是"testadd123/id的值/"
# 前端解析
<a href="{% url "testadd" 123 %}"> 添加</a>
# 在网页上显示:<a href="testadd/123/"> 添加</a>

3.3 有名分组的反向解析

# url.py中
    url(r"^testadd213123/(?P<year>\d+)$", view.testadd, name="testadd")

# 在后端反向解析
# 第一种方式:(和上面一样)
# views.py中
    from django.shortcuts import reverse
    def testadd(request, year):
        res = reverse("testadd", arg(year, ))
    # res结果就是"testadd123/year的值"

# 第二种方式:
# views.py中
    from django.shortcuts import reverse
    def testadd(request, year):
        res = reverse("testadd", kwargs={"year": year})
    # res结果就是"testadd123/year的值"


# 前端解析 year是参数
<a href="{% url "testadd" year %}"> 添加</a>
# 在网页上显示:<a href="testadd/2012/"> 添加</a>

4、路由分发

 
    总路由不再直接做路由与视图函数的对应关系,而是将获取的路由分发给下面的app去处理对应关系
    每一个app下都可以新建自己的urls.py,static文件夹,templates文件夹

 

# 项目名为mysite
# 总路由
# mysite文件夹下的urls.py
from django.conf.urls import include
from app01 import urls as app01_urls
from app02 import urls as app02_urls

# 两种方式:
# 第一种:
url(r'^app01/',include(app01_urls)),
url(r'^app02/',include(app02_urls))
# 第二种:(推荐)
url(r'^app01/',include("app01.urls")), 
url(r'^app02/',include("app02.urls"))

# 子路由
# app01文件的urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^index/',views.index, name="index")
    ]

# app02文件的urls.py
from django.conf.urls import url
from app02 import views
urlpatterns = [
    url(r'^index/',views.index, name="index")
    ]

强调:如果两个app下起了相同的名字,那么反向解析不支持自动查找应用前缀

# 解决办法:
# 1. 加上名称空间
url(r'^app01/',include(app01_urls,namespace='app01')),
url(r'^app02/',include(app02_urls,namespace='app02'))
# 后端反向解析:
print(reverse('app01:aaa'))
print(reverse('app02:aaa'))

# 2.不要起一样的名字
# app01文件的urls.py
    url(r'^index/',views.index, name="app01_index")
# app02文件的urls.py
    url(r'^index/',views.index, name="app02_index")

5、伪静态

  在url后面加上.html后缀,假装自己的路径是一个静态(数据写死的)文件的路径,其实你是经过了视图函数处理,动态渲染页面提高百度收藏你这个网页力度,当别人搜索你这个页面相关的内容百度会优先展示你的页面(这样虽然能提高你网页被访问概率,但是还是干不过RMB玩家)

6、python的虚拟环境

  原因:每个项目用到的模块不一样;提到解释器的运行效率

  目的:为了让每一个项目都有仅仅属于自己的项目解释器

   使用:

    new project的时候选择虚拟环境创建项目

    如果勾选了下面的make to all project你创建的虚拟环境就能够被其他新建的项目使用

 7、django1.0版本和2.0版本

   7.1 两者区别

    1. django1.0里面的url对应django2.0里面re_path

    2. django2.0里面的path第一个是精准匹配

    3. django1.0版本中匹配到的参数都是字符串类型

    4. Django2 后面创建外键时需要设置参数on_delate=models.CASCADE

# django2中的路由匹配
from django.urls import path, re_path
from app01 import index, edit

urlpatterns = [
    path(r'index/',views.index, name="index"),
    re_path(r"^edit/(\d+)/$", views.edit)
    ]

  7.2 django2.0版本自带转换器

    str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式

    int,匹配正整数,包含0。

    slug,匹配字母、数字以及横杠、下划线组成的字符串。

    uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。

    path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)

from django.urls import path  
from app01 import views  
urlpatterns = [  

    # path才支持,re_path不支持
    path('articles/2003/', views.special_case_2003),  
    path('articles/<int:year>/', views.year_archive),  
    path('articles/<int:year>/<int:month>/', views.month_archive), 
  path('order/<int:year>',views.order),
]  

  7.3 注册自定义转换器

# 例子:
class FourDigitYearConverter:  
    regex = '[0-9]{4}'  
    def to_python(self, value):  
        return int(value)  
    def to_url(self, value):  
        return '%04d' % value  

# 参数:
#    regex 类属性,字符串类型
#    to_python(self, value)方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,传递到对应的视图函数中。
#    to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。

# 使用:
from django.urls import register_converter, path  
from app01 import views  
register_converter(FourDigitYearConverter, 'yyyy')  
urlpatterns = [  
    path('articles/2003/', views.special_case_2003),  
    path('articles/<yyyy:year>/', views.year_archive), 
]

# 在view.py下
def year_archive(request, year):
    pass
# 得到的year是int类型

 

posted @ 2019-04-30 09:31  yw_sun  阅读(162)  评论(0)    收藏  举报