zoukankan      html  css  js  c++  java
  • Django路由控制总览

    今日内容:(路由层)
        1 简单配置
            -第一个参数是正则表达式(如果要精准匹配:'^publish/$')
            -第二个参数是视图函数(不要加括号)
            -url(r'^admin/', admin.site.urls),
        2 无名分组
            -按位置传参
            -分组之后,会把分组出来的数据,当位置参数,传到视图函数,所以,视图函数需要定义形参
            -url(r'^publish/([0-9]{4})/([0-9]{2})$', views.publish),
            -def publish(request,*args):   视图函数可以这样接收
        3 有名分组
            -按关键字传参
            -有名分组之后,会把分组出来的数据,当关键字参数,传到视图函数,所以,视图函数需要定义形参,形参名字要跟分组的名字对应,与顺序无关
            -url(r'^publish/(?P<year>[0-9]{4})/(?P<mounth>[0-9]{2})/$', views.publish),
            -def publish(request, mounth,year):
            *****有名分组和无名分组,不要混用
        4 反向解析
            -先命一个名:
                -1 无参数:url(r'^publishadd133/$', views.publishadd,name='ddd'),
                -2 无名分组:url(r'^publishadd/([0-9]{4})/([0-9]{2})/$', views.publishadd,name='ddd'),
                -3 有名分组:url(r'^publishadd/(?P<year>[0-9]{4})/(?P<mounth>[0-9]{2})/$', views.publishadd,name='ddd'),
            -在模板层:
                -1 无参数:{% url 'ddd' %}
                -2 无名分组的:{% url 'ddd' 2018 12 %}
                -3 有名分组:{% url 'ddd' 2018 12 %}  还可以 {% url 'ddd' year=2018 mounth=12 %}
                
            -在视图层:
                from django.shortcuts import reverse
                在视图函数里:
                1 无参数:url=reverse('ddd')
                1 无名分组:url=reverse('ddd',args=(2018,12,))
                1 有名分组:url=reverse('ddd',args=(2018,12,)) 还可以 url=reverse('ddd',kwargs={'year':2018,'mounth':12})
        5 路由分发    
            1 在不同的app里创建urls.py
            2 在总路由 
                -from django.conf.urls import include 
                -url(r'^blog/',include('blog.urls')),
                -url(r'^app01/',include('app01.urls')),
            3 在不同的app的urls里配置路由关系    
            ***重点***总路由,不能加结束符$
        6 名称空间
            -url(r'^blog/',include('blog.urls',namespace='blog')),
            -子路由:url(r'^publish/$', views.publish,name='test'),
            -反向解析:
                -视图层:url = reverse('blog:test')
                -模板层:{% url 'app01:test'%}
            ***一般不要用***
                子路由:url(r'^publish/$', views.publish,name='app01_test'),
                
        7 伪静态
            -路由:url(r'^book/(?P<id>d+.html)',views.book),
            -访问:http://127.0.0.1:8000/book/4.html
    
    作业:
        1 自己尝试对象有没有删除方法,更新方法
        2 有时间的同学研究一下如何手动创建第三张表
        3 图书管理系统,路由不用get形式传参,用有名分组,无名分组
        4 http://127.0.0.1:8000/ 访问这个路径,匹配到图书列表
        5 路由匹配不上,调到404的页面
        6 图书管理系统,继续写

    一:Django路由的简单分析:

    是一个路径到视图函数的转换  :路径---视图函数
    
    URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行。
    
    一般来说: 一个路径对应一个视图函数.他并不是一样对应! 多个路径可以对应一个视图函数,但是一个路径,不能对应多个视图函数

    举例一:

     
     
    urls.py
    from django.contrib import admin
    from django.urls import path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index),
    ]  
     
     
    views/index.py
     
    from django.shortcuts import render,HttpResponse
     
    # Create your views here.
    def index(request):
        return HttpResponse("INDEX")
     
    访问127.0.0.1:8000/index 会出现 INDEX 
     

    在urls.py中新增re_path模块,它是为了兼容django 1.0版本的路由写法。使用正则匹配

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from django.contrib import admin
    from django.urls import path,re_path
    from app01 import views
     
    urlpatterns = [
        path('admin/', admin.site.urls),
        # path('index/', views.index),
        re_path('^index/$', views.index),  #效果同上
    ]

    访问http://127.0.0.1:8000/index/,效果同上。后面加别的字符串,就会报404

      

    再次修改urls.py,去除^和$

    1
    2
    3
    4
    5
    urlpatterns = [
        path('admin/', admin.site.urls),
        # path('index/', views.index),
        re_path('index/', views.index),
    ]

     访问http://127.0.0.1:8000/index/,是正常的。

    举例二

    举例2:
    增加一个路径
    from django.contrib import admin
    from django.urls import path,re_path
    from app01 import views
     
    urlpatterns = [
        path('admin/', admin.site.urls),
        # path('index/', views.index),
        re_path('^index/$', views.index),  # index(request)
        re_path(r'^articles/2003/$', views.special_year),
    ]
    增加视图函数special_year
    
    def special_year(request):
        return HttpResponse("2003")
    访问url:http://127.0.0.1:8000/articles/2003/
    
    网页效果:
    
    
    
     
    
    匹配年份,它是4位数字的,修改urls.py
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        # path('index/', views.index),
        re_path('^index/$', views.index),  # index(request)
        re_path(r'^articles/2003/$', views.special_year), # special_year(request)
        re_path(r'^articles/d{4}/$', views.article_year), # article_year(request)
    ]
    增加视图函数article_year
    
    def article_year(request):
        return HttpResponse("year")
    访问url:http://127.0.0.1:8000/articles/2003/
    
    网页效果:
    
    
    
     
    
    匹配年份,它是4位数字的,修改urls.py
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        # path('index/', views.index),
        re_path('^index/$', views.index),  # index(request)
        re_path(r'^articles/2003/$', views.special_year), # special_year(request)
        re_path(r'^articles/d{4}/$', views.article_year), # article_year(request)
    ]
    增加视图函数article_year
    
    
    def article_year(request):
        return HttpResponse("year")
    访问url:http://127.0.0.1:8000/articles/2005/
    
    网页效果:
    
     
    
    访问url:http://127.0.0.1:8000/articles/20/   就会提示404,因为它不足4位

    匹配举例 三 .四:

    举例3:
    现在想要网页根据路径,动态显示年份,怎么做呢?
    
    这个时候,需要用到正则分组。当re_path检测到分组时,会将分组的值,传给视图函数。
    
    注意:如果是无命名分组,它是位置参数。如果是有名分组,它是关键字传参。
    
    无命名分组
    1
    2
    3
    4
    5
    6
    7
    urlpatterns = [
        path('admin/', admin.site.urls),
        # path('index/', views.index),
        re_path('^index/$', views.index),  # index(request)
        re_path(r'^articles/2003/$', views.special_year), # special_year(request)
        re_path(r'^articles/(d{4})/$', views.article_year), # article_year(request,分组匹配的值)
    ]
    修改article_year视图函数,它必须接收一个位置参数,否则报错
    
    下面代码的year是一个形参,叫什么名字都无所谓。
    
    叫abc都行,随你喜欢
    
    1
    2
    def article_year(request,year):
        return HttpResponse(year)
    访问url:http://127.0.0.1:8000/articles/2080/
    
    网页效果如下:
    
    
    
     
    
     新增url,获取月份,修改urls.py
    
    1
    2
    3
    4
    5
    6
    7
    8
    urlpatterns = [
        path('admin/', admin.site.urls),
        # path('index/', views.index),
        re_path('^index/$', views.index),  # index(request)
        re_path(r'^articles/2003/$', views.special_year), # special_year(request)
        re_path(r'^articles/(d{4})/$', views.article_year), # article_year(request,分组匹配的值)
        re_path(r'^articles/(d{4})/(d{2})/$', views.article_month), # article_month(request,value1,value2)
    ]
    新增article_month视图函数,它必须接收2个额外的参数,否则报错
    
    1
    2
    def article_month(request,year,month):
        return HttpResponse('{}-{}'.format(year,month))
    访问url:http://127.0.0.1:8000/articles/2080/10/
    
    网页效果如下:
    
    
    
    注意:如果视图函数用不到参数,正则部分不要加括号。
    
     
    
    访问url:http://127.0.0.1:8000
    
    网页提示404
    
    
    
    这样用户体验不好,怎么办呢?在index下面,加入以下的url规则
    
    re_path('^$', views.index),
     再次访问页面,输出:
    
    
    
     
    
    匹配年月日,新增一条规则。
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index),
        re_path('^$', views.index),
        re_path('^index/$', views.index),  # index(request)
        re_path(r'^articles/(d{4})/$', views.article_year), # article_year(request,分组匹配的值)
        re_path(r'^articles/2003/$', views.special_year), # special_year(request)
        re_path(r'^articles/(d{4})/(d{2})/$', views.article_month), # article_month(request,value1,value2)
        re_path(r'^articles/(d{4})/(d{2})/(d{2})/$', views.article_day), # article_month(request,value1,value2,value3)
     
    ]
    新增article_day视图函数,它必须接收3个额外的参数,否则报错
    
    1
    2
    def article_day(request,year,month,day):
        return HttpResponse('{}-{}-{}'.format(year,month,day))
    访问url:http://127.0.0.1:8000/articles/2080/10/12
    
    网页效果如下:
    
    
    
    注意:上面的分组,不建议使用。它是无名分组,推荐使用有名分组。
    如果视图函数,参数位置变动了。那么页面访问,就乱套了。
    
    修改article_day视图函数,参数的位置
    
    1
    2
    def article_day(request,day,month,year):
        return HttpResponse('{}-{}-{}'.format(year,month,day))
    再次访问网页,页面输出:
    
    
    
    因为urls.py是按照顺序传参给视图函数的。
    
     
    
    举例4:
    看下面的几个例子,就能方便理解了。
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from django.urls import path,re_path
     
    from app01 import views
     
    urlpatterns = [
        re_path(r'^articles/2003/$', views.special_case_2003),
        re_path(r'^articles/([0-9]{4})/$', views.year_archive),
        re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
        re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
    ]
    注意:
    
    若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
    不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
    每个正则表达式前面的'r' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义
    示例:
    
    1
    2
    3
    4
    5
    6
    7
    一些请求的例子:
     
    /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')。
    有名分组
    上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。
    
    在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。
    
     
    
    使用有名分组,可以解决上面,因为视图函数,参数位置变动而导致页面显示混乱的情况。
    
    修改url规则
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index),
        re_path('^$', views.index),
        re_path('^index/$', views.index),  # index(request)
        re_path(r'^articles/(d{4})/$', views.article_year), # article_year(request,分组匹配的值)
        re_path(r'^articles/2003/$', views.special_year), # special_year(request)
        re_path(r'^articles/(d{4})/(d{2})/$', views.article_month), # article_month(request,value1,value2)
        # article_month(request,year=value1,month=value2,day=value3)
        re_path(r'^articles/(?P<year>d{4})/(?P<month>d{2})/(?P<day>d{2})/$', views.article_day),
     
    ]
    再次访问页面,显示就不会混乱了。
    
    
    
    如果视图函数的变量名,更改了呢?
    
    1
    2
    def article_day(request,d,month,year):
        return HttpResponse('{}-{}-{}'.format(year,month,d))
    再次访问页面,报错!
    
    
    
    提示找不到关键字参数day
    
    在讲无命名分组的时候,提到视图函数的形参名,可以随便定义。但是有命名分组,名字必须一一对应。
    
    关键字参数在于,先赋值,再传参。所以视图函数,必须一一对应才行。
    
    
    下面是以上URLconf 使用命名组的重写:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from django.urls import path,re_path
     
    from app01 import views
     
    urlpatterns = [
        re_path(r'^articles/2003/$', views.special_case_2003),
        re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
        re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
        re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
    ]
    1
    这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。例如:
    1
    2
    3
    /articles/2005/03/ 请求将调用views.month_archive(request, year='2005', month='03')函数,而不是views.month_archive(request, '2005', '03')。
     
     /articles/2003/03/03/ 请求将调用函数views.article_detail(request, year='2003', month='03', day='03')。 
    在实际应用中,这意味你的URLconf 会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。当然,这些好处是以简洁为代价;
    
    分发
    1个Django 项目里面有多个APP目录,大家共有一个 url容易造成混淆。于是路由分发让每个APP的拥有了自己单独的url,方便以后的维护管理。
    
    现在不想将所有的url放到一个py文件里面,需要根据应用名,来拆分。
    看urls.py的说明
    
    1
    2
    3
    Including another URLconf
        1. Import the include() function: from django.urls import include, path
        2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
    意思就是:先导入include方法,再添加URL模式的URL
    
    在urls.py导入include方法:
    
    1
    from django.urls import path,re_path,include
    添加独立的url文件,在app01目录下创建app01_urls.py,将urls.py相关的内容复制过去  
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    from django.urls import path,re_path,include
    from app01 import views
    urlpatterns = [
        re_path(r'^articles/(d{4})/$', views.article_year),  # article_year(request,分组匹配的值)
        re_path(r'^articles/2003/$', views.special_year),  # special_year(request)
        re_path(r'^articles/(d{4})/(d{2})/$', views.article_month),  # article_month(request,value1,value2)
        # article_month(request,year=value1,month=value2,day=value3)
        re_path(r'^articles/(?P<year>d{4})/(?P<month>d{2})/(?P<day>d{2})/$', views.article_day),
    ]
    修改urls.py,删除多余的代码
    
    注意:app01后面,必须有斜杠,否则页面无法访问。
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from django.contrib import admin
    from django.urls import path,re_path,include
    from app01 import views
     
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index),
        re_path('^$', views.index),
        re_path('^index/$', views.index),  # index(request)
         
        path('app01/', include('app01.app01_urls')),
    ]
    访问原来的url,提示404。
    
    
    
    因为路由分发了,所以访问时,必须加应用名。
    
    访问url:http://127.0.0.1:8000/app01/articles/2003/
    
     页面访问正常。
    
    
    
    再增加一个应用,也是可以的。比如:
    
    path('app02/', include('app01.app02_urls')),
    由于这里只有一个应用,所以可以更改路由分发,将url访问方式还原为之前的。
    
    1
    2
    3
    4
    5
    6
    7
    8
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index),
        re_path('^$', views.index),
        re_path('^index/$', views.index),  # index(request)
     
        re_path('^', include('app01.app01_urls')),
    ]
    访问原来的url: http://127.0.0.1:8000/articles/2003/
    
    效果是一样的。
    
    
    
     
    
    反向解析
    在使用Django 项目时,一个常见的需求是获得URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。人们强烈希望不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 毫不相关的专门的URL 生成机制,因为这样容易导致一定程度上产生过期的URL。
    
    在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:
    
    在模板中:使用url 模板标签。
    在Python 代码中:使用from django.urls import reverse()函数
     
    做一个登陆页面
    修改app01_urls.py,添加login路径
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    urlpatterns = [
        re_path(r'^articles/(d{4})/$', views.article_year),  # article_year(request,分组匹配的值)
        re_path(r'^articles/2003/$', views.special_year),  # special_year(request)
        re_path(r'^articles/(d{4})/(d{2})/$', views.article_month),  # article_month(request,value1,value2)
        # article_month(request,year=value1,month=value2,day=value3)
        re_path(r'^articles/(?P<year>d{4})/(?P<month>d{2})/(?P<day>d{2})/$', views.article_day),
     
        path('login/', views.login),
    ]
    修改views.py,增加login视图函数
    
    def login(request):
        return render(request,"login.html")
    在mysite目录下创建templates,注意:是有manage.py文件的mysite目录。
    
    在templates目录下创建文件login.html
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
     
    </head>
    <body>
    <form action="/login/" method="post">
        <lable>用户名</lable><input type="text" name="user"/>
        <lable>用户名</lable><input type="password" name="pwd"/>
        <input type="submit">
    </form>
     
    </body>
    </html>
    修改settings.py-->MIDDLEWARE-->关闭CSRF
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        # 'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    修改settings.py-->TEMPLATES-->指定templates模板目录
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    访问url:http://127.0.0.1:8000/login/
    
    输入表单数据,单击提交。页面还是会回到登陆页面!至于登陆认证,下面会讲到。稍安勿躁!
    
    
    
    假设说,业务线的url要更改了,改为http://127.0.0.1:8000/login.html/
    
    怎么办呢?修改修改app01_urls.py的login路径
    
    path('login.html/', views.login),
    访问新的url:http://127.0.0.1:8000/login.html/
    
    页面访问正常,输入表单数据
    
    
    
    点击提交的时候,出现404。因为表单的action属性,指向的还是login页面,但是它已经不存在了!
    
    
    
    来一个简单粗暴的方法,直接修改action的属性为/login.html/,再次访问页面,重新提交。ok,正常了!
    
    这只是一个html文件,如果有多个怎么办?一个个改?太浪费时间了!
    
    如果交接给新人,再有变动时,他需要在项目里面,一个个找!
    
    现在问题的核心点,是更改了url。现有一个反向解析技术,能完美解决这个问题。
    
    修改修改app01_urls.py,增加一个别名
    
    path('login.html/', views.login, name="login_in"),
    这个别名,它代指的是这一条url。此时login_in对应的值是路径login.html/
    
    更改login.html文件,需要用到一个特殊写法,来引用url变量
    
    <form action="{% url 'login_in' %}" method="post">
    它表示从url文件(urls.py)中,调用变量login_in。利用render将页面渲染,返回给浏览器。
    
    重新访问url:http://127.0.0.1:8000/login.html/
    
    使用控制台查看html代码,发现action的属性,就是login.html。说明已经被后端给渲染出来了
    
     
    
    再次提交表单,就不会出现404错误了!
    
    这就是反向解析,路径会变,但是别名不会变。别名是随着路径的变动而变动的。
    
    推荐以后写页面,使用反向解析。
    
    增加登录验证
    修改视图函数login
    
     
    
    1
    2
    3
    4
    5
    6
    7
    def login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            if user == 'Jack' and pwd == '123':
                return HttpResponse("登录成功!")
        return render(request,"login.html")
      
    
    访问登录页面,输入用户名Jack,密码123。点击提交后,页面跳转,效果如下:  
    
     
    
    
    
    这样用户体验不好,一般是跳转到首页。
    使用重定向功能,需要在views首行导入redirect方法。
    
    from django.shortcuts import render,HttpResponse,redirect
    修改login视图函数:
    
    1
    2
    3
    4
    5
    6
    7
    8
    def login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            if user == 'xiao' and pwd == '123':
                # return HttpResponse("登录成功!")
                return redirect("/index/")  # 跳转首页
        return render(request,"login.html")
    再次输入正确的用户和密码,点击提交。页面就会跳转至首页!
    
    
    
    但是跳转路径写死了不好,如果首页路径改了,怎么办?比如这样:
    
    path('index_new/', views.index),
    需要用到反向解析!增加一个别名,修改urls.py
    
    1
    2
    3
    4
    5
    6
    7
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index, name="index_in"),
        re_path('^$', views.index),
     
        re_path('^', include('app01.app01_urls')),
    ]
    上面提到了html文件使用反向解析,那么视图函数如何使用反向解析呢?
    
    需要导入一个模块reverse,views.py前2行代码如下:
    
    from django.shortcuts import render,HttpResponse,redirect
    from django.urls import reverse
    修改login视图函数
    
    1
    2
    3
    4
    5
    6
    7
    8
    def login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            if user == 'Jack' and pwd == '123':
                url = reverse("index_in") # 反向解析url别名index_in
                return redirect(url)  # 跳转首页
        return render(request,"login.html")
    访问url:http://127.0.0.1:8000/login.html/
    
    输入表单数据,点击提交
    
    页面跳转正常。
    
    
    
    更改urls.py,修改路径
    
    path('index_new/', views.index, name="index_in"),
    访问url,提交数据。跳转也是正常的!
    
    因为视图函数
    
    url = reverse("index_in")
    它始终能解析最新的url
    
    总结:反向解析的2种情况
    复制代码
    复制代码
    情况1:    
        在模板(html文件): 
             {% url '别名' %}
             
        render方法
    
    情况2:
        视图函数(python文件)中
        
        from django.urls import reverse
        url=reverse(别名)
    复制代码
    复制代码
     
    
    当命名你的URL 模式时,请确保使用的名称不会与其它应用中名称冲突。如果你的URL 模式叫做comment,而另外一个应用中也有一个同样的名称,当你在模板中使用这个名称的时候不能保证将插入哪个URL。在URL 名称中加上一个前缀,比如应用的名称,将减少冲突的可能。我们建议使用myapp-comment 而不是comment。
    View Code

    二: Djangoa路由系统总览

    (一).URL组成部分详解

    URL是Uniform Resource Locator的简写,统一资源定位符,一个url是由下面几个部分组成的

    scheme://host:port/path/?query-string=xxx#anchor  

    scheme:代表访问的协议,一般为http或者https以及ftp

    host:主机名,域名,比如:www.baidu.com。

    port:端口号。浏览器默认使用80端口。

    path:查找路径。比如www.jianshu.com/trending/now,后面的trending/now就是path

    query-string:查询字符串。比如:www.baidu.com/s?wd=python,后面的wd=python就是查询字符串。

    anchor:锚点,后台一般不用管,前端用来做页面的定位的

    注:URL中所有的字符都是ASCII字符集,如果出现非ASCII字符集,比如中文,浏览器会先进行编码再进行传输。

    1 URL配置

    from django.conf.urls import url
    
    urlpatterns = [
         url(正则表达式, views视图,参数,别名),
    ]
    源码
    def url(regex, view, kwargs=None, name=None):
        if isinstance(view, (list, tuple)):
            # For include(...) processing.
            urlconf_module, app_name, namespace = view
            return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
        elif callable(view):
            return RegexURLPattern(regex, view, kwargs, name)
        else:
            raise TypeError('view must be a callable or a list/tuple in the case of include().')

    2参数说明:

    • 正则表达式:一个正则表达式字符串
    • views视图:一个可调用对象,通常为一个视图函数
    • 参数:可选的要传递给视图函数的默认参数(字典形式)
    • 别名:一个可选的name参数

    (3: 注意事项)

    1. urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
    2. 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
    3. 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
    4. 每个正则表达式前面的'r' 是可选的但是建议加上

    (二):分组

    1 无名分组:

    分组匹配,相当于按照位置参数传递给视图函数

    views.py

    def add2(request,a,b)
        c=int(a)+(b)
        return HttpResponse(str(c))

    usrl.py

    url(r'^add('d{2})/(d{2})/$',views.for_for,name='add1')

    2 有名分组

    分组名匹配---.>按照关键字参数传递给视图函数

    命名组可以使用命名的正则表达式组来捕获 URL 中的值并以关键字参数的方式传递给视图函数。

    在 Python 正则表达式中,命名正则表达式组的语法是 (?P<name>pattern),其中 name 是组的名称,pattern 是要匹配的模式。

    url(r'^test/(?P<year>[0-9]{4})/$', test),
    from django.http.response import HttpResponse
    
    # 上面 url 的最后四个数字作为关键字参数 year 被传入到视图函数 test 中
    def test(request, year):
        return HttpResponse('年份:' + year) 

     

    三:url反向解析

    本质就是给url匹配模式七别名,然后用别名拿到具体的url路径,避免挨个修改视图和模板中的url,改一个地方,全部都能改变

    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'^loginxxx/', views.login,name='login'),
        url(r'^indexxx/', views.index, name='index'),
    ]

    视图views.py

    在视图中如何使用:

    1、from django.urls import reverse

    2、reverse("别名") --> 得到具体的URL路径

     

    from diango.shortcuts import render,HttpResponse,redirect
    from django.core.urlresolvers import reversr #导入erverse包
    
    def login(request):
        if request,method == "POST":
            return redirect(reverse('index')) # 解析成indexwww/
        return render(request,'login.html')
    
    
    def index(request):
        return HttpResponse('this is index')

    模板 templates/login.html

    在模板语言里面使用:

    {% url "别名" %} --> 得到具体的URL路径

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
     
    <form action="{% url 'login' %}" method="post"> <!-- 解析成loginxxx/ -->
        {% csrf_token %}
        <input type="text" name="user" placeholder="username">
        <input type="password" name="pwd" placeholder="password">
        <input type="submit" value="提交">
    </form>
    </body>
    </html>

      

    四:路由,分组,反向,解析,小结

    1)URL常用有模式一FBV(function base view)

      url(r'^index/', views.index)     一个URL地址对应一个views中方法

     

        2)URL常用有模式一CBV(class base view)

      url(r'^home/', views.Home.as_view()) 
            #动太路由,一类URL,以不同的方式执行不同的方法,比如get,post等,view中也调用不同的get,post方法

     

        3)url中传递参数,分普通传递参数和带命名的参数

        A)普通传递参数

        url(r'^detail-(d+)-(d+).html',views.detail)传递两个参数

              def detail(request,nid,uid)和上面严格的按顺序对应,


          B)带命名的参数
              url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html',views.detail) 第一个传递给nid,第二个给uid
              def detail(request,nid,uid)==def detail(request,uid,nid)参数位置不对,也可以正确传递
             传递参数推荐使用带命名的参数。

     

     4)url中name属性:name对URL路由关系进行命名

        写法如下:

        url(r'^index11/', views.index,name="index"), 表示url有个名字,就是不管前面r^index/'怎么变,我们都可以通过name调用

        比如:原url(r'^index11/', views.index,name="index"), 该为url(r'^index/', views.index,name="index")

        这个时候模块中form的action 也要相应做调用。

        <form action="/index11/" method="post">

        调整为<form action="/index/" method="post">

        如何避免这种情况,可以采集如下办法:

        <form action="{% url "index"%}" method=post">

        用法:<form action="{% url "url中的name"%}" method=post">

         注:假如有变量a 和b如何传递

        <form action="{% url "index" a    b %}" method=post">

     

     

        特别情况1)上面的name只能获取到前缀url:比如url(r'^index11/', views.index,name="index"), 中的index11。如果url中带有参数就需要做相应的调整

        A)带参数url使用方法1

        url(r'^index11/(d+)', views.index,name="indexx"), 

        对应URL地址:http://127.0.0.1/index11/1

        模板中调整:<form action="{% url "indexx"% 1}" method="post">  1就是传递的参数,但是这里1是写死的,如果参数变了调整相当麻烦,如何解决?

     

        B)带参数url使用方法2

        可以通过views中request解决。request.path_info有访问地址,reqeust是传递给模板的(render中第一个参数)

        模板中调整<form action="{{request.path_info}}" method="post">,但是要注意这里跳转还是当前的页

     

        C)带参数url使用方法3

         还可以通过view中方法reveser实现参数传递

         示例:

    复制代码
    还可以通过view中方法实现reveser
    
      1)普通传递
    
        url(r'^index11/(d+)', views.index,name="indexx")
    
    
        def index(request,nid):
            print(request.path_info)
            
            from django.urls import reverse
            v=reverse("indexx",args=(90,))传递参数
            print(v)
            return render(request,"index.html",{"USER_DICT":USER_DICT})
      
        <form action="{% url "index11" 90 %}" method="post">
    
      2)带命名传递
    
          url(r'^index11/(?P<nid>d+)', views.index,name="indexx")
    
           v=reverse("indexx",kwargs=(90,))传递参数
            <form action="{% url "index11" nid=1%}" method="post">
    复制代码

     

    归纳一下:

     

    复制代码
    url的命名和反向解析
        
            urls.py:
                
                url(r'^author_list/$', views.author_list, name='author_list'),
                
                url(r'^home/([0-9]{4})/([0-9]{2})/',views.home,name='home'),
                
                url(r'^home/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/',views.home,name='home'),
            视图中反向解析:
                
                from django.urls import reverse
                
                reverse('author_list')  ——》 '/author_list/'
                
                无名分组:
                reverse('home',args=('1999','06'))                     ——》'/home/1999/06/'
                
                有名分组
                
                reverse('home',kwargs={'year':'1998','month':'06'})    ——》'/home/1998/06/'
                
            
            
            模板中反向解析:
                {% url 'author_list' %}     ——》 '/author_list/'
                
                无名分组:
                {% url 'home' '2000' '09'  %}
                
                有名分组:
                {% url 'home' '2000' '09'  %}
                {% url 'home'  month='09' year='1898' %}
    复制代码

     

     五:路由分发

    1、创建好Project后在全局配置文件中有一个urls.py这个模块,该模块主要管理本项目的全局url配置

    2、每个APP也应该创建一个urls.py模块来管理自己APP下的url集(

    (一)全局urls.py配置

    需要注意的是:

    1、需要import  include模块

    2、在urlpatterns中添加app下的urls模块, namespace 参数可以防止不同app下的 url name重名的问题。

    项目下的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')),
     
    ]
    复制代码

     

     (二)APP下的urls.py

    1、import django中url模块

    2、import app中的views模块

    3、需要注意的是url是以正则表达式来配置管理,访问web页面的url = 全局url+APP url

    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'),
     
    ]
    复制代码

    app01.views.py

    复制代码
    from django.shortcuts import HttpResponse
    from django.core.urlresolvers import reverse
     
     
    def index(request):
        return HttpResponse(reverse('app01:index'))
    复制代码

    app02.views.py

    复制代码
    from django.shortcuts import HttpResponse
    from django.core.urlresolvers import reverse
     
     
    def index(request):
        return HttpResponse(reverse('app02:index'))
    复制代码

     

    from django.contrib import admin
    from django.urls import path
    from app01 import views
     
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index),
    ]

    新建index视图函数,修改views.py文件

    1
    2
    3
    4
    5
    from django.shortcuts import render,HttpResponse
     
    # Create your views here.
    def index(request):
        return HttpResponse("INDEX")
  • 相关阅读:
    Building a flexiable renderer
    Indirect Illumination in mental ray
    我的心情
    Cellular Automata
    Subsurface Scattering in mental ray
    Shader Types in mental ray
    BSP Traversal
    我的渲染器终于达到了MR的速度
    How to handle displacement and motion blur
    说明
  • 原文地址:https://www.cnblogs.com/ouyang99-/p/9925700.html
Copyright © 2011-2022 走看看