orm03

admin后台管理

什么是admin后台管理

django提供了比较完善的后台数据库的接口,可供开发过程中调用和测试使用

django会搜集所有已注册的模型类,为这些模型类提供数据管理界面,供开发使用

admin配置步骤

创建后台管理账号

该账号为管理后台最高权限账号

shell 复制代码
$ python3 manage. py createsuperuser
Username (leave blank to use 'root'): zhangsan		# 此处输入用户名
Email address: [email protected]					# 此处输入邮箱
Password:							# 此处输入密码(密码要复杂些,否则会提示密码太简单)
Password(again):					# 再次输入重复密码
Superuser created successfully.
测试登录

启动服务后,后台管理的登录地址:http://127.0.0.1:8000/admin,使用刚才注册的管理员账号登录即可

实验:测试admin后台系统
  • 首先创建用户,在终端执行 python3 manage.py createsuperuser 命令

    复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py createsuperuser
    用户名 (leave blank to use 'root'): root
    电子邮件地址: [email protected]
    Password: 123456
    Password (again): 123456
    密码长度太短。密码必须包含至少 8 个字符。
    这个密码太常见了。
    密码只包含数字。
    Bypass password validation and create user anyway? [y/N]: y  # 如果密码短需要手动确定
    Superuser created successfully.
  • 启动服务 django 服务

    复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py runserver
  • 后台管理的登录地址:http://127.0.0.1:8000/admin

注册自定义模型类

  • 若要自己定义的模型类也能在admin后台管理系统界面中显示和管理,需要将自己的类注册到后台管理界面
注册步骤
  • 在应用app中的 admin.py 中导入注册要管理的模型 models 类,如:from .models import Book

  • 调用 admin.site.register 方法进行注册,如:admin.site.register(自定义模型类)

  • 案例

    python 复制代码
    # file: bookstore/admin.py
    from django. contrib import admin
    # Register your models here.
    
    from . import models
    ...
    admin. site.register(models.Book)# 将Book类注册为可管理页面
  • 修改自定义模型类的数据样式

    • admin后台管理数据库中对自定义的数据记录都展示为 XXX object 类型的记录,不便于阅读和理解

    • 在用户自定义的模型类中可以重写 def str(self)方法解决显示问题,如:

实验:注册模型类
  • 修改 bookstore 应用下的 admin.py 文件

    复制代码
    from django.contrib import admin
    # 方式一:引入模型模块,使用模型类: `models.模型类名`,例如 models.Book
    # from . import models
    
    # 方式二:直接导入模型类
    from .models import Book  
    
    
    # Register your models here.
    admin.site.register(Book)  # 在模型类Book注册到站点admin,admin站点就会提供模型类Book的管理页面
  • 启动服务,重新登录 admin 后台管理系统,观察界面

  • 点击Books链接,查看图书详情页

  • 这里显示的内容是 __str__ 方法封装的字符串,所以可以自定义修改显示的字段

python 复制代码
    def __str __ (self):
        return f'书名:{self.title},价格:{self.price},出版社:{self.pub},零售价:{self.market_price}'

模型管理器类

理解与说明

作用:为后台管理界面添加便于操作的新功能

说明:后台管理器类须继承自 Django.contrib.admin 里的 ModelAdmin

使用方法
  • 在 <应用app>/admin.py 里定义模型管理器类

  • 绑定注册模型管理器和模型类

  • 案例

类属性说明
  • **list_display:**去控制哪些字段会显示在admin后台管理的修改列表页面中
  • **list_display_links:**可以控制list_display中的字段是否应该链接到对象的"更改"页面
  • **list_filter:**设置激活admin修改列表页面右侧栏中的过滤器
  • **search_fields:**设置启用admin更改列表页面上的搜索框
实验:绑定模型管理器类
  • 修改 bookstore 应用下的 admin.py 文件,添加模型管理器类

    python 复制代码
    from django.contrib import admin
    from .models import Book
    
    
    
    # 定义一个模型管理类
    class BookManager(admin.ModelAdmin):    # 后台管理器类须继承自Django.contrib.admin里的ModelAdmin类
        # 列表页显示哪些字段的列
        list_display = ["id", "title", "price", "market_price", "pub"]
        # 控制 list_display 中的字段,哪些可以链接到修改页,缺省默认首列
        list_display_links = ["title"]   # 点击书名,可以进入该条数据的修改页面
        # list_display_links = ["title", "price"]   # 点击书名列或价格列,可以进入该条数据的修改页面
        # 添加过滤器
        list_filter = ["pub"]        # 以出版社列给出过滤项
        # 添加搜索框[模糊查询]
        search_fields = ["title"]    # 搜索框模糊匹配标题列
        # search_fields = ["title", "pub"]  # 搜索框模糊匹配书名列或出版社列
        # 添加可直接在列表编辑的字段(不必进入修改页面)
        list_editable = ["price"]
    
    
    
    
    admin.site.register(Book, BookManager)  # 将模型管理器类和模型类进行绑定
  • 启动服务,重新登录 admin 后台管理系统,观察界面

  • 点击Books进入详情页,发现修改内容均已在管理界面生效

默认自带按字段排序功能

Meta类

在管理页面看见的模型类的名称,可以通过Meta内嵌类来修改。

通过Meta内嵌类定义模型类的属性,用法如下:

实验:修改Meta类属性
  • 修改 bookstore 应用下的 admin.py 文件,修改 Book 模型类

    python 复制代码
    from django.db import models
    
    
    class Book(models.Model):
        title = models.CharField("书名", max_length=50, default="", unique=True)
        pub = models.CharField("出版社", max_length=50, default="")
        price = models.DecimalField("定价", max_digits=7, decimal_places=2, default=0.0)
        market_price = models.DecimalField("零售价", max_digits=7, decimal_places=2, default=0.0)
        is_active = models.BooleanField("是否活跃", default=True)
    
    
        def __str__(self):
            return f"{self.title}, {self.pub}, {self.price}, {self.market_price}"
    
    
        class Meta:
            db_table = "book"
            verbose_name = "图书"  # 修改单数显示
            verbose_name_plural = verbose_name  # 修改复数显示,缺省默认单数显示+s
  • 启动服务,重新登录 admin 后台管理系统,观察界面

练习

需求:对 Author 模型管理类的自定义设置

  • 将 Author 模型类加入后台管理
  • 制作一个 AuthorManager 管理器类,让后台管理 Authors 列表中显示作者的 ID、姓名、年龄信息
  • 用后台管理程序添加三条 Author 记录
  • 修改其中一条记录的年龄 -- Author
  • 删除最后一条添加的记录 -- Author
python 复制代码
修改bookstore 应用下的 admin.py 文件

from django.contrib import admin
from .models import Book,Author

# 定义一个模型管理类
class BookManager(admin.ModelAdmin):    # 后台管理器类须继承自Django.contrib.admin里的ModelAdmin类
    # 列表页显示哪些字段的列
    list_display = ["id", "title", "price", "market_price", "pub"]
    # 控制 list_display 中的字段,哪些可以链接到修改页,缺省默认首列
    list_display_links = ["title"]   # 点击书名,可以进入该条数据的修改页面
    # list_display_links = ["title", "price"]   # 点击书名列或价格列,可以进入该条数据的修改页面
    # 添加过滤器
    list_filter = ["pub"]        # 以出版社列给出过滤项
    # 添加搜索框[模糊查询]
    search_fields = ["title"]    # 搜索框模糊匹配标题列
    # search_fields = ["title", "pub"]  # 搜索框模糊匹配书名列或出版社列
    # 添加可直接在列表编辑的字段(不必进入修改页面)
    list_editable = ["price"]

class AuthorManager(admin.ModelAdmin): 
    list_display = ["id", "name", "age"]
    list_display_links = ["name"]

admin.site.register(Book, BookManager)  # 将模型管理器类和模型类进行绑定

admin.site.register(Author, AuthorManager)  # 将模型管理器类和模型类进行绑定
python 复制代码
修改 bookstore 应用下的 admin.py 文件,修改 Author 模型类

from django.db import models

class Author(models.Model):
    ...
    class Meta:
        db_table = "author"
        verbose_name = "作者"  # 修改单数显示
        verbose_name_plural = verbose_name  # 修改复数显示,缺省默认单数显示+s

总结

  • 注册自己的模型类
  • 修改自定义模型类的显示样式 - 模型管理器类
  • Meta类对模型类的属性修改

用户管理

  • 权限

关系映射

什么是关系映射

在关系型数据库中,通常不会把所有数据都放在同一张表中,不易于扩展,常见关系映射有:

  • 一对一映射
    • 如:一个身份证对应一个人
  • 一对多映射
    • 如:一个班级可以有多个学生
  • 多对多映射
    • 如:一个学生可以报多个课程,一个课程可以有多个学生学习

一对一映射 models.OneToOneField()

概念与理解
  • 一对一是表示现实事物间存在的一对一的对应关系

  • 如:一个家庭只有一个户主,一个男人有一个妻子,一个人有一个唯一的指纹信息等

  • 语法:OneToOneField(类名, on_delete=xxx)

特殊字段选项【必须】
on_delete:级联删除
  • 几个可选的值:

    • models.CASCADE:级联删除,Django模拟 SQL 约束 ON DELETE CASCADE 的行为,并删除包含 ForeignKey的对象。当主表数据被删除时,从表对应的数据也被删除。

    • Models.PROTECT:抛出 ProtectedError 以阻止被引用对象的删除;等同于 mysql 默认的 RESTRICT。当主表数据被删除时,从表对应的数据不被删除。

    • SET_NULL:设置 ForeignKey null;需要指定 null = True。当主表数据被删除时,从表对应的数据设置为null。

    • SET_DEFAULT:将 ForeignKey 设置为其默认值,必须设置 ForeignKey 的默认值。当主表数据被删除时,从表对应的数据设置为相应的默认值。

创建模型类
  • 示例 - 创建模型类 -- oto/models.py
添加数据
  • 无外键的模型类[Author]:
    • author1 = Author.objects.create(name="王老师")
  • 有外键的模型类[Wife]:
    • 方式1:wife1 = Wife.objects.create(name="王夫人", author=author1) # 关联王老师对象
    • 方式2:wife1 = Wife.objects.create(name="王夫人", author_id=1) # 关联王老师对应的主键值
查询数据
正向查询
  • 直接通过外键属性查询,则称为正向查询

反向查询

没有外键属性的一方,可以调用反向属性查询关联的另一方

  • 反向关联属性为:实例对象.引用类名(小写) ,如作家的反向引用为:作家对象.wife

  • 当反向引用不存在时,则会触发异常

    复制代码
    author1 = Author.objects.get(name='王老师')
    author1.wife.name
实验:一对一模型
  • 创建应用:oto

    shell 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py startapp oto
  • 并在 settings.py 中将 oto 应用进行注册

    python 复制代码
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'music',
        'news',
        'sport',
        'bookstore',
        'oto',  # 模型注册
    ]
  • 修改 oto 应用下的 models.py,创建模型类

    python 复制代码
    from django.db import models
    
    
    class Author(models.Model):
        # wife 反向属性:用作反向查询
        name = models.CharField('姓名', max_length=11)
    
    
    class Wife(models.Model):
        name = models.CharField('姓名', max_length=11)
        # 添加外键,指定关联的表
        author = models.OneToOneField(Author, on_delete=models.CASCADE)
  • 同步迁移数据库

    shell 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py makemigrations
    (testenv) [root@localhost mysite3]# python3 manage.py migrate
  • 进入 MySQL 环境,观察 wife 表中的外键,自动生成 author_id 外键

    mysql 复制代码
    (testenv) [root@localhost mysite3]# mysql -uroot -p123456
    MariaDB [(none)]> USE mysite3;
    MariaDB [mysite3]> DESC oto_author;
    +-------+-------------+------+-----+---------+----------------+
    | Field | Type        | Null | Key | Default | Extra          |
    +-------+-------------+------+-----+---------+----------------+
    | id    | int(11)     | NO   | PRI | NULL    | auto_increment |
    | name  | varchar(11) | NO   |     | NULL    |                |
    +-------+-------------+------+-----+---------+----------------+
    
    
    MariaDB [mysite3]> DESC oto_wife;
    +-----------+-------------+------+-----+---------+----------------+
    | Field     | Type        | Null | Key | Default | Extra          |
    +-----------+-------------+------+-----+---------+----------------+
    | id        | int(11)     | NO   | PRI | NULL    | auto_increment |
    | name      | varchar(11) | NO   |     | NULL    |                |
    | author_id | int(11)     | NO   | UNI | NULL    |                | # 外键
    +-----------+-------------+------+-----+---------+----------------+
  • 测试:给两张表中添加数据,使用 Django Shell 的方式,两种方式添加数据

    python 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py shell
    >>> from oto.models import *
    >>> a1 = Author.objects.create(name="ben")
    >>> a1.name
    	'ben'
    >>> a1.id
    	1
    >>> w1 = Wife.objects.create(name="benfuren", author=a1)    # 方式一:指定对象赋值
    >>> w1 = Wife.objects.create(name="benfuren", author_id=1)  # 方式二:指定数据库字段(外键)赋值
    
    
    >>> a2 = Author.objects.create(name="niu")
    >>> a2.id  # 查看作者id
    	2
    >>> w2 = Wife.objects.create(name="niufuren", author_id=2)  # 数据库字段赋值
  • 查询:正向查询(带外键的表)

    python 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py shell
    >>> from oto.models import *
    >>> wife = Wife.objects.get(name="benfuren")
    >>> wife.name
    'benfuren'
    >>> wife.author.name       # 正向查询
    'ben'
  • 查询:反向查询(不带外键的表)

    python 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py shell
    >>> from oto.models import *
    >>> author1 = Author.objects.get(name="ben")
    >>> author1.wife.name       # 利用反向属性进行数据查询
    'benfuren'
一对一映射关系总结
  • 一对一的模型类创建
  • 一对一的数据创建
  • 一对一的数据查询
    • 正向查询
    • 反向查询

一对多映射 models.ForeignKey()

概念与理解
  • 一对多是表示现实事物存在的一对多的对应关系
  • 如:一个学校有多个班级,一个班级有多个学生,一本书只能属于一个出版社,但是出版社可以出版多本书
  • 一对多需要明确出具体角色,在多表上设置外键
创建模型类
  • 语法:当一个A类对象可以关联多个B类对象时

  • ForeignKey必须指定 on_delete 模式

  • 示例 -- 创建模型类 - otm/models.py

添加数据
  • 先创建"一"再创建多"多"

  • 示例:

    python 复制代码
    from .models import *
    pub1=Publisher.objects.create(name='清华大学出版社')
    Book.objects.create(title='C++', publisher=pub1)
    Book.objects.create(title='Java', publisher_id=1)
查询数据
  • 正向查询 [通过Book查询Publisher]

  • 反向查询 [通过Publisher查询对应的所有的Book] 需要用到 反向属性

实验:一对多模型
  • 创建应用:otm

    shell 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py startapp otm
  • 并在 settings.py 中将 otm 应用进行注册

    python 复制代码
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'music',
        'news',
        'sport',
        'bookstore',
        'oto',
        'otm',  # 模型注册
    ]
  • 修改 otm 应用下的 models.py,创建模型类

    python 复制代码
    from django.db import models
    
    
    class Publisher(models.Model):
        #出版社  [一]
        name = models.CharField('出版社名称', max_length=50)
    
    
    class Book(models.Model):
        #书名 [多]
        title = models.CharField('书名', max_length=11)
        publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)  # 外键
  • 同步迁移数据库

    shell 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py makemigrations
    (testenv) [root@localhost mysite3]# python3 manage.py migrate
  • 进入 MySQL 环境,观察 Book 表中的外键

    mysql 复制代码
    (testenv) [root@localhost mysite3]# mysql -uroot -p123456
    MariaDB [(none)]> USE mysite3;
    
    
    MariaDB [mysite3]> DESC otm_publisher;
    +-------+-------------+------+-----+---------+----------------+
    | Field | Type        | Null | Key | Default | Extra          |
    +-------+-------------+------+-----+---------+----------------+
    | id    | int(11)     | NO   | PRI | NULL    | auto_increment |
    | name  | varchar(50) | NO   |     | NULL    |                |
    +-------+-------------+------+-----+---------+----------------+
    
    MariaDB [mysite3]> DESC otm_book;
    +--------------+-------------+------+-----+---------+----------------+
    | Field        | Type        | Null | Key | Default | Extra          |
    +--------------+-------------+------+-----+---------+----------------+
    | id           | int(11)     | NO   | PRI | NULL    | auto_increment |
    | title        | varchar(11) | NO   |     | NULL    |                |
    | publisher_id | int(11)     | NO   | MUL | NULL    |                | # 外键
    +--------------+-------------+------+-----+---------+----------------+
                                         MUL 允许多条数据有相同的publisher_id
  • 测试:给两张表中添加数据,使用 Django Shell 的方式,先创建一,再创建多

    python 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py shell
    >>> from otm.models import *
    >>> p1 = Publisher.objects.create(name="中信出版社")
    >>> p1
    <Publisher: Publisher object (1)>
    >>> p1.name
    	'中信出版社'
    >>> p1.id
    	1
    >>> b1 = Book.objects.create(title="python1", publisher=p1)    # 类属性赋值
    >>> b2 = Book.objects.create(title="python2", publisher_id=1)  # 数据库字段赋值
    >>> b1.publisher_id
    	1
    >>> b2.publisher_id
    	1
    
    MariaDB [mysite3]> select * from otm_book;
  • 查询:正向查询

    python 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py shell
    >>> from otm.models import *
    >>> b1 = Book.objects.get(id=1)
    >>> b1
    	<Book: Book object (1)>
    >>> print(b1.title, b1.publisher.name)
    	python1 中信出版社
  • 查询:反向查询

    python 复制代码
    >>> from otm.models import *
    >>> pub1 = Publisher.objects.get(name="中信出版社")
    >>> pub1
    	<Publisher: Publisher object (1)>
    >>> books = pub1.book_set.all()
    >>> books
    	<QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>
    >>> for book in books:
    ...     print(book.title)
    ... 
    	python1
    	python2
        

多对多映射 models.ManyToManyField()

概念与理解
  • 多对多表达对象之间多对多的复杂关系,如:每个都有不同的学校(小学,初中,高中......),每个学校都有不同的学生......
  • Mysql 中创建多对多需要依赖第三张表来实现
  • Django 中无需手动创建第三张表,这个操作Django自动完成
  • 语法:在关联的两个类中的任意一个类中,增加:
    • 属性 = models.ManyToManyField(MyModel)
创建模型类

用法示例:

  • 一个作者可以出版多本图书

  • 一本图书可以由多个作者共同编写

  • 用法示例---创建模型类:

添加数据
  • 用法示例---创建数据

数据查询

**正向查询:**有多对多属性的对象查另一方

  • 通过 Book 查询对应的所有的 Author

  • 此时多对多属性相当于 objects

反向查询:

  • 通过 Author查询对应的所有的 Book

  • 利用反向属性 book_set

实验:多对多模型
  • 创建应用:mtm

    shell 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py startapp otm
  • 并在 settings.py 中将 mtm 应用进行注册

    python 复制代码
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'music',
        'news',
        'sport',
        'bookstore',
        'oto',
        'otm',
        'mtm',  # 模型注册
    ]
  • 修改 mtm 应用下的 models.py,创建模型类

    python 复制代码
    from django.db import models
    
    
    class Author(models.Model):
        name = models.CharField('姓名', max_length=11)
    
    
    class Book(models.Model):
        title = models.CharField('书名', max_length=11)
        authors = models.ManyToManyField(Author)
  • 同步迁移数据库

    shell 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py makemigrations
    (testenv) [root@localhost mysite3]# python3 manage.py migrate
  • 进入 MySQL 环境,观察 Django 帮助我们生成的中间表

    mysql 复制代码
    (testenv) [root@localhost mysite3]# mysql -uroot -p123456
    MariaDB [(none)]> USE mysite3;
    
    MariaDB [mysite3]> DESC mtm_author;
    +-------+-------------+------+-----+---------+----------------+
    | Field | Type        | Null | Key | Default | Extra          |
    +-------+-------------+------+-----+---------+----------------+
    | id    | int(11)     | NO   | PRI | NULL    | auto_increment |
    | name  | varchar(11) | NO   |     | NULL    |                |
    +-------+-------------+------+-----+---------+----------------+
    
    
    MariaDB [mysite3]> DESC mtm_book;
    +-------+-------------+------+-----+---------+----------------+
    | Field | Type        | Null | Key | Default | Extra          |
    +-------+-------------+------+-----+---------+----------------+
    | id    | int(11)     | NO   | PRI | NULL    | auto_increment |
    | title | varchar(11) | NO   |     | NULL    |                |
    +-------+-------------+------+-----+---------+----------------+
    
    
    MariaDB [mysite3]> DESC mtm_book_authors;  # 中间表
    +-----------+---------+------+-----+---------+----------------+
    | Field     | Type    | Null | Key | Default | Extra          |
    +-----------+---------+------+-----+---------+----------------+
    | id        | int(11) | NO   | PRI | NULL    | auto_increment |
    | book_id   | int(11) | NO   | MUL | NULL    |                |
    | author_id | int(11) | NO   | MUL | NULL    |                |
    +-----------+---------+------+-----+---------+----------------+
  • 测试:给两张表中添加数据,使用 Django Shell 的方式

    python 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py shell
    >>> from mtm.models import *
    
    # 两个人写了一本书
    ## 方案1:先创建 author,再关联 book 
    >>> author1 = Author.objects.create(name="teacher ben")
    >>> author2 = Author.objects.create(name="teacher niu")
    >>> book1 = author1.book_set.create(title="Python")
    >>> author2.book_set.add(book1)
    
    MariaDB [mysite3]> select * from mtm_book_authors;
    
    ## 方案2:先创建 book,再关联 author
    >>> book2 = Book.objects.create(title="Django")
    >>> author3 = book2.authors.create(name="teacher hu")
    >>> book2.authors.add(author2) 
    
    
    # 一个人写了两本书
    >>> book3 = Book.objects.create(title="HH")
    >>> book4 = Book.objects.create(title="AA")
    >>> author4 = book3.authors.create(name="teacher xie")
    >>> book4.authors.add(author4)
  • 查询:正向查询,通过 Book 查询对应的所有的 Author

    python 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py shell
    >>> from mtm.models import *
    >>> book1 = Book.objects.get(title="Django")
    >>> book1.title
    	'Django'
    >>> users = book1.authors.all()
    >>> for user in users:
    ...     print(user.name)
    ... 
        teacher niu
        teacher hu
  • 查询:反向查询

    python 复制代码
    (testenv) [root@localhost mysite3]# python3 manage.py shell
    >>> from mtm.models import *
    >>> author2 = Author.objects.get(name="teacher niu")
    >>> books = author2.book_set.all()
    >>> for book in books:
    ...     print(book.title)
    ... 
        Python
        Django

Cookies 和 Session

会话概念

  • 从打开浏览器访问一个网站,到关闭浏览器结束此次访问,称之为一次会话
  • HTTP 协议是无状态的,导致会话状态难以保持
  • 试想一下,如果不保持会话状态,再电商网站购物的场景体验?
  • Cookies和Session就是为了保持会话状态而诞生的两个存储技术

Cookies

Cookies 定义

cookies 是保存在客户端浏览器上的存储空间

在讲cookie前先了解下它的使用场景

  • 使用Chrome浏览器打开京东网站且未登录情况下我的购物车未添加商品,所以商品数量是0

  • 挑选3个商品加入购物车,此时购物车数量显示3

  • 关闭 Chrome 浏览器再次打开京东首页发现购物车数量还是 3

  • 如果此时换成 Firefox 浏览器打开京东首页发现购物车里的商品数量是 0

  • 为什么 Chrome 浏览器未登录关闭浏览器后再次打开购物车商品数量没变,换个浏览器购物车商品数量就不是 3 了,这个场景就说明了 2 点

    • 商品信息保留在本地了,未保留在浏览器缓存
    • 不同的浏览器cookie的保留路径不一样,并且各个浏览器的cookie信息互不影响
Cookies 特点
  • cookie 在浏览器上 是以键值对的形式进行存储的,键和值都是以 ASCII 字符串的形式存储(不能是中文字符串)
  • 存储的数据带有生命周期
  • cookie 中的数据是按域存储隔离的,不同的域之间无法访问
  • cookie 的内部的数据会在每次访问此网站时携带到服务器端,如果 cookie 过大会降低响应速度
实验:Cookies 操作
  • 添加 cookies:修改 mysite3 下的 views.py 文件,添加指定视图函数

    python 复制代码
    from django.shortcuts import render
    from django.http import HttpResponse
    
    
    def test_static(request):
        return render(request, "test_static.html")
    
    
    def set_cookies(request):  # 添加测试cookie的函数
        resp = HttpResponse('set cookies is ok')
        resp.set_cookie('uuname', 'nfx' , 500)  # cookie的key为'uuname',value为'nfx',过期时间500s
        return resp
  • 修改主路由 urls.py

    python 复制代码
    from django.contrib import admin
    from django.urls import path, include
    from . import views
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
    	......
        path('set_cookies', views.set_cookies),
    ]
  • 启动服务,测试 http://127.0.0.1:8000/set_cookies,观察网络请求中的 cookies 变化

    python 复制代码
    网页返回 
    set cookies is ok
    
    F12查看'网络',点击set_cookies,可以看到消息头中的响应头的Set-Cookies
    
    查看'存储',Cookie中可以看到键值对 uuname: nfx
  • 获取 cookies:修改 mysite3 下的 views.py 文件,添加指定视图函数

    python 复制代码
    from django.shortcuts import render
    from django.http import HttpResponse
    
    
    def test_static(request):
        return render(request, "test_static.html")
    
    
    def set_cookies(request):
        resp = HttpResponse('set cookies is ok')
        resp.set_cookie('uuname', 'nfx',500)
        return resp
    
    
    def get_cookies(request):  # 添加获取cookie的函数
        value = request.COOKIES.get('uuname')
        return HttpResponse(f'value is {value}')  # 如果cookies过期了,则值为None
  • 修改主路由 urls.py

    python 复制代码
    from django.contrib import admin
    from django.urls import path, include
    from . import views
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        # ......
        path('set_cookies', views.set_cookies),
        path('get_cookies', views.get_cookies),  # 获取cookie的url
    ]
  • 启动服务,测试 http://127.0.0.1:8000/get_cookies,观察网络请求中的 cookies 变化

Session

Session概念

session 是在服务器上开辟了一段用于保留浏览器和服务器交互时的重要数据

实现方式
  • 使用session需要在浏览器客户端启动 cookie,且在cookie中存储 sessionid
  • 每个客户端都可以在服务端有一个独立的 session
  • 注意:不同的请求者之间不会共享这个数据,与请求者一一对应
在 Django 中的配置

向 INSTALLED_APPS 列表中添加

向 MIDDLEWARE 列表中添加

session的使用
  • session 对象是一个类似与字典的 SessionStore 类型的对象,可以用类拟于字典的方式进行操作

  • session 能够存储如字符串,整型,字典,列表等数据

  • 保存 session 的值到服务器

    • request.session['KEY'] = VALUE
  • 获取 session 的值

    • value = request.session['KEY']
    • value = request.session.get('KEY', '默认值')
  • 删除 session

    • del request.session['KEY']
实验:Session 操作
  • 添加以及获取 session:修改 mysite3 下的 views.py 文件,添加指定视图函数

    python 复制代码
    def set_session(request):
        request.session['uname'] = 'nfx'
        return HttpResponse('set session is ok')
    
    
    def get_session(request):
        value = request.session['uname']
        return HttpResponse(f'session value is {value}')
  • 修改主路由 urls.py

    python 复制代码
    from django.contrib import admin
    from django.urls import path, include
    from . import views
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        ......
        path('set_cookies', views.set_cookies),
        path('get_cookies', views.get_cookies),
        
        path('set_session', views.set_session),  # 设置session
        path('get_session', views.get_session),  # 获取session
    ]
  • 启动服务:先测试 set 设置 session,然后再测试 get 获取 session

mysql 复制代码
select * from django_session;


执行 `del request.session['KEY']` 删除session,但只是让数据过期失效,实际上数据库里的数据没有被删除
django_session 表是单表设计;且该表数据量持续增加
- 可以定期执行 **python3 manage.py clearsessions**
- 该命令可删除已过期的 session 数据
settings.py 中相关配置项以及注意事项
  • SESSION_COOKIE_AGE

    • 作用:指定sessionid在cookies中的保存时长 (默认2周),如下:
    • 例如:SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2
  • SESSION_EXPIRE_AT_BROWSER_CLOSE = True

    • 设置只要浏览器关闭时,session就失效(默认False)
  • 注意:Django中的session数据存储在数据库中,所以使用session前需要确保已经执行过migrate操作将存储session表创建出来

  • django_session 表是单表设计;且该表数据量持续增加

    • 可以定期执行 python3 manage.py clearsessions
    • 该命令可删除已过期的 session 数据

Cookie和Session的对比

相关推荐
blues_C13 小时前
十三、【核心功能篇】测试计划管理:组织和编排测试用例
vue.js·django·测试用例·drf·测试平台
恸流失21 小时前
DJango项目
后端·python·django
编程大全1 天前
41道Django高频题整理(附答案背诵版)
数据库·django·sqlite
网安小张1 天前
解锁FastAPI与MongoDB聚合管道的性能奥秘
数据库·python·django
KENYCHEN奉孝1 天前
Pandas和Django的示例Demo
python·django·pandas
老胖闲聊1 天前
Python Django完整教程与代码示例
数据库·python·django
noravinsc1 天前
django paramiko 跳转登录
后端·python·django
践行见远1 天前
django之请求处理过程分析
数据库·django·sqlite
声声codeGrandMaster1 天前
Django之表格上传
后端·python·django
菌菌的快乐生活2 天前
网站静态文件加速-Django项目静态文件存储到腾讯云COS存储提升网络请求速度
django·cos存储