pt26django教程

admin 后台数据库管理

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

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

创建后台管理帐号:

[root@vm mysite2]# python3 manage.py createsuperuser
/root/mysite2
用户名 (leave blank to use 'root'): tarena
电子邮件地址: 123456@qq.com
Password:

[root@vm mysite2]#  mysql -uroot -p123456 -e 'select * from mysite2.auth_user\G'
*************************** 1. row ***************************
          id: 1
    password: pbkdf2_sha256$150000$yE0lYzKHcN9i$VShFRN+WFSWd4qOuZDdnEJIi0j0b3u2XHZMJMuQuPvQ=
  last_login: NULL
is_superuser: 1
    username: tarena
  first_name:
   last_name:
       email: 123456@qq.com
    is_staff: 1
   is_active: 1

后台管理的登录地址: http://127.0.0.1:8000/admin/ tarena 123456

Django提供了完善的后台管理功能,也是一个完善的用户权限管理模块。登录到后台,我们可以管理系统的提供的用户、组、权限等信息。也可以管理用户的模型类呢?例如:Book类。

注册自定义模型类

若要自己定义的模型类也能在 /admin 后台管理界中显示和管理,需要将自己的类注册到后台管理界面。添加自己定义模型类的后台管理数据表的,需要用admin.site.register(自定义模型类) 方法进行注册

在应用app中的admin.py中导入models类,并注册

[root@vm mysite2]# vim bookstore/admin.py
from django.contrib import admin

# Register your models here.
from .models import Book  #导入
admin.site.register(Book)  #注册

使用预览(功能还不是很完善需改造)
pt26django教程_第1张图片
pt26django教程_第2张图片
pt26django教程_第3张图片

修改自定义模型类的展现样式

  • 在admin后台管理数据库中对自定义的数据记录都展示为 XXXX object 类型的记录,不便于阅读和判断
  • 在用户自定义的模型类中可以重写 def __str__(self): 方法解决显示问题,如:
    • 在 自定义模型类中重写 str(self) 方法返回显示文字内容:
    class Book(models.Model):
        ...
        def __str__(self):
            return "书名" + self.title
        
        
        
    [root@vm mysite2]# cat bookstore/models.py
    from django.db import models
    
    # Create your models here.
    class Book(models.Model):
        title = models.CharField("书名", max_length=50, default='')
        price = models.DecimalField('定价', max_digits=7,decimal_places=2, default=0.0)
    
        # 新增属性/字段 (要有默认值)
        market_price = models.DecimalField("零售价", max_digits=5,decimal_places=2,default=0.0)
    
        pub = models.CharField("出版社", max_length=50,default="")
    
        def __str__(self):
            info = "书名: %s, 出版社: %s, 定价: %s" % (self.title, self.pub, self.price)
            return info
        
    

模型管理器类

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

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

模型管理器的使用方法:

<应用app>/admin.py 里定义模型管理器类

class XXXXManager(admin.ModelAdmin):
    ......

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

admin.site.register(YYYY, XXXXManager) # 绑定YYYY 模型类与管理器类XXXManager

示例:

# file : bookstore/admin.py
from django.contrib import admin
from .models import Book

class BookManager(admin.ModelAdmin):
    list_display = ['id', 'title', 'price', 'market_price']

admin.site.register(Book, BookManager)

进入http://127.0.0.1:8000/admin/bookstore/book/ 查看显示方式和以前有所不同
pt26django教程_第4张图片

  • 模型管理器类ModelAdmin中实现的高级管理功能
    1. list_display 去控制哪些字段会显示在Admin 的修改列表页面中。
    2. list_display_links 可以控制list_display中的字段是否应该链接到对象的“更改”页面。
    3. list_filter 设置激活Admin 修改列表页面右侧栏中的过滤器
    4. search_fields 设置启用Admin 更改列表页面上的搜索框。
    5. list_editable 设置为模型上的字段名称列表,这将允许在更改列表页面上进行编辑。
    6. 其它参见https://docs.djangoproject.com/en/2.2/ref/contrib/admin/
# file : bookstore/admin.py
from django.contrib import admin
from .models import Book

class BookManager(admin.ModelAdmin):
    list_display = ['id', 'title', 'price', 'market_price']
    ist_display_links =['id', 'title', 'price']
    list_filter = ['pub']
    search_fields = ['id','title']
    list_editable = []
admin.site.register(Book, BookManager)

再谈Meta类

模型类可以通过定义内部类class Meta 来重新定义当前模型类和数据表的一些属性信息,一般不建议使用

用法格式如下:

class Book(models.Model):
    title = CharField(....)
    class Meta:
        1. db_table = '数据表名'
            - 该模型所用的数据表的名称。(设置完成后需要立马更新同步数据库)
        2. verbose_name = '单数名'
            - 给模型对象的一个易于理解的名称(单数),用于显示在/admin管理界面中
        3. verbose_name_plural = '复数名'
            - 该对象复数形式的名称(复数),用于显示在/admin管理界面中
            
...            
    class Meta:
        verbose_name = '图书' 
        verbose_name_plural = '图书'
在后台/admin管理界面中 ,站点管理之前显示 books,现在显示图书          

数据表关联关系映射

#新建项目,初始化配置
[root@vm mysite5]# mysql -uroot -p123456 -e 'create database mysite5 default charset utf8;'
[root@vm ~]# django-admin startproject mysite5
[root@vm ~]# cd mysite5/
[root@vm mysite5]# vim mysite5/settings.py

ALLOWED_HOSTS = ['*',]
DATABASES = {
    'default' : {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mysite5',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': 3306,
    }
}

LANGUAGE_CODE = 'zh-Hans'

TIME_ZONE = "Asia/Shanghai"

[root@vm mysite5]# python3 manage.py runserver 0.0.0.0:8000

常用的表关联方式有三种:

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

一对一映射OneToOneField

语法

class A(model.Model):
    ...
class B(model.Model):
    属性 = models.OneToOneField(A, on_delete=xxx)

外键类字段选项,特殊字段参数on_delete【必须项】:

models.CASCADE  级联删除。 Django模拟SQL约束ON DELETE CASCADE的行为,并删除包含ForeignKey的对象。

models.PROTECT 抛出ProtectedError 以阻止被引用对象的删除;[等同于mysql默认的RESTRICT]

models.SET_NULL 设置ForeignKey null;需要指定null=True

models.SET_DEFAULT  将ForeignKey设置为其默认值;必须设置ForeignKey的默认值。

其它参请参考文档 https://docs.djangoproject.com/en/2.2/ref/models/fields/#foreignkey

其余常用的字段选项【非必须项】;如: null , unique 等

用法示例

创建作家和作家妻子类

[root@vm mysite5]# python3 manage.py startapp oto
[root@vm mysite5]# vim mysite5/settings.py
INSTALLED_APPS = [
...
    'oto',[root@vm mysite5]# vim oto/models.py

from django.db import models

class Author(models.Model):
    '''作家模型类'''
    # 有一个反向属性,wife。下面会提到

    name = models.CharField('作家', max_length=50)

class Wife(models.Model):
    '''作家妻子模型类'''
    name = models.CharField("妻子", max_length=50)
    
    author = models.OneToOneField(Author,on_delete=models.CASCADE)  # 增加一对一属性  author规范一下写法是关联Author类的小写 
    #CASCADE  将产生级联删除
    
[root@vm mysite5]# python3 manage.py makemigrations
[root@vm mysite5]# python3 manage.py migrate
[root@vm mysite5]# mysql -uroot -p123456 -e 'desc mysite5.oto_author;'
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(50) | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
[root@vm mysite5]# mysql -uroot -p123456 -e 'desc mysite5.oto_wife;'
+-----------+-------------+------+-----+---------+----------------+
| Field     | Type        | Null | Key | Default | Extra          |
+-----------+-------------+------+-----+---------+----------------+
| id        | int(11)     | NO   | PRI | NULL    | auto_increment |
| name      | varchar(50) | NO   |     | NULL    |                |
| author_id | int(11)     | NO   | UNI | NULL    |                |
+-----------+-------------+------+-----+---------+----------------+

创建一对一的数据记录

使用对象关联或主键关联

[root@vm mysite5]# python3 manage.py shell

from oto.models import *
author1 = Author.objects.create(name='王老师')
wife1 = Wife.objects.create(name='王夫人', author=author1)  # 对象关联王老师

author2 = Author.objects.create(name='张老师')  # 主键关联的第二种方式
wife1 = Wife.objects.create(name='张夫人', author_id=author2.id)

>>> author3 = Author.objects.create(name='小李老师') #创建无关联的数据,主表数据可以比从表多
> select * from oto_author;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 王老师    |
|  2 | 张老师    |
|  3 | 小李老师  |
+----+-----------+
> select * from oto_wife;
+----+-----------+-----------+
| id | name      | author_id |
+----+-----------+-----------+
|  1 | 王夫人    |         1 |
|  2 | 张夫人    |         2 |
+----+-----------+-----------+
#CASCADE  将产生级联删除
>>> Author.objects.get(id=1).delete()
(2, {'oto.Wife': 1, 'oto.Author': 1}) #王夫人随之删除
>>> Wife.objects.get(id=2).delete()
(1, {'oto.Wife': 1})  #张老师不受影响

> select * from oto_author;
+----+--------------+
| id | name         |
+----+--------------+
|  2 | 张老师       |
|  3 | 小李老师     |
+----+--------------+
2 rows in set (0.00 sec)

> select * from oto_wife;
Empty set (0.00 sec)

添加数据

>>> wife1 = Wife.objects.create(name='张夫人', author_id=author2.id)
>>> author1 = Author.objects.create(name='王老师')
>>> wife1 = Wife.objects.create(name='王夫人', author=author1)
> select * from oto_author;
+----+--------------+
| id | name         |
+----+--------------+
|  2 | 张老师       |
|  3 | 小李老师     |
|  4 | 王老师       |
+----+--------------+

> select * from oto_wife;
+----+-----------+-----------+
| id | name      | author_id |
+----+-----------+-----------+
|  3 | 张夫人    |         2 |
|  4 | 王夫人    |         4 |
+----+-----------+-----------+

数据查询

  1. 正向查询:直接通过关联属性查询即可

    # 通过 wife 找 author 
    from oto.models import Wife
    wife = Wife.objects.get(name='王夫人')
    print(wife.name, '的老公是', wife.author.name)#王夫人 的老公是 王老师
    
  2. 反向查询

    • 通过反向关联属性查询
    • 反向关联属性为实例对象.引用类名(小写),如作家的反向引用为作家对象.wife
    • 当反向引用不存在时,则会触发异常
    # 通过 author.wife 关联属性 找 wife,如果没有对应的wife则触发异常
    author1 = Author.objects.get(name='王老师')
    print(author1.name, '的妻子是', author1.wife.name)
    
    
    author2 = Author.objects.get(name='小李老师')
    try:
        print(author2.name, '的妻子是', author2.wife.name)
    except:
        print(author2.name, '还没有妻子')
        
    #小李老师 还没有妻子 
    

一对多映射ForeignKey

一对多是表示现实事物间存在的一对多的对应关系。语法:当一个A类对象可以关联多个B类对象时

class A(model.Model):
    ...

class B(model.Model):
    属性 = models.ForeignKey("一"的模型类, on_delete=xx)

创建项目

[root@vm mysite5]# python3 manage.py startapp otm
[root@vm mysite5]# vim mysite5/settings.py
INSTALLED_APPS = [
...
    'otm',  

创建模型类

[root@vm mysite5]# vim otm/models.py
from django.db import models

class Publisher(models.Model):
        # 有一个反向属性,book_set
    name = models.CharField("名称", max_length=50,
                            unique=True)

class Book(models.Model):
    title = models.CharField('书名', max_length=50)
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

    
[root@vm mysite5]# python3 manage.py makemigrations
[root@vm mysite5]# python3 manage.py migrate
> desc otm_publisher;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(50) | NO   | UNI | NULL    |                |
+-------+-------------+------+-----+---------+----------------+

desc otm_book;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| id           | int(11)     | NO   | PRI | NULL    | auto_increment |
| title        | varchar(50) | NO   |     | NULL    |                |
| publisher_id | int(11)     | NO   | MUL | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+

创建数据

#先创建 '一' ,再创建 '多'
from otm.models import *
pub1 = Publisher.objects.create(name='清华大学出版社')

#用对象关联
Book.objects.create(title='python', publisher=pub1)
#用主键关联
Book.objects.create(title='Java', publisher_id=1)  

#高级创建 - 利用 反向属性
pub2 = Publisher.objects.create(name='北京大学出版社')
pub2.book_set.create(title='西游记')


> select * from otm_publisher;
+----+-----------------------+
| id | name                  |
+----+-----------------------+
|  2 | 北京大学出版社        |
|  1 | 清华大学出版社        |
+----+-----------------------+

> select * from otm_book;
+----+--------------+--------------+
| id | title        | publisher_id |
+----+--------------+--------------+
|  1 | python       |            1 |
|  2 | Java         |            1 |
|  3 | 西游记       |            2 |
|  4 | 红楼梦       |            2 |
|  5 | 三国演义     |            2 |
+----+--------------+--------------+

数据查询

通过 Book 查询 Publisher【正向】

通过 publisher 属性查询即可 book.publisher

>>> Book.objects.get(title='java').publisher.name
'清华大学出版社'

abook = Book.objects.get(id=1)
print(abook.title, '的出版社是:', abook.publisher.name)

通过 Publisher 查询 对应的所有的 Book 【反向】

Django会在Publisher中增加一个属性来表示对对应的Book们的查询引用
属性:book_set  等价于 objects

# 通过出版社查询对应的书
pub1 = Publisher.objects.get(name='清华大学出版社')
books = pub1.book_set.all()  # 通过book_set 获取pub1对应的多个Book数据对象
#books = Book.objects.filter(publisher=pub1)  # 也可以采用此方式获取
print("清华大学出版社的书有:")
for book in books:
   print(book.title)

多对多映射ManyToManyField

多对多表达对象之间多对多复杂关系,不用指定on_delete,语法:在关联的两个类中的任意一个类中,增加:

属性 = models.ManyToManyField(MyModel)

创建项目

一个作者可以出版多本图书,一本图书可以被多名作者同时编写

[root@vm mysite5]# python3 manage.py startapp mtm
[root@vm mysite5]# vim mysite5/settings.py
INSTALLED_APPS = [
...
    'mtm',  

创建模型类

[root@vm mysite5]# vim mtm/models.py
class Author(models.Model):
    name = models.CharField('作家', max_length=50)

    
class Book(models.Model):
    title = models.CharField('书名', max_length=50)
    authors = models.ManyToManyField(Author)
    
[root@vm mysite5]# python3 manage.py makemigrations
[root@vm mysite5]# python3 manage.py migrate

> desc mtm_author;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(50) | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+

> desc mtm_book;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| title | varchar(50) | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+

> 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    |                |
+-----------+---------+------+-----+---------+----------------+

创建数据

from mtm.models import * 

#   方案1 先创建 author 再关联 book

author1 = Author.objects.create(name='吕老师')
author2 = Author.objects.create(name='王老师')
# 关联图书
book11 = author1.book_set.create(title="Python")
author2.book_set.add(book11) 

> select * from mtm_author;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 吕老师    |
|  2 | 王老师    |
+----+-----------+
2 rows in set (0.00 sec)

> select * from mtm_book;
+----+--------+
| id | title  |
+----+--------+
|  1 | Python |
+----+--------+
1 row in set (0.00 sec)

> select * from mtm_book_authors;
+----+---------+-----------+
| id | book_id | author_id |
+----+---------+-----------+
|  1 |       1 |         1 |
|  2 |       1 |         2 |
+----+---------+-----------+

    
方案2 先创建 book 再关联 author
book = Book.objects.create(title='java')
author3 = book.authors.create(name='李老师')
book.authors.add(author1)

数据查询

  1. 通过 Book 查询对应的所有的 Author【正向】
from mtm.models import * 

>>> b1 = Book.objects.get(title='java')
>>> authors = b1.authors.all()
>>> for a in authors:
...    print(a.name)
...
王老师


author1 = Author.objects.get(name='吕老师')
book.authors.all() -> 获取 book 对应的所有的author的信息
book.authors.filter(age__gt=80) -> 获取book对应的作者中年龄大于80岁的作者的信息
  1. 通过 Author 查询对应的所有的Book【反向】

Django会生成一个反向属性 book_set 用于表示对对应的book的查询对象相关操作

>>> author1 = Author.objects.get(name='吕老师')
>>> books=author1.book_set.all()   # author1.book_set.filter()

>>> for book in books:
...    print(book.title)
...
Python

表的关联关系总结

一对一
      属性 = models.OneToOneField(A, on_delete=xxx)
      1. 生成表结构
      2. 添加数据
      3. 查询数据
          3.1 正向查询   
          3.2 反向查询 
 
一对多【使用最多】
      属性 = models.ForeignKey("一"的模型类, on_delete=xx)
      1. 生成表结构
      2. 添加数据

多对多【难度最大】
     属性 = models.ManyToManyField(MyModel)

添加到djanto管理界面

[root@vm mysite5]# python3 manage.py createsuperuser
用户名 (leave blank to use 'root'): tarena

[root@vm mysite5]# vim mtm/admin.py
from django.contrib import admin
from .models import *

# Register your models here.
class AuthorManager(admin.ModelAdmin):
    list_display = ['id','name']
    list_display_links = ['id','name']
class BookManager(admin.ModelAdmin):
    list_display = ['id','title']
admin.site.register(Author,AuthorManager)
admin.site.register(Book,BookManager)

#__str__重写,不重写 django的web界面显示的是object对象,没可读写
[root@vm mysite5]# vim mtm/models.py
class Author(models.Model):
    name = models.CharField('作家', max_length=50)
    def __str__(self):
        return self.name
    
class Book(models.Model):
    title = models.CharField('书名', max_length=50)
    authors = models.ManyToManyField(Author)
    def __str__(self):
   		return self.title
   		
   		
 #浏览器访问,体验功能管理  		

cookies 和 session

会话 - 从打开浏览器访问一个网站,到关闭浏览器结束此次访问,称之为一次会话。HTTP协议是无状态的,导致会话状态难以保持。Cookies和Session就是为了保持会话状态而诞生的两个存储技术

#新建项目,初始化配置
[root@vm ~]# mysql -uroot -p123456 -e 'create database mysite6 default charset utf8;'
[root@vm ~]# django-admin startproject mysite6
[root@vm ~]# cd mysite6/
[root@vm mysite6]# vim mysite6/settings.py

ALLOWED_HOSTS = ['*',]
DATABASES = {
    'default' : {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mysite6',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': 3306,
    }
}

LANGUAGE_CODE = 'zh-Hans'

TIME_ZONE = "Asia/Shanghai"

[root@vm mysite6]# python3 manage.py runserver 0.0.0.0:8000

cookies

查看和操作浏览器端所有的 Cookies 值
    Chrome 浏览器 可能通过开发者工具的Application >>Storage >>Cookies
    火狐浏览器 可能通过开发者工具的 存储 -> Cookie
cookies是"保存在客户端"浏览器上的存储空间,

cookies 在浏览器上是以键-值对的形式进行存储的,键和值都是"以ASCII字符串"的形存储

cookies中的数据是"按域"存储隔离的,不同的域之间无法访问

cookies 每次访问此网址时都会携带到服务器端,如果"cookies过大会降低响应速度"

cookies  不要存储敏感的信息,不安全,(存储sessionid,相对安全)

Django 设置COOKIE

在Django 设置浏览器的COOKIE 必须通过 HttpResponse 对象来完成

  • 添加、修改COOKIE

    HttpResponse.set_cookie(key, value='', max_age=None, expires=None)
        - key:cookie的名字
        - value:cookie的值
        - max_age:cookie存活时间,秒为单位
        - expires:具体过期时间
        - 当不指定max_age和expires 时,关闭浏览器时此数据失效
    
  • 删除COOKIE

    - HttpResponse.delete_cookie(key)
    - 删除指定的key 的Cookie。 如果key 不存在则什么也不发生。
    
  • 获取cookie

    通过 request.COOKIES 绑定的字典(dict) 获取客户端的 COOKIES数据

    value = request.COOKIES.get('cookies名', '默认值')
    print("cookies名 = ", value)
    

使用示例

添加cookie

[root@vm mysite6]# vim mysite6/urls.py
urlpatterns = [
...
    path('set_cookie',views.set_cookie),
]

[root@vm mysite6]# vim mysite6/views.py
from django.http import HttpResponse

def set_cookie(request):
    resp = HttpResponse("set cookie ok!")
    resp.set_cookie('username','tarena',60)
    return resp

访问 http://192.168.1.11:8000/set_cookie

#开发者工具 查看cookie username的键值对儿
Application >>Storage >>Cookies>>http://192.168.1.11:8000

#开发者工具  查看响应头
Network >>set_cookie >> Response Header >> Set-Cookie:
Set-Cookie: username=tarena; expires=Sun, ... GMT; Max-Age=60; Path=/

获取cookie

[root@vm mysite6]# vim mysite6/urls.py    

   path('get_cookie',views.get_cookie),
[root@vm mysite6]# vim mysite6/views.py
...
def get_cookie(request):
    name = request.COOKIES.get('username', 'no-value')
    return HttpResponse("cookie value is %s" % name)

访问 http://192.168.1.11:8000/get_cookie

#开发者工具  请求头
Network >>get_cookie >> resquest Header >> 没有cookie(已过期)

刷新http://192.168.1.11:8000/set_cookie
再次访问 http://192.168.1.11:8000/get_cookie   页面显示:cookie value is tarena

Network >>get_cookie >> resquest Header >> Cookie: 末尾有username=tarena

删除cookie

[root@vm mysite6]# vim mysite6/urls.py  

    path('del_cookie',views.del_cookie),

[root@vm mysite6]# vim mysite6/views.py

def del_cookie(request):
    resp = HttpResponse("del cookie ok!")
    resp.delete_cookie('username')
    return resp

访问 http://192.168.1.11:8000/del_cookie

Network >>set_cookie >> Response Header >> Set-Cookie:
Set-Cookie: username=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/
#注意 expires有效时间    Max-Age存活时间

session

session又名会话控制,是在服务器上开辟一段空间用于保留浏览器和服务器交互时的重要数据,实现方式

- 使用 session 需要在浏览器客户端启动 cookie,且用在cookie中存储sessionid
- 每个客户端都可以在服务器端有一个独立的Session
- 注意:不同的请求者之间不会共享这个数据,与请求者一一对应
cookies 的特点
      1>保存在客户端浏览器
      2>按域隔离
      3>键值对存储
      4>不安全,不要保存敏感数据
session的特点
      1>保存在服务器
      2>session的使用需要借助于cookie来存储sessionid
      3>相对安全,但是也不要存储敏感数据     
   虽然session的原理和步骤都比cookie更复杂,但是在Django中
   使用时,由于做了相应的处理,反而使用更简单。会使用字典就会使用session。

Django中配置Session

在 settings.py 文件中,向 INSTALLED_APPS 列表中添加:

INSTALLED_APPS = [
    # 启用 sessions 应用,默认启用
    'django.contrib.sessions',
]

向 MIDDLEWARE 列表中添加:

MIDDLEWARE = [
    # 启用 Session 中间件,默认启用
    'django.contrib.sessions.middleware.SessionMiddleware',
]
[root@vm mysite6]# python3 manage.py makemigrations
[root@vm mysite6]# python3 manage.py migrate

> show tables;
+----------------------------+
| Tables_in_mysite6          |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+
> desc django_session;
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| session_key  | varchar(40) | NO   | PRI | NULL    |       |
| session_data | longtext    | NO   |     | NULL    |       |
| expire_date  | datetime(6) | NO   | MUL | NULL    |       |
+--------------+-------------+------+-----+---------+-------+

session的基本操作:

  • session对于象是一个类似于字典的SessionStore类型的对象, 可以用类拟于字典的方式进行操作
  • session 只能够存储能够序列化的数据,如字典,列表等。
保存 session 的值到服务器
	request.session['KEY'] = VALUE

获取session的值
    VALUE = request.session['KEY']
    VALUE = request.session.get('KEY', 缺省值)

删除session的值
	del request.session['KEY']

在 settings.py 中有关 session 的设置
  1. SESSION_COOKIE_AGE
     - 作用: 指定sessionid在cookies中的保存时长(默认是2周),如下:
     - SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2
  2. SESSION_EXPIRE_AT_BROWSER_CLOSE = True
     设置只要浏览器关闭时,session就失效(默认为False)  

当使用session时需要迁移数据库,否则会出现错误
	python3 manage.py migrate

session添加

[root@vm mysite6]# vim mysite6/urls.py
    path('set_session',views.set_session),
    path('get_session',views.get_session),

[root@vm mysite6]# vim mysite6/views.py
...
def set_session(request):
    request.session['username'] = 'tarena'
    return HttpResponse("set session is ok")
def get_session(request):
    username = request.session.get('username', 'no-value')
    return HttpResponse("user name  is %s" % username)

http://192.168.1.11:8000/set_session

#开发者工具 查看cookie username的键值对儿
Application >>Storage >>Cookies>>http://192.168.1.11:8000
sessionid: kim2qi8v4lcfy92ax9r7gn6r4c4zkj0v
#开发者工具  查看响应头
Set-Cookie: sessionid=kim2qi8v4lcfy92ax9r7gn6r4c4zkj0v
这与数据库里存储的session_key是同一个


> select * from  django_session\G
*************************** 1. row ***************************
 session_key: kim2qi8v4lcfy92ax9r7gn6r4c4zkj0v
session_data: YjFkZjBiZmQ4MzFhZDIwZWI0YWZhNDMxOTE5ZDE0Nj...
...

http://192.168.1.11:8000/get_session
user name is tarena

session删除

[root@vm mysite6]# vim mysite6/urls.py
    path('del_session',views.del_session),

[root@vm mysite6]# vim mysite6/views.py
def del_session(request):
    if 'username' in request.session:
        del request.session['username']
    return HttpResponse("del session   is ok")

设置session 时间

[root@vm mysite6]# vim mysite6/settings.py
SESSION_COOKIE_AGE = 60

http://192.168.1.11:8000/set_session     看响应头Max-Age=60

删除已过期session

django 原生session 问题:

1,django_session表是 单表设计;且该表数据量持续增持,不会删除包括
        恶意删除的sessionid(客户端手动删掉sessionid,重新请求服务器生成新的)
    	过期的sessionid数据
2,可以每晚执行 python3 manage.py clearsessions可删除已过期的session数据
        恶意删除的sessionid,未过期,命令无法删除

你可能感兴趣的:(sqlite,数据库,android,django)