目录
模型层:
ORM查询
ORM中常用字段和参数: 1.int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列 (AutoField) 2.一个整数类型,范围在 -2147483648 to 2147483647(用字符串存储)(IntegerField) 3.字符类型,必须提供max_length参数, max_length表示字符最大长度(CharField) 4.日期字段,日期格式 YYYY-MM-DD (DateField)\ 5.日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] (DateTimeField) 6.表示某个字段可以为空。 (null) 7.设置为unique=True 则该字段在此表中必须是唯一的 。(unique) 8.db_index=True 则代表着为此字段设置索引。 9.为该字段设置默认值。 (default) 10.配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库 (auto_now_add) 11.配置上auto_now=True,每次更新数据记录的时候会更新该字段 (auto_now : 仅仅记载最新的记录) 12.EmailField() : 数据类型是 varchar(254)
表之间的关系:
表之间的关联 : 外键 (ForeignKey) 1.外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 '一对多'中'多'的一方。 2.ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。 参数:to ; 设置要关联的表 to_file: 设置要关联表的字段 on_delete:删除关联表中的数据时,当前表与其关联的行的行为。 models.CASCADE : 删除关联数据,与之关联也删除! db_constraint : 是否在数据库中创建外键约束,默认为True。
定义新字段:
自定义新的字段: 1.必须要有max_length 2.返回值必须为字符串 class xxCharField(models.Fiels): '''自定义char类型的字段类''' def __init__(self,max_length,*args,**kwargs): self.max_length = max_length super().__init__(max_length=max_length,*args,**kwargs) def db_type(self,connection): #返回字符类型 return 'char(%s)' %self.max_length #创表(运用自定义的字段类) class Class(models.Model): title=models.CharField(max_length=32) class_name=FixCharField(max_length=16)
配置测试脚本
配置orm操作数据库(mysql)的测式文件: import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings") import django django.setup() from app01 import models models.Books.objects.all() 注意: 1.from app01 import models放置在建立测试脚本搭建完毕后 2.新建一个.py文件,要导入以上代码 3.在orm测式文件内部对数据进行操作
日志记录:
记录数据库操作: --》放置在settings LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
orm对表内数据的操作:
查找数据: --》 res = models.Books.objects.filter(pk=1) # pk :会自动帮你查找到当前表的主键字段(指代主键字段) # filter 查询出来的结果是一个Queryset对象: 1.只要是queryset对象就可以无限制的调用queryset的方法 res = models.Books.objects.filter(pk=1).filter()..... 2.只要是queryset对象就可以点query查看当前结果内部对应的sql语句 res = queryset_obj.query ==== > sql 语句 创建数据: 1.create() : book_obj = models.Books.objects.create(title='三国演义',publish_date='2019-11-11') #输入时间格式 :可以输入字符串 # ctime = date.today() book_obj = models.Books.objects.create(title='三国演义',publish_date=ctime) 2.利用对象的绑定方法: book_obj = models.Books(title='西游记',publish_date='ctime) book_obj.save() 修改数据: 1.利用queryset方法: models.Books.objects.filter(pk=1).update(price=444) 2,利用对象: book_obj = models.Books.objects.get(pk=1) book_obj.price = 222 book_obj.save() 注意 : 利用对象的修改 内部其实是重头到位将数据的所有字段都重新写一遍(先删再创一个新的) 删除数据: 1.利用queryset方法 delete() models.Books.objects.filter(pk=3).delete() 2,对象方法 book_obj = models.Books.objects.get(pk=3) book_obj.delete()
get 与 filter 的区别:
区别: 1.filter获取到的是一个queryset对象 类似于一个列表 2.get获取到的直接就是数据对象本身 当条件不存在的情况下: filter不报错直接返回一个空 get直接报错 所以不推荐使用get方法
单表查询13条方法
orm语句的查询 : 惰性查询,只有当你真正要使用数据的时候才会执行orm语句 1.all() : 查询匹配的所有数据 --》 返回 QuerySet对象 eg: res = models.Books.objects.all() 2.filter() : 筛选 (类似于 where 条件) -返回 QuerySet对象 eg: res = models.Books.object.filter(pk=1) 3.get() : 筛选 返回数据对象本身 查询条件必须是唯一的 eg: res = models.Books.objects.get(title='西游记') 4.first() : 取queryset中第一个数据对象 返回数据对象 eg: res = models.Books.objects.filter(pk=1).first() 5.last() 取queryset中最后一个数据对象 数据对象 eg: res = models.Books.objects.filter(pk=1).last() 6. count() 统计数据的个数(表记录的个数) 数字 eg: num = models.Books.objects.count() 7.values() 获取数据对象中指定的字段的值 多个 queryset 列表套字典 eg: res = models.Books.objects.values('title','price') <QuerySet [{'title': '三国演义', 'price': Decimal('222.66')} 8.values_list() 获取数据对象中指定的字段的值 多个 queryset 列表套元祖 eg: res = models.Books.objects.values_list('title','price') <QuerySet [('三国演义', Decimal('222.66')) 9.order_by() 按照指定的字段排序 # 默认是升序 eg: res = models.Books.objects.all().order_by('price') # 降序 字段前面加负号 res1 = models.Books.objects.all().order_by('-price') 10.reverse() 颠倒顺序 前提是跌倒的对象必须有顺序(排序之前才能颠倒) res1 = models.Books.objects.all().reverse() 11.exclude() 排除什么什么之外 queryset对象 res = models.Books.objects.all().exclude(title='三国演义') 12.exists() 判断查询结果是否有值 返回结果是一个布尔值 res = models.Books.objects.filter(pk=1).exists() 13..distinct() 去重操作 去重的前提:表记录数据必须是完全相同的情况下 res = models.Books.objects.values('title','price').distinct() 注意 : 1.去重必须是一条表记录内所有的数据都一样(包括主键) 2.能对帅选过后的数据进行去重
双下划线查询方法:
-->范围查询 大于 :xx_gt / 小于 : xx_lt 大于等于: xx__gte 缺陷 :python 对小数不敏感(识别有误) 小于等于: xx__lte eg: res = models.Books.objects.filter(price__lte=500) 或者..或者是 :xx__in=[] eg: res = models.Books.objects.filter(price__in=[222,444,500]) 在...到...之间 : xx__range = (,) 顾头顾尾 eg: res = models.Books.objects.filter(price__range=(200,800)) 查询日期: publish_date__year' eg: res = models.Books.objects.filter(publish_date__year='2019')
模糊查询
MySQL中的模糊查询 -->关键字 like 模糊匹配的符号: %:匹配任何个数的任意字符 _:匹配一位任意的字符 以....开头: __startswith res = models.Books.objects.filter(title__startswith='三') 以....结尾: __endswith res = models.Books.objects.filter(title__endswith='1') 包含...在其中:__contains res = models.Books.objects.filter(title__contains='p') # 默认区分大小写 res = models.Books.objects.filter(title__icontains='p') # 忽略大小写 加i
一对多数据的增删改查:
增: 第一种 :models.Book.objects.create(title='三国演义',ublish_id=1) #直接传表里面的实际字段 跟数据主键值 publish_id 第二种 :publish_obj = models.Publish.objects.filter(pk=2).first() models.Book.objects.create(title='红楼梦',publish=publish_obj) # 传虚拟字段 跟数据对象即可 改: 第一种 :models.Book.objects.filter(pk=1).update(publish_id=2) 第二种 :publish_obj = models.Publish.objects.filter(pk=1).first() models.Book.objects.filter(pk=1).update(publish=publish_obj) 删: models.Publish.objects.filter(pk=1).delete() # 默认就是级联删除 级联更新 (关联表一起变化)
多对多数据的增删改查:
--》创建第三张表进行操作。 增: add() 把指定的model对象添加到第三张关联表中。 添加对象: >>> author_objs = models.Author.objects.filter(id__lt=3) >>> models.Book.objects.first().authors.add(*author_objs) 添加id: >>> models.Book.objects.first().authors.add(*[1, 2]) 改 : set() 更新某个对象在第三张表中的关联对象。不同于上面的add是添加,set相当于重置 -->括号内的数据必须要是可迭代对象!!! >>> book_obj = models.Book.objects.first() >>> book_obj.authors.set([2, 3]) 删 : remove() / clear() 从关联对象集中移除执行的model对象(移除对象在第三张表中与某个关联对象的关系) >>> book_obj = models.Book.objects.first() >>> book_obj.authors.remove(3) 清空 删除某个数据在第三张表中的所有记录: clear() # book_obj = models.Book.objects.filter(pk=2).first() # book_obj.authors.clear()
跨表设计
正反向查询 ; 正 向查询 :有外键查的一边,查询另一边 --》查询按字段 反 向查询 :没有外键的一边, 查询拥有外键一边 ---》按表明小写 反向:对象_set ---> 查询数据有多个 / 一个就不加 基于对象的跨表查询: --》 子查询 分步操作 # 基于对象的跨表查询 子查询 分步操作 # 1.查询书籍主键为2的出版社名称 book_obj = models.Book.objects.filter(pk=2).first() print(book_obj.publish) # 出版社对象 print(book_obj.publish.name) # 2.查询书籍主键为4的作者姓名 book_obj = models.Book.objects.filter(pk=4).first() print(book_obj.authors) # app01.Author.None print(book_obj.authors.all()) # 3.查询作者是jason的手机号码 author_obj = models.Author.objects.filter(name='jason').first() print(author_obj.author_detail) print(author_obj.author_detail.phone) # 4.查询出版社是东方出版社出版过的书籍 publish_obj = models.Publish.objects.filter(name='东方出版社').first() # print(publish_obj.book_set) # app01.Book.None print(publish_obj.book_set.all()) # 5.查询作者是jason写过的书籍 author_obj = models.Author.objects.filter(name='jason').first() # print(author_obj.book_set) # app01.Book.None print(author_obj.book_set.all()) # app01.Book.None # 6.查询手机号是120的作者姓名 author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first() print(author_detail_obj.author) print(author_detail_obj.author.email)
基于双下滑先的跨表查询
基于双下滑先的跨表查询: --》联表操作 # 1.查询书籍pk为2的出版社名称 # 正向 res = models.Book.objects.filter(pk=2).values('publish__name') # 写外键字段就相当于已经跨到外键字段所关联的表 # 你想要改表的哪个字段信息 你只需要加__获取即可 print(res) # 反向 res = models.Publish.objects.filter(book__pk=2).values('name') print(res) # 2.查询书籍pk为2的作者姓名和邮箱 res = models.Book.objects.filter(pk=2).values('authors__name','authors__email') print(res) res = models.Author.objects.filter(book__pk=2).values('name','email') print(res) # 3.查询作者是egon的家庭地址 res = models.Author.objects.filter(name='egon').values('author_detail__addr') print(res) res = models.AuthorDetail.objects.filter(author__name='egon').values('addr') print(res) # 4.查询出版社是东方出版社出版过的书的名字 res = models.Publish.objects.filter(name='东方出版社').values('book__title') print(res) res = models.Book.objects.filter(publish__name='东方出版社').values('title') print(res) # 查询书籍pk是2的作者的手机号 res = models.Book.objects.filter(pk=2).values('authors__author_detail__phone') print(res) res = models.Author.objects.filter(book__pk=2).values('author_detail__phone') print(res)
小技巧
models + 表名 --》 查询以表名为基表 !! 什么时候需要加all ??? 1.当正向查询点击外键字段数据有多个的情况下 需要.all() 2.app01.Author.None 一旦看到该结果 只需要加.all()即可 mysql : 链表操作( inner join left join right join union #两边表都没有 ) 什么时候反向查询的时候表名小写需要加_set?? 一对多表关系 多对多表关系 一对一表关系不需要加_set 技巧:在写orm语句的时候跟你写sql语句一样 不要想着一次性写完,查一点再写一点