分组
项目里的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)