Django 框架
- 📑 虚拟环境的创建! 盘它
- 📑 Django 项目的配置
- 📑 初始项目文件细分析
- 📑 如何增添 APP 及其内部文件分析
- 📑 URL 和视图挂钩
- 📑 URL 中添加参数
- 📑 模板文件及其引入顺序
- 📑 模板变量及标签
- 📑 模板常用过滤器
- 📑 模板自定义过滤器
- 📑 加载静态文件
- 📑 引入数据库
- 📑 利用视图给表格模型增添数据
- 📑 查询数据
- 📑 页面重定向
- 📑 模板继承
- 📑 管理器类 Manage
- 📑 404 和 500 视图
- 📑 COOKIE 设置
- 📑 session 设置
- 📑 类视图之 View 视图
- 📑 类视图之 TemplateView 视图
📑 虚拟环境的创建! 盘它
此处介绍二个工具(库)用于创建虚拟环境:
- 「virtualenv」
- 「pipenv」
virtualenv 库
第一步:选择一个文件夹 (如:虚拟环境)
第二步:进入该文件夹并启动 cmd ,如何键入命令 virtualenv [虚拟环境的名字(如:first_virtualenv)]
前二步的结果:会在 虚拟环境文件夹 下生成 first_virtualenv文件夹 ,并在 first_virtualenv文件夹
如何进入虚拟环境:cmd 进入 Script 文件夹,执行 activate
pipenv 库
第一步:选择一个文件夹 (如:虚拟环境)
第二步:在该文件夹下启动 cmd 命令,然后用 pipenv shell
如何进入虚拟环境:在该文件夹下启动 cmd 命令,执行 pipenv shell
📑 Django 项目的配置
第一步:本地环境下安装 django,此处我安装的版本是 2.2
第二步:创建一个文件夹,命名为 Django_Framework,然后在此文件夹下启动 cmd,输入命令 django-admin startproject 「项目名称(如:first_project)」
上述二步的结果:在 Django_Framework 文件夹下产生了 first_project 项目文件
📑 初始项目文件细分析
产生 first_project 项目文件夹的同时,会在内部生成几个文件
1. manager.py —— 项目入口
2. first_project —— 主 APP 文件
其中 APP 是项目的分支,APP 是基于项目而产生的,生成项目的同时,会生成一个和项目同名的 APP
📑 如何增添 APP 及其内部文件分析
第一个问题:如何增添 APP
进入项目文件 first_project,在其中启动 cmd,然后输入命令 python manage.py startapp 「APP 名称(如:book)」
第二个问题:APP 内部文件
1. init.py 说明目录是一个Python模块
2. models.py 写和数据库相关的内容
3. views.py 接收请求,处理数据
4. tests.py 写测试代码的文件
5. admin.py 网站后台管理相关的
📑 URL 和视图挂钩
第一个问题:在哪里写 URL 以及怎么写
在名称为 first_project 的 APP 中,找到 urls.py 文件,然后
- 模块
from django.contrib import admin
from django.urls import path
from django.http import HttpResponse
- 定义路由
urlpatterns = [
path('admin/', admin.site.urls),
# path() 中第一个参数是路由,第二个参数是视图函数名
path('', index),
]
- 定义视图函数
def index(request):
return HttpResponse('首页')
http://127.0.0.1:8000/ 即为视图函数 index 定义的页面
http://127.0.0.1:8000/admin 与网站后台管理有关
第二个问题:APP 过多,URL 全堆在主 APP 文件里不妥,那么怎么解决?
在名称为 book 的 APP 中,找到 views.py 和创建 urls.py 文件,我们将各个 APP 的 URL 写在对应的 urls.py 文件中,视图函数写在对应的 views.py 文件中
第三个问题:如何解决 URL 的关联问题
在主 APP 中导入 include 模块,并创建多个 APP
from django.contrib import admin
from django.urls import path, include
from django.http import HttpResponse
urlpatterns = [
path('admin/', admin.site.urls),
# path() 中第一个参数是路由,第二个参数是视图函数名
path('', index),
# 127.0.0.1:8000/book/ 为此基础路由,但是还会继续去与 book APP 的 urls 文件匹配
path('book/', include('book.urls'),
path('movie/', include('movie.urls'),
path('song/', include('song.urls'),
path('static/', include('static.urls'),
path('article/', include('article.urls'),
path('cms/', include('cms.urls'),
path('child/', include('child.urls'),
path('test1/', include('test1.urls'),
path('test2/', include('test2.urls'),
path('test3/', include('test3.urls'),
path('user/', include('user.urls'),
path('test4/', include('test4.urls'),
path('test5/', include('test5.urls'),
]
在名称为 book 的 APP 中
- book/urls.py 文件模块
from django.urls import path
from book import views
- book/urls.py 文件中定义路由
urlpatterns = [
# 127.0.0.1:8000/book/
path('', book_index),
# 127.0.0.1:8000/book/details
path('details', views.book_details),
]
- book/views.py 模块
from django.http import HttpResponse
- book/views.py 定义视图函数
def book_index(request):
return HttpResponse('图书首页')
def book_details(request):
return HttpResponse('图书1~100')
📑 URL 中添加参数
在名称为 book 的 APP 中演示参数添加的过程
参数类型1:关键字传参
- book/views.py
from django.http import HttpResponse
# 127.0.0.1:8000/book/details/var_1/1
def book_detail(request, book_id):
return HttpResponse('图书%s' % book_id)
- book/urls.py
from django.urls import path
from book import views
urlpatterns = [
# 127.0.0.1:8000/book/
path('', book_index),
# 127.0.0.1:8000/book/details
path('details', views.book_details),
# 127.0.0.1:8000/book/details/var_1/1
path('details/var_1/<int:book_id>', views.book_detail_id_1),
]
参数类型2:位置传参
- book/views.py
from django.http import HttpResponse
# 127.0.0.1:8000/book/details/var_2/2
def url_position(request, random_name):
return HttpResponse('图书%s' % random_name)
- book/urls.py
from django.urls import path, re_path
from book import views
urlpatterns = [
# 127.0.0.1:8000/book/
path('', book_index),
# 127.0.0.1:8000/book/details
path('details', views.book_details),
# 127.0.0.1:8000/book/details/var_1/1
path('details/var_1/<int:book_id>', views.book_detail_id_1),
# 127.0.0.1:8000/book/details/var_2/2 -- 此处涉及正则表达式
re_path(r'^/details/var_2/(\d+)$', views.book_detail_id_2),
]
📑 模板文件及其引入顺序
找到主 APP 文件下的 settings.py 文件
设置 TEMPLATES 列表下 DIRS 的值,默认路径为 first_project/templates,其次路径为 APP名称/templates/
TEMPLATES = ['DIRS': [os.path.join(BASE_DIR, 'templates')]
1. 在名称为 movie 的 APP 中演示主模板文件引入的过程
- first_project/templates/movie/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>电影首页</h1>
</body>
</html>
- movie/views.py
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request, 'movie/index.html')
引入模板文件,只需利用到 render 模块,第一个参数为 request,第二个参数为模板文件默认查找的路径 first_project/templates/ + 第二个参数
- movie/urls.py
from django.urls import path
from movie import views
urlpatterns = [
# 127.0.0.1:8000/movie/
path('', views.index),
]
2. 在名称为 song 的 APP 中演示应用模板文件引入的过程
- first_project/song/templates/song_index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>音乐首页</h1>
</body>
</html>
- song/views.py
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request, 'song_index.html')
引入模板文件,只需利用到 render 模块,第一个参数为 request,第二个参数为模板文件次级查找的路径 first_project/song/templates/ + 第二个参数
- song/urls.py
from django.urls import path
from movie import views
urlpatterns = [
# 127.0.0.1:8000/song/
path('', views.index),
]
📑 模板变量及标签
在名称为 movie 的 APP 中演示模板变量及标签
- first_project/templates/movie/var_tag.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>固定列表的二个数据均取出:</h1>
{% for data in my_list %}
<h2>{{ data }}</h2>
{% endfor %}
<h1>字典的数据取出:</h1>
<h2>{{ my_dict.name }}</h2>
</body>
</html>
渲染模板时传递了二组数据,my_list,my_dict;想要遍历列表 my_list 中的元素,需要用到 for 语句,语法如上;想要取出字典 my_dict 中的元素,需要用到 . 方法,语法如上:字典.键值;
- movie/views.py
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request, 'movie/index.html')
def var_tag(request):
data_list = [1, 2, 3]
data_dict = {
'name': 'Xiao Su'
}
data_random1 = random.randint(0, 10)
data_random2 = random.randint(0, 10)
content = {
# 固定数字的列表
'my_list': data_list,
# 一个键值对的字典
'my_dict': data_dict
}
return render(request, 'var_tag.html', content)
- movie/urls.py
from django.urls import path
from movie import views
urlpatterns = [
# 127.0.0.1:8000/movie/
path('', views.index),
# 127.0.0.1:8000/movie/var_tag
path('var_tag', views.var_tag),
]
📑 模板常用过滤器
在名称为 song 的 APP 中演示模板过滤器
- first_project/song/templates/song_filter.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>大写字母变小写:</h1>
{% for data in my_upper_list %}
<h2>{{ data|lower }}</h2>
{% endfor %}
<h1>小写字母变大写:</h1>
{% for data in my_lower_list %}
<h2>{{ data|upper }}</h2>
{% endfor %}
</body>
</html>
渲染模板时传递了三组数据,my_random,my_lower_list,my_upper_list;想要大写字母在遍历的过程中显示为小写则需要使用 lower 过滤器,用法如上;想要小写字母在遍历的过程中显示为大写则需要使用 upper 过滤器,用法如上;
- song/views.py
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request, 'song_index.html')
def filter(request):
data_random1 = random.randint(0, 10)
data_random2 = random.randint(0, 10)
my_random = [data_random1, data_random2]
my_lower_list = ['a', 'b', 'c']
my_upper_list = ['D', 'E', 'F']
content = {
'my_random': my_random,
'my_lower_list': my_lower_list,
'my_upper_list': my_upper_list,
}
return render(request, 'song_filter.html', content)
- song/urls.py
from django.urls import path
from movie import views
urlpatterns = [
# 127.0.0.1:8000/song/
path('', views.index),
# 127.0.0.1:8000/song/filter
path('filter', views.filter),
]
📑 模板自定义过滤器
条件准备
1. 在 book/ 下创建 templatetags 包(包含 init.py )
2. 创建编写过滤器的 python 文件(filter.py)
在名称为 song 的 APP 中演示自定义过滤器
- first_project/song/templatetags/filter.py
# 导入 Library
from django.template import Library
# 创建 Library 对象
register = Library()
# 使用装饰器进行注册
@register.filter()
def mod(value):
return value % 2 == 0
@register.filter()
def mod_val(num, val):
return num % val == 0
@register.filter()
def add_num(num1, num2):
return num1 + num2
我们创建了三个过滤器,名称分别为 mod,mod_val,add_num;
- first_project/song/templates/song_my_filter.html
<!DOCTYPE html>
<html lang="en">
{% load filter %}
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>自定义过滤器 mod:</h1>
{% for data in my_random %}
{% if data|mod %}
<h2>{{ data }}</h2>
{% endif %}
{% endfor %}
<h1>自定义过滤器 mod_val:</h1>
{% for data in my_random %}
{% if data|mod_val:3 %}
<h2>{{ data }}</h2>
{% endif %}
{% endfor %}
<h1>自定义过滤器 add_num:</h1>
{% for data in my_random %}
<h2>{{ data|add_num:100 }}</h2>
{% endfor %}
</body>
</html>
渲染模板时传递了一组数据,my_random;想要使用自定义过滤器还必须加载过滤器文件,语法如上:{% load 过滤器文件名 %};过滤器 mod 的用处在于判断数据能否被 2 整除;过滤器 mod_val 的用处在于判断数据能否被指定数据(此处为 3)整除;过滤器 add_num 的用处在于将某个数据加上指定数据(此处为 100)
- song/views.py
import random
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request, 'song_index.html')
def my_filter(request):
data_random1 = random.randint(0, 10)
data_random2 = random.randint(0, 10)
my_random = [data_random1, data_random2]
content = {
'my_random': my_random
}
return render(request, 'song_my_filter.html', content)
- song/urls.py
from django.urls import path
from movie import views
urlpatterns = [
# 127.0.0.1:8000/song/
path('', views.index),
# 127.0.0.1:8000/song/filter
path('filter', views.filter),
# 127.0.0.1:8000/song/my_filter
path('my_filter', views.my_filter),
]
📑 加载静态文件
查找静态文件和查找模板文件类似,可以细分为优先查找和次级查找,即先在项目下查找,然后在应用下查找
条件准备
1. 在 first_project/first_project/settings.py 文件末尾添加
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
2 在 first_project/ 下创建 static 目录,然后创建 css,js,img 分目录
3. 在 css 里创建 style.css 文件
h2{
color: green;
}
在名称为 static 的 APP 中演示加载静态文件
- first_project/static/templates/static_index.py
<!DOCTYPE html>
<html lang="en">
{% load static %}
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="{% static 'style.css' %}">
<title>Title</title>
</head>
<body>
<h2>我是绿色!</h2>
</body>
</html>
想要加载静态文件,需要用到 {% load static %};想要指定加载的 css 静态文件,需要用到 link 标签,语法如上;
- static/views.py
import random
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request, 'static_index.html')
- static/urls.py
from django.urls import path
from movie import views
urlpatterns = [
# 127.0.0.1:8000/static/
path('', views.index),
]
📑 引入数据库
在名称为 article 的 APP 中演示引入数据库
1. 使用 Django 自带的 sqlite3 数据库(无需重新配置)
- first_project/article/modles.py
from django.db import models
# Create your models here.
class ArticleMessage(models.Model):
# 图书标题
article_title = models.CharField(max_length=20)
# 图书出版日期
article_pub_date = models.DateField()
# 图书评论量
article_comment = models.IntegerField(default=0)
# 图书阅读量
article_read = models.IntegerField(default=0)
# 逻辑删除
isDelete = models.BooleanField(default=False)
# 定义元选项
class Meta:
# 指定表名
# db_table = 'Su_article'
然后在 first_project 项目文件夹下运行 cmd,然后使用命令生成迁移文件,最后将迁移文件迁移到数据库
python .manage.py makemigrations
python .manage.py migrate
在后台查看模型数据之前,需要注册超管用户(用户名,密码,邮箱),在项目文件下运行 cmd,输入命令
python manage.py createsuperuser
2. 使用 MySQL 数据库(需要重新配置)
- 在 first_project/first_project/settings.py 文件对 DATABASES 进行修改(必须!)
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
# 链接 MySQL 数据库
'default': {
# 引擎(不变)
'ENGINE': 'django.db.backends.mysql',
# 数据库名字(根据自己数据库的名字)
'NAME': 'django_1',
# 用户名(根据自己数据库的用户名)
'USER': 'root',
# 密码(根据自己数据库的密码)
'PASSWORD': 'root',
# 数据库所在主机(一般不变)
'HOST': 'localhost',
# 端口(一般不变)
'PORT': '3306',
}
}
- 在 first_project/first_project/init.py 中注册 MySQL 数据库(必须!)
import pymysql
pymysql.install_as_MySQLdb()
- 在 first_project/article/admin.py 文件中绑定模型(便于后台查看数据)
from django.contrib import admin
from article.models import ArticleMessage
# Register your models here.
admin.site.register(ArticleMessage)
然后在 first_project 项目文件夹下运行 cmd,然后使用命令生成迁移文件,最后将迁移文件迁移到数据库
python .manage.py makemigrations
python .manage.py migrate
此处使用 SQLyog 软件查看数据(可视化)
📑 利用视图给表格模型增添数据
在名称为 article 的 APP 中演示增添数据
- first_project/article/views.py
import random
from django.http import HttpResponse
from django.shortcuts import render
from article.models import ArticleMessage
def index(request):
return HttpResponse('文章首页')
def create_article(request):
title = request.GET.get('title')
new_article = ArticleMessage()
new_article.article_title = title
new_article.article_read = random.randint(0, 100)
new_article.article_comment = random.randint(0, 100)
new_article.article_pub_date = date(random.randint(1900, 2021), random.randint(1, 12), random.randint(1, 30))
new_article.isDelete = False
new_article.save()
# 跳转首页
return HttpResponse('上传完成')
如果想要在视图模块(views.py)完成数据的添加过程,那么就得将该应用的模型(models.py)导入进来;然后实例化,具体语法:new_article = Article();然后就可以完成数据的增添过程了,具体语法:new_article.字段名 = 值;最重要!最后一定要写 new_article.save();
- first_project/article/urls.py
from django.urls import path
from movie import views
urlpatterns = [
# 127.0.0.1:8000/article/
path('', views.index),
# 127.0.0.1:8000/article/create_article?title=追风筝的人
path('create_article', views.create_article),
]
访问网址:127.0.0.1:8000/article/create_article?title=追风筝的人,将使表格增添 article_title 为人 ‘追风筝的人’ 的文章
📑 查询数据
准备工作
1. 在名称为 article 的 APP 中,再添加一个模型
- first_project/article/models.py
class HeroMessage(models.Model):
hero_name = models.CharField(max_length=20)
hero_gender = models.BooleanField(default=True)
hero_comment = models.CharField(max_length=200)
isDelete = models.BooleanField(default=False)
# 表关联
hero_book = models.ForeignKey('ArticleMessage', 'id')
2. 利用 SQL 语句插入数据(MySQL 数据库的表名字 (全是小写):应用名_模型名)
use django_1
insert into article_articlemessage(article_title,article_pub_date,article_read,article_comment,isDelete) values
('射雕英雄传','1980-5-1',12,34,0),
('天龙八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飞狐','1987-11-11',58,24,0);
insert into article_heromessage(hero_name,hero_gender,hero_book_id,hero_comment,isDelete) values
('郭靖',1,1,'降龙十八掌',0),
('黄蓉',0,1,'打狗棍法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙十八掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'天山六阳掌',0),
('王语嫣',0,2,'神仙姐姐',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'弹琴',0),
('岳不群',1,3,'华山剑法',0),
('东方不败',0,3,'葵花宝典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若兰',0,4,'黄衣',0),
('程灵素',0,4,'医术',0),
('袁紫衣',0,4,'六合拳',0);
3. 在项目文件夹下运行 cmd,输入命令进入 shell 环境
python manage.py shell
主键查询(shell 环境下)
以下均是查询 id 为 1 的一行数据
In[0]:from article.models import ArticleMessage, HeroMessage
In[1]:article = ArticleMessage.objects.get(pk=1)
In[2]:article = ArticleMessage.objects.get(id=1)
字段查询(shell 环境下)
In[3]:article = ArticleMessage.objects.filter(article_title="笑傲江湖")
条件查询(shell 环境下)
1. exact – 精确查找 – 全等于
In[4]:article = ArticleMessage.objects.filter(id__exact=1)
2. contains – 模糊匹配 – 包含
In[5]:article = ArticleMessage.objects.filter(article_title__contains="八")
3. endswith – 模糊匹配 – 以什么结尾
In[6]:article = ArticleMessage.objects.filter(article_title__endswith="部"
4. startswith – 模糊匹配 – 以什么开头
In[7]:article = ArticleMessage.objects.filter(article_title__startswith="雪"
5. in=[1, 3, 5] – 模糊查询 – 包含其中
In[8]:article = ArticleMessage.objects.filter(id__in=[1, 3, 5])
6. gt=3 – 模糊查询 – 字段大于
In[9]:article = ArticleMessage.objects.filter(id__gt=3)
7. lt=3 – 模糊查询 – 字段小于
In[10]:article = ArticleMessage.objects.filter(id__lt=3)
8. gte=3 – 模糊查询 – 字段大于等于
In[11]:article = ArticleMessage.objects.filter(id__gte=3)
9. lte=3 – 模糊查询 – 字段小于等于
In[12]:article = ArticleMessage.objects.filter(id__lte=3)
10. exclude – 模糊查询 – 不等于
In[13]:article = ArticleMessage.objects.exclude(id__exact=3)
条件查询之日期(shell 环境下)
In[14]:from datetime import date
1. year – 模糊查询 – 年
In[15]:article = ArticleMessage.objects.filter(article_pub_date__year=1995)
2. month – 模糊查询 – 月
In[16]:article = ArticleMessage.objects.filter(article_pub_date__month=7)
3. day – 模糊查询 – 日
In[17]:article = ArticleMessage.objects.filter(article_pub_date__day=17)
4. gt=date(1990,1,1)) – 模糊查询 – 在某日期之后
In[18]:article = ArticleMessage.objects.filter(article_pub_date__gt=date(1990,1,1))
5. lte=date(1990,1,1)) – 模糊查询 – 在某日期之前(包括此日期)
In[19]:article = ArticleMessage.objects.filter(article_pub_date__lte=date(1990,1,1))
并集查询(shell 环境下)
In[20]:from djang.db.models import F
In[21]:from django.db.models import Q
1. Q 表达式 – 条件 &(且)、|(或)、~(非)
In[22]:article = ArticleMessage.objects.filter(Q(id__gt=1) & Q(book_read__gt=20))
2. F 表达式 – 可以进行算术运算
In[23]:article = ArticleMessage.objects.filter(article_read__gt=(F('article_comment') + 2))
聚合函数查询(shell 环境下)
In[24]:from django.db.models import Avg, Max, Min, Count, Sum
1. Avg – 字段平均值
In[25]:article = ArticleMessage.objects.aggregate(Avg('article_read'))
2. Max – 字段最大值
In[26]:article = ArticleMessage.objects.aggregate(Max('article_read'))
3. Min – 字段最小值
In[27]:article = ArticleMessage.objects.aggregate(Min('article_read'))
4. Count – 数据总数
In[28]:article = ArticleMessage.objects.aggregate(Count('id'))
In[29]:article = ArticleMessage.objects.count()
5. Sum – 字段总数
In[30]:article = ArticleMessage.objects.aggregate(Sum('article_read'))
查询后返回布尔值(shell 环境下)
In[31]:article = ArticleMessage.objects.filter(article_title__contains="卡").exists()
关联查询(shell 环境下)
1. 通过对象执行关联查询
- 从表格关系一对多,一的这一方去查询数据
In[32]:article = BookMessage.objects.get(id=1)
In[33]:article .heromessage_set.all()
首先生成一个 id 为 1 的书的对象;然后查询 heromessage 里面 hero_book 为 1 的英雄,语法:对象.表名_set.all()(heromessage_set.all())
- 从表格关系一对多,多的这一方去查询数据
In[34]:hero = HeroMessage.objects.get(id=11)
In[35]:hero.hero_book
首先生成一个 id 为 11 的英雄的对象;然后根据此英雄的 hero_book 属性去查询 articlemessage 里面对应的文章,语法:对象.关联字段名(hero_book)
2. 通过模型类进行关联查询
- 查询英雄描述中含有“八” 的图书
In[36]:article = ArticleMessage.objects.filter(heromessage_set__hero_comment__contains='八')
- 查询图书“天龙八部”里面的英雄
In[37]:hero = HeroMessage.objects.filter(hero_book__article_title='天龙八部')
📑 页面重定向
在名称为 cms 的 APP 中演示页面重定向
- first_project/templates/cms/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>后台首页</h1>
</body>
</html>
- first_project/cms/views.py
from django.shortcuts import render, redirect, reverse
from django.http import HttpResponse
def index(request):
return render(request, 'cms/index.html'
def login(request):
return redirect(reverse('app_cms:index')
此处还需要了解 URL 反转
- first_project/cms/urls.py
from django.http import HttpResponse
from django.urls import path
from cms import views
app_name = 'app_cms'
urlpatterns = [
path('', views.index, name='index'),
path('login', views.login),
]
此处还需要了解命名空间
当我们访问网址:http://127.0.0.1:8000/cms/login 后将跳转到 http://127.0.0.1:8000/cms/ 页面
📑 模板继承
在名称为 child 的 APP 中演示模板继承的过程
准备工作
1. 在 first_project/child/templates/inherit 里面创建二个文件,base.html 和 child.html
2. base.html 文件为基础(父亲)文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}模板继承基本文件--父模板{% endblock title %}</title>
</head>
<body>
<h1>导航条</h1>
{% block b1 %}
<h2>父亲父亲!-- 这是父模板中 b1 预留块的内容</h2>
{% endblock b1 %}
<h1>版权信息</h1>
</body>
</html>
3. child.html 文件为继承(儿子)文件
{% extends 'inherit/base.html' %}
{% block title %}模板继承基本文件--子模板{% endblock title %}
{% block b1 %}
<!--代表父模板预留块 b1 的内容-->
{{ block.super }}
<h2>儿子儿子!-- 这是子模板中 b1 预留块的内容</h2>
{% endblock b1 %}
代码 {% extends ‘inherit/base.html’ %} 必须写在首行!
如果想在继承模板中写独有的代码,则需要在继承模板中填充预留块!
📑 管理器类 Manage
在名称为 article 的 APP 中演示修改管理器
1. 修改 first_project/article/models.py 中的代码
from django.db import models
class BookManager(models.Manager):
# 重写 all() 方法
def all(self):
return super().all().filter(isDelete=False)
def create_article(self, title):
new_article = self.model()
new_article.article_title = title
new_article.article_read = random.randint(0, 100)
new_article.article_comment = random.randint(0, 100)
new_article.article_pub_date = date(random.randint(1900, 2021), random.randint(1, 12), random.randint(1, 30))
new_article.isDelete = False
new_article.save()
return new_article
# Create your models here.
class ArticleMessage(models.Model):
# 图书标题
article_title = models.CharField(max_length=20)
# 图书出版日期
article_pub_date = models.DateField()
# 图书评论量
article_comment = models.IntegerField(default=0)
# 图书阅读量
article_read = models.IntegerField(default=0)
# 逻辑删除
isDelete = models.BooleanField(default=False)
# 定义元选项
class Meta:
# 指定表名
# db_table = 'Su_article'
# 定义 Manager 对象
# articles = models.Manager()
# 自定义 Manager 对象,BookManager 对象继承自 models.Manager,便于重写代码
articles = BookManager()
# 英雄模型类
class HeroMessage(models.Model):
hero_name = models.CharField(max_length=20)
hero_gender = models.BooleanField(default=True)
hero_comment = models.CharField(max_length=200)
isDelete = models.BooleanField(default=False)
# 表关联
hero_book = models.ForeignKey('ArticleMessage', 'id')
2. 在项目文件下运行 cmd,然后输入命令进入 shell 环境
python manage.py shell
3. 通过自定义管理器,在查询数据层面上会发生变化
In[0]:article = ArticleMessage.articles.all()
查询操作中语法规定:模型名.管理器名(ArticleMessage.articles)此处我们修改了管理器名,自然就不再是之前的 objects;由于重写了 all 方法,所以此处查询的是 isDelete 属性不为 True 的数据;
In[1]:article = ArticleMessage.articles.create_article('追风筝的人')
由于增加了方法 create_article,所以上述使用该方法不会出现报错;此方法需要传递一个字符串作为 article 的标题,然后返回创建的 article 对象;
📑 404 和 500 视图
准备工作
1. 修改 first_project/first_project/settings.py 文件(关闭 Debug 模式)
# DEBUG = True
DEBUG = False
# ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['*']
2. 创建 first_project/templates/404.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>页面没找到</title>
</head>
<body>
<h1>你个憨憨!页面没找到</h1>
</body>
</html>
3. 创建 first_project/templates/500.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>服务器错误</title>
</head>
<body>
<h1>你个憨憨!服务器内部错误</h1>
</body>
</html>
在名称为 test1 的 APP 中演示 404 和 500 视图
1. first_project/test1/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse('测试1首页')
def error(request):
num = 1 + 'a'
return HttpResponse('你前一步是错的!')
2. first_project/test1/urls.py
from test1 import views
from django.urls import path
urlpatterns = [
path('', views.index),
path('error', views.error),
]
分析
1. 访问 127.0.0.1:8000/test1/13441 将返回 404.html 渲染的页面
2. 访问 127.0.0.1:8000/error 将返回 500.html 渲染的页面
📑 COOKIE 设置
在名称为 test2 的 APP 中演示 COOKIE 设置的过程
1. first_project/test2/views.py
from django.http import HttpResponse
from datetime import datetime, timedelta
# 8000/test2/set_cookie
def set_cookie(request):
# 设置 cookie 信息
response = HttpResponse('设置 cookie 成功')
response.set_cookie('my_name', 'Su', max_age=14*24*60*60)
response.set_cookie('my_age', 19, expires=datetime.now() + timedelta(days=14))
return response
# 8000/test2/get_cookie
def get_cookie(request):
# 获取 cookie 信息
my_name = request.COOKIES['my_name']
my_age = request.COOKIES['my_age']
return JsonResponse({'my_name': my_name, 'my_age': my_age})
2. first_project/test2/urls.py
from django.urls import path
from test2 import views
urlpatterns = [
path('set_cookie', views.set_cookie),
path('get_cookie', views.get_cookie),
]
分析:
1. 想要设置 COOKIE 必须先实例化 HttpResponse 或其子类对象;然后使用该对象的 set_cookie 方法
2. 注意该方法有三个参数,第一个是 COOKIE 的键,第二个是值,第三个是过期时间;且过期时间的设置存在二种方法
3. 第一种 :max_age=14 * 24 * 60 * 60 属于直接传递时间(单位:s)
4. 第二种:expires=datetime.now() + timedelta(days=14) 属于在目前的时间上加上到期时间(单位:day)
5. COOKIE 需要在视图函数 request 参数中取得
📑 session 设置
在名称为 test3 的 APP 中演示 session 设置的过程
1. first_project/test3/views.py
from django.http import HttpResponse
# 8000/test3/set_session
def set_session(request):
# 设置 session 信息
request.session['username'] = 'Ke'
request.session['age'] = 15
return HttpResponse('设置 session 成功')
# 8000/test3/get_session
def get_session(request):
# 获取 session 信息
username = request.session['username']
age = request.session['age']
return JsonResponse({'username': username, 'age': age})
2. first_project/test3/urls.py
from django.urls import path
from test2 import views
urlpatterns = [
path('set_session', views.set_session),
path('get_session', views.get_session),
]
分析:
1. session 的设置和取值都是在视图函数的 request 对象中完成的
2. 与 COOKIE 的设置不同的是,COOKIE 的设置是直接保存在浏览器中的;而一组 session 设置完成后,只是在浏览器中保存一个 session_id 属性用来对应服务端的 session 数据,相对更加安全
📑 类视图之 View 视图
准备工作
1. 创建 first_project/templates/user/register.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<form method="post">
<span>用户名:</span><input type="text" name="username"><br>
<span>密 码:</span><input type="password" name="password"><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
在名称为 user 的 APP 中演示类视图的实现过程
1. first_project/user/views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.views import View
class Register(View):
@staticmethod
def get(request):
return render(request, 'user/register.html')
@staticmethod
def post(request):
username = request.POST.get('username')
password = request.POST.get('password')
return JsonResponse({'状态': '注册成功', 'username': username, 'password': password})
2. first_project/user/urls.py
urlpatterns = [
# 127.0.0.1:8000/user/resister
path('register', views.Register.as_view()),
]
分析:
1. 访问网址:127.0.0.1:8000/user/resister 直接渲染模板文件 first_project/templates/user/register.html(实现了类视图的 get 方法)
2. 提交表单后,又返回 Json 数据(实现了类视图的 post 方法)
📑 类视图之 TemplateView 视图
准备工作
1. 创建 first_project/templates/test4/about.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>关于我们</title>
</head>
<body>
<h1>关于我们</h1>
<p>我们是小猪猪!</p>
</body>
</html>
2. 创建 first_project/templates/test4/home.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>家家家</title>
</head>
<body>
<h1>{{ username }} -- 的家</h1>
</body>
</html>
在名称为 test4 的 APP 中演示类视图的实现过程
1. first_project/test4/views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import TemplateView
class HomeView(TemplateView):
template_name = 'test4/home.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['username'] = 'XIAO SU'
return context
2. first_project/test4/urls.py
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
# 直接将 URL 和模板文件关联
# 127.0.0.1:8000/test4/about
path('about', TemplateView.as_view(template_name='about.html')),
# 在视图函数中重写继承自 TemplateView 的类
# 127.0.0.1:8000/test4/home
path('home', views.HomeView.as_view()),
]
分析:
1. 访问网址:127.0.0.1:8000/test4/about 将直接渲染 about.html 文件
2. 访问网址:127.0.0.1:8000/test4/home 将先通过视图函数传递参数 username,然后再渲染模板文件 home.html