来源引用网络知识与某站曹老师视频相互结合学习记录,仅供参考!
Django 模板引擎
Django 作为 Web 框架,需要一种很便利的方法动态地生成 HTML 网页,因此有了模板这个概念;模板包含所需 HTML 的部分代码以及一些特殊语法,特殊语法用于描述如何将视图传递的数据动态插入 HTML 网页中;简单来说,模板引擎的具体思路就是通过一个通用模板加动态数据等于生成一个网页。
Django 可以配置一个或者多个模板引擎(甚至是 0 个,例如前后端分离(就不需要模板了,只需要提供 API 接口,返回 JSON 数据),Django 只提供 API 接口,无须使用模板引擎),模板引擎有Django 模板语言(Django Template Language,DTL)和 Jinja2 v3.16(也有称作"Jinja3");Django 模板语言是Django 内置的功能之一,Jinja2 v3.16 是当前 Python 流行的模板语,Jinja2 v3.16 是对Django 内置模板的一个扩展,一些高级开发扩展一般建议使用Jinja。
Django 内置模板引擎
Django 内置的模板引擎包含模板上下文 (亦可称为模板变量)、标签 和过滤器,各个功能说明如下:
- 模板上下文是以变量的形式写入模板文件里面,变量值由视图函数或视图类传递所得;
- 标签是对模板上下文进行控制输出,比如模板上下文的判断和循环控制等;
- 公共模板抽取,模板继承隶属于标签,它是将每个模板文件重复的代码抽取出来并写在一个共用的模板文件中,其他模板文件通过继承共用模板文件来实现完整的网页输出;
- 过滤器是对模板上下文进行操作处理;例如说模板上下文的内容截取、替换或者格式转化等。
模板上下文
模板上下文是模板中基本的组成单位,上下文的数据由视图函数或视图类传递;它是以两个大/花括号,里面加上变量内容来{{ variable }}表示,其中 variable 是上下文的名称,它支持 Python 所有的数据类型 ,如字典、列表、元组、字符串、整型或实例化对象等;上下文的数据格式不同,在模板里的使用方式也有所差异;
使用变量的注意事项:
- 当模板引擎遇到一个变量,将计算这个变量,然后输出结果;
- 变量约定,变量名必须由字母、数字、下划线、点组成,不能由数字和下划线开头;
- 当模板引擎遇到 " . " 的时候,按以下顺序进行解析;
- 按照 dict 解析 varkey;
- 按照对象的属性或方法解析 var.var/func;
- 按照索引解析 varindex;
- 如果变量不存在,不会引发异常,模板会插入""空字符串;
- 在模板中使用变量或方法时,不能出现 ()小括号、\[\] 中括号、{} 大/花括号;
- 调用方法时,不能传递参数;
自定义标签
标签是对模板上下文进行控制输出,它是以{% tag %}表示的,其中 tag是标签的名称,Django内置了许多模板标签;例如:{% if %}(判断标签)、{% for %}(循环标签)或{% url %}(路由标签)等;
常用内置标签如下:
|-------------------|---|---|
| 标签 | 描述 ||
| {% for %} | 遍历输出上下文的内容。 ||
| {% if %} | 对上下文进行条件判断。 ||
| {% csrf_token %} | 生成csrf token的标签,用于防护跨站请求伪造攻击。 ||
| {% url %} | 引用路由配置的地址,生成相应的路由地址。 ||
| {% with %} | 将上下文名重新命名。 ||
| {% load %} | 加载导入 Django的标签库。 ||
| {% static %} | 读取静态资源的文件内容。 ||
| {% extends xxx %} | 模板继承,xxx为模板文件名,使当前模板继承xxx模板。 ||
| {% block xxx %} | 重写父类模板的代码。 ||
模板继承
Django模板继承是一个强大的工具,可以将通用页面元素(比如说"页眉、页脚、侧边栏"等)分离出来,并在多个页面之间共享它们;就是说可以做一个基础模板,其他页面的模板可以继承这个基础模板来实现一个通用功能的一些封装;模板继承和 Python 语言中类的继承含义是一样的,在 Django 中模板只是一个文本文件(例如:HTML),只需要一个文件(HTML)放在 templates 模板目录文件路径下即可;模板继承是 Django 模板语言中最强大的部分,模板继承可以构建基本的"骨架"模板,将通用的功能或者属性写在基础模板中,也叫基类模板或者父模板;子模板可以继承父类模板,子模板继承后将自动拥有父类中的属性和方法,还可以在子模板中对父模板进行重写,即重写父模板中方法或者属性,从而实现子模板的定制;模板继承大大提高了代码的可重用性,减轻开发人员的工作量;
在模板继承中最常用了标签就是 {% block %} 与 {% extends %} 标签,其中 {% block% } 标签与 {% endblock %} 标签成对出现;
新建基础模板
26、在项目"static"目录文件路径下存放(新建或者复制粘贴等)一个名称为"Djangologo.png"的图片;

27、 在"helloWorld"应用下"templates "目录文件路径下新建一个名称为"base"的 HTML 文件,用于作为基础模板(基类模板);
其中"title"使用默认实现,因为title 其他子类模板继承后有些子类模板需要修改(如果需要子类模板能修改的话需要用到 block 定义一个变量 title,子类模板如需重写的话只要重写title 这个标识名称就行了),有些子类模板则不需要更改;
简单模拟:
- 页头"head":页头head也是不需要更改的;目前先放一个静态资源图片,书写固定,后续再灵活优化;
- 内容"content":内容content 是一个子页面,基本都需要更改的,所以使用定义一个 block,后面再跟上content 到时候再重写它;
- 页脚"footer":页脚footer约定好不需要修改,让所有的子类模板都能继承;因为很多情况下都是不变的,包括菜单,像不变的地方在基类模板中书写完成后由子类模板继承就全部继承下来了,子类模板不需要再次书写;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
{% block title %}
Python3 学习
{% endblock %}
</title>
</head>
<body>
<div id="head">
<img src="http://127.0.0.1:8000/static/Djangologo.png">
</div>
<div id="content">
{% block content %}
这是 content 内容,它是一个子页面,基本都需要更改的,烦请自定义;
{% endblock %}
</div>
<div id="footer">
页脚footer约定好不需要修改,让所有的子类模板都能继承。
</div>
</body>
</html>

28、继续在"helloWorld"应用下"templates"目录文件路径下再新建一个名称为"course"的 HTML 文件(子类模板),用于继承"base.html"基类模板;
首先使用 {% extends %} 标签来继承'base.html';然后需要重写title、重写内容content;
{% extends 'base.html' %}
<!-- 重写title -->
{% block title %}
这是重写title--Python3
{% endblock %}
<!-- 重写内容content -->
{% block content %}
这是重写content--重写内容自定义course
{% endblock %}

29、修改"helloWorld"应用下"views.py"文件内容;
# 导包
import os
from django.http import HttpResponse, HttpResponseNotFound, JsonResponse, StreamingHttpResponse, FileResponse
from django.shortcuts import render, redirect
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from helloWorld.forms import StudentForm
from helloWorld.models import StudentInfo
# Create your views here.
# 定义类
class Person:
# 属性 姓名
name = None
# 属性 年龄
age = None
def __init__(self, name, age):
self.name = name
self.age = age
# 自定义一个index方法,里面要加上request请求对象
def index(request):
# 传递字符串类型数据,定义字符串类型变量str
str = '传递字符串类型--模板引擎'
# 定义字典类型数据
myDict = {"Jack":"11", "Queen":"12", "King":"13"}
# 创建一个对象,例如:zhangsan
zhangsan = Person("张三", 18)
# 定义列表myList、元组myTuple--列表和元组里面的元素类型没有限制,列表里面可以嵌套列表,元组里面可以嵌套元组
myList = [1, 'apple', 3.1415926, True, [5, 6], (7, 8), {9, 10}]
myTuple = (1, 'apple', 3.1415926, True, [5, 6], (7, 8), {9, 10})
# 变量content_value是字典格式
content_value = {"content_msg": str, "msg2": myDict, "msg3": zhangsan, "msg4": myList, "msg5": myTuple}
# context= 传递的本身要求格式是一个字典类型
return render(request, 'index.html', context=content_value)
# 定义index_id方法,里面第一个参数request请求对象,第二个参数 id
def index_id(request, id):
# 判断 id是否为0
if id == 0:
# 导包引入redirect模块,如果id等于0的话,重定向到一个目标静态地址
return redirect("/static/error.html")
else:
# 使用HttpResponse直接返回内容--因为id是int类型,里面得使用str()进行转换
return HttpResponse("id是" + str(id) + "的某某平台系统页面")
# 定义index_id方法,第一个参数request请求对象,里面继续跟多个路由变量"year, month, day, id"
def index_id02(request, year, month, day, id):
# 使用HttpResponse直接返回内容--因为id是int类型,里面得使用str()进行转换
return HttpResponse(str(year) + "/" + str(month) + "/" + str(day) + "/" +"id是" + str(id) + "的某某平台系统页面")
# 定义index_id方法,第一个参数request请求对象,后面跟多个路由变量"year, month, day"--注意,使用正则后不能与"id"再混合使用了
def index_id03(request, year, month, day):
# 使用HttpResponse直接返回内容--因为id是int类型,里面得使用str()进行转换
return HttpResponse(str(year) + '/' + str(month) + '/' + str(day) + "使用正则路由后的某某平台系统页面")
# 定义目标文件路径
file_path = "D:\\works\\djangoProject\\datas\\IDM.rar"
# 定义download_file1下载方法,请求需要带上request(所有的请求都要带上request)
def download_file1(request):
# 定义文件--使用open函数方法以"rb"二进制读取模式打开文件--然后返回一个file文件对象
file = open(file_path, 'rb')
# 创建构造好了HttpResponse对象之后返回给response
response = HttpResponse(file)
# 指定文件类型
response['Content-Type'] = 'application/rar-compressed'
# 扩展--指定附件及文件名字(可以动态拼接filename,并不建议使用原始名称)
response['Content-Disposition'] = 'attachment; filename=file1.rar'
return response
def download_file2(request):
file = open(file_path, 'rb')
# 创建构造好了StreamingHttpResponse对象之后返回给response
response = StreamingHttpResponse(file)
response['Content-Type'] = 'application/rar-compressed'
response['Content-Disposition'] = 'attachment; filename=file2.rar'
return response
def download_file3(request):
file = open(file_path, 'rb')
# 创建构造好了FileResponse对象之后返回给response
response = FileResponse(file)
response['Content-Type'] = 'application/rar-compressed'
response['Content-Disposition'] = 'attachment; filename=file3.rar'
return response
def get_test(request):
"""
get 请求测试
:param request:
:return:
"""
print(f'打印请求方式request.method:{request.method}')
print(f'打印常用属性request.content_type:{request.content_type}')
print(f'打印常用属性request.content_params:{request.content_params}')
print(f'打印常用属性request.COOKIES:{request.COOKIES}')
print(f'打印常用属性request.scheme:{request.scheme}')
print(f'打印常用方法request.is_secure:{request.is_secure()}')
print(f'打印常用方法request.get_host:{request.get_host()}')
print(f'打印常用方法request.get_full_path:{request.get_full_path()}')
print(f'使用request.GET.get("name")方法获取对应key值参数:{request.GET.get("name")}' )
print(f'使用request.GET.get("pwd")方法获取对应key值参数:{request.GET.get("pwd")}')
print(f'使用request.GET.get("dev")方法获取不存在的参数,返回值是'None':{request.GET.get("dev")}')
print(f'request.GET.get("prod", "555")获取的prod参数是不存在的,设置返回值'555':{request.GET.get("prod", "555")}')
return HttpResponse("hello world!http get ok!")
def post_test(request):
"""
post 请求测试方法
:param request:
:return:
"""
print(f'打印请求方式request.method:{request.method}')
print(f'使用request.POST.get("name")方法获取对应key值参数:{request.POST.get("name")}')
print(f'使用request.POST.get("pwd")方法获取对应key值参数:{request.POST.get("pwd")}')
print(f'使用request.POST.get("dev")方法获取不存在的参数,返回值是'None':{request.POST.get("dev")}')
print(f'request.POST.get("prod", "556")获取的prod参数是不存在的,设置返回值'556':{request.POST.get("prod", "556")}')
return HttpResponse("hello world!http post ok!")
def to_login(request):
"""
跳转到登录页面
:param request:
:return:
"""
# 跳转到登录页面可直接使用渲染render()方法
return render(request, 'login.html')
def login(request):
"""
登录到主页面
:param request:
:return:
"""
# 首先获取用户名和密码
user_name = request.POST.get('user_name')
pwd = request.POST.get('pwd')
# 模拟用户登录(暂不连接数据库)
if user_name == "python3" and pwd == "123456":
# session中存一个用户名
request.session['currentUserName'] = user_name
print(f'代码脚本中session获取:{request.session['currentUserName']}')
# 获取HttpResponse
response = render(request, 'main.html')
# 通过response.set_Cookie()方法来设置cookie
response.set_cookie('remember_me', True)
return response
else:
# 定义变量content_value为报错提示信息,里面是键值对格式的对象
content_value = {"error_info":"用户名或者密码错误!"}
return render(request, 'login.html', context=content_value)
def to_upload(request):
"""
跳转到上传文件页面
:param request:
:return:
"""
return render(request, 'upload.html')
def upload(request):
"""
上传文件处理
:param request:
:return:
"""
# 获取上传的文件,如果没有文件,就默认为None(如果不写指定的None,也是默认None)
myFile = request.FILES.get("myfile", None)
# 判断如果是有myFile的情况,就是说明有文件
if myFile:
# 打开特定的文件进行二进制的写操作--上传文件路径烦请自行创建(例如:在项目datas路径下新建"myFile"目录文件)
f = open(os.path.join("D:\\works\\djangoProject\\datas\\myFile", myFile.name), "wb+")
# 分块写入文件
for chunk in myFile.chunks():
f.write(chunk)
f.close()
return HttpResponse("文件上传成功!")
else:
return HttpResponse("没有发现可以上传的文件!")
# 定义List类,继续继承ListView(导包引入 from django.views.generic import ListView)
class List(ListView):
# 设置模版文件
template_name = 'student/list.html'
# 设置模型外的数据--例如:指定标题
extra_context = {'title': '学生信息列表'}
# 定义数据集(查询结果集)--StudentInfo(导入 from helloWorld.models import StudentInfo)
queryset = StudentInfo.objects.all()
# 每页展示数据的条数(自行设置)
paginate_by = 5
# 设置上下文对象名称(其实就是一个列表的对象),建议使用自定义名称,不然就默认为 objectlist
context_object_name = 'student_list'
# 定义Detail类,继续继承DetailView(导包引入 from django.views.generic import DetailView)
class Detail(DetailView):
# 设置模版文件
template_name = 'student/detail.html'
# 设置模型外的数据--例如:指定标题
extra_context = {'title': '学生信息详情'}
# 设置查询模型--指定model(不然无法查询数据)
model = StudentInfo
# 设置上下文对象名称
context_object_name = 'student'
# 指定URL中用于获取对象的唯一标识符的参数名称,默认为'pk';
# 如若在urls.py文件中自定义了名称,则需要添加对应pk_url_kwarg参数为自定义名称
# pk_url_kwarg = 'id'
# 定义Create类,继续继承CreateView(导包引入 from django.views.generic import CreateView)
class Create(CreateView):
# 设置模版文件,名称修改为create(有的名称叫"add"也行)
template_name = 'student/create.html'
# 设置模型外的数据--例如:指定标题"添加"或者"新增"都行
extra_context = {'title': '学生信息新增'}
# 因为是表单,所以需要使用form_class参数来指定form表单
form_class = StudentForm
# 执行成功后跳转地址(跳转地址可以是一个新的页面,也可以进入一个列表页面)
success_url = '/student/list'
# 定义Update类,继续继承UpdateView(导包引入 from django.views.generic import UpdateView)
class Update(UpdateView):
# 设置模版文件,名称修改为update(自定义)
template_name = 'student/update.html'
# 设置模型外的数据--例如:指定标题"编辑"或者"修改"都行
extra_context = {'title': '学生信息编辑'}
# 设置查询模型--指定model(不然无法查询数据)--传来一个组件"pk"会自动的去查数据、封装对象、显示到页面上
model = StudentInfo
# 因为是表单,所以需要使用form_class参数来指定form表单
form_class = StudentForm
# 执行成功后跳转地址(跳转地址可以是一个新的页面,也可以进入一个列表页面)
success_url = '/student/list'
# 定义Delete类,继续继承DeleteView(导包引入 from django.views.generic import DeleteView)
class Delete(DeleteView):
# 设置模版文件,名称修改为delete(自定义)
template_name = 'student/delete.html'
# 设置模型外的数据--例如:指定标题"删除"或者"修改"都行
extra_context = {'title': '学生信息删除'}
# 设置上下文对象名称
context_object_name = 'student'
# 设置查询模型--指定model(不然无法查询数据)--传来一个组件"pk"会自动的去查数据、封装对象、显示到页面上
model = StudentInfo
# 执行成功后跳转地址(跳转地址可以是一个新的页面,也可以进入一个列表页面)
success_url = '/student/list'
# 自定义跳转子类模板页面方法
def to_course(request):
"""
跳转到子类模板页面
:param request:
:return:
"""
return render(request, 'course.html')

30、修改"djangoProject"应用下的"urls.py"配置文件内容,配置定义映射关系;
"""
URL configuration for djangoProject project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.conf import settings
from django.contrib import admin
from django.urls import path, re_path, include
from django.views.generic import RedirectView
from django.views.static import serve
import helloWorld.views
urlpatterns = [
path('admin/', admin.site.urls),
# 可直接复制上面"admin",把"admin"修改为"index";后面是跟的"处理函数helloWorld.views.index"
# 是helloWorld应用的views里面的index()--引入helloWorld.views,记得index后不能加小括号,因为传入的是对象;
path('index/', helloWorld.views.index, name='index'),
# 要是请求"redirectTo"这个请求的话给重定向到"index"--重定向使用RedirectView.as_view(),里面使用关键词参数url
path('redirectTo', RedirectView.as_view(url="index/")),
# 自定义名称,例如叫"index_id/",后面再跟上某网页id;<int:id> int指定类型,路由变量为id;对应对应的路由映射
path('index_id/<int:id>', helloWorld.views.index_id),
# 多个路由变量
path('index_id02/<int:year>/<int:month>/<int:day>/<int:id>', helloWorld.views.index_id02),
# 正则表达式匹配是必须使用re_path方法,正则表达式"?P"开头是固定格式
re_path('index_id03/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})', helloWorld.views.index_id03),
# 配置媒体文件的路由地址
re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}, name='media'),
# 命名空间namespace--比如说是"user/"开头的,第一个参数include(),第二个参数namespace
# 导包引入include模块,include()里面也有两个参数,第一个是指定user的urls,第二个是项目名;
path('user/', include(('user.urls', 'user'), namespace='user')),
path('order/', include(('order.urls', 'order'), namespace='order')),
# 配置 download_file
path('download1/', helloWorld.views.download_file1),
path('download2/', helloWorld.views.download_file2),
path('download3/', helloWorld.views.download_file3),
path('get', helloWorld.views.get_test),
path('post', helloWorld.views.post_test),
path('toLogin/', helloWorld.views.to_login),
path('login', helloWorld.views.login),
path('toUpload/', helloWorld.views.to_upload),
path('upload', helloWorld.views.upload),
path('student/list', helloWorld.views.List.as_view()),
# 默认名称就是"pk",建议不要更改,在开发过程中就默认为pk即可
path('student/<int:pk>', helloWorld.views.Detail.as_view()),
# 如果把默认名称"pk"更改为其他(例如:id),则需要在urls.py配置文件Detail类中添加pk_url_kwarg参数
# path('student/<int:id>', helloWorld.views.Detail.as_view())
path('student/create', helloWorld.views.Create.as_view()),
path('student/update/<int:pk>', helloWorld.views.Update.as_view()),
path('student/delete/<int:pk>', helloWorld.views.Delete.as_view()),
path('toCourse/', helloWorld.views.to_course)
]

31、运行项目测试验证,浏览器输入"http://127.0.0.1:8000/toCourse/"打开子类模板页面,已成功实现模板继承功能;

优化图片地址
32、 修改"helloWorld"应用"templates "目录文件下"base.html"文件内容,先使用{% load %}标签加载导入 Django的标签库(加载项目中的静态文件,包括图片、css、js文件、字体文件等),然后再使用 {% static %} 标签读取静态资源的文件内容;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
{% block title %}
Python 学习
{% endblock %}
</title>
</head>
{% load static %}
<body>
<div id="head">
<img src="{% static 'Djangologo.png' %}">
</div>
<div id="content">
{% block content %}
这是 content 内容,它是一个子页面,基本都需要更改的,烦请自定义;
{% endblock %}
</div>
<div id="footer">
页脚footer约定好不需要修改,让所有的子类模板都能继承。
</div>
</body>
</html>


自定义过滤器
Django过滤器是一种用于在Django模板中处理数据的一种技术;过滤器的作用是可以对模板中的变量进行加工、过滤或格式化,返回一个新的值供模板使用;过滤器作用是在变量输出时,对输出的变量值做进一步的处理,可以使用过滤器来更改变量的输出显示;过滤器跟模板标签一样,也是在模板中对函数进行调用对输出的日期进行格式化处理,或者转换大小写字母等,这些都是有对应的过滤器去处理它们;
过滤器的语法格式():
{{ 变量 | 过滤器1:参数值1 | 过滤器2:参数值2 ... }}
{{ 变量 过滤器1:参数值1 | 过滤器2:参数值2 ... }} ● 首先是"模板变量" ● 其次是一个竖线"|(管道符)" ● 后面再跟"过滤器的名称" ● 然后冒号":"后面跟参数 里面可以跟多个管道过滤器,可以处理多次。内置的过滤器比较多,需要什么功能自行查找即可,某些个别功能会很少用到;一些常用的内置过滤器如"日期格式化、时间格式化的、排序的、转义的、长度类的、转换、对齐、截断"等;
常用内置过滤器如下:
|--------------------|---|---|
| 过滤器 | 说明描述 ||
| add | 加法。 ||
| addslashes | 添加斜杠。 ||
| capfirst | 首字母大写。 ||
| center | 文本居中。 ||
| cut | 切除字符。 ||
| date | 日期格式化。 ||
| default | 设置默认值。 ||
| default_if_none | 为None设置默认值。 ||
| dictsort | 字典排序。 ||
| dictsortreversed | 字典反向排序。 ||
| divisibleby | 整除判断。 ||
| escape | 转义。 ||
| escapejs | 转义js代码。 ||
| filesizeformat | 文件尺寸人性化显示。 ||
| first | 第一个元素。 ||
| floatformat | 浮点数格式化。 ||
| force_escape | 强制立刻转义。 ||
| get_digit | 获取数字。 ||
| iriencode | 转换IRI。 ||
| join | 字符列表链接。 ||
| last | 最后一个。 ||
| length | 长度。 ||
| length_is | 长度等于。 ||
| linebreaks | 行转换。 ||
| linebreaksbr | 行转换。 ||
| linenumbers | 行号。 ||
| ljust | 左对齐。 ||
| lower | 小写。 ||
| make_list | 分割成字符列表。 ||
| phone2numeric | 电话号码。 ||
| pluralize | 复数形式。 ||
| pprint | 调试。 ||
| random | 随机获取。 ||
| rjust | 右对齐。 ||
| safe | 安全确认。 ||
| safeseq | 列表安全确认。 ||
| slice | 切片。 ||
| slugify | 转换成ASCII。 ||
| stringformat | 字符串格式化。 ||
| striptags | 去除HTML中的标签。 ||
| time | 时间格式化。 ||
| timesince | 从何时开始。 ||
| timeuntil | 到何时多久。 ||
| title | 所有单词首字母大写。 ||
| truncatechars | 截断字符。 ||
| truncatechars_html | 截断字符。 ||
| truncatewords | 截断单词。 ||
| truncatewords_html | 截断单词。 ||
| unordered_list | 无序列表。 ||
| upper | 大写。 ||
| urlencode | 转义url。 ||
| urlize | url转成可点击的链接。 ||
| urlizetrunc | urlize的截断方式。 ||
| wordcount | 单词计数。 ||
| wordwrap | 单词包裹。 ||
| yesno | 将True,False和None,映射成字符串'yes','no','maybe'。 ||
根据给定的格式,日期格式化格式字符(专门是日期格式化时的一些参数说明);
|------|----------------------|-------------------------------------------------|
| 格式字符 | 描述说明 | 示例输出 |
| a | 'a.m.' or 'p.m.' | 'a.m.' |
| A | 'AM' or 'PM' | 'AM' |
| b | 月份,文字形式,3个字幕库,小写。 | 'jan' |
| B | 未实现。 | |
| c | ISO 8601格式。 | 2008-01-02T10:30:00.000123+02:00 |
| d | 月的日子,带前导零的2位数字。 | '01'到'31' |
| D | 周几的文字表述形式,3个字母。 | 'Fri' |
| e | 时区名称。 | ",'GMT,'-500',US/Eastern'等 |
| E | 月份,分地区。 | |
| f | 时间。 | '1',1:30' |
| g | 12小时格式,无前导零。 | '1'到'12' |
| G | 24小时格式,无前导零。 | '0'到'23' |
| h | 12小时格式。 | '01'到'12' |
| H | 24小时格式。 | '00'到23' |
| i | 分钟。 | '00'到'59' |
| I | 夏令时间,无论是否生效。 | '1'或'0' |
| j | 没有前导零的月份的日子。 | '1'到'31' |
| l | 星期几,完整英文名。 | 'Friday' |
| L | 布尔值是否是---个闰年。 | True或False |
| m | 月,2位数字带前导零。 | '01'到'12' |
| M | 月,文字,3个字母。 | "Jan" |
| n | 月无前导零。 | '1'到'12' |
| N | 美联社风格的月份缩写。 | 'Jan.' ,'Feb.','March','May' |
| o | ISO-8601周编号。 | '1999' |
| O | 与格林威治时间的差,单位小时。 | '+0200' |
| P | 时间为12小时。 | 1:30 p.m.' , 'midnight' , 'noon' , '12:30 p.m.' |
| r | RFC 5322格式化日期。 | 'Thu,21 Dec 2000 16:01:07+0200' |
| s | 秒,带前导零的2位数字。 | '00'到59' |
| S | 一个月的英文序数后缀,2个字符。 | 'st' ,'nd', 'rd'或'th' |
| t | 给定月份的天数。 | 28 to 31 |
| u | 微秒。 | 000000 to 999999 |
| U | 自Unix Epoch以来的秒数(1970年1月1日00:00:00 UTC)。无示例输出。 ||
| w | 星期几,数字无前导零。 | 'O'(星期日)至'6'(星期六) |
| W | ISO-8601周数,周数从星期一开始。 | 1,53 |
| y | 年份,2位数字。 | 99 |
| Y | 年,4位数。 | '1999' |
| z | ---年中的日子。 | 0到365 |
| Z | 时区偏移量,单位为秒。 | -43200到43200 |
33、修改"djangoProject"项目"helloWorld"应用下的"views.py "配置文件中的"index"函数方法;
# 导包
import datetime
import os
from django.http import HttpResponse, HttpResponseNotFound, JsonResponse, StreamingHttpResponse, FileResponse
from django.shortcuts import render, redirect
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from helloWorld.forms import StudentForm
from helloWorld.models import StudentInfo
# Create your views here.
# 定义类
class Person:
# 属性 姓名
name = None
# 属性 年龄
age = None
def __init__(self, name, age):
self.name = name
self.age = age
# 自定义一个index方法,里面要加上request请求对象
def index(request):
# 传递字符串类型数据,定义字符串类型变量str
str = 'hello world!'
# 日期对象date,导包引入import datetime
date = datetime.datetime.now()
# 定义字典类型数据
myDict = {"Jack":"11", "Queen":"12", "King":"13"}
# 创建一个对象,例如:zhangsan
zhangsan = Person("张三", 18)
# 定义列表myList、元组myTuple--列表和元组里面的元素类型没有限制,列表里面可以嵌套列表,元组里面可以嵌套元组
myList = [1, 'apple', 3.1415926, True, [5, 6], (7, 8), {9, 10}]
myTuple = (1, 'apple', 3.1415926, True, [5, 6], (7, 8), {9, 10})
# 变量content_value是字典格式
content_value = {"content_msg": str, "msg2": myDict, "msg3": zhangsan, "msg4": myList, "msg5": myTuple, "date": date}
# context= 传递的本身要求格式是一个字典类型
return render(request, 'index.html', context=content_value)
# 定义index_id方法,里面第一个参数request请求对象,第二个参数 id
def index_id(request, id):
# 判断 id是否为0
if id == 0:
# 导包引入redirect模块,如果id等于0的话,重定向到一个目标静态地址
return redirect("/static/error.html")
else:
# 使用HttpResponse直接返回内容--因为id是int类型,里面得使用str()进行转换
return HttpResponse("id是" + str(id) + "的某某平台系统页面")
# 定义index_id方法,第一个参数request请求对象,里面继续跟多个路由变量"year, month, day, id"
def index_id02(request, year, month, day, id):
# 使用HttpResponse直接返回内容--因为id是int类型,里面得使用str()进行转换
return HttpResponse(str(year) + "/" + str(month) + "/" + str(day) + "/" +"id是" + str(id) + "的某某平台系统页面")
# 定义index_id方法,第一个参数request请求对象,后面跟多个路由变量"year, month, day"--注意,使用正则后不能与"id"再混合使用了
def index_id03(request, year, month, day):
# 使用HttpResponse直接返回内容--因为id是int类型,里面得使用str()进行转换
return HttpResponse(str(year) + '/' + str(month) + '/' + str(day) + "使用正则路由后的某某平台系统页面")
# 定义目标文件路径
file_path = "D:\\works\\djangoProject\\datas\\IDM.rar"
# 定义download_file1下载方法,请求需要带上request(所有的请求都要带上request)
def download_file1(request):
# 定义文件--使用open函数方法以"rb"二进制读取模式打开文件--然后返回一个file文件对象
file = open(file_path, 'rb')
# 创建构造好了HttpResponse对象之后返回给response
response = HttpResponse(file)
# 指定文件类型
response['Content-Type'] = 'application/rar-compressed'
# 扩展--指定附件及文件名字(可以动态拼接filename,并不建议使用原始名称)
response['Content-Disposition'] = 'attachment; filename=file1.rar'
return response
def download_file2(request):
file = open(file_path, 'rb')
# 创建构造好了StreamingHttpResponse对象之后返回给response
response = StreamingHttpResponse(file)
response['Content-Type'] = 'application/rar-compressed'
response['Content-Disposition'] = 'attachment; filename=file2.rar'
return response
def download_file3(request):
file = open(file_path, 'rb')
# 创建构造好了FileResponse对象之后返回给response
response = FileResponse(file)
response['Content-Type'] = 'application/rar-compressed'
response['Content-Disposition'] = 'attachment; filename=file3.rar'
return response
def get_test(request):
"""
get 请求测试
:param request:
:return:
"""
print(f'打印请求方式request.method:{request.method}')
print(f'打印常用属性request.content_type:{request.content_type}')
print(f'打印常用属性request.content_params:{request.content_params}')
print(f'打印常用属性request.COOKIES:{request.COOKIES}')
print(f'打印常用属性request.scheme:{request.scheme}')
print(f'打印常用方法request.is_secure:{request.is_secure()}')
print(f'打印常用方法request.get_host:{request.get_host()}')
print(f'打印常用方法request.get_full_path:{request.get_full_path()}')
print(f'使用request.GET.get("name")方法获取对应key值参数:{request.GET.get("name")}' )
print(f'使用request.GET.get("pwd")方法获取对应key值参数:{request.GET.get("pwd")}')
print(f'使用request.GET.get("dev")方法获取不存在的参数,返回值是'None':{request.GET.get("dev")}')
print(f'request.GET.get("prod", "555")获取的prod参数是不存在的,设置返回值'555':{request.GET.get("prod", "555")}')
return HttpResponse("hello world!http get ok!")
def post_test(request):
"""
post 请求测试方法
:param request:
:return:
"""
print(f'打印请求方式request.method:{request.method}')
print(f'使用request.POST.get("name")方法获取对应key值参数:{request.POST.get("name")}')
print(f'使用request.POST.get("pwd")方法获取对应key值参数:{request.POST.get("pwd")}')
print(f'使用request.POST.get("dev")方法获取不存在的参数,返回值是'None':{request.POST.get("dev")}')
print(f'request.POST.get("prod", "556")获取的prod参数是不存在的,设置返回值'556':{request.POST.get("prod", "556")}')
return HttpResponse("hello world!http post ok!")
def to_login(request):
"""
跳转到登录页面
:param request:
:return:
"""
# 跳转到登录页面可直接使用渲染render()方法
return render(request, 'login.html')
def login(request):
"""
登录到主页面
:param request:
:return:
"""
# 首先获取用户名和密码
user_name = request.POST.get('user_name')
pwd = request.POST.get('pwd')
# 模拟用户登录(暂不连接数据库)
if user_name == "python3" and pwd == "123456":
# session中存一个用户名
request.session['currentUserName'] = user_name
print(f'代码脚本中session获取:{request.session['currentUserName']}')
# 获取HttpResponse
response = render(request, 'main.html')
# 通过response.set_Cookie()方法来设置cookie
response.set_cookie('remember_me', True)
return response
else:
# 定义变量content_value为报错提示信息,里面是键值对格式的对象
content_value = {"error_info":"用户名或者密码错误!"}
return render(request, 'login.html', context=content_value)
def to_upload(request):
"""
跳转到上传文件页面
:param request:
:return:
"""
return render(request, 'upload.html')
def upload(request):
"""
上传文件处理
:param request:
:return:
"""
# 获取上传的文件,如果没有文件,就默认为None(如果不写指定的None,也是默认None)
myFile = request.FILES.get("myfile", None)
# 判断如果是有myFile的情况,就是说明有文件
if myFile:
# 打开特定的文件进行二进制的写操作--上传文件路径烦请自行创建(例如:在项目datas路径下新建"myFile"目录文件)
f = open(os.path.join("D:\\works\\djangoProject\\datas\\myFile", myFile.name), "wb+")
# 分块写入文件
for chunk in myFile.chunks():
f.write(chunk)
f.close()
return HttpResponse("文件上传成功!")
else:
return HttpResponse("没有发现可以上传的文件!")
# 定义List类,继续继承ListView(导包引入 from django.views.generic import ListView)
class List(ListView):
# 设置模版文件
template_name = 'student/list.html'
# 设置模型外的数据--例如:指定标题
extra_context = {'title': '学生信息列表'}
# 定义数据集(查询结果集)--StudentInfo(导入 from helloWorld.models import StudentInfo)
queryset = StudentInfo.objects.all()
# 每页展示数据的条数(自行设置)
paginate_by = 5
# 设置上下文对象名称(其实就是一个列表的对象),建议使用自定义名称,不然就默认为 objectlist
context_object_name = 'student_list'
# 定义Detail类,继续继承DetailView(导包引入 from django.views.generic import DetailView)
class Detail(DetailView):
# 设置模版文件
template_name = 'student/detail.html'
# 设置模型外的数据--例如:指定标题
extra_context = {'title': '学生信息详情'}
# 设置查询模型--指定model(不然无法查询数据)
model = StudentInfo
# 设置上下文对象名称
context_object_name = 'student'
# 指定URL中用于获取对象的唯一标识符的参数名称,默认为'pk';
# 如若在urls.py文件中自定义了名称,则需要添加对应pk_url_kwarg参数为自定义名称
# pk_url_kwarg = 'id'
# 定义Create类,继续继承CreateView(导包引入 from django.views.generic import CreateView)
class Create(CreateView):
# 设置模版文件,名称修改为create(有的名称叫"add"也行)
template_name = 'student/create.html'
# 设置模型外的数据--例如:指定标题"添加"或者"新增"都行
extra_context = {'title': '学生信息新增'}
# 因为是表单,所以需要使用form_class参数来指定form表单
form_class = StudentForm
# 执行成功后跳转地址(跳转地址可以是一个新的页面,也可以进入一个列表页面)
success_url = '/student/list'
# 定义Update类,继续继承UpdateView(导包引入 from django.views.generic import UpdateView)
class Update(UpdateView):
# 设置模版文件,名称修改为update(自定义)
template_name = 'student/update.html'
# 设置模型外的数据--例如:指定标题"编辑"或者"修改"都行
extra_context = {'title': '学生信息编辑'}
# 设置查询模型--指定model(不然无法查询数据)--传来一个组件"pk"会自动的去查数据、封装对象、显示到页面上
model = StudentInfo
# 因为是表单,所以需要使用form_class参数来指定form表单
form_class = StudentForm
# 执行成功后跳转地址(跳转地址可以是一个新的页面,也可以进入一个列表页面)
success_url = '/student/list'
# 定义Delete类,继续继承DeleteView(导包引入 from django.views.generic import DeleteView)
class Delete(DeleteView):
# 设置模版文件,名称修改为delete(自定义)
template_name = 'student/delete.html'
# 设置模型外的数据--例如:指定标题"删除"或者"修改"都行
extra_context = {'title': '学生信息删除'}
# 设置上下文对象名称
context_object_name = 'student'
# 设置查询模型--指定model(不然无法查询数据)--传来一个组件"pk"会自动的去查数据、封装对象、显示到页面上
model = StudentInfo
# 执行成功后跳转地址(跳转地址可以是一个新的页面,也可以进入一个列表页面)
success_url = '/student/list'
# 自定义跳转子类模板页面方法
def to_course(request):
"""
跳转到子类模板页面
:param request:
:return:
"""
return render(request, 'course.html')

34、修改"helloWorld"应用下"templates "目录文件路径下的"index.html"文件内容,添加常用过滤器;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title Is Django Hello World index2</title>
</head>
<body>
模板取值--字符串:{{ content_msg }}<br>
模板取值--字典类型:{{ msg2.Jack }},{{ msg2.Queen }},{{ msg2.King }}<br>
模板取值--对象:{{ msg3.name }},{{ msg3.age }}<br>
模板取值--列表:{{ msg4.0 }},{{ msg4.1 }},{{ msg4.2 }},{{ msg4.3 }},{{ msg4.4 }},{{ msg4.5 }},{{ msg4.6 }}<br>
模板取值--元组:{{ msg5.0 }},{{ msg5.6 }},{{ msg5.5 }},{{ msg5.4 }},{{ msg5.3 }},{{ msg5.2 }},{{ msg5.1 }}<br>
<h3>模板标签</h3>
<p>遍历for标签:</p>
{% for item in msg4 %}
<p>这个是第{{ forloop.counter }}次遍历</p>
{% if forloop.first %}
<p>这个是第一项:{{ item }}</p>
{% elif forloop.last %}
<p>这个是最后一项:{{ item }}</p>
{% endif %}
{% endfor %}
<p>判断标签if</p>
{% if content_msg == '模板变量' %}
<p>模板变量</p>
{% elif content_msg == '传递字符串类型--模板引擎' %}
<p>传递字符串类型--模板引擎</p>
{% else %}
<p>其他</p>
{% endif %}
<p>url标签</p>
<a href="{% url 'index' %}" target="_blank">请求index地址</a>
<p>with标签</p>
{% with info=content_msg %}
{{ info }}
{% endwith %}
<p>内置过滤器</p>
首字母大写capfirst:{{ content_msg | capfirst }}<br>
长度length:{{ content_msg | length }}<br>
日期date(打印日期对象后需要再进行格式化):{{ date }} - >> {{ date | date:'Y-m-d H:i:s' }}<br>
<h1>定义一个h1大标题"index2"</h1>
<p>定义一个段落"index2"</p>
<h2>h2标题"index2" Django Hello World</h2>
<p>又是一个段落;"index2"然后下面是一张图片。</p>
<img src="https://www.runoob.com/wp-content/uploads/2015/01/admin1.png" width="304" height="228" alt=""/>
<br>
<a href="https://www.runoob.com/html/html-tutorial.html">这是一个"HTML 教程 index2"链接</a>
</body>
</html>

35、重新运行项目,浏览器输入"http://127.0.0.1:8000/index/"测试验证。

未完待续......