Django之url

2018-03-23  本文已影响0人  Python野路子

Django 如何处理一个请求

URL解释:

url的匹配规则:

#1.普通用法,无参数情况,配置URL及其视图如下:
from django.conf.urls import url,include
from TestApp import views
urlpatterns = [
    url('^test/2018/$',views.TestOne.as_view())
]
#views.py
# -*- coding: utf-8 -*-
from django.views import View
from django.http import HttpResponse
class TestOne(View):
    def get(self,request):
        return HttpResponse('TestOne:普通url的写法')

输入地址:http://127.0.0.1:8000/test/2018/

image.png
#urls.py写法:
from django.conf.urls import url,include
from TestApp import views
urlpatterns = [
    url('^test/[0-9]{4}/$',views.TestTwo.as_view())
]
#views.py写法:
# -*- coding: utf-8 -*-
from django.views import View
from django.http import HttpResponse
class TestTwo(View):
    def get(self,request):
        return HttpResponse('TestTwo:正则url写法')

输入地址:http://127.0.0.1:8000/test/2017

image.png
#2.传递参数情况,URL中通过正则指定参数:
url('^test/([0-9]{4})/$',views.TestThree.as_view())
class TestThree(View):
    def get(self,request,year):
        return HttpResponse('TestThree:带单个非命名写法')


url('^test/([0-9]{4})/([0-9]{2})/([0-9]{2})/$',views.TestFour.as_view())

class TestFour(View):
    def get(self,request,year,month,day):
        return HttpResponse('TestFour:带多个非命名写法')

#因为当加上圆括号的时候,django就能从URL中捕获这一个值并传递给相对应的views函数,当然使用的是位置传参。
* 域名部分会被过滤掉;
* 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^test 而不是 ^/test;
* 每个正则表达式前面的'r' 是可选的但是建议加上,表示字符串中任何字符都不转义;
* 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
* 任何组匹配的变量,都会议字符串的形式传递给view, 例如通过([0-9]{4})匹配出了2019,但2019会被当做字符串传递给year。
从这里可以看出,视图的参数是根据URL的正则式,按顺序匹配并自动赋值的。虽然这样可以实现任意多个参数的传递,但是却不够灵活,URL看起来很混乱,而且
由于是正则匹配,有些情况下容易出错。
url('^test/(?P<year>[0-9]{4})/$',views.TestFive.as_view())
class TestFive(View):
    def get(self,request,year):  #入参year一定要与url中的参数命一致
        print(year)  #获取的是传过来的值
        return HttpResponse('TestFive:带单个命名参数的写法')

url('^test/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$',views.TestSix.as_view())
class TestSix(View):
    def get(self,request,year,month,day):
        print(year,month,day)
        return HttpResponse('TestSix:带多个命名参数的写法')
url(r'^test/$',views.TestFive.as_view()),
url(r'^test/(?P<year>[0-9]{4})/$',views.TestFive.as_view())

class TestFive(View):
    def get(self, request, year = '2010'):
        print('-->===>', self, request, year)
        return HttpResponse('TestFive: 命名组1')
#地址栏输入http://127.0.0.1:8000/test,调用TestFive的话,则会取year默认值2010
handler404 = 'TestApp.views.erropage' #需要app名称.views.函数名, 这个指定的实际上是一个引入的路径。只能调用函数,不能用类方法
#views.py中
def erropage(request):
    return HttpResponse('not found page')
#settings.py中调试模式关闭才能看到自定义的信息
DEBUG = False
image.png
#在应用app中新建一个urls.py放置具体的
url(r'^2018/$',views.TestOne.as_view()),
url(r'^(?P<year>[0-9]{4})/$',views.TestFive.as_view()),
url(r'^(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.TestSix.as_view()),
url(r'^(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.TestSeven.as_view())
#在项目的根 urls.py 配置文件改为:
import views
from django.conf.urls import url,include
url(r'^test/',include('TestApp.urls'))
#如果项目非常庞大,应用非常多,应用的 URL 都写在根 urls.py 配置文件中的话,会显的非常杂乱,
还会出现名称冲突之类的问题,这样对开发整个项目是非常不利的。可以这样解决,把每个应用的 URL
写在它们各自的 urls.py 配置文件里,然后在根 urls.py 里用 include() 函数引用
  1. 重定向:
#利用redirect跳转
#主程序urls.py中
from django.conf.urls import url,include
url(r'^test/',include('TestApp.urls'))
#应用程序urls.py中
import views
url(r'^2018/$',views.TestOne.as_view()),
url(r'^visit/(?P<flag>[0-9]{1})$',views.Visit.as_view())
#views.py中
from django.shortcuts import render,redirect
class Visit(View):
    def get(self,request,flag):
        #这是一个重定向方法
        #如果需要在这做一个跳转
        if flag == '1':
            return HttpResponse('hello success!')
        else:
            return redirect('/test/2018')   #重定向跳一个地址, 因为url地址开始肯定是一个/,  如果你不带斜杠的话,它就会当成一个相对地址,它自会自动在当前的url中往后添加。
  1. URL 的反向解析
    URL反向解析一般是通过[reverse函数]使用django.core.urlresolvers.reverse() 函数,以及模板中的url标记实现。
url(r'^visit/(?P<flag>[0-9]{1})$',views.Visit.as_view())
url(r'^2018/$',views.TestOne.as_view(),name='login'),
#views.py
class TestOne(View):
    def get(self,request):
        print('-->===>',self,request)
        return HttpResponse('TestOne:普通用法')
class TestOne(View):
    def get(self,request):
        print('-->===>',self,request)
        return HttpResponse('TestOne:普通用法')
class Visit(View):
    def get(self,request,flag):
        #这是一个重定向方法
        #如果需要在这做一个跳转
        if flag == '1':
            return HttpResponse('hello success!')
        else:
            # reverse未带参数
            return redirect(reverse('login'))
url(r'^visit/(?P<flag>[0-9]{1})$',views.Visit.as_view()),
url(r'^([0-9]{4})/([0-9]{2})/([0-9]{2})$', views.TestFour.as_view(),name='login3')

class Visit(View):
    def get(self,request,flag):
        #这是一个重定向方法
        #如果需要在这做一个跳转
        if flag == '1':
            return HttpResponse('hello success!')
        else:
            # reverse
            return redirect(reverse('login3',args=("2018", "03","21")))
class TestFour(View):
    def get(self, request, year,month,day):
        print('-->===>', self, request, year,month,day)
        return HttpResponse('TestFour: 3个非命名参数')
#主urls.py
url(r'^test/',include('TestApp.urls')) 
#应用urls.py
url(r'^visit/(?P<flag>[0-9]{1})/$',views.Visit.as_view()),
url(r'^login/(?P<username>[a-z]{3})/$', views.Login.as_view(),name='regist')
#views.py
class Visit(View):
    def get(self,request,flag):
        if flag =='1':
            return HttpResponse('登录成功')
        else:
            return redirect(reverse('regist',kwargs={'username':'llp'}))
class Login(View):
    def get(self,request,username):
        message = '{} please login'.format(username)
        return HttpResponse(message)
总结:如果url里面带了无名或者有名参数,那么在重定向时,reverse需要带上args或者kwargs。

如果name是唯一的时候,你可以直接只使用name,但是如果name在其它include中也存在相同name,为了区分,我们可以给inlude设置一个namespace
我们通过命名空间名称+名称访问。
为了程序的健壮性,我们尽量使用命名空间+名称访问
顶层其实有一个app名称,但是我们日常开发中,几乎不使用,该功能了解知道即可

#主urls.py
#namespace只有在有多个include时,才需要
#namespace 与name的设置规则一样,同一级别,名称需要保持唯一
url(r'^test/',include('TestApp.urls',namespace='test'))
#应用下的urls.py
url(r'^visit/(?P<flag>[0-9]{1})$',views.Visit.as_view()),
url(r'^2018/$',views.TestOne.as_view(),name='login')
#views.py
class Visit(View):
    def get(self,request,flag):
        #这是一个重定向方法
        #如果需要在这做一个跳转
        if flag == '1':
            return HttpResponse('hello success!')
        else:
            return redirect(reverse('test:login')) 
#如果url写了namespace,则这里需要namespace:name形式,否则报错;

class TestOne(View):
    def get(self,request):
        print('-->===>',self,request)
        return HttpResponse('TestOne:普通用法')

地址栏输入:http://127.0.0.1:8000/test/visit/0会重定向到http://127.0.0.1:8000/test/2018/

image.png
url(r'^test/',include('TestApp.urls',namespace='visit'))

url(r'^visit/(?P<flag>[0-9]{1})/$',views.Visit.as_view()),
url(r'^login/(?P<username>[a-z]{3})/$', views.Login.as_view(),name='regist')

class Visit(View):
    def get(self,request,flag):
        if flag =='1':
            return HttpResponse('登录成功')
        else:
            print(reverse('visit:regist',kwargs={'username':'llp'}))
            return redirect(reverse('visit:regist',kwargs={'username':'llp'}))

class Login(View):
    def get(self,request,username):
        message = '{} please login'.format(username)
        return HttpResponse(message)
#输入
http://127.0.0.1:8000/test/visit/0=>跳转到http://127.0.0.1:8000/test/login/llp/
打印出来的是:llp please login
要记住reverse这个函数其实就是返回一个字符串/test/login/llp/。
上一篇 下一篇

猜你喜欢

热点阅读