网站到期续费吗,网站开发是培训,北京制作页面,漳州网站设计制作ORM的介绍 # ORM是什么#xff1f; 我们在使用Django框架开发web应用的过程中#xff0c;不可避免地会涉及到数据的管理操作#xff08;增、删、改、查#xff09;#xff0c;而一旦谈到数据的管理操作#xff0c;就需要用到数据库管理软件#xff0c;例如mysql、oracle… ORM的介绍 # ORM是什么 我们在使用Django框架开发web应用的过程中不可避免地会涉及到数据的管理操作增、删、改、查而一旦谈到数据的管理操作就需要用到数据库管理软件例如mysql、oracle、Microsoft SQL Server等。 # ORM的概念 ORM全称Object Relational Mapping即对象关系映射是在pymysq之上又进行了一层封装对于数据的操作我们无需再去编写原生sql取代代之的是基于面向对象的思想去编写类、对象、调用相应的方法等ORM会将其转换/映射成原生SQL然后交给pymysql执行 ORM的使用之数据库迁移 1、创建模型数据来源于数据库的表而ORM的模型类对应数据库表 # 创建django项目新建名为app01的app在app01的models.py中创建模型
class Employee(models.Model): # 必须是models.Model的子类idmodels.AutoField(primary_keyTrue)namemodels.CharField(max_length16)gendermodels.BooleanField(default1)birthmodels.DateField()departmentmodels.CharField(max_length30)salarymodels.DecimalField(max_digits10,decimal_places1) 2、 配置settings.py INSTALLED_APPS [django.contrib.admin,django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.messages,django.contrib.staticfiles, app01.apps.App01Config, # django2.x版本 # app01, # django1.x版本]DATABASES { # 删除\注释掉原来的DATABASES配置项新增下述配置default: {ENGINE: django.db.backends.mysql, # 使用mysql数据库NAME: db1, # 要连接的数据库USER: root, # 链接数据库的用于名PASSWORD: , # 链接数据库的用于名 HOST: 127.0.0.1, # mysql服务监听的ip PORT: 3306, # mysql服务监听的端口 ATOMIC_REQUEST: True, #设置为True代表同一个http请求所对应的所有sql都放在一个事务中 3.配置日志:如果想打印orm转换过程中的sql需要在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,},}
} 4、数据库迁移命令 python manage.py makemigrations
python manage.py migrate 模型层models表查询 模型层的表查询跟数据库打交道的 1、单表查询 insert update delete all filter 2、常见的查询方法 单表操作 1、all() 查询所有数据索引取值 2、filter() 过滤条件查询 3、get() 查询数据查询数据为空的情况直接报错 4、last() 取所有数据的最后一条 5、values( id,username,password ) 取值列表套字典[{id:1,username:...},{...}] 6、vallues_list() 取值列表套元组都支持for循环 7、pring(res.quert) 查看内部的SQL语句只有防御的结果是queryset对象的时候才能查看 8、distinct() 去重 9、order_by( id ) 默认情况升序排序(-id)倒序 10、reverse() 翻转 11、count() 统计当前表中数据的个数 12、exclude(pk1) 排除在外 13、exists() 看数据到底有没有 3、基于双下划线的查询 res models.UserInfo.object.filter(age_gt38).all()
age__gt1---大于
age__lt1---小于
age__gte1---大于等于
age__lte1---小于等于
ageage__in[18,40] 年龄在十八或40的或
age__range[18,40] 年龄在十八到40的之间# 包含s的数据模糊查询 包含s的数据模糊查询# select * from userinfor where name like %s%,res models.UserInfo.object.filter(username__containss).all()print(res)print(res.query)
username__icontains--忽略大小写
username__startswitho--以o开头的
username__endswitho--以o结尾的 # 日期查询 register_time models.DateTimeField(auto_nowTrue,auto_now_addTrue,nullTrue)
auto_now: 修改的时间
auto_now_add: 刚加进去时间
查询时间查2020年1月份的
filter(register_time__year2020,register_time__month01).all() 多表查询(跨表查询) 子查询分步查询 链表查询把多个有关系的表拼接成一个大表(虚拟表) inner join left join right join 基于双下划线的查询 年龄大于35岁的数据 res models.User.objects.filter(age__gt35) 年龄小于35岁的数据 res models.User.objects.filter(age__lt35) 大于等于 小于等于 res models.User.objects.filter(age__gte32) res models.User.objects.filter(age__lte32) 年龄是18 或者 32 或者40 res models.User.objects.filter(age__in[18,32,40]) 年龄在18到40岁之间的 首尾都要 res models.User.objects.filter(age__range[18,40]) 查询出名字里面含有s的数据 模糊查询 res models.User.objects.filter(name__containss) 是否区分大小写 查询出名字里面含有p的数据 区分大小写 res models.User.objects.filter(name__containsp) 忽略大小写 res models.User.objects.filter(name__icontainsp) 以 j 开头或以 j 结尾 res models.User.objects.filter(name__startswithj) res1 models.User.objects.filter(name__endswithj) 查询出注册时间是 2020 1月 res models.User.objects.filter(register_time__month1) res models.User.objects.filter(register_time__year2020) 多表查询前期表准备 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) 一对多外键增删改查 # 增 方式一直接写实际字段 id
models.Book.objects.create(title论语,price899.23,publish_id1)
models.Book.objects.create(title聊斋,price444.23,publish_id2)
models.Book.objects.create(title老子,price333.66,publish_id1)
方式二虚拟字段 对象
publish_obj models.Publish.objects.filter(pk2).first()
models.Book.objects.create(title红楼梦,price666.23,publishpublish_obj) # 删 models.Publish.objects.filter(pk1).delete() # 级联删除 # 修改 models.Book.objects.filter(pk1).update(publish_id2)
publish_obj models.Publish.objects.filter(pk1).first()
models.Book.objects.filter(pk1).update(publishpublish_obj) 多对多外键增删改查 # 增给书籍添加作者 book_obj models.Book.objects.filter(pk1).first()
print(book_obj.authors) # 就类似于你已经到了第三张关系表了
book_obj.authors.add(1) # 书籍id为1的书籍绑定一个主键为1 的作者
book_obj.authors.add(2,3)author_obj models.Author.objects.filter(pk1).first()
author_obj1 models.Author.objects.filter(pk2).first()
author_obj2 models.Author.objects.filter(pk3).first()
book_obj.authors.add(author_obj)
add给第三张关系表添加数据括号内既可以传数字也可以传对象 并且都支持多个 # 删 book_obj.authors.remove(2)
book_obj.authors.remove(1,3)author_obj models.Author.objects.filter(pk2).first()
author_obj1 models.Author.objects.filter(pk3).first()
book_obj.authors.remove(author_obj,author_obj1)
remove括号内既可以传数字也可以传对象 并且都支持多个 # 修改 book_obj.authors.set([1,2]) # 括号内必须给一个可迭代对象
book_obj.authors.set([3]) # 括号内必须给一个可迭代对象author_obj models.Author.objects.filter(pk2).first()
author_obj1 models.Author.objects.filter(pk3).first()
book_obj.authors.set([author_obj,author_obj1]) # 括号内必须给一个可迭代对象 # 清空在第三张关系表中清空某个书籍与作者的绑定关系 book_obj.authors.clear() clear括号内不要加任何参数 正反向的概念 正向外键字段在我手上那么我查你就是正向按 外键字段 反向外键字段如果不在手上我查你就是反向按 表名小写 book 外键字段在书那儿(正向) publish publish 外键字段在书那儿(反向)book _set 多表查询之子查询 子查询---基于对象的跨表查询 1.查询书籍主键为1的出版社 book_obj models.Book.objects.filter(pk1).first() # 书查出版社 正向
res book_obj.publish
print(res)
print(res.name)
print(res.addr) 2.查询书籍主键为2的作者 book_obj models.Book.objects.filter(pk2).first() # 书查作者 正向
res book_obj.authors # app01.Author.None
res book_obj.authors.all() # 查的多的话要用all()
print(res) 3.查询作者jason的电话号码: author_obj models.Author.objects.filter(namejason).first()
res author_obj.author_detail
print(res)
print(res.phone)
print(res.addr) 4.查询出版社是东方出版社出版的书: publish_obj models.Publish.objects.filter(name东方出版社).first() # 出版社查书 反向
res publish_obj.book_set # app01.Book.None
res publish_obj.book_set.all()
print(res) 5.查询作者是jason写过的书: author_obj models.Author.objects.filter(namejason).first() # 作者查书 反向
res author_obj.book_set # app01.Book.None
res author_obj.book_set.all()
print(res) 6.查询手机号是110的作者姓名: author_detail_obj models.AuthorDetail.objects.filter(phone110).first()
res author_detail_obj.author
print(res.name) # 如果是一个则直接拿到数据对象 book_obj.publish book_obj.authors.all() author_obj.author_detail # 在书写orm语句的时候跟写sql语句一样的,不要企图一次性将orm语句写完 如果比较复杂 就写一点看一点 # 基于对象 : 反向查询的时候 当你的查询结果可以有多个的时候 就必须加_set.all() 当你的结果只有一个的时候 不需要加_set.all() 多表查询之联表查询 联表查询---基于双下划线的跨表查询 1.查询jason的手机号和作者姓名 res models.Author.objects.filter(namejason).values(author_detail__phone,name)
print(res)
# 反向
res models.AuthorDetail.objects.filter(author__namejason) # 拿作者姓名是jason的作者详情
res models.AuthorDetail.objects.filter(author__namejason).values(phone,author__name)
print(res) 2.查询书籍主键为1的出版社名称和书的名称 res models.Book.objects.filter(pk1).values(title,publish__name)
print(res)
# 反向
res models.Publish.objects.filter(book__id1).values(name,book__title)
print(res) 3.查询书籍主键为1的作者姓名 res models.Book.objects.filter(pk1).values(authors__name)
print(res)
# 反向
res models.Author.objects.filter(book__id1).values(name)
print(res) 4.查询书籍主键是1的作者的手机号 book author authordetail
res models.Book.objects.filter(pk1).values(authors__author_detail__phone)
print(res) # 你只要掌握了正反向的概念以及双下划线那么你就可以无限制的跨表 多表查询之分组查询 select age from t group by age;
MySQL分组查询都有哪些特点分组之后默认只能获取到分组的依据 组内其他字段都无法直接获取了严格模式ONLY_FULL_GROUP_BYset global sql_modeONLY_FULL_GROUP_BY# 你们的机器上如果出现分组查询报错的情况你需要修改数据库严格模式 # 分组查询 annotate from django.db.models import Max, Min, Sum, Count, Avg 1.统计每一本书的作者个数 res models.Book.objects.annotate() # models后面点什么 就是按什么分组
res models.Book.objects.annotate(author_numCount(authors)).values(title,author_num)
res1 models.Book.objects.annotate(author_numCount(authors__id)).values(title,author_num)
print(res,res1)
author_num是我们自己定义的字段 用来存储统计出来的每本书对应的作者个数 2.统计每个出版社卖的最便宜的书的价格 res models.Publish.objects.annotate(min_priceMin(book__price)).values(name,min_price)
print(res) 3.统计不止一个作者的图书 # 先按照图书分组 求每一本书对应的作者个数 # 过滤出不止一个作者的图书 res models.Book.objects.annotate(author_numCount(authors)).filter(author_num__gt1).values(title,author_num)
print(res) 4.查询每个作者出的书的总价格 res models.Author.objects.annotate(sum_priceSum(book__price)).values(name,sum_price)
print(res) # 代码没有补全 不要怕正常写补全给你是pycharm给你的到后面在服务器上直接书写代码什么补全都没有颜色提示也没有 # 只要你的orm语句得出的结果还是一个queryset对象那么它就可以继续无限制的点queryset对象封装的方法 F查询 F查询能够帮助你直接获取到表中某个字段对应的数据 1.查询卖出数大于库存数的书籍 from django.db.models import F
res models.Book.objects.filter(maichu__gtF(kucun))
print(res) 2.将所有书籍的价格提升500块 models.Book.objects.update(priceF(price) 500) 3.将所有书的名称后面加上爆款两个字 from django.db.models.functions import Concat #拼接字符串
from django.db.models import Value
models.Book.objects.update(titleConcat(F(title), Value(爆款)))
# models.Book.objects.update(titleF(title) 爆款) # 所有的名称会全部变成空白
在操作字符类型的数据的时候 F不能够直接做到字符串的拼接 Q查询 1.查询卖出数大于100或者价格小于600的书籍 res models.Book.objects.filter(maichu__gt100,price__lt600)
filter括号内多个参数是and关系
from django.db.models import Q
# res models.Book.objects.filter(Q(maichu__gt100),Q(price__lt600)) #Q逗号分割还是and关系
res models.Book.objects.filter(Q(maichu__gt100)|Q(price__lt600)) # | or关系
# res models.Book.objects.filter(~Q(maichu__gt100)|Q(price__lt600)) # ~ not关系
print(res) # QuerySet [] 2、Q的高阶用法 能够将查询条件的左边也变成字符串的形式 q Q()
q.connector or
q.children.append((maichu__gt,100))
q.children.append((price__lt,600))
res models.Book.objects.filter(q) # 默认还是and关系
print(res) 查看内部sql语句的方式 方式1queryset对象才能够点击query查看内部的sql语句 res models.User.objects.values_list(name,age)
# QuerySet [(jason, 18), (egonPPP, 84)]
print(res.query) 方式2:所有的sql语句都能查看 # uptade等等没有queryset对象的只需设置配置文件setting LOGGING {version: 1,disable_existing_loggers: False,handlers: {console:{level:DEBUG,class:logging.StreamHandler,},},loggers: {django.db.backends: {handlers: [console],propagate: True,level:DEBUG,},}
} 今日思维导图