四、进阶知识
4.1 admin后台管理
-
django提供了比较完善的后台管理数据库的接口,可供开发过程中调用和测试使用
-
django会搜集所有已注册的模型类,为这些模型类提供数据管理界面,供开发者使用
-
创建后台管理账号 - 该账号为管理后台最高权限账号
python3 manage.py createsuperuser
-
注册自定义模型类
若要自己定义的模型类也能在/admin后台管理界中显示和管理,需要将自己的类注册到后台管理界面
注册步骤:
-
在应用app中的admin.py中导入注册要管理的模型models类,如:from .models import Book
-
调用admin.site.register方法进行注册,如:
admin.site.register(自定义模型类)
使用方法:
-
在<应用app>/admin.py里定义模型管理器类
class XXXXManager(admin.ModelAdmin): ......
-
绑定注册模型管理器和模型类
from django.contrib import admin from .models import * admin.site.register(YYYY, XXXXManager)# 绑定YYYY模型类与管理器类XXXXManager
案例:
# 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)
一些选项:
- list_display去控制哪些字段会显示在Admin的修改列表页面中
- list_display_links可以控制list_display中的字段是否应该链接到对象的“更改"页
- list_filter设置激活Admin修改列表页面右侧栏中的过滤器
- search_fields设置启用Admin更改列表页面上的搜索框
- list_editable设置为模型上的字段名称列表,这将允许在更改列表页面上进行编辑
https://docs.djangoproject.com/en/2.2/ref/contrib/admin
-
4.2 关系映射
在关系型数据库中,通常不会把所有数据都放在同一张表中,不易于扩展,常见关系映射有:
- 一对一映射
- 一对多映射
- 多对对映射
一对一
语法:OneToOneField(类名,on_delete=xxx)
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]
-
SET_NULL设置为ForeignKey null;需要指定null=True
-
SET_DEFAULT将ForeignKey设置为默认值;必须设置ForeignKey的默认值
-
更多内容见官方文档https://docs.djangoproject.com/en/2.2/ref/models/fields/#foreignkey
from django.db import models
class Author(models.Model):
"""作家模型类"""
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]:
author1 = Author.objects.create(name=‘王老师’)
-
有外键的模型类[Wife]:
#关联王老师obj
wife1 = Wife.objects.create(name=‘王夫人’,author=author1)
#关联王老师对应主键值
wife1 = Wife.objects.create(name=‘王老师’,author_id=1)
-
查询数据
1.正向查询:直接通过外键属性查询,则称为正向查询
# 通过wife找author from .models import Wife wife = Wife.objects.get(name='王夫人') print(wife.name, '的老公是', wife.author.name)
2.反向查询:没有外键属性的一方,可以调用反向属性查询到关联的另一方
反向关联属性为
实例对象.引用类名(小写)
,如作家的反向引用为作家对象.wife
当反向引用不存在时,则会触发异常
author1 = Author.objects.get(name=‘王老师’)
author1.wife.name
一对多
一对多是表示现实事物之间存在的一对多的对应关系
一对多需要明确出具体角色,在多表上设置外键
语法
当一个A类对象可以关联多个B类对象时
class A(model.Model):
...
class B(model.Model):
属性 = models.ForeignKey("一"的模型类, on_delete=xx)
ForeignKey必须指定on_delete模式
示例 - 创建模型类 - otm/models.py
# file: otm/models.py
from django.db import models
class Publisher(models.Model):
"""出版社【一】"""
name = model.CharField('名称', max_length=50, unique=True)
class Book(models.Model):
"""书【多】"""
title = models.CharField('书名', max_length=50)
publisher = ForeignKey(Publisher, on_delete=models.CASCADE)
-
查询数据
1.正向查询[通过Book查询Publisher]
# 通过publisher属性查询即可:book.publisher abook = Book.objects.get(id=1) print(abook.title, '的出版社是:', abook.publisher.name)
2.反向查询[通过Publisher查询对应的所有的Book]
# 通过出版社查询对应的书 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)
多对多
多对多表达对象之间多对多复杂关系。
- mysql中创建多对多需要依赖第三张表来实现
- Django中无需手动创建第三张表,Django自动完成
语法:在关联的两个类的任意一个类中,增加
属性 = models.ManyToManyField(MyModel)
class Author(models.Model):
name = models.CharField('姓名', max_length=11)
class Book(models.Model):
title = models.CharField('书名', max_length=11)
authors = models.ManyToManyField(Author)
示例
# 方案1 先创建author再关联book
author1 = Author.objects.create(name='吕老师')
author2 = Author.objects.create(name='王老师')
# 吕老师和王老师同时写了一本Python
book11 = author1.book_set.create(title='Python')
author2.book_set.add(book11)
# 方案2 先创建book再关联author
book = Book.objects.create(title='python1')
# 郭小闹和吕老师都参与了python1的创作
author3 = book.authors.create(name='guoxiaonao')
book.authors.add(author1)
-
正向查询 有多对多属性的一方查另一方
通过Book查询对应所有的Author
此时多对多属性等价于objects
book.authors.all() -> 获取book对应的所有author的信息 book.authors.filter(age__gt=80) -> 获取book对应的作者中年龄大于80岁的作者的信息
-
反向查询
通过Author查询对应的所有的Book
利用反向属性book_set
author.book_set.all() author.book_set.filter()
4.3 cookies和session
会话定义
-
从打开浏览器访问一个网站,到关闭浏览器结束此次访问,称之为一次会话
-
HTTP协议是无状态的,导致会话状态难以保持
-
Cookies和Session就是为了保持会话状态二而诞生的两个存储技术
-
cookies是保存在客户端浏览器上的存储空间
Chrome浏览器通过开发者工具的Application>>Storage>>Cookies可查看
火狐浏览器通过开发者工具的存储>>Cookie查看
-
cookies在浏览器上是以键值对的形式存储,键和值都是以ASCII字符串的形式存储(不能是中文字符)
-
存储的数据带有生命周期
-
cookies中的数据是按域存储隔离的,不同的域之间无法访问
-
cookies的内部的数据会在每次访问此网址时都会携带到服务器端,如果cookies过大会降低响应速度
Cookies的使用
HttpResponse.set_cookie(key, value=’’, max_age=None, expires = None)
- key:cookies的名字
- value:cookies的值
- max_age:cookies存活时间
- expires:具体过期时间
- 当不指定max_age和expires时,关闭浏览器时此数据失效
存储示例:
-
添加cookie
# 为浏览器添加键为my_var1,值为123,过期时间为1个小时的cookie responds = HttpResponse("已添加my_var1,值为123") responds.set_cookie('my_var1', 123, 3600) return responds
-
修改cookie
# 为浏览器添加键为my_var1,值为456,过期时间为2个小时的cookie responds = HttpResponse("已修改my_var1,值为456") responds.set_cookie("my_var1", 456, 3600*2) return responds
-
删除cookie
HttpResponse.delete_cookie(key)
删除指定的key的Cookie。如果key不存在则什么也不发生
-
获取cookie
通过request.COOKIES绑定的字典(dict)获取客户端的COOKIES数据
value = request.COOKIES.get(‘cookies名’, ‘默认值’)
session定义
session是在服务器上开辟一段空间用于保存浏览器和服务器交互时的重要数据
实现方式
- 使用session需要在浏览器客户端启动cookie,且在cookie中存储sessionid
- 每个客户端都可以在服务器端有一个独立的Session
- 注意:不同的请求者之间不会共享这个数据,与请求者一一对应
settings.py中配置session
-
向INSTALLED_APPS列表中添加:
INSTALLED_APPS = [ # 启用sessions应用 'django.contrib.sessions' ]
-
向MIDDLEWARE列表中添加:
MIDDLEWARE = [ # 启用Session中间件 'django.contrib.sessions.middleware.SessionMiddleware' ]
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_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
Django session的问题
- django_session是单表设计;且该表数据量持续增持[浏览器故意删掉sessionid&过期数据未删除]
- 可以每晚执行python3 manage.py clearsessions[该命令可删除过期的session数据]
注意:Cookies存储在浏览器,session存储在服务器,所以session相对安全