django框架——路由控制url----分组,分发,反向解析,名称空间,转换器,自定义转换器

分组

项目里的ulrs文件

from django.contrib import admin
from django.urls import path,re_path

from app01 import views  

urlpatterns = [
    path('admin/', admin.site.urls),
    path('timer/', views.timer), 

    # 路由配置:

    # 路径对应相关试图处理,
    # 正则表达式,注意2003匹配第一个,不往下匹配
    # path引入后添加一个re_path

    re_path(r'^articles/2003/$', views.special_case_2003),

    re_path(r'^articles/([0-9]{4})/$', views.year_archive),
    # 分组匹配成功,调用函数会传入多个参数,
    # 因此view里定义时要注意形参个数,year-archive(request,1999)

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

    # 有名分组 ?P<名字> 相当于关键字传参,此时函数定义形参时命名一致。
    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),
]

应用里的views文件

from django.shortcuts import render,HttpResponse
# 文件自己引入的,在后面添加 HttpResponse 响应对象

def timer(request):
    # 文件会把浏览器请求信息作为参数request值传入,在此要接收request
    import time
    ctime = time.time()
    return render(request, "timer.html", {"ct": ctime})
    # render方法自动去找html文件,注意传入的ctime是字典格式

# 路由配置
def special_case_2003(request):

    # 响应体的内容
    return HttpResponse("special2003")

def year_archive(request,year):
    return HttpResponse('year...')
def month_archive(request,year,month):
    pass
def article_detail(request,year,month,num):
    pass

分发

根据全局urls文件路径分发到各个应用的urls文件里,每个urls文件里可以再分组匹配不同的路径视图。

urls全局文件

from django.contrib import admin
from django.urls import path,re_path,include  # include引入
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('timer/', views.timer), 

    # 分发 除了全局的,把各自应用单独的放在各自新建文件夹urls里
    re_path(r"app01/",include("app01.urls"))  # 匹配路径之后,include各自的urls文件里执行

]

app01 urls


urlpatterns = [

    # 有名分组 ?P<名字> 相当于关键字传参,此时函数定义形参时命名一致。
    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),

]

反向解析

form 表单post请求完整执行过程以及数据获取

  • 在url里添加路径 path('login/', views.login),
  • 在views里设置执行函数
  • 写html文件
    执行过程:浏览器get请求获取页面,输入用户名密码提交,post请求给action,action当前路径又执行view里的login。所以,login执行两次,需要根据请求方式返回不同的结果。

view

def login(request):
    # 请求方式判断
    if request.method =='GET':
        return render(request,"login.html")
    else:
        # request.POST字典格式,获取数据
        user=request.POST.get('user')
        pwd=request.POST.get('pwd')
       
        # 连接数据库校验。。。
       
        # 最后一定要有return
        return HttpResponse("....")

login.html

<form action="http://127.0.0.1:8000/login/" method="post">
{#    get 请求返回页面,点击按钮post请求提交数据,又回到login,需要login校验,action是当前路径 #}

    用户名 <input type="text" name="user">
    密码 <input type="password" name="pwd">
    <input type="submit">  
</form>

如果url里路径改变,那action里也要修改,反向解析就是可以保持同步

反向解析1 模板语法

  • 给url加name标记,form表单action里模板语法渲染
# 路径可能会更改,更改之后,form表单action也得更改
    # 反向解析
    path('login/', views.login,name="Log")
<form action="{% url "Log" %}"></form>
{#    模板语法,在view里函数返回页面,render渲染时候,去找一个name=Log的url替换#}

在python脚本中

url起个name

from django.urls import path,re_path,include

from app01 import views

urlpatterns = [
    re_path(r'^articles/2003/$',views.special_case_2003,name='s_c_2003'),
    re_path(r'^articles/(?P<year>[0-9]{4})/$',views.year_archive,name='y'),
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})$',views.month_archive),
     
    path('index/',views.index,name='indexes')
]    

views,reverse函数

from django.shortcuts import render,HttpResponse
from django.urls import reverse


def special_case_2003(request): 
    url = reverse('s_c_2003')
    print(url)  # /app01/articles/2003/
    return HttpResponse('special_case_2003')


def year_archive(request,year):
    url = reverse('y',args=(year,))  # 这里有这正则表达式
    print(url)  # /app01/articles/2018/
    return HttpResponse(year)

名称空间

由于name没有作用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回。也就是说使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。

  • 分发到各个应用里urls文件时,include函数以元祖形式传入参数。
  • 以下代码是演示即使name属性相同,引入名称空间之后,反解出url也不会出错。

项目的urls文件:

rom django.urls import path,re_path,include

urlpatterns = [
    path('app01/',include(('app01.urls','app01'))), # 元祖形式,限制名称空间
    path('app02/',include(('app02.urls','app02'))),

]

app01.urls:

from django.urls import path,re_path,include
from app01 import views

urlpatterns = [
    path('index/', views.index, name='index')

]

app02.urls:

from django.urls import path, re_path, include
from app02 import views

urlpatterns = [
    path('index/', views.index, name='index')
    
]   

app01.views

from django.shortcuts import render,HttpResponse
from django.urls import reverse

def index(request):

    return HttpResponse(reverse('app01:index'))

app02.views

from django.shortcuts import render,HttpResponse
from django.urls import reverse

def index(request):

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

path

在上述路径获取执行对应的views里的函数时,传参数传入的都是字符串类型。比如正则匹配的1999,就是字符串。

re_path(r'^articles/([0-9]{4})/$', views.year_archive),
    # 分组匹配成功,调用函数会传入多个参数,
    # 因此view里定义时要注意形参个数,year-archive(request,1999)

在视图里可以转换,那可以在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),  
]

django的path可以解决:

from django.urls import path
from app01 import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),  # 注意<int:year>
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:str_data>/', views.article_detail),
]

views文件

from django.shortcuts import render,HttpResponse
...
def year_archive(request,year):
    print(year,type(year))
    return HttpResponse(year)
...
def article_detail(request,year,month,str_data):
    print(str_data,type(str_data))
    return HttpResponse(str_data)

Django默认支持以下5个转化器:

  • str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
  • int,匹配正整数,包含0。
  • slug,匹配字母、数字以及横杠、下划线组成的字符串。
  • uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
  • path,匹配任何非空字符串,包含了路径分隔符

自定义转换器

  • 新建一个文件,自定义一个类

  • 自定义一个规则属性regex,

  • 两个方法,

  • to_python(self, value) 方法,value是由类属性 regex
    所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中

  • to_url(self, value) 方法,和 to_python
    相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。

  • 在项目url里引用文件,用register_converter注册下。

  • 在path里正常用

自定义py文件放在应用文件里app01文件夹下。

# 自定义一个类
class MonConvert:

# 自定义一个规则regex,
    regex = '[0-9]{2}'

    def to_python(self,value):
        return int(value)  # 直接就转换成int了

    def to_url(self,value):
        return '%04d'%value

urls.py文件

from django.urls import path,register_converter
from app01 import views

#文件引用
from app01.urlconvert import MonConvert

# 并用register_converter注册下
register_converter(MonConvert,'mm')

urlpatterns = [
    # 上面注册成mm,这里就用mm
    path('articles/<mm:month>/', views.year_archive),
]

views.py文件

from django.shortcuts import render,HttpResponse

def year_archive(request,month):
    print(month,type(month))
    return HttpResponse(month)

猜你喜欢

转载自blog.csdn.net/Light__1024/article/details/88045878