Django 框架

  • 📑 虚拟环境的创建! 盘它
  • 📑 Django 项目的配置
  • 📑 初始项目文件细分析
  • 📑 如何增添 APP 及其内部文件分析
  • 📑 URL 和视图挂钩
  • 📑 URL 中添加参数
  • 📑 模板文件及其引入顺序
  • 📑 模板变量及标签
  • 📑 模板常用过滤器
  • 📑 模板自定义过滤器
  • 📑 加载静态文件
  • 📑 引入数据库
  • 📑 利用视图给表格模型增添数据
  • 📑 查询数据
  • 📑 页面重定向
  • 📑 模板继承
  • 📑 管理器类 Manage
  • 📑 404 和 500 视图
  • 📑 COOKIE 设置
  • 📑 session 设置
  • 📑 类视图之 View 视图
  • 📑 类视图之 TemplateView 视图


📑 虚拟环境的创建! 盘它

此处介绍二个工具(库)用于创建虚拟环境:

  1. 「virtualenv」
  2. 「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