路由分发
django中每个应用都可以有自己独立
的 urls.py(路由层
)、templates文件夹(模板层
)、static文件夹(静态文件资源
)。
基于以上特性多人开发项目就可以完全解耦合
,之后利用路由分发还能整合到一起
。
路由分发:总路由去匹配各应用下的子路由,让子路由去匹配各自的视图函数
使用路由分发:
①.创建不同的app应用
最下方命令行Terminal中>>python38 manage.py startapp app02
# 执行完创建app命令后不要忘记去配置文件中注册一下app
②.在每个app应用下创建urls.py文件并编写子路由
#【app01中的urls.py】
from django.urls import path
from app01 import views
urlpatterns = [
path('index/', views.index),
]
#【app02中的urls.py】
from django.urls import path
from app02 import views
urlpatterns = [
path('index/', views.index),
]
③.在各自app应用下的views.py(视图层)中写视图函数
#【app01中的views.py】:
def index(request):
return HttpResponse('这是app01中的index')
#【app02中的views.py】:
def index(request):
return HttpResponse('这是app02中的index')
④总路由中的路由分发
需导入from django.urls import include
from django.urls import path, include
urlpatterns = [
path('app01/', include('app01.urls')),
path('app02/', include('app02.urls')),
]
名称空间
路由分发后,针对相同的别名去做反向解析时无法识别各自的应用前缀
#【app01与app02中的urls.py】中起了相同的别名:
urlpatterns = [path('index/', views.index, name='index_view'),]
解决方案一:名称空间
#【总路由urls.py】中:
path('app01/', include(('app01.urls','app01'),namespace='app01')),
path('app02/', include(('app02.urls','app02'),namespace='app02')),
#【app01与的urls.py】中:
path('index/', views.index, name='index_view'),
——————————————————————————————————————————————————
#【app02与的urls.py】中:
path('index/', views.index, name='index_view'),
#【app01中的views.py】中
def index(request):
# 反向解析
print(reverse('app01:index_view'))
return HttpResponse('这是app01中的index')
——————————————————————————————————————————————————
#【app02中的views.py】中
def index(request):
# 反向解析
print(reverse('app02:index_view'))
return HttpResponse('这是app02中的index')
以上方法虽然可以实现但是很麻烦,建议用方案二
解决方案二:别名别冲突
让不同app中起的别名别一样
,前面带上各自app的名字如:
#【总路由urls.py】中:
path('app01/', include('app01.urls')),
path('app02/', include('app02.urls')),
#【app01与的urls.py】中:
path('index/', views.index, name='app01_index_view'),
——————————————————————————————————————————————————
#【app02与的urls.py】中:
path('index/', views.index, name='app02_index_view'),
#【app01中的views.py】中
def index(request):
# 反向解析
print(reverse('app01_index_view'))
return HttpResponse('这是app01中的index')
——————————————————————————————————————————————————
#【app02中的views.py】中
def index(request):
# 反向解析
print(reverse('app02_index_view'))
return HttpResponse('这是app02中的index')
虚拟环境
假如:
项目1需要使用:python38 django1.11
项目2需要使用:python38 django2.22 pymysql requests
项目3需要使用:python38 django3.11 request_html flask urllib3
#实际项目中只会给项目配备所需的环境,不需要的不配。这个时候就需要用到虚拟环境
虚拟环境:能够针对相同版本解释器可以实现多个分身,每个分身可以有自己独立的环境。(每创建一个虚拟环境就相当于重新下载了一个全新的解释器
)
(1)创建虚拟环境
①pycharm创建方式
②命令行创建方式
Terminal终端>>python -m venv pyvenv38
# python命令此处不支持多版本共存的操作 python27 python36 python38
激活
activate
关闭
deactivate
安装django1.11.1报错:
pip install django==1.11.1 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
django视图层
1)视图层之必备三板斧
用来处理请求的视图函数都必须返回一个HttpResponse对象
如果没有返回HttpResponse对象则会报以下错误
#查看源码
class HttpResponse:
pass
return HttpResponse()
def render():
return HttpResponse()
return render()
def redirect():
redirect_class = 三元表达式结果是个类(祖先有个类是HttpResponse)
return redirect_class()
return redirect()
'''
通过查看三板斧里的(HttpResonse、render、redirect)底层源码发现他们最终都是继承了HttpResponse。所以视图函数必须返回一个HttpResponse对象是没问题的
'''
JsonResponse对象
(1)把字典返回给浏览器json格式字符串
json_dumps_params={'ensure_ascii':False}
让中文不编码
#django提供的序列化模块
from django.http import JsonResponse
def index_func(request):
# 返回给浏览器一个json格式字符串
user_dict = {'name': 'jason老哥', 'age': 18}
return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
从源码中确定不让中文编码的方式:
(2)其他数据返回给浏览器json格式字符串
JsonResponse主要序列化字典 针对非字典的【其他可以被序列化的数据
】需要修改safe参数为False
from django.http import JsonResponse
def index_func(request):
# 返回给浏览器一个json格式字符串
l1 = ['张三', 'jason', 'torry']
return JsonResponse(l1, json_dumps_params={'ensure_ascii': False}, safe=False)
request对象获取文件
form表单携带文件数据需要具备的条件:
【前端html页面中:】
1.method属性值必须是"post"
2.enctype属性值必须是"multipart/form-data"
<form action="" method="post" enctype="multipart/form-data">
——————————————————————————————————————————————————————————————————
【后端views.py中:】
print(request.FILES)
request.POST # 获取的是其他数据
request.FILES # 获取的是文件数据
'可以自动区分出来各自获取各自的'
1)案例
把用户上传来的文件保存在pycharm中并保存在本地
#【urls.py】中:
urlpatterns = [
path('admin/', admin.site.urls),
path('index/',views.index_func)
]
#【views.py】中:
def index_func(request):
if request.method == 'POST':
# 一个用get() 列表多个可用getlist()
file_obj = request.FILES.get('file')
# print(file_obj.name) # 获取文件名
with open(r'%s' % file_obj.name,'wb')as f:
for i in file_obj:
f.write(i)
return render(request, 'index.html')
#【index.html】中:
<body>
<h1>获取数据</h1>
<form action="" method="post" enctype="multipart/form-data">
<p>name:
<input type="text" name="name">
</p>
<p>hobby:
<input type="checkbox" name="hobby" value="篮球">篮球
<input type="checkbox" name="hobby" value="足球">足球
<input type="checkbox" name="hobby" value="双色球">双色球
</p>
<p>file:
<input type="file" name="file">
</p>
<input type="submit" value="提交1">
<button>提交2</button>
</form>
</body>
FBV与CBV
FBV:基于函数的视图
区分不同的请求需做if判断来执行不同功能
#【urls.py】
path('index/', views.index)
#【views.py】
def index(request):
return HttpResponse()
CBV:基于类的视图
在类中只要写和请求方法相同的函数,CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行
#【urls.py】
from app01 import views
path('func/', views.MyViews.as_view())
#【views.py】
from django import views
class MyViews(views.View):
def get(self, request):
return HttpResponse('我是FBV里的get方法')
def post(self, request):
return HttpResponse('我是FBV里的post方法')
CBV源码刨析
源码分析入口:
path('func/', views.MyView.as_view())
"""
1.类名点名字(名字的查找问题)
2.类名点名字并加括号调用(静态方法、绑定给类的方法)
"""
1.绑定给类的as_view方法
def as_view(...):
def view(...):
pass
return view
2.CBV路由匹配本质:跟FBV是一致的
path('func/', views.view)
3.浏览器访问func触发view执行
def view(...):
obj = cls()
return obj.dispatch()
'''涉及到对象点名字 一定要确定对象是谁 再确定查找顺序'''
4.研究dispatch方法
def dispatch(...):
func_name = getattr(obj,request.method.lower())
func_name(...)
django模板层
1)模板语法传值
方式1:指名道姓的传 (数据较少时使用)
缺点:数据多的时候要写很多键值对
def modal(request):
name='jason'
age=18
return render(request,'modal.html',{'name':name,'age':age})
方式2:一次性全传 locals() (数据较多时使用)
#将整个局部名称空间中的名字去全部传入页面
def modal(request):
name='jason'
age=18
...
return render(request,'modal.html',locals())
模板语法传值特性
【基本数据类型:】直接传递使用
【函数名:】传递会'自动加括号'执行并将'返回值'展示到页面上
#函数如果有参数则不会执行也不会展示 模板语法不支持有参函数
【类名:】传递会'自动加括号'产生对象并展示到页面上
【对象:】传递则直接使用即可
ps:模板语法会判断每一个名字是否可调用 如果可以则调用!!!
"""django的模板语法在操作容器类型的时候只允许使用句点符"""
模板语法之过滤器
<p>统计长度:{{ s|length }}</p>
<p>加法运算:{{ i|add:123 }} 加法运算:{{ s|add:'heiheihei' }}</p>
<p>日期转换:{{ s|date:'Y-m-d H:i:s' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>数据切片:{{ l|slice:'0:10' }}</p>
<p>字符截取(...算一个字符):{{ s1|truncatechars:6 }}</p>#hello...
<p>单词截取(根据空格算一个单词):{{ s1|truncatewords:6 }}</p>
#语法转义就类似于在后端写一个前端的代码,前端展示时显示代码还是样式。显示样式需要加safe
<p>语法转义:{{ script_tag|safe }}</p>
from django.utils.safestring import mark_safe
script_tag1 = '<script>alert(666)</script>'
res = mark_safe(script_tag1)
ps:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入
'''
django模板语法中的符号就两个 一个{{}} 一个{%%}
需要使用数据的时候 {{ }}
需要使用方法的时候 {% %}
'''
标签:index,框架,views,py,request,django,app01,urls
From: https://www.cnblogs.com/lvqingmei/p/16980826.html