1.知识回顾
-
创建项目:新项目、别人项目、新版版、老版本 + 项目目录(v1.0版本)
-
路由系统
-
常见路由编写加粗样式
/index/ 函数 /index/<str:v1> 函数 re_path(r'yy/(\d{4})-(\d{2})-(\d{2})/', views.yy), re_path(r'yy/(?P<v1>\d{4})-(?P<v2>\d{2})-(?P<v3>\d{2})/', views.mm), def yy(request,a1,a2,aa3): pass def mm(request,v1,v2,v3): pass
-
路由的命名
/index/ 函数 name='xx1' /index/<str:v1> 函数 name='xx2'
注意:权限的校验。
-
路由底层的实现
-
路由定义的本质
pythonurlpatterns = [ # URLPattern.resolve -> RoutePattern.match URLPattern(RoutePattern("login/", name=None, is_endpoint=True), views.login, None, None), # resolve -> RoutePattern.match path('login/', views.login), # resolve re_path(r'yy/(\d{4})-(\d{2})-(\d{2})/', views.yy), ]
-
输入网址访问我们的网站:
-
原生请求 -> 封装Request对象 /info/v1/
-
...
-
URLResolver.resolve
resolver = URLResolver("/") resolver.resolve for pattern in self.url_patterns: pattern=URLPattern对象.resolve URLPattern对象.RoutePattern对象.match /info/v1/
-
-
-
答疑:path / re_path 有啥区别呀?
-
表象:
-
path
pythonpath('login/', views.login) path('other/<int:v1>/<str:v2>/', views.other)
-
re_path
pythonre_path(r'yy/(\d{4})-(\d{2})-(\d{2})/', views.yy)
-
-
底层
path = partial(_path, Pattern=RoutePattern) re_path = partial(_path, Pattern=RegexPattern)
-
path
pythonpath('login/', views.login) path('other/<int:v1>/<str:v2>/', views.other) URLPattern(RoutePattern("login/", name=None, is_endpoint=True), views.login, None, None),
-
re_path
pythonre_path(r'yy/(\d{4})/', views.yy) URLPattern(RegexPattern("yy/(\d{4})/", name=None, is_endpoint=True), views.yy, None, None),
-
2.路由系统
2.1 常见路由
...
2.2 路由名称
...
2.3 路由底层实现
...
2.4 路由分发
研究django admin源码时:
namespace是什么?
-
无namespace
pythonfrom django.urls import reverse url = reverse("v2") print(url)
-
有namespace
pythonfrom django.urls import reverse url = reverse("namespace名称:v2") print(url) url = reverse("namespace名称:namespace名称:v2") print(url)
问题:什么叫反向
生成?
path('login/login/login/login/', views.login, name='login'),
2.5 路由本质
2.5.1 关于导入和反射
- 反射,以字符串的形式去操作对象中的成员。
- 导入模块
2.5.2 include源码
python
urlpatterns = [
path('login/', views.login),
path('api/', include("apps.base.urls")),
path('api/', (
import_module("apps.base.urls"), # 模块对象 from app.base import urls
None,
None)
)
]
python
urlpatterns = [
path('login/', views.login),
path('api/', include("apps.base.urls")),
path('api/', (
import_module("apps.base.urls"), # 模块对象 from app.base import urls
None,
None)
),
path('web/', (
[
path('v1/', www_views.login, name='v1'),
path('v2/', www_views.login, name='v2'),
],
None,
None)
),
]
在path执行时,传入的参数种类:
-
网址 + 函数
-
网址 + (模块对象,None,None)
urlpatterns = [ ... ]
-
网址 + (列表,None,None)
2.5.3 path源码
-
网址 + 函数
pythonpath('login/', views.login), URLPattern( RoutePattern("login/", name=None, is_endpoint=True), views.login, None, None )
-
网址 + (模块对象,None,None)
pythonpath('api/', include("apps.base.urls")), path('api/', ( import_module("apps.base.urls"), # 模块对象 from app.base import urls None, None) ), URLResolver( RoutePattern('api/',name=None,is_endpoint=False), import_module("apps.base.urls"), # 模块对象 from app.base import urls None, app_name=None, namespace=None )
-
网址 + (列表,None,None)
pythonpath('web/', ( [ path('v1/', www_views.login, name='v1'), path('v2/', www_views.login, name='v2'), ], None, None) ) URLResolver( RoutePattern('api/',name=None,is_endpoint=False), [ path('v1/', www_views.login, name='v1'), path('v2/', www_views.login, name='v2'), ], None, app_name=None, namespace=None )
所有URL用类和对象嵌套的形式实现:
python
from django.urls import path, re_path, include
from apps.www import views
from django.urls import URLPattern, ResolverMatch
from django.urls.resolvers import RoutePattern
from importlib import import_module
from apps.www import views as www_views
from django.urls.resolvers import URLResolver
urlpatterns = [
URLPattern(
RoutePattern("login/", name=None, is_endpoint=True),
views.login,
None,
None
),
URLResolver(
RoutePattern('api/', name=None, is_endpoint=False),
import_module("apps.base.urls"), # 模块对象 from app.base import urls
None,
app_name=None,
namespace=None
),
URLResolver(
RoutePattern('web/', name=None, is_endpoint=False),
[
path('v1/', www_views.login, name='v1'),
path('v2/', www_views.login, name='v2'),
],
None,
app_name=None,
namespace=None
)
]
2.5.4 路由匹配源码
1.请求来了
2.路由匹配
3.匹配过程
答疑:多个app的时候,路由分发到不同的app里,如果1个app,有100个路由,能不能按大类功能进行分组。
path('api/user/login/', views.login, name='login'),
path('api/user/logout/', views.login, name='login'),
path('api/user/order/', views.login, name='login'),
path('api/user/info/', views.login, name='login'),
path('api/user/ad/', views.login, name='login'),
2.6 关于网址之后的 /
-
APPEND_SLASH = True
path('login/', views.login, name='login') http://127.0.0.1:8000/login/ 成功 http://127.0.0.1:8000/login 重定向,GET http://127.0.0.1:8000/login/
当我们直接访问网址或GET请求访问网址,都会成功,如果是POST请求有问题。
-
APPEND_SLASH = False
path('login/', views.login, name='login') http://127.0.0.1:8000/login/ 成功 http://127.0.0.1:8000/login 失败 path('login', views.login, name='login') http://127.0.0.1:8000/login/ 失败 http://127.0.0.1:8000/login 成功
严格模式,自己定义是什么就以什么方式访问。
2.7 其他
3.视图
3.1 FBV和CBV
问题:你习惯用函数视图比较多还是类视图比较多。
- 非前后端分离,FBV
- 前后端分离、小程序API,CBV【django rest framekwork框架)
3.2 参数
-
request对象,读取请求相关所有的数据。
request.method request.GET ?name=123&age=123&age=199 => 特殊的字典:{name:[123],"age":[123,1999]} reqeust.POST request.FILES request.path_info request.body request.resover_math request.session
-
v1,v2 或 *args,**kwargs,用于接收动态路由中的参数值
3.3 业务处理
...
3.4 返回值
python
from django.http import HttpResponse
from django.http import JsonResponse
from django.shortcuts import render, redirect
# `构建` 响应体和响应头
# return HttpResponse("中国北京")
# return JsonResponse({"status": True, "name": "一夜白头"}, json_dumps_params={"ensure_ascii": False})
# return render(request, "demo.txt")
# return redirect("https://www.baidu.com") # 301/302
问题:那什么时候是301,什么时候是302?
python
class HttpResponseRedirect(HttpResponseRedirectBase):
status_code = 302 # 临时重定向
class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
status_code = 301 # 永久重定向
pythonav.com
5xclass.com 【运行】
4.HTML模板
希望数据 + 嵌套 HTML标签,返回给用户浏览器。
4.1 基本使用
-
编写
pythondef demo(request): # 业务处理,获取到值 user_list = ["一夜白头","星翼"] # 1.寻找demo.html,去哪里找? 优先DIRS,再去已注册APP的templates # 2.读取文件内容 + 参数 => 模板渲染(替换)【模板语法】 # 3.封装到HttpResponse的请求体中 # 4.后续给用户返回 return render(request,"demo.html",{"v1":user_list})
-
寻找
pythonINSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.staticfiles', "apps.app01.apps.App01Config", "apps.www.apps.WwwConfig", ] TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', # 'django.contrib.auth.context_processors.auth', # 'django.contrib.messages.context_processors.messages', ], }, }, ]
4.2 底层处理方式
python
namespace = {'name': 'wupeiqi', 'data': [18, 73, 84]}
code = '''def hellocute():return "name %s ,age %d" %(name,data[0],) '''
func = compile(code, '<string>', "exec")
exec(func, namespace)
result = namespace['hellocute']()
print(result)
info="""
def _execute():
_buffer = []
_buffer.append("<h1>")
_buffer.append(name)
_buffer.append("123")
_buffer.append("</h1>")
return "".join(_buffer)
"""
func = compile(info, '<string>', "exec")
exec(func, namespace)
result = namespace['_execute']()
print(result)
4.3 其他
1.继承
2.导入
3.常见问题和应用
- 页面的title问题
- 关于模板渲染的时机
4.4 自定义模板函数
-
app必须注册
-
创建templatetags的文件夹
-
任意创建文件,内容:
pythonfrom django.template.library import Library register = Library() @register.simple_tag() def my_func(v1, v2, v3): return "哈哈哈哈" + v1 + v2 + v3 @register.inclusion_tag("xo.html") def my_xo(num): return {"x1": [item for item in num if item > 22]} @register.filter def my_tt(a1, a2): return "哈哈哈" + a1 + a2
-
调用
{% load xxx %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div>{{ name }}</div> <div>{{ num }}</div> <div>{% my_func "一夜白头" "星翼" name %}</div> <div>{% my_xo num %}</div> <div>{{ "alex"|my_tt:"xxxx" }}</div> {% if "alex"|my_tt:"xxxx" %} <h1>真</h1> {% else %} <h1>家</h1> {% endif %} </body> </html>
-
片段:xo.html
<ul> {% for item in x1 %} <li>{{ item }}</li> {% endfor %} </ul>