Django之深入了解路由层
ORM表关系建立
换位思考,先粘在一张表上面分析, 然后再站在另一张表上分析
一对一
外键字段创建在任意一张表都可以,简易在查询频率较高的一方添加
OneToOneField
models.OneToOneField(to='Author_detail') # fk + unique
一对多
外键字段创建在多的那一方
ForeignKey
models.ForeignKey(to='Publish') # to用来指代跟哪张表有关系 默认关联的就是表的主键字段
多对多
外键关系需要创建第三张表来处理。
ManyToManyField
models.ManyToManyField(to='Author') # django orm会自动帮你创建第三张关系表
Django 请求生命周期
url 路由层
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
url的第一个参数其实就是一个正则表达式,只要该正则表达式能够匹配到内容,就会立刻执行后面的视图函数,不再往下继续匹配。
路由匹配
Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'。
我们定义了urls.py:
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^blog/$', views.blog),
]
其效果就是:
访问 http://www.example.com/blog 时,默认将网址自动转换为 http://www.example/com/blog/ 。
如果在settings.py中设置了 APPEND_SLASH=False,此时我们再请求 http://www.example.com/blog 时就会提示找不到页面。
Django 路由匹配的规律:
- 先是不加斜杠,先匹配依次试试,
- 如果匹配不上,会让浏览器重定向,url最后加上斜杠再次匹配一次,
- 如果还是匹配不上就报错了。
- 并且不会匹配GET请求
?
后面携带的参数
无名分组
将分组内正则表达式匹配到的内容当做位置参数传递给视图函数
url(r'^test/([0-9]{4})/', views.test)
访问的url:http://127.0.0.1/test/1111
# 当你的路由中有分组的正则表达式 那么在匹配到内容
# 执行视图函数的时候 会将分组内正则表达式匹配到的内容当做位置参数传递给视图函数
def test(request,xxx):
'''
此时url有第二个参数,会传递给视图函数位置参数传进来。
如果不写接收的位置参数则会报错
test() takes 1 positional argument but 2 were given
'''
print(xxx) # 1111
pass
有名分组
将分组内正则表达式匹配到的内容当做关键字参数传递给视图函数
url(r'^test/(?P<year>[0-9]{4})/', views.test)
访问的url:http://127.0.0.1/test/1111
# 当你的路由中有分组的正则表达式 那么在匹配到内容
# 执行视图函数的时候 会将分组内正则表达式匹配到的内容当做关键字参数传递给视图函数
def test(request,year):
'''
此时url有第二个参数,会传递给视图函数关键字参数传进来。
如果不写接收的关键字参数则会报错
testadd() got an unexpected keyword argument 'year'
'''
print(year) # 1111
pass
利用有名个无名分组 我们就可以在调用视图函数之前给函数传递额外的参数
注意:无名分组和有名分组不能混合使用
但是同一种分组的情况下 可以使用多次,
无名可以有多个
有名可以有多个
反向解析
给路由匹配设置一个别名,
根据这个别名,动态解析出一个结果,该结果可以直接访问对应的url。
路由匹配条件无分组的情况的反向解析
urls.py:
url(r'^home/',views.home,name='hm'),
url(r'^index/$',views.index),
views.py:
def home(request):
return HttpResponse(reverse('hm'))
def index(request):
print(reverse('hm')) # /home/
return render(request,'test.html')
test.html:
<body>
<div>TEST</div>
<p><a href="{% url 'hm' %}">点我点我</a></p>
</body>
当我们在浏览器URL输入http://127.0.0.1:8000/index/的时候,
python后端进行reverse反向解析成 别名为'hm'的路径前缀,也就是home路径,
用test.html 页面渲染,html也可以使用反向解析
python后端使用反向解析:
reverse('hm')
前端html使用反向解析:
{% url 'hm' %}
将路径解析为/home/。
无名分组情况的反向解析
urls.py:
url(r'^home/(\d+)/',views.home,name='hm'),
url(r'^index/',views.index),
views.py:
def home(request,xxx):
# 使用无名分组,视图函数必须写位置参数
print(xxx)
return HttpResponse('ok')
def index(request):
print(reverse('hm',args=(1,))) # 无名分组需要手动给别名传递一个参数才能匹配上,这个参数会传递到视图函数当做位置参数。
return render(request,'test.html')
test.html:
<body>
<div>TEST</div>
<p><a href="{% url 'hm' 1 %}">点我点我</a></p>
</body>
当一个无名分组使用别名的时候,在浏览器URL输入http://127.0.0.1:8000/index/,python后端进行reverse反向解析成 别名为'hm'的路径前缀,也就是home路径,需要手动给解析出来的路径加参数,不然匹配不成功
用test.html 页面渲染,并且html使用反向解析,也需要手动传入参数
python后端使用反向解析:
reverse('hm',args=(1,))
前端html使用反向解析:
{% url 'hm' 1 %}
将路径解析为/home/1。
有名分组的反向解析
urls.py:
url(r'^home/(?P<year>\d+)/',views.home,name='hm'),
url(r'^index/',views.index),
views.py:
def home(request,year):
# 使用有名分组,视图函数必须写关键字参数
print(year)
return HttpResponse('ok')
def index(request):
print(reverse('hm',args=(1,))) # 这样也可以,但不正规
print(reverse('hm',kwargs={"year":1})) # 最正规的写法,因为有名分组传入的是关键字参数,用kwargs参数来表示
return render(request,'test.html')
test.html:
<body>
<div>TEST</div>
<p><a href="{% url 'hm' 1 %}">点我点我</a></p> # 这样也可以,但不正规
<p><a href="{% url 'hm' year=1 %}">点我点我</a></p> # 最正规的写法,因为有名分组传入的是关键字参数
</body>
当一个无名分组使用别名的时候,在浏览器URL输入http://127.0.0.1:8000/index/,python后端进行reverse反向解析成 别名为'hm'的路径前缀,也就是home路径,需要手动给解析出来的路径加参数,不然匹配不成功。
用test.html 页面渲染,并且html使用反向解析,也需要手动传入参数
python后端使用反向解析:
reverse('hm',kwargs={"year":1})
前端html使用反向解析:
{% url 'hm' year=1 %}
将路径解析为/home/1。
例子
伪代码以编辑用户信息为例,演示具体用法:
urls.py:
url(r'^edit_user/(\d+)',views.edit_user,name='edit'),
views.py:
def edit_user(request,edit_id):
# 查出来所有 user_list
# edit_id 就是用户想要编辑数据的主键值
print(edit_id)
return render(request,'edit_user.html',{"user_list":user_list})
edit_user.hmtl:
{% for user_obj in user_list %}
<a href="/edit_user/{{ user_obj.id }}">编辑</a>
<a href="{% url 'edit' user_obj.id %}">编辑</a>
{% endfor %}
路由分发
前言,在django中所有的app都可以有自己的独立的urls.py、templates、static文件夹
那么正是由于这个特点,你的django项目可以由多个人一起开发。小组长最后只需要把所有的开发的app整合到一个空的django项目里面,在settings配置文件里注册就可以了。
路由分发解决的就是项目的总路由匹配关系过多的情况,使用路由分发 会将总路由不再做匹配的活 而仅仅是做任务分发
我们新建一个app02,现在我的目录结构是:
python3 manage.py startapp app02
- app01
- app02
- mysite
- static
- templates
- manage.py
好了之后
我们在app01目录中创建urs.py
app01/urls.py:
from app01 import views
from django.conf.urls import url
urlpatterns = [
url(r'^reg/',views.reg),
]
app01/views.py:
def reg(request):
return HttpResponse("app01 reg")
-----------------------------------
app02/urls.py:
from app02 import views
from django.conf.urls import url
urlpatterns = [
url(r'^reg/',views.reg),
]
app02/views.py:
def reg(request):
return HttpResponse("app02 reg")
总urls:mysite/urls.py:
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'^app01/',include(app01_urls)),
url(r'^app02/',include(app02_urls)),
]
或者更省事的写法,不用把两个app的urls.py导过来:
urlpatterns = [
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls')),
]
最终效果,在浏览器url中输入
http://127.0.0.1:8000/app01/reg # app01 reg
http://127.0.0.1:8000/app02/reg # app02 reg
名称空间
当多个app中出现了起别名冲突的情况 你在做路由分发的时候 可以给每一个app创建一个名称空间,然后在反向解析的时候 可以选择到底去哪个名称空间中查找别名
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
# 后端
print(reverse('app01:reg'))
print(reverse('app02:reg'))
# 前端
<a href="{% url 'app01:reg' %}"></a>
<a href="{% url 'app02:reg' %}"></a>
其实不用这么麻烦,
参考建议
起别名的时候统一加上应用名前缀,这样你的别名就不会重复了。
urlpatterns = [url(r'^reg/',views.reg,name='app01_reg')]
urlpatterns = [url(r'^reg/',views.reg,name='app02_reg')]
伪静态
将一个动态网页伪装成一个静态的网页,来提高搜索引擎SEO的查询频率,提高网站的曝光度!
怎么做呢,比如博客园是一个动态网站,但是看起来像一个静态网站,是因为每篇文章都有后缀名.html
那么我们也可以写,在路由匹配规则中写上
# https://www.cnblogs.com/qinyujie/p/11394671.html
url(r'^article/(\d+).html',views.article)
虚拟环境
虚拟环境就相当于重新下载了一个纯净的python解释器,之后项目用这个虚拟环境,你需要什么就安装什么,与系统环境上存在的软件不冲突。
Django版本区别
urls.py路由匹配的方法有区别。
django 1.X
导入的模块是
from django.conf.urls import url
,
urlpatterns 中 url 对应的是正则表达式,
如下:
from django.conf.urls import url
urlpatterns = [
url = ('test',view.test)
]
django 2.X
导入的模块是from django.urls import re_path,path
path中第一个参数不支持正则表达式,写了什么就只能匹配什么,匹配不到就报错。
django 2.X 觉得你习惯了之前的正则表达式来匹配,特别人性化 ,
提供一个re_path
方法,这个方法就是1.X版本中的url()
如下:
from django.urls import path,re_path
urlpatterns = [
path = ('test',view.test),
re_path = (r'^test/(\d+)',view.test)
]
django 2.X的版本中还提供了五种转换器,
- str:匹配除路径分隔符/外的字符串
- int:匹配自然数
- slug:匹配字母,数字,横杠及下划线组成的字符串
- uuid:匹配uuid形式的数据
- path:匹配任何字符串,包括路径分隔符/
urlpatterns = [
path = ('test/<str:\d+>',view.test)
path = ('test/<int:\d+>',view.test)
path = ('test/<slug:\d+>',view.test)
path = ('test/<uuid:\d+>',view.test)
path = ('test/<path:\d+>',view.test)
]
除了内置的五种转换器外,还可以自定义自己的转换器。
- 在应用文件夹下创建converter.py文件
- 在converter.py文件中创建自定义类
- 在类中定义regex 正则,to_python方法,to_url方法
class CVT185Phone:
regex = '185\d{8}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%11d' % value
from django.urls import register_converter
from app.converter import CVT185phone
register_converter(CVT185phone,'phone185')
path('page/<phone185:msg>/',views.page,name="pages")
小例子
通过路由分发,使用app01上传文件的功能上传一个文件;
mysite/urls.py
urlpatterns = [
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls')),
]
app01/urls.py
from app01 import views
from django.conf.urls import url
urlpatterns = [
url(r'^upload/',views.upload,name='app01_upload'),
]
app01/views.py
from django.shortcuts import reverse,render,HttpResponse,redirect
def upload(request):
if request.method == "POST":
print(request.FILES)
file_obj = request.FILES.get("myfile")
with open(file_obj.name,"wb") as f:
for i in file_obj:
f.write(i)
return render(request,'upload.html')
templates/upload.html
<body>
<form action="" method="post" enctype="multipart/form-data">
请选择文件
<input type="file" name="myfile">
<input type="submit" class="btn btn-primary">提交
</form>
Django之深入了解路由层的更多相关文章
- django 实战篇之路由层
路由层 如何给网页添加首页及尾页 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'test',views.test), url(r'te ...
- day 45 Django 的初识2 路由层,视图层,模板层
前情提要: 今天继续学习Django 的内容, 今天主要和渲染相关 1>配置路由 >2:写函数 >3 指向url 一:路由层 1:配置静态支持文件 1:路由层的简单配置 >dj ...
- Django的日常-路由层
目录 Django的日常-2 路由层 有名分组和无名分组 反向解析 路由的分发 Django的日常-2 路由层 我们之前已经接触过路由层,只是我们可能不知道他叫这个名字,实际上在Django里面路由层 ...
- Django( 学习第三部 Django的url路由层)
目录 url路由层 路由匹配(有名分组与无名分组) 反向解析 路由分发 名称空间(了解) Django版本区别 url 路由匹配 注意事项: url方法,第一个参数是正则表达式,只要第一个参数能够匹配 ...
- Django学习——路由层之路由匹配、无名分组、有名分组、反向解析
路由层之路由匹配 """路由你可以看成就是出去ip和port之后的地址""" url()方法 1.第一个参数其实是一个正则表达式 2.一旦第 ...
- Django 路由层(urlconf)
Django 的路由层(URLconf) URL配置(conf)就像是Django所支撑的网站的目录; 本质就是:URL与调用该URL执行的视图函数的映射表; 通俗的讲:就是用户使用哪个url,URL ...
- Django 的路由层 视图层 模板层
--------------------------------------------------------------通过苦难,走向欢乐.——贝多芬 Django-2的路由层(URLconf) ...
- Django路由层
路由层简单配置 urlpatterns = [ url(r'^admin/$', admin.site.urls), url(r'^articles/2003/$', views.special_ca ...
- $Django 虚拟环境,2.0、1.0路由层区别,Httprequest对象,视图层(fbv,cbv),文件上传
1 虚拟环境:解决问题同一台机器上可以运行不同版本的django, 1 用pychanrm创建--->files-->newproject--->选择虚拟环境 2 setting ...
随机推荐
- JVM内核-原理、诊断与优化学习笔记(二):JVM运行机制
文章目录 JVM启动流程 PC寄存器 方法区 保存装载的类信息 通常和永久区(Perm)关联在一起 Java堆 Java栈 Java栈 – 局部变量表 ** 包含参数和局部变量 ** Java栈 – ...
- C89,C99: C数组&结构体&联合体快速初始化
1. 背景 C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序. C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组 ...
- python生成当前时间的时间戳
有时会用到时间戳,查了相关资料,在这里记一下 主要有两种方案: import datetime time_stamp = '{0:%Y-%m-%d-%H-%M}'.format(datetime.da ...
- 23-Ubuntu-文件和目录命令-查看文件内容-more 和 cat
1. more---适合查看内容多的文件 格式: more 文件名 操作键 功能 空格键 显示手册页下一屏 Enter键 一次滚动手册页的一行 b 返回上一屏 f 前滚一屏 q 退出 例: more ...
- EFCore学习记录笔记
1:连接slqlocaldb数据库 (1)在CMD下可以输入sqllocaldb info 查看本机安装的所有的localdb实例 (2)数据库连接字符串为:“Server=(localdb)\\MS ...
- 关于python merge后数据行数增加的问题
其中一个可能的原因是 join 的 data 里面的列不唯一,也就是要匹配的表里面有些一行数据对应了被匹配表多条数据,这样出来可能会增加行数,可以再查一下被匹配表里的数据是否去重
- [转]Nginx配置详解
Nginx是lgor Sysoev为俄罗斯访问量第二的rambler.ru站点设计开发的.从2004年发布至今,凭借开源的力量,已经接近成熟与完善. Nginx功能丰富,可作为HTTP服务器,也可作为 ...
- [JZOJ4331] 【清华集训模拟】树
题目 题目大意 给你一棵带点权的树,求将树变成一堆不相交的链,而且这些链的权值和非负的方案数. 正解 显然这道题是个\(DP\). 首先求个前缀和\(sum\). 为了后面讲述方便,我这样设:\(f_ ...
- 【JZOJ6342】Tiny Counting
description analysis 首先不管\(a,b,c,d\)重复的情况方案数是正逆序对之积 如果考虑\(a,b,c,d\)有重复,只有四种情况,下面括号括起来表示该位置重复 比如\(\{a ...
- QQ空间批量删除说说
按下F12,贴下如下代码 var delay = 1000; function del() { if (document.querySelector(".app_canvas_frame&q ...