Django之路由层、视图层、模板层介绍
一、Django请求生命周期
1.路由层urls.py
1.1 urls.py配置基本格式
from django.conf.urls import url urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
]
1.11.x版本默认
from django.conf.urls import url urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test/$', views.test),
]
# 获取到用户输入的url后,根据正则匹配是否对应
# http://127.0.0.1:8000/test 请求的时候实际是请求了2次,第一次请求是按照浏览器输入的进行请求,但是没有匹配到,第二次请求浏览器会自动在末尾加一个/之后进行匹配,如果还匹配不上直接报错
# 注意事项
1 urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
2 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
3 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
4 每个正则表达式前面的'r' 是可选的但是建议加上。
urlpatterns = [
url(r'^admin/', admin.site.urls),
# url(r'test/[0-9]{4}/$', views.test),
# 无名分组:会将分组内的结果 当做位置参数自动传递给后面的视图函数views.py
url(r'test/([0-9]{4})/$', views.test),
# url(r'^test/(\d+)/$',views.test),
# 有名分组:会将分组内的结果 当做关键字参数自动传递给后面的视图函数
url(r'^testadd/(?P<id>[0-9]{4})/$',views.testadd),
]
# 无名分组:http://127.0.0.1:8000/test/3333/,视图函数加参数后可以访问,如果不加会提示test() takes 1 positional argument but 2 were given
# 有名分组
1.2 反向解析
根据别名动态解析出可以匹配上视图函数之前的url的一个结果(注意:在起别名的时候,一定要保证 所有的别名都不能重复,必须是唯一的)
# urls.py
url(r'^testxxx/',views.test,name='t')
url(r'^test/(\d+)/$',views.test,name='ttt'), # 前端
没有正则表达式的反向解析
{% url 't' %}
无名分组反向解析
有名分组同上
有正则表达式的反向解析
{% url 'ttt' 1 %} # 数字通常是数据库中字典的pk值 # 后端
from django.shortcuts import render,HttpResponse,redirect,reverse
没有正则表达式的反向解析
reverse('t')
无名分组反向解析
reverse('ttt',args=(1,)) #有正则表达式的反向解析函数视图views.py
有名分组同上 # urls.py中使用别名后,testxxx无论怎么变,浏览器中路径也会自动变化,动态解析到前端
有名分组和无名分组能否混合使用?
---有名无名不能混合使用!!!
1.3 页面伪静态
# 伪静态
让一个动态页面伪装成一个看似数据已经写死了的静态页面,其实是经过了视图函数处理,动态渲染的页面
好处:让搜索引擎加大对你这个页面的收藏力度,当别人搜索你这个页面相关内容,提高优先展示概率(花钱最好)
加大seo查询
# 例如:在urls.py中将路由设置成,视图函数views.py中还是不变:return HttpResponse("index.html")
url(r'^index.html$',views.index),
例如:10982293.html https://www.cnblogs.com/Dominic-Ji/articles/10982293.html
1.4 django版本区别1.x与2.x
1.X
路由里面用的是url()
2.X
路由里面的用的是path()
url第一个参数放的是正则表达式
而你的path第一个参数写什么就是什么,不支持正则
如果你还想使用第一个参数是正则的方法
django2.X版本中有一个叫re_path()
ps:2.x中re_path就等价于1.x中的url # 虽然path不支持正则表达式,但是它提供了五种转换器(了解)
1.5 路由分发
当一个django项目下面有多个app的情况下,总的urls.py中路由与视图函数的对应关系太多 不便于管理
这个时候就可以再每个app下创建自己的urls.py,总的urls.py不再做对应关系,而只是做分发任务
每个app下都可以有自己的urls.py static文件夹 templates模板文件,也就意味着 每个app都可以被独立的开发出来 而不需要讨论交互
# 路由分发:根据前缀,去对应的目录下查找路由 # 总路由下urls.py配置
# 重名的使用别名
from django.conf.urls import url,include
from app01 import urls as app01_urls
from app02 import urls as app02_urls urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/',include(app01_urls)),
url(r'^app02/',include(app02_urls)),
] # 应用app01下的路由
from django.conf.urls import url
from app01 import views urlpatterns = [
url(r'^urlindex',views.urlindex),
] # app01下的视图函数views.py
from django.shortcuts import render,HttpResponse,redirect def urlindex(request):
return HttpResponse("app01下的index") # 应用app02下的路由
from app02 import views urlpatterns = [
url(r'^urlindex',views.urlindex)
] # app02下的视图函数views.py
from django.shortcuts import render,HttpResponse,redirect def urlindex(request):
return HttpResponse("app02下的urlindex") # 访问app01下的链接:http://127.0.0.1:8000/app01/urlindex
# 访问app02下的链接:http://127.0.0.1:8000/app02/urlindex
# 都可以显示对应的提示
# 如果2个app下起了相同的名字,那么反向解析不支持自动查找应用前缀,需要了解名称空间的概念
# app01
urlpatterns = [
url(r'^urlindex',views.urlindex,name='aaa')
]
# app02
urlpatterns = [
url(r'^urlindex',views.urlindex,name='aaa')
]
# views.py中都打印下print('aaa')
# 访问app01和app02的urlindex后端打印的都是一样的 # 第一种方法:
# 反向解析的时候可以在name='aaa'中添加前缀解决
# 例如:name='app01_aaa' # 第二种方法:
# 名称空间(了解既可):在分发的时候再起一个名字
# 总路由urls.py中
urlpatterns = [
url(r'^app01/',include(app01_urls,namespace='app01')),
url(r'^app02/',include(app02_urls,namespace='app02')),
] #app01中的路由urls.py
urlpatterns = [
url(r'^urlindex',views.urlindex,name='aaa')
]
# app01的views.py
def urlindex(request):
print(reverse('app01:aaa'))
return HttpResponse("app01下的index")
# app02的路由
urlpatterns = [
url(r'^urlindex',views.urlindex,name='aaa')
]
# app02的views.py
def urlindex(request):
print(reverse('app02:aaa'))
return HttpResponse("app02下的urlindex") # 然后分别访问就正常了
# 使用importlib方法:
urlpatterns = [
# path('admin/', admin.site.urls),
path('home/', views.home),
path('news/<int:nid>/edit/', views.news),
path('article/', views.article),
] # int 整数
path('news/<int:nid>/edit/', views.news),
http://127.0.0.1:8000/news/1/edit/ # str 字符串
path('news/<str:nid>/edit/', views.news),
http://127.0.0.1:8000/news/s1/edit/
# slug 字母+数字+下划线+-
# uuid uuid格式,随机生成命令 uuid.uuid4()
# path 路径
path('news/<path:nid>/edit/', views.news),
http://127.0.0.1:8000/news/s1/ss/edit/
2. 视图层
2.1 JsonResponse
# views.py
import json
def index(request):
d = {'name':'simon','password':'123','hobby':'读书'}
# 前端不支持字典,需要转成json格式
return HttpResponse(json.dumps(d,ensure_ascii=False))
# 前端页面显示:http://127.0.0.1:8000/index/
{"name": "simon", "password": "123", "hobby": "读书"} # 第二种方式:
from django.http import JsonResponse
def index(request):
d = {'name':'simon','password':'123','hobby':'读书'}
# 前端不支持字典,需要转成json格式
# return HttpResponse(json.dumps(d))
return JsonResponse(d) # JsonResponse直接转换成json格式
# 前端没显示中文,可以通过JsonResponse源代码来看方法
# return JsonResponse(d,json_dumps_params={'ensure_ascii':False})
2.2 FBV与CBV
FBV function based views
CBV class based views
# views.py
from django.views import View
class MyLogin(View):
def get(self,request):
return HttpResponse("Get") def post(self,request):
return HttpResponse("Post") # urls.py中如何添加路径?
# CBV路由配置
url(r'^login/',views.MyLogin.as_view()), # 可以在前端home.html写一个页面测试post提交方式
<form action="/login/" method="post">
<input type="submit">
</form> # 可以看到我们访问login直接返回Get
# 访问home.html点击提交就会跳到login页面显示post
# 可以看到get请求来走get,post请求走post
3.模板层
模板语法--模板传值
# 模板语法 url.py
url(r'^demo/',views.demo),
# views.py
def demo(request):
i = 1
f = 1.11
s = 'hello'
# s = []
l = [1,2,3,4,5,6,7,8,9]
t = (1,2,3,4)
d = {'name':'simon','password':'123'}
se = {1,2,3,4}
# 通过字典传值方式
# return render(request,'demo.html',{'xxx':[1,2,3,4]}) def foo():
print("foo")
return "0000000oooooooooo" class Demo(object):
def index(self):
return 'index' @classmethod
def login(cls):
return 'cls' @staticmethod
def reg():
return 'reg' obj = Demo()
return render(request,'demo.html',locals()) # locals 会将所在名称空间中的所有名字全部传递给前端页面 # 前端页面
# 第一种传值方式
return render(request,'demo.html',{'xxx':[1,2,3,4]})
# 前端使用
{{ xxx }} # 第二种传值方式
# locals 会将所在名称空间中的所有名字全部传递给前端页面
return render(request,'demo.html',locals())
# 前端页面需要将所有定义的:i f s等使用双大括号括起来显示
# 如果是函数传到前端显示
<p>{{ foo }} 如果是函数名,传递到前端会自动加()调用,将调用后的结果展示到前端页面</p>
#如果是类
{#<p>{{ obj.index }} 只要是方法 都会自动加括号调用</p>#}
# 获取列表字典中某一个值
前端{{ l.0 }} or {{ d.name }}
3.1.过滤器
# 后端3中demo类中直接定义n和i
import datetime
ctime = datetime.datetime.now()
sss = 'sadfasf sdfasf fasdfsadf sdfa' # 前端:
{{i|add:19}} # 结果:20
{{n|filesizeformat}} # n的值进行转化成文件大小M、G等
{{ ctime|date:'Y-m-d' }} # 日期获取
{{ sss|truncatechars:20 }} # 截断一部分...来省略(20包含3个点)
{{ sss|truncatewords:2 }} # 截断,只识别空格
#后端
def demo(request):
h = "<h1>我是h1标签</h1>"
s1 = "<script>alter(123)</script>"
# 后端转义views.py
from django.utils.safestring import mark_safe
s2 = "<h2>我是h2标签</h2>"
s2 = mark_safe(s2) # 这样前端就不需要用safe了 # safe告诉前端我这个代码是安全的,可以渲染
# 前端转义
{{ h|safe }}
{{ s1 }} # 这个如果加safe,前端就会死循环
{{ s2 }}
3.2 标签
# 后端
def demo(request):
l = [1,2,3,4,5,6,7,8,9]
s3 = [1,2]
s4 =[None,1] # 模板语法的if判断
# 前端demo.html
{% if s3 %}
<p> 有值{{ s3 }}</p> # 返回结果就是这个了
{% else %}
<p>这个东西是空的</p>
{% endif %}
{% if s4.0 %}
<p> 有值{{ s4 }}</p>
{% elif s4.1 %}
<p>没值</p>
{% else %}
<p>这个东西是空的</p>
{% endif %}
# 就算值取不到也不会报错 {% for foo in l %}
{# # foo为每次列表循环的元素,first为第一个值,last为最后一个值,中间可以#}
{% if forloop.first %}
<p>first...</p>
{% elif forloop.last %}
<p>这是last</p>
{% else %}
<p>继续啊~~~</p>
{% endif %}
{% empty %}
<p>是空的,不能循环</p>
{% endfor %}
3.3 模板的继承与导入
# 模板的继承
# 在你想做成模板的页面上 添加block块儿 来标识其他用户可以占用的区域
{% extends 'tmp.html' %} {% block content %}
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>...</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}
# 先在模板中划定区域,之后子板利用block就能够找到模板中可以被使用的区域 # 通常情况下 模板中最少有三个区域
css
content
js
ps:模板中的block块儿越多 页面的可扩展性越高
# 模板的导入
将一块html页面作为模块的方式 导入使用
{% include 'goodpage.html' %}
将goodpage.html页面内容直接导入到该语句的位置
# 模板的继承与导入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
<link href="/static/bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div> <!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<div class="list-group">
<a href="/loginn/" class="list-group-item active">登录</a>
<a href="/register/" class="list-group-item">注册</a>
<a href="#" class="list-group-item">Morbi leo risus</a>
<a href="#" class="list-group-item">Porta ac consectetur ac</a>
<a href="#" class="list-group-item">Vestibulum at eros</a>
</div>
</div>
<div class="col-md-9">
{% block content %}
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>...</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}
</div>
</div> </div>
</body>
</html> # login.html 模板的导入
{% extends 'tmp.html' %} {% block content %}
<h3>登录</h3>
<form action="" method="post" class="form-group">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="text" class="form-control"></p>
<input type="submit" class="btn btn-danger pull-right">
</form>
{% endblock %} # reg.html模板的导入与继承
{% extends 'tmp.html' %} {% block content %}
{# 模板的导入#}
{% include 'good.html' %}
<h3 class="text-center">注册</h3>
<form action="" method="post" class="form-group">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="text" class="form-control"></p>
<input type="submit" class="btn btn-danger pull-right">
</form>
{% endblock %}
Django之路由层、视图层、模板层介绍的更多相关文章
- day 45 Django 的初识2 路由层,视图层,模板层
前情提要: 今天继续学习Django 的内容, 今天主要和渲染相关 1>配置路由 >2:写函数 >3 指向url 一:路由层 1:配置静态支持文件 1:路由层的简单配置 >dj ...
- 模板层语法、模板层之标签、模板的继承与导入、模型层之ORM常见关键字
模板层语法.模板层之标签.模板的继承与导入.模型层之ORM常见关键字 一.模板层语法 1.模板语法的传值 urls代码: path('modal/', views.modal) views代码: de ...
- Web框架之Django_03 路由层了解(路有层 无名分组、有名分组、反向解析、路由分发 视图层 JsonResponse,FBV、CBV、文件上传)
摘要: 路由层 无名分组 有名分组 反向解析 路由分发 名称空间 伪静态网页.虚拟环境 视图层 JsonResponse FBV 与 CBV(function base views与class bas ...
- django 实战篇之视图层
视图层(views.py) django必会三板斧 HttpResponse >>> 返回字符串 render >>> 支持模板语法,渲染页面,并返回给前端 red ...
- django之视图层和部分模板层
视图层 小白必会三板斧(三个返回的都是HttpResponse对象,通过看源码,可以知道是内部实现) 1.HttpResponse # 返回字符串 2.render # 返回一个html页面 还可以给 ...
- Django之深入了解视图层
目录 视图层三板斧 HttpResponse render redirect JsonResponse FBV CBV CBV源码 如何给FBV和CBV加装饰器 视图层三板斧 规定视图函数必须有一个返 ...
- Django的View(视图层)
目录 Django的View(视图层) 一.JsonResponse 二.后端接收前端的文件 三. FBV和CBV(源码分析) 四.settings.py配置文件源码分析 五. 请求对象(HttpRe ...
- Django学习---路由url,视图,模板,orm操作
Django请求周期 url -> 路由系统 ->函数或者类 -> 返回字符串 或者 模板语言 Form表单提交: 点击提交 -> 进入url系统 -> 执行函数 ...
- 052.Python前端Django框架路由层和视图层
一.路由层(URLconf) 1.1 路由层简单配置 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Dj ...
- [Django框架之视图层]
[Django框架之视图层] 视图层 Django视图层, 视图就是Django项目下的views.py文件,它的内部是一系列的函数或者是类,用来专门处理客户端访问请求后处理请求并且返回相应的数据,相 ...
随机推荐
- 记录--卸下if-else 侠的皮衣!- 策略模式
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 当我是if-else侠的时候 怕出错 给我一个功能,我总是要写很多if-else,虽然能跑,但是维护起来确实很难受,每次都要在一个方法里面 ...
- linux 时钟同步
yum install ntp -y #cn.pool.ntp.org ntp[1-7].aliyun.com ntpdate ntp1.aliyun.com #把当前系统时间写入到CMOS中 clo ...
- opensips的dispatcher模块笔记
操作系统 :CentOS 7.6_x64 opensips版本:2.4.9 dispatcher模块模块实现了基于目的地址的调度功能,可用作无状态负载均衡,但不能保证均匀分配.今天整理下CentOS7 ...
- MySQL配置和常用命令
目录 数据库配置 常用操作 项目地址:https://github.com/aijisjtu/Bot-Battle graph LR A[配置数据源] --> B[建立连接] B --> ...
- 直播预告丨 OpenHarmony 标准系统多媒体子系统之相机解读
5 月 26日(周四)晚上 19 点,OpenHarmony 开源开发者成长计划知识赋能第五期"掌握 OpenHarmony 多媒体的框架原理"的第六节直播课,即将开播! 深开鸿资 ...
- HTML基础之input系列
<form action=""> <div> 用户名:<input type="text" name="user&quo ...
- 粗心的小红qsnctfwp
将原 apk 安装包后缀名修改为 zip 将其中的 classes3.dex 文件解压 使用 Notepad++ 或其他工具打开 classes3.dex,将第 2 行的 38 修改为 35 或 36 ...
- 基于openstack安装部署私有云详细图文教程
本文主要分享的是云计算.openstack的使用.私有云平台建设.云服务器云硬盘的构建和使用.从基本概念入手到私有云建设,信息量非常大.对于openstack的安装部署都是从官方文档中一步步的介绍,内 ...
- CentOS下修改 MySQL 的密码
做服务器运维,修改 MySQL 的密码是经常的需要,定期修改 MySQL 密码是网站安全的一个保证.这里记录一下修改 MySQL 密码的一些命令,方便以后查看. 修改root密码 CentOS 下 M ...
- 重新点亮shell————awk数组[十四]
前言 简单介绍一下awk的数组. 正文 数组的定义: 数组的遍历: 删除数组: 例子: 例子2: 结 下一节awk函数.