名称空间
路由分发之后 针对相同的别名能否自动反向解析出不同的应用前缀 默认情况下是无法识别应用前缀的
如果想要正常识别区分有两种方式
方式1:名称空间
总路由
反向解析:reverse("app名称:路由别名")
方式2:别名不冲突就可以
多个应用别名不冲突可以用应用名作为别名的前缀
path('index/',views.index,name='app01_index_view')
path('index/',views.index,name='app02_index_view')
存在问题:路由别名 name 没有作用域,Django 在反向解析 URL 时,会在项目全局顺序搜索,当查找到第一个路由别名 name 指定 URL 时,立即返回。当在不同的 app 目录下的urls 中定义相同的路由别名 name 时,可能会导致 URL 反向解析错误。
解决: 使用命名空间。
普通路径:定义命名空间(include 里面是一个元组)格式如下:include(("app名称:urls","app名称"))
虚拟环境
安装python的时候相当于安装了一个全局的环境:
-
site-packages目录下是python第三方包(也就是pip install 安装的包都在该目录下)
-
标准库就是原生库(os,sys, math 等等)
-
Scripts下是可执行文件(pip install 时就会使用pip.exe这个可执行文件)
-
python.exe就是python解释器
-
虚拟环境可以看作是原生Python的副本,但是标准库都是一样的,每次都复制是不合算的
-
所以每次就不复制标准库,而是直接调用原来的标准库就行。
-
同时解释器也存到Scripts这个目录下,path环境变量只需要增加一个即可。
-
虚拟环境:能够针对相同版本的解释器创建多个分身 每个分身可以有自己独立的环境
-
pycharm创建虚拟环境:每创建一个虚拟环境就相当于重新下载了一个全新的解释器
-
在这里要注意的是python不支持多版本共存的操作
激活:activate 关闭:deactivate
视图层必会三板斧
用来处理请求的是视图函数都必须返回HttpResponse
class HttpResponse:
pass
return HttpResponse()
def render():
return HttpResponse()
return render()
def redirect():
redirect_class = 类(祖先有个类是HttpResponse)
return redirect_class()
return redirect()
JsonResponse对象
from django.http import JsonResponse
def index_func(request):
# return HttpResponse('哈哈哈')
# return render()
# return redirect()
# 返回给浏览器一个json格式的字符串
user_dict = {'name': 'jason老师', 'age': 18}
# import json
# user_json = json.dumps(user_dict, ensure_ascii=False)
# return HttpResponse(user_json)
return JsonResponse(user_dict)
以后写代码很多时候可能需要参考源码及所学知识扩展功能
class JsonResponse():
def __init__(self,data,json_dumps_params=None):
json.dumps(data,**json_dumps_params)
JsonResponse主要序列化字典 针对非字典的其他可以被序列化的数据需要修改safe参数为False
视图层之request对象获取文件
form表单携带文件类型的数据需要做到以下几点
1.method必须是post
2.enctype必须是multipart/form-data
django后端需要通过request.FILES获取文件类型的数据
视图层之FBV与CBV
FBV
-
基于函数的视图其实我们前面章节一直在使用,就是使用了函数来处理用户的请求
urls.py 文件 urlpatterns = [ path("login/", views.login), ] views.py 文件 from django.shortcuts import render,HttpResponse def login(request): if request.method == "GET": return HttpResponse("GET 方法") if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") if user == "runoob" and pwd == "123456": return HttpResponse("POST 方法") else: return HttpResponse("POST 方法1")
CBV
-
基于类的视图,就是使用了类来处理用户的请求,不同的请求我们可以在类中使用不同方法来处理,这样大大的提高了代码的可读性。
-
定义的类要继承父类 View,所以需要先引入库: from django.views import View
-
执行对应请求的方法前会优先执行 dispatch 方法(在get/post/put...方法前执行),dispatch() 方法会根据请求的不同调用相应的方法来处理。
-
Django 的 url 是将一个请求分配给可调用的函数的,而不是一个类, 主要还是通过父类 View 提供的一个静态方法 as_view() ,as_view 方法是基于类的外部接口, 他返回一个视图函数,调用后请求会传递给 dispatch 方法,dispatch 方法再根据不同请求来处理不同的方法。
urls.py 文件 urlpatterns = [ path("login/", views.Login.as_view()), ] views.py 文件 from django.shortcuts import render,HttpResponse from django.views import View class Login(View): def get(self,request): return HttpResponse("GET 方法") def post(self,request): user = request.POST.get("user") pwd = request.POST.get("pwd") if user == "runoob" and pwd == "123456": return HttpResponse("POST 方法") else: return HttpResponse("POST 方法 1")
CBV源码剖析
1.从CBV的路由匹配切入
path('login/', views.MyLoginView.as_view())
1.类名点名字(名字的查找问题)
2.类名点名字并加括号调用(静态方法、绑定给类的方法)
2.函数名加括号执行优先级最高 项目一启动就会自动执行as_view方法
path('login/', views.view) # CBV路由本质还是FBV
3.浏览器地址栏访问login路由需要执行view函数
1.产生我们自己编写类的对象
2.对象调用dispatch方法(注意查找顺序)
4.研究父类中的dispatch方法
获取当前请求方法并转小写 之后利用反射获取类中对应的方法并执行
class View:
@classmethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs)
return self.dispatch(request, *args, **kwargs)
def dispatch(self, request, *args, **kwargs):
handler = getattr(self, request.method.lower())
return handler(request, *args, **kwargs)
模板层
{{}}:主要与数据值相关
{%%}:主要与逻辑相关
django的模板语法是自己写的 跟jinja2不一样
1.针对需要加括号调用的名字 django模板语法会自动加括号调用你只需要写名字就行
2.模板语法的注释前端浏览器是无法查看的 {##}
3.
"""
1.模板语法传值
return render(request, 'demo02.html', {'n1': name, 'a1': age}) # 传值方式1:精准传值 不浪费资源 针对多资源的传递书写麻烦
return render(request,'demo02.html', locals()) # 传值方式2:将函数名称空间中所有的名字全部传递 名字过多并且不使用的情况下比较浪费资源
2.模板语法传值特性
1.基本数据类型正常展示
2.文件对象也可以展示并调用方法
3.函数名会自动加括号执行并将返回值展示到页面上(不支持额外传参)
4.类名也会自动加括号调用
5.对象则不会
ps:总结针对可以加括号调用的名字模板语法都会自动加括号调用
3.模板语法之过滤器(内置函数)
<p>统计数据的长度:{{ s1|length }}</p>
<p>算术加法或者字符串加法:{{ n1|add:111 }}、{{ s1|add:'big baby' }}</p>
<p>将数字转成合适的文件计量单位:{{ file_size|filesizeformat }}、{{ file_size1|filesizeformat }}</p> # 返回KB\MB计量单位
<p>判断当前数据对象对应的布尔值是否是False:{{ b|default:'前面的值对应的布尔值是False' }}、{{ s1|default:'前面的值对应的布尔值是False' }}</p>
<p>时间格式化:{{ ctime|date:'Y-m-d' }}</p>
<p>索引切片:{{ s1|slice:'0:8' }}</p>
<p>按照空格截取指定个数的文本:{{ s2|truncatewords:5 }}、{{ s1|truncatewords:1 }}</p> # 数字5表示截取5次 文本后面用...结尾
<p>按照字符个数截取文本(包含三个点):{{ s2|truncatechars:5 }}、{{ s1|truncatechars:10 }}</p> # 数字5表示截取2个字符加上...共五个字符
<p>移除指定的字符:{{ info|cut:'|' }}</p> # cut(移除)
<p>是否取消转换:{{ tag1 }}、{{ tag1|safe }}、{{ scripts1|safe }}、{{ res }}</p>