烟台网站建设方案书,wordpress getvar,wordpress getpagenumlink,平面ui设计网站目录
一、前言
【1】测试脚本
【2】数据准备
二、单表操作
【1】数据的增加
【2】数据的删除
【3】数据的更改
三、常见的十几种查询方法
四、查看内部sql语句的方式
【1】方式一
【2】方式二
五、基于双下划线的查询
六、多表查询引入
【1】数据准备
【2】外键…目录
一、前言
【1】测试脚本
【2】数据准备
二、单表操作
【1】数据的增加
【2】数据的删除
【3】数据的更改
三、常见的十几种查询方法
四、查看内部sql语句的方式
【1】方式一
【2】方式二
五、基于双下划线的查询
六、多表查询引入
【1】数据准备
【2】外键的增删改查
(1)一对多外键的增删改查
(2)多对多外键的增删改查
【补充】正反向的概念
七、多表查询
【1】子查询(基于对象的跨表查询)
【2】联表查询(基于双下划线的跨表查询)
八、聚合查询
九、分组查询
十、F与Q查询
【1】F查询
【2】Q查询
十一、Django中如何开启事务
【1】ACID是数据库事务的四个关键特性
【2】Django中如何开启事务
十二、ORM中常用的字段及参数
【1】ORM字段
【2】ORM字段参数
【3】ORM关系字段
【4】自定义字段(了解) 一、前言 Django自带的sqlite3数据对日期格式不敏感处理的时候容易出错 【1】测试脚本
测试脚本 当我们只想要测试Django中的某一个py文件的内容时我们可以不需要书写前后端交互的形式而是直接写一个测试脚本即可测试环境的准备 在测试文件中书写下面内容这内容其实就是最外部 manage.py 文件中的上面几句话 脚本代码无论是写在应用下的 tests.py文件还是自己新建文件将内容写在新文件中都会生效
from django.test import TestCase# Create your tests here.
import osif __name__ __main__:os.environ.setdefault(DJANGO_SETTINGS_MODULE, day07.settings)import djangodjango.setup()# 在下面书写我们需要测试的代码# 即所有的测试代码都必须等待环境准备完毕之后才能书写
【2】数据准备
在models里面创建我们需要的数据库中的表
from django.db import models# Create your models here.class User(models.Model):name models.CharField(verbose_name姓名, help_text姓名, max_length32)age models.IntegerField(verbose_name年龄, help_text年龄)register_time models.DateTimeField(verbose_name注册时间, help_text注册时间)DateFieldDateTimeField两个关键参数auto_now 每次操作数据的时候该字段会自动将当前时间更新auto_now_add 在创建数据的时候会自动将当前创建时间记录下来只要不是人为修改就不会发生更改
配置数据库文件(settings.py)
DATABASES {default: {ENGINE: django.db.backends.mysql,# 数据库名字NAME: django_day10,# 用户USER: root,# 密码PASSWORD: 123,# IPHOST: 127.0.0.1,# 端口PORT: 3306,# 编码集CHARSET: utf8,}
}
在项目下的 init.py 中声明数据库类型
import pymysqlpymysql.install_as_MySQLdb()
二、单表操作
【1】数据的增加
from django.test import TestCase# Create your tests here.
import osif __name__ __main__:os.environ.setdefault(DJANGO_SETTINGS_MODULE, day07.settings)import djangodjango.setup()# 在下面书写我们需要测试的代码# 即所有的测试代码都必须等待环境准备完毕之后才能书写from app01 import models# 增加数据# register_time (1)支持自己指定传值res models.User.objects.create(namejerry, age20, register_time2023-11-15)# 返回值为对象本身print(res) # User object# register_time (2)支持传入日期对象import datetime# 生成一个当前的时间对象c_time datetime.datetime.now()user_obj models.User.objects.create(nameegon, age20, register_timec_time)# 保存数据user_obj.save()
【2】数据的删除
# 删除数据
pk : 自动查找到当前表的主键字段指代的就是当前表的主键字段
使用 pk 后不需要知道当前表的主键字段它会自动帮我们查找并匹配
# (1)方式一
res models.User.objects.filter(pk4).delete()
print(res) # (1, {app01.User: 1})
# (2)方式二
# 拿到当前用户对象
user_obj models.User.objects.filter(pk1).first()
# 利用对象的方法进行删除
user_obj.delete()
【3】数据的更改
# 数据的更改
# (1)方式一
res models.User.objects.filter(pk5).update(namemengmeng)
print(res) # 1
# (2)方式二
get方法返回的直接就是当前数据对象;
但是该方法不推荐使用如果查询的数据不存在会直接报错 fileter不会
user_onj models.User.objects.get(pk5)
# 调用对象更改数据
user_onj.name xiaomeng
user_onj.save()
三、常见的十几种查询方法 ################必知必会十三条################# (1) all() - 查询所有数据# (2) filter() - 带有过滤条件的查询# (3) get() - 根据条件拿数据对象但是条件不存在会直接抛出异常# (4) first() - 拿queryset中的第一个元素res models.User.objects.all().first()print(res)# (5) last() - 拿queryset中的最后一个元素res models.User.objects.all().last()print(res)# (6) values() - 可以指定获取的数据字段res models.User.objects.values(name)# 返回的数据格式为列表套字典 - 本质上是一个 QuerySet 对象 而不是真的列表print(res) # QuerySet [{name: xiaomeng}]# (7) values_list() - 可以指定获取的数据字段res_list models.User.objects.values_list(name, age)# 返回的数据格式为列表套元祖 - 本质上是一个 QuerySet 对象 而不是真的列表print(res_list) # QuerySet [(xiaomeng, 18)]# 该语句可以查看当前执行命令的 SQL 语句 - 只有queryset对象才能使用该方法print(res_list.query) # SELECT app01_user.name, app01_user.age FROM app01_user# (8) distinct() - 去重(带有主键就意味着数据存在不一样的地方# 所以一定要去除主键后再去重去重一定要是一模一样的数据)res models.User.objects.values(name, age).distinct()print(res)# (9) order_by() - 排序# 默认升序res models.User.objects.order_by(age)print(res)# 降序res models.User.objects.order_by(-age)print(res)# (10) reverse() - 反转的前提是数据已经经过排序过的数据# 只能对有序的数据进行反转res models.User.objects.order_by(age).reverse()print(res)# (11) count() - 统计当前数据的个数res models.User.objects.count()print(res)# (12) exclude() - 排出在外# 将某个数据排出在结果之外res models.User.objects.exclude(userdream)# (13) exists() - 是否存在 - 返回布尔值 - 用处不大因为数据本身就有布尔值的状态res models.User.objects.filter(pk5).exists()print(res)
四、查看内部sql语句的方式
【1】方式一 只有queryset对象才能使用该方法 res_list models.User.objects.values_list(name, age)# 返回的数据格式为列表套元祖 - 本质上是一个 QuerySet 对象 而不是真的列表print(res_list) # QuerySet [(xiaomeng, 18)]# 该语句可以查看当前执行命令的 SQL 语句 - 只有queryset对象才能使用该方法print(res_list.query) # SELECT app01_user.name, app01_user.age FROM app01_user
【2】方式二 所有 SQL语句 都可以使用 在项目的settings.py文件中增加默认配置
LOGGING {version: 1,disable_existing_loggers: False,handlers: {console:{level:DEBUG,class:logging.StreamHandler,},},loggers: {django.db.backends: {handlers: [console],propagate: True,level:DEBUG,},}
}
五、基于双下划线的查询 # 神奇的双下划线查询# (1)年龄大于35岁的数据res models.User.objects.filter(age__gt35)print(res)# (2)年龄小于35岁的数据res models.User.objects.filter(age__lt35)print(res)# (3)年龄大于等于32岁的数据res models.User.objects.filter(age__gte32)print(res)# (4)年龄小于等于30岁的数据res models.User.objects.filter(age__lte30)print(res)# (5)年龄是18或者32或者40res models.User.objects.filter(age__in(18, 32, 40))print(res)# (6)年龄是18-40之间 - 首尾都要res models.User.objects.filter(age__range(18, 40))print(res)# (7)查询出名字中含有 s 的数据 -- 模糊查询res models.User.objects.filter(name__containss)print(res)# (7.1)是否区分大小写res models.User.objects.filter(name__containsN)print(res)# 默认区分大小写# (7.2)忽略大小写res models.User.objects.filter(name__icontainsN)print(res)# (8)以什么开头/结尾res models.User.objects.filter(name__startswithd)print(res)res models.User.objects.filter(name__endswithm)print(res)# (9)查询出注册时间是2020年1月份的数据/年/月/日res models.User.objects.filter(register_time__month1)print(res)res models.User.objects.filter(register_time__year2020)print(res)res models.User.objects.filter(register_time__day28)print(res)
六、多表查询引入
【1】数据准备
class Book(models.Model):title models.CharField(max_length32)price models.DecimalField(max_digits8,decimal_places2)publish_date models.DateField(auto_now_addTrue)# 一对多publish models.ForeignKey(toPublish)# 多对多authors models.ManyToManyField(toAuthor)class Publish(models.Model):name models.CharField(max_length32)addr models.CharField(max_length64)# varchar(254) 该字段类型不是给models看的而是给后面我们会学到的校验性组件看的def __str__(self):return self.nameclass Author(models.Model):name models.CharField(max_length32)age models.IntegerField()# 一对一author_detail models.OneToOneField(toAuthorDetail)class AuthorDetail(models.Model):phone models.BigIntegerField() # 电话号码用BigIntegerField或者直接用CharFieldaddr models.CharField(max_length64)
重载数据库
python36 manage.py makemigrationspython36 manage.py migrate 【2】外键的增删改查
(1)一对多外键的增删改查
1.1 外键的增加
# (1)外键的增加 - 直接写实际字段
models.Book.objects.create(title三国演义, price1369.25, publish_id1)
# (2)外键的增加 - 虚拟字段
publish_obj models.Publish.objects.filter(pk2).first()
models.Book.objects.create(title红楼梦, price1569.25, publishpublish_obj)
1.2 外键的删除
# (2)一对多的外键的删除
models.Publish.objects.filter(pk1).delete() # 级联删除
1.3 外键的修改
# - 直接写实际字段
models.Book.objects.filter(pk1).update(publish_id2)
# - 虚拟字段
publish_obj models.Publish.objects.filter(pk1).first()
models.Book.objects.filter(pk1).update(publishpublish_obj)
(2)多对多外键的增删改查 多对多增删改查就是在操作第三张表 2.1 增加
# (1)如何给书籍添加作者
book_obj models.Book.objects.filter(pk1).first()
# book_obj.authors - 这样我们就已经能操作第三张关系表了
# 书籍ID为1的书籍绑定了一个主键为1的作者
book_obj.authors.add(1)
# 可以传多个参数
book_obj.authors.add(2,3)
# 支持参数传对象 - 且支持多个对象
book_obj.authors.add(author_obj)
2.2 删除(remove) 支持多个参数/支持对象 # (2)删除
book_obj models.Book.objects.filter(pk1).first()
# 支持多个参数 - 支持多个对象
book_obj.authors.remove(2)
2.3 更改(set) 先删除后增加 # (3)修改
book_obj models.Book.objects.filter(pk1).first()
# 括号内必须给一个可迭代对象
# 把 1 删掉 替换成 2
book_obj.authors.set([1, 2]) # 括号内必须给一个可迭代对象
# 把原来都删掉 替换成 3
book_obj.authors.set([3]) # 括号内必须给一个可迭代对象
# 支持放对象
book_obj.authors.set([author_obj])
2.4 清空
# (4) 清空
# 在第三张表中清除某一本书和作者的绑定关系
book_obj models.Book.objects.filter(pk1).first()
# clear括号内不要加任何参数
book_obj.authors.clear()
【补充】正反向的概念 正向 外键字段在我手上那么我查你就是正向book 外键字段在书这边(正向) 出版社 反向 外键字段不在我手上那么我查你就是反向出版社 外键字段在书这边(反向) book 一对一和一对多的判断也是这样 正向查询按字段 反向查询按表明名(小写) __set ... 七、多表查询
【1】子查询(基于对象的跨表查询)
# (1)查询书籍主键为1的出版社
book_obj models.Book.objects.filter(pk1).first()
# 书查出版社 - 正向 - 按字段查
res book_obj.publish
print(res) # Publish object
print(res.name) # 东方出版社
print(res.addr) # 东方# (2)查询书籍主键为2的作者
book_obj models.Book.objects.filter(pk1).first()
# 书查作者 - 正向查询按字段
res book_obj.authors
print(res) # app01.Author.None
# 列表中存放的是作者对象
print(res.all()) # QuerySet [Author: Author object]# (3)查询作者 的 电话号码
author_obj models.Author.objects.filter(namedream).first()
# 作者查询作者详情 - 正向查询按字段
res author_obj.author_detail
print(res) # AuthDetail object
print(res.phone) # 110
print(res.addr) # 山东在书写ORM语句的时候跟写SQL语句一样的不要企图一次性将ORM语句写完如果比较复杂需要写一些看一些正向 什么时候需要加 .all()当查询返回的结果是多个的时候就需要用 .all()当查询的结果只有一个的时候直接拿到数据对象book_obj.publishbook_obj.authors.all()author_obj.author_detail# (4)查询出版社是东方出版社出版的书
# 先拿到出版社对象
publish_obj models.Publish.objects.filter(name东方出版社).first()
# 出版社查书 - 主键字段在书 - 反向查询
res publish_obj.book_set.all()
# publish_obj.book_set
# print(res) # app01.Book.None
# publish_obj.book_set.all()
print(res)
# QuerySet [Book: Book object, Book: Book object, Book: Book object]# (5)查询作者是dream写过的书
# 先拿到作者对象
author_obj models.Author.objects.filter(namedream).first()
# 作者查书 - 主键在书 - 反向
res author_obj.book_set.all()
print(res) # QuerySet [Book: Book object]# (6)查询手机号是 110的作者姓名
# 先拿到作者详情的对象
author_detail_obj models.AuthDetail.objects.filter(phone110).first()
# 详情查作者 - 主键在作者 - 反向
res author_detail_obj.author
print(res) # Author object
print(res.name) # dream
基于对象
反向查询的时候 当你的查询结果可以有多个的时候 就必须加_set.all()当你的结果只有一个的时候 不需要加_set.all()
【2】联表查询(基于双下划线的跨表查询)
# (1)查询dream的手机号和作者的姓名
# 正向先查询到作者信息再 .value(需要查询信息的表__需要查询的字段,其他字段)
res models.Author.objects.filter(namedream).values(author_detail__phone, name)
print(res)
# QuerySet [{author_detail__phone: 110, name: dream}]# 反向先拿到详情再用作者详情关联作者表通过 __字段的方法 过滤出我们想要的指定数据
res models.AuthDetail.objects.filter(author__namedream).values(phone, author__name)
# AuthDetail.objects.filter(author__namedream)
print(res) # QuerySet [AuthDetail: AuthDetail object]
# AuthDetail.objects.filter(author__namedream).values(phone,author__name)
print(res) # QuerySet [{phone: 110, author__name: dream}]# (2)查询书籍主键ID为1的出版社名字和书的名字
# 正向先过滤出书籍ID为1的书籍对象再去关联出版者表利用__字段取值
res models.Book.objects.filter(pk1).values(title, publish__name)
print(res)
# QuerySet [{title: 三国演义, publish__name: 东方出版社}]# 反向先查询到指定出版社再从出版社反向找到书籍名字
res models.Publish.objects.filter(book__id1).values(name, book__title)
print(res) # QuerySet [{name: 东方出版社, book__title: 三国演义}]# (3)查询书籍主键ID为1的作者姓名
# 先拿到 书籍主键ID为1的对象再关联作者信息表通过__字段取值
res models.Book.objects.filter(pk1).values(authors__name)
print(res) # QuerySet [{authors__name: dream}]# 反向 : 先拿到 书籍ID为1的作者数据再去取作者的名字
res models.Author.objects.filter(book__id1).values(name)
print(res) # QuerySet [{name: dream}]# 查询书籍主键是1的作者的手机号
# book author authordetail
res models.Book.objects.filter(pk1).values(authors__author_detail__phone)
print(res) # QuerySet [{authors__author_detail__phone: 110}]
只要掌握了正反向的概念以及双下划线查询就可以无限跨表
八、聚合查询
# 聚合查询# 聚合查询通常情况下都是配合分组一起使用的只要是和数据库相关的模块基本上都在 django.db.models 里面如果这里面没有 那大概率可能在 django.db 里面from django.db.models import Max, Min, Sum, Count, Avg# (1)所有书的平均价格# 正常情况下我们是需要先进行分组再进行聚合函数运算的# 但是Django给我们提供了一种方法 aggregate-- 可以不分组进行某个字段的聚合函数res models.Book.objects.aggregate(Avg(price))print(res) # {price__avg: 1890.083333}# (2)一次性使用res models.Book.objects.aggregate(Avg(price), Max(price), Min(price), Sum(price), Count(pk))print(res) # {price__avg: 1890.083333, price__max: Decimal(5959.25), price__min: Decimal(555.25), price__sum: Decimal(11340.50), pk__count: 6}
九、分组查询
# 分组查询 annotate
MySQL中的分组查询分组之后只能获取到分组的依据组内其他字段都无法获取严格模式中可以修改ONLY_FULL_GROUP_BYset global sql_modeONLY_FULL_GROUP_BY
from django.db.models import Max, Min, Sum, Count, Avg
# (1)统计每一本书的作者个数
# models 后面跟的是什么就是按什么分组
# res models.Book.objects.annotate()
res models.Book.objects.annotate(author_numberCount(authors)).values(title,author_number)author_number 是我们自己定义的字段用来存储统计出来的每本书的作者个数# 等价于
# res models.Book.objects.annotate(author_numberCount(authors__pk)).values(title,author_number)
# print(res)
# QuerySet [{title: 三国演义, author_number: 1}, {title: 红楼梦, author_number: 0}, {title: 水浒传, author_number: 0}, {title: 论语, author_number: 0}, {title: 孙子兵法, author_number: 0}, {title: 镇魂街, author_number: 0}]# (2)统计每个出版社最便宜的书的价格
res models.Publish.objects.annotate(min_priceMin(book__price)).values(name, min_price)
print(res)
# QuerySet [{name: 东方出版社, min_price: Decimal(555.25)}, {name: 北方出版社, min_price: Decimal(888.25)}]# (3)统计不止一个作者的图书
# (3.1)先按照图书分组
# (3.2)过滤出不止一个作者的图书
# 我的数据有限我统计的是大于0的作者的图书
res models.Book.objects.annotate(author_numCount(authors)).filter(author_num__gt0).values(title, author_num) 只要ORM语句得到的是 一个 queryset 对象
那么就可以继续无限制的调用封装 的方法print(res) # QuerySet [{title: 三国演义, author_num: 1}]# (4)查询每个作者出的书的总价格
res models.Author.objects.annotate(sum_priceSum(book__price)).values(name, sum_price)
print(res)
# QuerySet [{name: dream, sum_price: Decimal(1369.25)}, {name: hope, sum_price: None}, {name: sad, sum_price: None}]如果想按照指定的字段分组该如何处理如果 annotate 前面没东西 则会按照 Book 分组 如果前面有参数 就会按照前面的参数进行分组 pricemodels.Book.objects.values(price).annotate()机器上如果出现分组查询报错的情况需要修改数据库严格模式十、F与Q查询
【1】F查询
from django.db.models import F# (1)查出卖出数大于库存数的书籍
# F 查询 : 帮助我们直接获取到表中的某个字段对应的数据
res models.Book.objects.filter(sales__gtF(stock))
print(res) # QuerySet [Book: 水浒传]# (2).将所有书籍的价格提升500块
res models.Book.objects.update(priceF(price) 500)
print(res) # 6 - 影响到了 6 条数据# (3)将所有书的名称后边加上爆款两个字
# 在操作字符串的时候F查询不能够直接坐到字符串的拼接
from django.db.models.functions import Concat
from django.db.models import Valueres models.Book.objects.update(titleConcat(F(title), Value(爆款)))
print(res)
# models.Book.objects.update(titleF(title) 爆款) # 所有的名称会全部变成空白
【2】Q查询
# F与Q查询from django.db.models import Q# (1)查询卖出数大于100或者价格小于500的书籍# (1.1)直接使用 filter 查询数据逗号隔开,里面放的参数是 and 关系
res models.Book.objects.filter(sales__gt100, price__lt500)
print(res) # QuerySet []# (1.2)直接使用 Q 查询数据逗号隔开,里面放的参数还是 and 关系
res models.Book.objects.filter(Q(sales__gt100), Q(price__lt500))
print(res) # QuerySet []# (1.3)直接使用 Q 查询数据逗号可以换成其他连接符达到效果
res models.Book.objects.filter(Q(sales__gt100) or Q(price__lt500))
# 二者等价 (| 或关系) (~ 取反 not 关系)
res models.Book.objects.filter(Q(sales__gt100) | Q(price__lt500))
print(res)
# QuerySet [Book: 三国演义爆款, Book: 水浒传爆款, Book: 论语爆款, Book: 孙子兵法爆款]# (2) Q的高阶用法 能够将查询条件的左边也变成 字符串形式
# 产生 Q 对象
q Q()
# 修改Q查询的默认连接条件
q.connector or
q.children.append(sales, 100)
q.children.append(stock, 600)
# filter 参数支持Q对象默认还是 and 关系
res models.Book.objects.filter(q)
print(res)
十一、Django中如何开启事务
【1】ACID是数据库事务的四个关键特性
事务是MySQL数据库中的一个重要概念。事务的目的为了保证多个SQL语句执行成功或执行失败前后保持一致保证数据安全。它代表了原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。 原子性(Atomicity) 事务被视为一个不可分割的原子操作单元。这意味着要么全部操作成功并永久保存要么全部操作失败并回滚到事务开始前的状态不存在部分成功或部分失败的情况。一致性(Consistency) 事务在执行前后数据库都必须保持一致状态。这意味着事务执行前后数据库中的数据必须满足所有定义的完整性约束例如列级别的约束、外键关系等。隔离性(Isolation) 事务之间应该相互隔离每个事务的执行应该与其他事务的执行相互独立互不干扰。隔离性确保了多个事务可以并发执行而不会产生不一致的结果。持久性(Durability) 一旦事务成功提交后其所做的修改将永久保存在数据库中即使发生系统故障或重启数据也能够恢复到提交后的状态。持久性通过将事务日志写入非易失性存储介质来实现如硬盘驱动器或固态硬盘。
【2】Django中如何开启事务
from django.db import transactiontry:with transaction.atomic():# SQL1# SQL2# SQL3在with代码块内书写所有的orm操作写在同一个with语句的代码块都是属于同一个事务要么同时成功要么同时失败
except Exception as e:print(e) # 记录日志transaction.rollback()
十二、ORM中常用的字段及参数
【1】ORM字段
AutoField
int自增列必须填入参数 primary_keyTrue。当model中如果没有自增列则自动会创建一个列名为id的列。
IntegerField
一个整数类型范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够)直接用字符串存)
CharField
字符类型必须提供max_length参数 max_length表示字符长度。
DateField
日期字段日期格式 YYYY-MM-DD相当于Python中的datetime.date()实例。
DateTimeField
日期时间字段格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]相当于Python中的datetime.datetime()实例 常用的字段
BigAutoField(AutoField)
- bigint自增列必须填入参数 primary_keyTrueSmallIntegerField(IntegerField):
- 小整数 -32768 32767PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 32767BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 9223372036854775807BooleanField(Field)
- 布尔值类型
True/False 1/0name varchar(1024)
content text;TextField(Field)
- 文本类型FileField(Field)
- 字符串路径保存在数据库文件上传到指定目录
- 参数
upload_to 上传文件的保存路径
storage None 存储组件默认django.core.files.storage.FileSystemStorageImageField(FileField)
- 字符串路径保存在数据库文件上传到指定目录
- 参数
upload_to 上传文件的保存路径
storage None 存储组件默认django.core.files.storage.FileSystemStorageTimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]]FloatField(Field)
- 浮点型DecimalField(Field)
- 10进制小数
- 参数
max_digits小数总长度
decimal_places小数位长度BinaryField(Field)
- 二进制类型
【2】ORM字段参数
null
用于表示某个字段可以为空。
unique
如果设置为uniqueTrue 则该字段在此表中必须是唯一的
Foregin(unique True) ---- OneToOneField
db_index
如果db_indexTrue 则代表着为此字段设置索引。
default
为该字段设置默认值。
auto_now_add
配置auto_now_addTrue创建数据记录的时候会把当前时间添加到数据库。
auto_now
配置上auto_nowTrue每次更新数据记录的时候会更新该字段。
【3】ORM关系字段
Foreignkey
外键类型在ORM中用来表示外键关联关系一般把ForeignKey字段设置在 一对多中多的一方。ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。
to
设置要关联的表
to-field
设置要关联的表的字段
related_name
反向操作时使用的字段名用于代替原反向查询是的’表名_set’。
related_query_name
反向查询操作时使用的连接前缀用于替换表名。
on_delete
当删除关联表中的数据时当前表与其关联的行的行为。
models.CASCADE
删除关联数据与之关联也删除
models.DO_NOTHING
删除关联数据引发错误IntegrityError
models.PROTECT
删除关联数据引发错误ProtectedError
models.SET_NULL
删除关联数据与之关联的值设置为null前提FK字段需要设置为可空
models.SET_DEFAULT
删除关联数据与之关联的值设置为默认值前提FK字段需要设置默认值
models.SET
删除关联数据 a. 与之关联的值设置为指定值设置models.SET(值)b. 与之关联的值设置为可执行对象的返回值设置models.SET(可执行对象)
db_constraint
是否在数据库中创建外键约束默认为True。
OneToOneField
一对一字段。
通常一对一字段用来扩展已有字段。
一对一的关联关系多用在当一张表的不同字段查询频次差距过大的情况下将本可以存储在一张表的字段拆开放置在两张表中然后将两张表建立一对一的关联关系。
class Author(models.Model):name models.CharField(max_length32)info models.OneToOneField(toAuthorInfo)class AuthorInfo(models.Model):phone models.CharField(max_length11)email models.EmailField()to
设置要关联的表。
to_field
设置要关联的字段。
on_delete
同ForeignKey字段。
ManyToManyField
用于表示多对多的关联关系。在数据库中通过第三张表来建立关联关系
to
设置要关联的表
related_name
同ForeignKey字段。
related_query_name
同ForeignKey字段。
symmetrical
仅用于多对多自关联时指定内部是否创建反向操作的字段。默认为True。
举个例子
class Person(models.Model):name models.CharField(max_length16)friends models.ManyToManyField(self)
此时person对象就没有person_set属性。
class Person(models.Model):name models.CharField(max_length16)friends models.ManyToManyField(self, symmetricalFalse)此时person对象现在就可以使用person_set属性进行反向查询。
through
在使用ManyToManyField字段时Django将自动生成一张表来管理多对多的关联关系。但我们也可以手动创建第三张表来管理多对多关系此时就需要通过through来指定第三张表的表名。
through_fields
设置关联的字段。
db_table
默认创建第三张表时数据库中表的名称。
【4】自定义字段(了解)
from django.db import models# Create your models here.
# Django中没有对应的char类型字段但是我们可以自己创建
class FixCharField(models.Field):自定义的char类型的字段类def __init__(self,max_length,*args,**kwargs):self.max_lengthmax_lengthsuper().__init__(max_lengthmax_length,*args,**kwargs)def db_type(self, connection):限定生成的数据库表字段类型char长度为max_length指定的值:param connection::return:return char(%s)%self.max_length
# 应用上面自定义的char类型
class Class(models.Model):id models.AutoField(primary_keyTrue)title models.CharField(max_length32)class_name FixCharField(max_length16)gender_choice ((1,男),(2,女),(3,保密))gender models.SmallIntegerField(choicesgender_choice,default3)