创建项目:新项目、别人项目、新版版、老版本 + 项目目录(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'
注意:权限的校验。
路由底层的实现
路由定义的本质
urlpatterns = [
# 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
path('login/', views.login)
path('other/<int:v1>/<str:v2>/', views.other)
re_path
re_path(r'yy/(\d{4})-(\d{2})-(\d{2})/', views.yy)
底层
path = partial(_path, Pattern=RoutePattern)
re_path = partial(_path, Pattern=RegexPattern)
path
path('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
re_path(r'yy/(\d{4})/', views.yy)
URLPattern(RegexPattern("yy/(\d{4})/", name=None, is_endpoint=True), views.yy, None, None),
…
…
…
研究django admin源码时:
namespace是什么?
无namespace
from django.urls import reverse
url = reverse("v2")
print(url)
有namespace
from 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'),
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)
)
]
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)
网址 + 函数
path('login/', views.login),
URLPattern(
RoutePattern("login/", name=None, is_endpoint=True),
views.login,
None,
None
)
网址 + (模块对象,None,None)
path('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)
path('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用类和对象嵌套的形式实现:
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
)
]
答疑:多个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'),
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 成功
严格模式,自己定义是什么就以什么方式访问。
问题:你习惯用函数视图比较多还是类视图比较多。
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,用于接收动态路由中的参数值
…
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?
class HttpResponseRedirect(HttpResponseRedirectBase):
status_code = 302 # 临时重定向
class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
status_code = 301 # 永久重定向
pythonav.com
5xclass.com 【运行】
希望数据 + 嵌套 HTML标签,返回给用户浏览器。
编写
def demo(request):
# 业务处理,获取到值
user_list = ["一夜白头","星翼"]
# 1.寻找demo.html,去哪里找? 优先DIRS,再去已注册APP的templates
# 2.读取文件内容 + 参数 => 模板渲染(替换)【模板语法】
# 3.封装到HttpResponse的请求体中
# 4.后续给用户返回
return render(request,"demo.html",{"v1":user_list})
寻找
INSTALLED_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',
],
},
},
]
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)
app必须注册
创建templatetags的文件夹
任意创建文件,内容:
from 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>