一.URL
1.Django中路由的作用
URL与要为该URL调用的视图函数之间的映射表,就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行.
from django.urls import path
urlpatterns = [
path('test', views.test),
]
test,浏览器输入这个链接,就会响应到test这个函数来执行
2.简单的路由配置
from django.conf.urls import url
urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
url(r'^test/', views.test),
]
- 正则表达式:一个正则表达式字符串
- views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
- 参数:可选的要传递给视图函数的默认参数(字典形式)
- 别名:一个可选的name参数
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),
]
注意:
1.若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
2.不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
3.每个正则表达式前面的'r' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义
4.urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续
APPEND_SLASH
# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
APPEND_SLASH=True
Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'。
如果在settings.py中设置了 APPEND_SLASH=False,此时我们再请求页面最后不加/就会提示找不到页面。
3.有名分组与无名分组
3.1有名分组
import re
ret = re.search("(?P<year>[0-9]{4})/([0-9]{2})",'2012/12')
print(ret.group())
print(ret.group(1))
print(ret.group(2))
print(ret.group('year'))
上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL中的值并以位置参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL中的值并以关键字参数传递给视图。
在Python 正则表达式中,命名正则表达式组的语法是**(?Ppattern)**,其中name
是组的名称,pattern
是要匹配的模式。
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),
]
#捕获到的数据都是str类型
#视图函数里可以指定默认值
url('blog/$', views.blog),
url('blog/?(?P<num>[0-9]{1})', views.blog),
def blog(request,num=1):
print(num)
return HttpResponse('ok')
这里捕获的值作为关键字参数而不是位置参数传递给视图函数。
/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会更加清晰也不容易产生参顺序错误的问题。
3.2无名分组
url(r'^admin/',views.urls)
1 第一个参数,可以写一个正则表达式
2 从上往下匹配,一旦匹配成功,就不往下走了
3 在正则表达式中,用()进行分组,分组出来的数据会当作参数传到视图函数中,所以分了几个组,视图函数中必须要有几个形参接受
4 在ssetting里设置:APPEND_SLASH =False,请求时,浏览器不会自动补全全斜杠,带上斜杠就匹配失败
伪静态,方便搜索引擎收录
1.urls.py文件里面写:
url(r'^delete_publish/(\d+).html', views.delete_publish)
2.views.py里面写:
def delete_publish(request,id):
Publish.objects.filter(id=id).delete()
return redirect('/publish_list/')
3.template目录下的index.html里写:
<a href="/delete_publish/{{ publish.id }}.html">删除</a>
无名分组会把(\d+)匹配到的当作参数传给views的视图函数中,所以视图函数中一定要写用于接受的形参
注意:
有名分组和无名分组不要混用
有名分组可以用**kwargs
接收,无名分组可以用*args
接收
4.路由分发
1.在项目的urls里面写:
from django.conf.urls import url,include
2.#主urls
from django.urls import path,re_path,include
from app01 import views
from app01 import urls
urlpatterns = [
# re_path(r'^app01/',include('app01.urls')),
#namespace是指定名称空间,下面会讲解到
path('app01/',include('app01.urls',namespace='app01')),
# path('app01/', include(urls)),
]
3.在app01里创建一个urls
from django.urls import path,re_path
from app01 import views
urlpatterns = [
re_path(r'^test/(?P<year>[0-9]{2})/$',views.url_test),
]
5.反向解析
1.路由中,命一个名, url(r'index/',views.index,name='n1'),
2.在视图函数里:
from django.shortcuts import reverse
#这样就能拿到我反向解析出来的url
url = reverse('n1')
def test(request):
url = reverse('n1')
# return render(request,'test.html')
# return redirect('/index/')
return redirect(url)
def index(request):
return HttpResponse('欢迎来到首页')
3.在模板里:
<a href="{% url 'n1' %}">点我跳转首页</a>
4.带位置参数反向解析
urls: url(r'index/([0-9]{4})/([0-9]{1,2})',views.index,name='n1')
视图:url = reverse('n1',args=(2012,12))
模板:<a href="{% url 'n1' 2012 12 %}">点我跳转首页</a>
5.带关键字参数反向解析
urls: url(r'index/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})',views.index,name='n1')
视图:url = reverse('n1',args=(2012,12))
url = reverse('n1',kwargs={'year':2012,'month':12})
模板:<a href="{% url 'n1' year=2012 month=12 %}">点我跳转首页</a>
注:按位置传,顺序是固定的
总结:修改路由中url的时候,其它地方不需要改动
5.名称空间(建议不同app的url里name不要重名,可以用app_名字)
一.url(r'app01/',include('app01.urls',namespace='app01')),
2. urlpatterns = [
url(r'^test1/',views.test1,name='test')
]
3.视图函数里:
def test1(request):
url = reverse('app01:test')
print('-----app01------',url)
return HttpResponse('我是app01')
4.模板里:
<a href="{% url 'app01:test' %}">点我跳转首页</a>
=================================================================
二.url(r'app02/',include('app02.urls',namespace='app02')),
2. urlpatterns = [
url(r'^test2/',views.test2,name='test')
]
3.视图函数里:
def test2(request):
url = reverse('app02:test')
print(url)
return HttpResponse('我是app02的test2')
4.模板里:
<a href="{% url 'app02:test' %}">点我跳转首页</a>
7.django2.0的path
1.from django.urls import path
2.不支持正则,精准匹配
3.有5个转换器,int,str,slug,path,uuid
4.自定义转换器:
1.先写一个类
class Test: # 转换器
# regex这个变量名不能变,=右边是个正则表达式
regex = '[0-9]{4}'
def to_python(self, value): # 给视图函数用的
# 写一些逻辑处理
return int(value)
def to_url(self, value):
return '%04d' % value
2.from django.urls import register_converter
3.自定义转换器
register_converter(Test,'yyy')
4. path(r'index/<yyy:year>', views.index),
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
8.MTV架构与MVC架构
MTV与MVC执行流程是一样的,干的事情也是一样的
MTV:
M:models
T:template 模板
V:views(视图函数) 逻辑的处理
MVC:
M:models
V(模板):views(对应的模板)
C(控制器):controler(路由+views)
视图层:request对象
form表单,不写method,默认是get请求
1.什么情况下用get:请求数据,请求页面
2.用post请求:向服务器提交数据
request.GET ==><QueryDict: {'name': ['tom'], 'pwd': ['123']}>
request.POST ==><QueryDict: {'name': ['tom'], 'pwd': ['123']}>
request.method 请求类型
路径
http://127.0.0.1:8000/index/ppp/?name=tom
协议:IP地址和端口/路径?参数(数据)
print(request.path)==>/index/ppp/
print(request.get_full_path())==>/index/ppp/?name=tom
print(request.body) ==>就是body体内的东西