目录
三、视图
3.1、文件or文件夹
3.2、相对和绝对导入urls
3.3、视图参数requests
3.4、返回值
3.5、响应头
3.6、FBV和CBV
FBV
四、静态资源
4.1、静态文件
4.2、媒体文件
五、模板
5.1、寻找html模板
5.2、模板处理的本质
5.3、常见模板语法
5.4、内置模板函数
5.5、自定义模板功能
filter
simple_tag
inclusion_tag
5.6、继承和母版
5.7、模板的导入
六、Django中间件
6.1、原始方式
6.2、MiddlewareMixin(建议)
6.3、MiddlewareMixin多个
三、视图
3.1、文件or文件夹
如果你是开发一个功能较少的小项目,一个views.py文件足够了。
但如果你要开发的业务比较复杂,功能比较多,那你就要创建个文件夹来管理很多视图文件了。
3.2、相对和绝对导入urls
主urls.py
from django.urls import path,includeurlpatterns = [path('api/', include("apps.api.urls")),
]
app/urls.py
from django.contrib import admin
from django.urls import path
from apps.api.views import account # 绝对路径导入
from apps.api.views import auth # 绝对路径导入
from .views import order # 相对路径导入urlpatterns = [path('login/', account.login),path('auth/', auth.auth),path('order/', order.selectOrder),
]
注意:不要在项目根目录做相对导入。
尽量我们就用绝对导入。
3.3、视图参数requests
requests是一个对象,存放了浏览器给咱们发过来的所有内容,所以含有:
- 请求相关所有的数据: 当前访问的url、请求方式、...
- django额外添加的数据
from django.shortcuts import HttpResponsedef login(request):# 1.当前URL /api/login/print(request.path_info)# 2.URL传递的参数print(request.GET)print(request.GET.get("age"))# 3.请求方式 GET/POSTprint(request.method)# 4.如果post请求,传递请求体(原始数据)print(request.body) # b'{"code":"083Sjmll2yla694F3bll2DguCM2SjmlG","unionId":"oP6QCsyT_9bk1dfSaVf0GEV5Y-yE"}' b'v1=123&v2=456'# 4.1 请求体+请求头 b'v1=123&v2=456' + content-type:application/x-www-form-urlencoded# 当前端传的数据结构是b'v1=123&v2=456'并且content-type:application/x-www-form-urlencoded django才会自动为我们将body里的信息解析到POST中print(request.POST)print(request.POST.get("v1"))print(request.POST.get("v2"))# 4.2 请求体+请求头 文件print(request.FILES) # 文件格式 + multipart/form-dataprint(request.FILES.get("n1"))print(request.FILES.get("n2"))# 5.请求头# {'Content-Length': '', 'Content-Type': 'text/plain', 'Host': '127.0.0.1:8000', 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0', 'Sec-Ch-Ua': '" Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"', 'Sec-Ch-Ua-Mobile': '?0', 'Sec-Ch-Ua-Platform': '"macOS"', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Sec-Fetch-Site': 'none', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-User': '?1', 'Sec-Fetch-Dest': 'document', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7', 'Cookie': 'csrftoken=CdidpKSGbLxzmOXnbmlkvrZep1eJmKLAA81T73UjcjxEnMOa4YOZqtc849AkYfUy'}print(request.headers)# 5.1 请求头有个特殊的cookie# request.headers['cookie'] # 'csrftoken=CdidpKSGbLxzmOXnbmlkvrZep1eJmKLAA81T73UjcjxEnMOa4YOZqtc849AkYfUy;session=xxxx'# {'csrftoken': 'CdidpKSGbLxzmOXnbmlkvrZep1eJmKLAA81T73UjcjxEnMOa4YOZqtc849AkYfUy'}print(request.COOKIES)# 6.requests中其他值print(request.resolver_match)return HttpResponse("login")
3.4、返回值
-
HttpResponse
-
JsonResponse
-
render
-
redirect
from django.shortcuts import HttpResponse, redirect, render
from django.http import JsonResponsedef auth(request):passdef login(request):# 1、字符串/字节/文本数据(图片验证码)# return HttpResponse("login")# 2、JSON格式(前后端分离、app小程序后端、ajax请求)# data_dict = {"status": True, 'data': [11, 22, 33]}# return JsonResponse(data_dict)# 3、重定向# return redirect("https://www.baidu.com")# return redirect("http://127.0.0.1:8000/api/auth/")# return redirect("http://127.0.0.1:8000/api/auth/")# return redirect("/api/auth/")# return redirect("/api/auth/") # name## from django.urls import reverse# url = reverse("auth")# return redirect(url) # name# return redirect("auth")# 4、渲染# - a.找到 'login.html' 并读取的内容,问题:去哪里找?# - 默认先去settings.TEMPLATES.DIRS指定的路径找。(公共)# - 按注册顺序每个已注册的app中找他templates目录,去这个目录中寻找'login.html'# - 一般情况下,原则,哪个app中的模板,就去哪个app中寻找。# - b.渲染(替换)得到替换完成的字符串# - c.返回浏览器return render(request, 'api/login.html') # 这里api代表是api模块下的templates/api文件夹,里面存放着login.html
一般这么配置,在根目录下创建templates文件夹,里面存放各种html文件。
3.5、响应头
from django.shortcuts import HttpResponse, redirect, render
from django.http import JsonResponsedef login(request):res = HttpResponse("login")res['xx1'] = "hahaha"res['xx2'] = "hahaha"res['xx3'] = "hahaha"res.set_cookie('k1',"aaaaaaaa")res.set_cookie('k2',"bbbbbb")return res
而响应体其实就是我们返回的字符串login,如果你返回html,那么请求体就是你html文件的代码。
3.6、FBV和CBV
-
FBV,视图用函数的形式编写。(目前主流)
-
CBV,视图用类的形式编写。
FBV
urls.py
urlpatterns = [path('users/', views.UserView.as_view())
]
views.py
from django.shortcuts import render, HttpResponse, redirect
from django.views import Viewclass UserView(View):# 请求方式GET形式def get(self, request):pass# 请求方式POST形式def post(self, request):pass
其实本质上这段代码和下面这段代码一模一样:
def users(request):if request.method == 'GET':res = HttpResponse("GET请求")return reselse:res = HttpResponse("POST请求")return res
四、静态资源
静态资源:
-
开发需要:css、js、图片。
- 根目录的 /static/
- 已经app目录下载 /static/ 文件夹下
- 媒体文件:用户上传的数据(excel/pdf/video)
- 根目录的 /media/
4.1、静态文件
INSTALLED_APPS = [# 'django.contrib.admin',# 'django.contrib.auth',# 'django.contrib.contenttypes',# 'django.contrib.sessions',# 'django.contrib.messages','django.contrib.staticfiles',"apps.api.apps.ApiConfig","apps.web.apps.WebConfig",
]
...STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),
)
-
顺序:先去项目根目录找static,如果没有再按注册组件的顺序去找,如上:先去api模块下找static,如果没有再去web模块下找。
-
多app开发:各自app的图片放在各自
/static/app名字/。。。
例如api模块,就是apps/api/static/api/1.jpg,web模块就是apps/web/static/web/1.jpg -
在开发过程中
禁止:
<img src="/static/api/1.png">
建议:
{% load static %}<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>登录页面</h1>
<a href="/xxx/xxxxx/">调换dao xx</a>
<a href="{% url 'login' %}">跳转</a><img src="{% static 'api/1.png' %}"></body>
</html>
4.2、媒体文件
主urls.py
from django.contrib import admin
from django.urls import path, re_path, include
from django.conf.urls.static import static
from django.conf import settingsfrom apps.api import views# 很多功能,很多URL
urlpatterns = [path('api/', include('apps.api.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
五、模板
5.1、寻找html模板
先问大家一个问题
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [os.path.join(BASE_DIR, 'templates')],'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',],},},
]
当我们在settings.py文件配置了DIRS,那么就去哪里找,一般这么配置都是去项目根目录找templates文件夹。
如果配置的DIRS路径没有找到,那就继续去每一个注册的app下的templates找,顺序是按注册顺序。
优先去项目根目录 > 每个已注册的app的templates目录找。
如何选择:
-
简单的项目,模板都放在根目录。
-
复杂的项目,模板放在各自的app中,公共部分放在templates目录。
5.2、模板处理的本质
渲染完成后,生成了字符串,再返回给浏览器。
return render(request, 'app01/index.html') 的本质步骤:
- 打开app01/index.html文件,读取内容
- 渲染完成,得到一个渲染完成的文本
- 将文本返回给浏览器
其实html文件的作用就是展示,是我们django把渲染好的字符串一口气返回给html文件,然后进行展示,我们可以将index.html改为index.txt,发现也是好使的。
我们接下来分几段代码来验证模板处理的本质:
代码段1:
结果毫无疑问可以弹出100。
代码段2:
这时我们发现不但没有弹出理想的“红茶”,控制台还报错了。
我们打开网页源代码看一眼...
从这里就能看出,是django先读取html代码,将{{}}占位符都替换完后再返回到html页面的,这里我们加上引号即可。
代码段3:
这又表明了模板处理的本质,django先读取html页面代码,将所有的占位符都替换为真实的数据,它不管你外引的js文件,它只管当前页面的占位符。
5.3、常见模板语法
class Person(object):def __init__(self, name, age):self.name = nameself.age = agedef getData(self):return "利拉德"def index(request):context = {"n1": "绿茶", # 字符串"n2": [11, 22, 33, 44], # 列表"n3": { # 字典"name": "编程抗氧化","age": 29},"n4": Person("德罗赞", 20) # 对象}return render(request, 'app01/index.html', context)
5.4、内置模板函数
5.5、自定义模板功能
filter
第一步:确保你的app已经在settings.py中注册了
第二步:在你的app(这里是app01)创建templatetags文件夹
注意:只能叫templatetags。
第三步:在templatetags文件夹下创建py文件并编写自定义代码
from django import templateregister = template.Library()@register.filter()
def myfunc(value):return value.upper()
第四步:index.html使用你定义的函数
simple_tag
inclusion_tag
5.6、继承和母版
5.7、模板的导入
六、Django中间件
中间件说白了其实就是类,我们请求经过中间件(类)里的方法。
6.1、原始方式
第一步:根目录创建middlewares/md.py文件存放我们的中间件
class MyMd(object):def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):# 进来print('来了')response = self.get_response(request)# 出去print('走了')return response
第二步:注册此中间件
第三步:在某个app下的views.py随便创建一个方法
def login(request):print('函数')return HttpResponse('登录')
第四步:测试并看打印信息
这倒有点像Java里的拦截器...
6.2、MiddlewareMixin(建议)
from django.utils.deprecation import MiddlewareMixinclass MyMd(MiddlewareMixin):def process_request(self, request):print('来了')def process_response(self, request, response):print('走了')return response
6.3、MiddlewareMixin多个
执行结果是:
md1来了
md2来了
md3来了
函数
md3走了
md2走了
md1走了