路由分发
如果一个django项目特别庞大,里面有很多应用,每个应用下有很多对应关系。那么django自带的路由层里面的代码就会非常非常的多。
我们可以根据应用的不同拆分路由对应关系到不同的应用中。django支持每个应用都可以有自己独立的路由层、模板层、静态文件、视图层(默认)、模型层(默认)。所以所有人都可以在应用中开发完整的项目功能,最后汇总到一个空的django项目中,然后通过路由分发整合所有人的应用。
路由分发的作用:能够让基于django开发的多个应用完全独立,便于小组开发
- 1.创建多个应用,并去配置文件中注册
INSTALLED_APPS = [
'app01',
'app02'
]
- 2.路由分发:总路由
# 正规写法
from django.urls import path, include
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
path('app01/',include(app01_urls)),
path('app02/',include(app02_urls))
]
# 简便写法
# 同名文件夹下urls.py文件内
from django.urls import path, include
urlpatterns = [
path('app01/', include('app01.urls')),
path('app02/', include('app02.urls')),
]
- 3.子路由
# app01应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after) # app01
]
# app02应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after) # app02
]
应用场景:当项目特别大,应用特别多的时候,可以使用路由分发,非常方便。
名称空间
在路由分发场景下多个应用在涉及到反向解析别名冲突的时候无法正常解析。默认情况下是无法直接识别应用前缀的
解决方法1:名称空间
总路由添加名称空间。
path('app01/', include(('app01.urls', 'app01'), namespace='app01')),
path('app02/', include(('app02.urls', 'app02'), namespace='app02')),
应用反向解析自动提示
# app01应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after, name='after_view'),
]
# app01应用文件夹下views.py文件内
reverse('app01:after_view')
# app02应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after, name='after_view'),
]
# app02应用文件夹下views.py文件内
reverse('app02:after_view')
#html页面
{% url 'app01:after_view' %}
{% url 'app02:after_view' %}
解决方法2:别名不冲突即可
路由分发:总路由
path('app01/', include('app01.urls')),
path('app02/', include('app02.urls')),
子路由
# app01应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after, name='app01_after_view'),
] # 给别名加个前缀,保证别名不冲突
# app01应用文件夹下views.py文件内
reverse('app01_after_view')
# app02应用文件夹下urls.py文件内
urlpatterns = [
path('after/', views.after, name='app02_after_view'),
]
# app02应用文件夹下views.py文件内
reverse('app02_after_view')
#html页面
{% url 'app01_after_view' %}
{% url 'app02_after_view' %}
虚拟环境
项目1需要使用:django1.11 python38
项目2需要使用:django2.22 pymysql requests python38
项目3需要使用:django3.22 request_html flask urllib3 python38
实际开发项目中我们只会给项目配备所需的环境,不需要的一概不配!!!
虚拟环境:能够针对相同版本的解释器创建多个分身 每个分身可以有自己独立的环境
pycharm创建虚拟环境:(每创建一个虚拟环境就相当于重新下载了一个全新的解释器)
命令行的方式: python -m venv pyvenv38
注意:python命令此处不支持多版本共存的操作 python27 python36 python38
激活
activate
关闭
deactivate
pip install --index-url http://mirrors.aliyun.com/pypi/simple/ django==1.11.11 --trusted-host mirrors.aliyun.com
视图层之必会三板斧
视图函数的返回值
视图函数必须返回一个HttpResponse对象。(HttpResponse其实是一个类)
HttpResponse
class HttpResponse(HttpResponseBase):
return HttpResponse()
render
def render():
return HttpResponse()
return render()
redirect
def redirect(to, *args, permanent=False, **kwargs):
redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect # 三元表达式
相当于 redirect_class = 类(祖先有个类是HttpResponse)
return redirect_class(resolve_url(to, *args, **kwargs))
JsonResponse对象
视图函数返回json格式数据
将下列数据用json格式展示到网页
user_dict = {'name': 'jason老师', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
json方法
def obj_json(request):
json_str = json.dumps(user_dict, ensure_ascii=False)
return HttpResponse(json_str)
JsonResponse方法
from django.http import JsonResponse
def obj_json(request):
return JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False}, safe=False)
'''序列化非字典类型的数据还需要指定safe参数为False'''
JsonResponse源码解析
from django.http import JsonResponse
class JsonResponse(HttpResponse):
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
if json_dumps_params is None:
json_dumps_params = {}
data = json.dumps(data, cls=encoder, **json_dumps_params)
super().__init__(content=data, **kwargs)
视图层之request对象获取文件
from表单携带文件数据
form表单上传的数据中如果含有文件,那么需要做以下几件事。
第一:method属性值必须是post。
第二:enctype属性值必须修改为multipart/form-data,默认是application/x-www-form-urlencoded。
第三:后端需要使用request.FILES获取,然后就可以通过句点符和with open等查看和下载文件信息。
视图层之FBV与CBV
FBV:基于函数的视图
def index(request):
return HttpResponse()
path('index/', views.index)
CBV:基于类的视图
from django import views
class MyView(views.View):
def get(self, request):
return HttpResponse('我是CBV里面的get方法')
def post(self, request):
return HttpResponse('我是CBV里面的post方法')
path('func/', views.MyView.as_view())
"""
CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行
"""
CBV源码分析(重要)
源码分析入口
path('func/', views.MyView.as_view())
1.切入点:路由匹配
类名点属性as_view并且还加了括号
as_view可能是普通的静态方法
as_view也可能是绑定给类的方法
2.对象查找属性的顺序
先从对象自身开始、再从产生对象的类、之后是各个父类
MyView.as_view()
先从我们自己写的MyView中查找,没有再去父类Views中查找
3.CBV路由匹配本质:跟FBV是一致的
项目已启动就会执行as_view方法 查看源码返回了一个闭包函数名view
def as_view(cls):
def view(cls):
pass
return view
path('func/', views.view)
# 函数名加括号执行优先级最高
4.路由匹配成功之后执行view函数(访问func触发view执行)
def view(...):
obj = cls() # cls我们直接写的类,加括号产生一个自己写的类的对象
return obj.dispatch(request, *args, **kwargs)
'''涉及到对象点名字 一定要确定对象是谁 再确定查找顺序'''
5.研究dispatch方法
def dispatch(...):
# 利用getattr反射(通过字符串操作对象的属性和方法)
#参数:obj自己写的类产生的对象,当前的请求方法。 handler就等于自己写的类里的请求方法
handler = getattr(obj, request.method.lower())
# 返回的时候加括号传承调用自己写的类里的请求方法
return handler(request, *args, **kwargs)
ps:查看源码也可以修改,但是尽量不要这么做,很容易产生bug。
模板层
模板语法传值
django提供的模板语法只有两个符号:
{{}}:主要用于数据值相关;{%%}:主要用于逻辑
django的模板语法是自己写的 跟jinja2不一样
1.针对需要加括号调用的名字 django模板语法会自动加括号调用你只需要写名字就行
2.模板语法的注释前端浏览器是无法查看的 {##}
传值的两种方式
# 方式1:指名道姓的传,适用于数据量较少的情况,节省资源
return render(request, 'modal.html', {'name':name})
# 方式2:打包传值(关键字locals()),将整个局部名称空间中的名字全部传入,适用于数据量较多的情况,简单快捷
return render(request,'modal.html',locals())
模板语法传值的特性
django的模板语法在操作容器类型的时候只允许使用句点符
data1 = {'info':{'pro':[11, 22, 33, {'name':'jason','msg':'努力就有收获'}]}}
{{ data1.info.pro.3.msg }} # 既可以点key也可以点索引 django内部自动识别
模板语法过滤器(类似于python内置函数)
<p>统计长度:{{ s|length }}</p>
<p>加法运算:{{ i|add:123 }}</p>、<p>加法运算:{{ s|add:'heihei' }}</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>
<p>单词截取(空格):{{ s1|truncatewords:6 }}</p>
# 在前端使用 |safe
<p>语法转义:{{ script_tag|safe }}</p> # safe:将后端写的代码可以在前端被识别被转换
# 在后端使用mark_safe
from django.utils.safestring import mark_safe
script_tag1 = '<script>alert(666)</script>'
res = mark_safe(script_tag1)
<p>{{ res }}</p>
ps:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入
标签:urls,after,视图,虚拟环境,CBV,app01,app02,path,view
From: https://www.cnblogs.com/wxlxl/p/16980721.html