Django----模型层(ORM)

Django----模型层(ORM)

配置测试脚本

再要测试的app文件夹下,建一个tests文件

需要注意的是,导入models时,一定要把导入语句放在main方法内部

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")

    import django
    django.setup()
    
    # 一定要等待测试脚本搭建完毕之后 才能导入django文件进行测试
    from app01 import models

单表操作

  1. all() 查询所有数据
res = models.Books.objects.all()

==>#	<QuerySet [<Books: 假如给我三天光明>, <Books: 鲁滨逊漂流记>]>
  1. filter() 筛选

    该筛选方法,类似于原生sql语句中的where关键字,如有多个值,关系为and,返回的值是queryset对象

res = models.Books.objects.filter(pk=2,title='鲁滨逊漂流记')#支持传多个参数

==>#	<QuerySet [<Books: 鲁滨逊漂流记>]>
  1. get() 筛选

    该筛选方法,获取的是数据对象本身,如果匹配的条件不存在,会直接报错

    并且,要求查询到的结果只能是唯一的,如果有两条及以上,会报错

res = models.Books.objects.get(title='鲁滨逊漂流记')
  1. first() 通过该方法,可以取queryset对象的第一个数据对象
res = models.Books.objects.filter(title='鲁滨逊漂流记').first()
  1. last() 通过该方法,可以取queryset对象的最后一个数据对象
res = models.Books.objects.filter(title='鲁滨逊漂流记').last()
  1. count() 通过该方法,可以统计数据个数
num = models.Books.objects.count()
  1. values() 通过该方法,可以获取数据对象中指定字段的值,可以取多个

    ​ 返回的值以列表套字典的形式返回

res = models.Books.objects.values('title','price')
  1. values_list() 通过该方法,可以获取数据对象中指定字段的值,可以取多个

    ​ 返回的值以列表套元祖的形式返回

res = models.Books.objects.values_list('title','price')
  1. order_by() 通过该方法,让查询结果按照指定的字段排序
res = models.Books.objects.order_by('price')	#默认是升序,在字段前加'-'号,变成降序
  1. reverse() 通过该方法,可以是查询结果的顺序颠倒

    ​ 但是该方法有一个前提条件,颠倒的对象必须是已经排序过的结果,否则没有效果

res3 = models.Books.objects.all().order_by('price').reverse()
  1. exclude() 通过该方法,可以剔除指定数据
res = models.Books.objects.all().exclude(title='假如给我三天光明')
  1. exists() 通过该方法,可以判断查询到的结果,是否为空,结果返回一个布尔值
res = models.Books.objects.filter(pk=1).exists()
  1. distinct() 通过该方法,可以对查询到的结果进行去重操作

    ​ 该方法,需要数据必须是完全一样的条件下,才能生效

res = models.Books.objects.values('title','price').distinct()

双下划綫查询

查询价格大于80的书籍 __gt

res = models.Books.objects.filter(price__gt=80)

查询价格小于400 的书籍 __lt

res = models.Books.objects.filter(price__lt=80)

查询价格大于等于80 __gte

res = models.Books.objects.filter(price__gte=80)

查询价格小于等于80 __lte

res = models.Books.objects.filter(price__lte=80)

查询价格是77或者88的书籍 price__in

res = models.Books.objects.filter(price__in=[77,88])

查询价格在90到100之间的书籍 price__range头尾兼顾

res = models.Books.objects.filter(price__range=(90,100))

查询出版日期是2019年的书籍 __year

res = models.Books.objects.filter(publish_date__year='2019')

查询出版日期是1月份的书籍 __month

res = models.Books.objects.filter(publish_date__month='1')

模糊查询

查询书籍是以三开头的书 title__startswith

res = models.Books.objects.filter(title__startswith='假')

查询书籍是以义结尾的书 title__endswith

res = models.Books.objects.filter(title__endswith='记')

查询书籍名称中包含游字的书籍 title__contains

__contains默认区别字母大小写,通过使用__icontains,该方法不区分大小写

res = models.Books.objects.filter(title__contains='游')

图书管理表设计

创建图书表

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish_date = models.DateField(auto_now=True)
    publish = models.ForeignKey(to='Publish')
    authors = models.ManyToManyField(to='Author')

#auto_now:每次修改的数据的时候 都会自动更新修改书籍(展示最新的一次修改时间)
#auto_now_add:当数据创建出来的时候 会自动将创建时间记录下来

创建出版社表

class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)

创建作者表

class Author(models.Model):
    name = models.CharField(max_length=32)
    email = models.EmailField()
    author_detail = models.OneToOneField(to = 'AuthorDetail')

创建作者详细表

class AuthorDetail(models.Model):
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=64)

外键字段(一对多)的增删改查

第一种方式

models.Book.objects.create(title='狂人日记',price=888,publish_id=1)

第二种方法

publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='狂人日记2',price=333,publish=publish_obj)  # 传虚拟字段  跟数据对象即可

第一种方式

models.Book.objects.filter(pk=1).update(publish_id=2)

第二种方式

publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)

models.Publish.objects.filter(pk=1).delete()  # 默认就是级联删除 级联更新

外键字段(多对多)的增删改查

第一种方式

book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add(2)

#book_obj通过.authors就能跨到第三张表,在通过add()添加作者id

第二种方式

book_obj = models.Book.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj,author_obj1)

#add()方法可以接受对象

add方法 能够朝第三张关系表添加数据

​ 即支持传数字,也支持传对象,并且两者都可以是多个

第一种方法

book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.set((1,3))

第二种方法

​ 通过传入对象

author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set((author_obj,author_obj1))

通过set修改多对多关系表中的数据
该方法既可以传数字也可以传对象,但是需要注意的是括号内必须是可迭代对象,都支持多个

第一种方式

book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.remove(2,3)

第二种方式

author_obj = models.Author.objects.filter(pk=3).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.remove(author_obj,author_obj1)

通过remove方法删除,既可以传数字,也可以穿对象

​ 并且都支持传多个,不需要迭代

清空数据

#删除某个数据在第三张表中的所有记录
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.clear()

跨表查询

正反向查询

关键字段所在的表----->关联表 为正向查找

通过对象查找(子查询)

语法:
    对象.关联字段.字段

通过字段查找(联表查询)

语法:
    关联字段__字段

关联表-------->关键字段所在表 为反向查找

通过对象查找(子查询)

语法:
    obj.表名_set

通过字段查找(联表查询)

语法:
    表名__字段

子查询(分步操作)

查询书籍主键为2的出版社名称

book_obj = models.Book.objects.filter(pk=2).first()	# 出版社对象
publish_name = book_obj.publish.name

查询书籍主键为4的作者姓名

book_obj = models.Book.objects.filter(pk=4).first()
name_list = book_obj.authors.all()		#若查询结果不止一个,需要用all()方法

#当正向查询 ' . ' 外键字段数据有多个的情况下 需要.all()来接受所有数据

查询作者是鲁迅的手机号码

author_obj = models.Author.objects.filter(name='鲁迅').first()
author_phone = author_obj.author_detail.phone

查询出版社是东方出版社出版过的书籍 (反向查找) obj.表名_set

publish_obj = models.Publish.objects.filter(name='哈哈出版社').first()
book_obj_list = publish_obj.book_set.all()

查询手机号是111的作者姓名 (一对一反向查找)

author_detail_obj = models.AuthorDetail.objects.filter(phone=222).first()
author_name = author_detail_obj.author.name

一对多,多对多反向查找时,对象 . 表名 后需要加_set

一对一反向查找则不需要_set

联表查询

类似于sql中inner join , left join , right join , union

查询书籍pk为2的出版社名称

正向查找

models.Book.objects.filter(pk=2).values('publish__name')

反向查找

models.Publish.objects.filter(book__pk = 2).values('name')

查询书籍pk为2的作者姓名和邮箱

models.Author.objects.filter(book__pk=2).values('name','email')

#models后面跟哪张表,就以那张表为基表

查询书籍pk是2的作者的手机号 (三表联查)

models.Book.objects.filter(pk=2).values('authors__author_detail__phone')
models.Author.objects.filter(book__pk=2).values('author_detail__phone')

聚合查询( aggregate() )

聚合函数的方法不是内置的,需要导入模块

from django.db.models import Avg, Sum, Max, Min, Count

筛选出价格最高的书籍的

models.Book.objects.aggregate(name = Max('price'))	
#name可以自定义名字,不定名字,会自定义名字格式 字段名_函数名

求书籍平均价格

models.Book.objects.aggregate(Avg('price'))

支持所有函数一起使用

models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('price'),Avg('price'))

分组查询( annotate() )

统计每一本书的书名和对应的作者人数

models.Book.objects.annotate(author_count=Count('authors__id')).values('title','author_count')
#models后面跟分组的表

统计出每个出版社卖的最便宜的书的价格 出版社的名字 价格

models.Publish.objects.annotate(price_min=Min('book__price')).values('name','price_min')

统计不止一个作者的图书的书名和作者个数

models.Book.objects.annotate(author_count=Count('authors__id')).filter(author_count__gt=1).values('title','author_count')

F与Q查询

F和Q查询也需要导入模块

from django.db.models import F,Q

查询库存数大于卖出数的书籍

models.Book.objects.filter(stock__gt=F('sale')).values('title')

所有书的价格上涨100块

models.Book.objects.all().update(price=F('price')+10)

将所有书的名称后面全部加上 "爆款" 后缀 操作字符串数据需要借助于Concat方法

from django.db.models.functions import Concat
from django.db.models import Value

res = models.Book.objects.update(title=Concat(F('title'), Value('新款')))

Q查询

Q包裹之后如果是逗号,那么还是and关系

如果使用 | ,那么是or关系

~就是not关系

查询书籍名称是阿Q正传 或者 作者手机号是111的书籍

models.Book.objects.filter(Q(title='阿Q正传')|Q(authors__author_detail__phone='111')).values('title')

Q对象高级用法

q = Q()
q.connector = 'or'  # 默认是and  可以改成or

涉及知识点

通过模型表建表

  1. create方法
book_obj = models.Books.objects.create(
    title='假如给我三天光明',price='99',publish_date = datetime.datetime.now()
)
  1. 利用对象的绑定方法
book_obj = models.Books(
    title='鲁滨逊漂流记',price='77',publish_date = '2011-1-1'
)
book_obj.save()

通过模型表修改数据

res = models.Books.objects.filter(pk=1)
#pk会自动识别当前标的主键字段,可以使用pk指代主键字段
filter查询出来的结果是一个Queryset对象
	1.只要是queryset对象就可以一直调用queryset的方法
    2.只要是queryset对象,就可以通过 . query查看当前结果内部对应的sql语句

方式一:利用queryset方法

models.Books.objects.filter(pk=1).update(price=444)

方式二:通过对象的绑定方法

book_obj = models.Books.objects.get(pk=1)
book_obj.price = 222
book_obj.save()

get和filter区别

1.filter获取到的是一个queryset对象 类似于一个列表
    
2.get获取到的直接就是数据对象本身
    当条件不存在的情况下
        使用filter不报错直接返回一个空
        使用get直接报错

删除数据

方式一:利用queryset方法 delete()

models.Books.objects.filter(pk=3).delete()

方式二:通过对象的绑定方法

book_obj = models.Books.objects.get(pk=3)
book_obj.delete()

MySQL中的模糊查询

关键字 like
模糊匹配的符号
     %:匹配任何个数的任意字符
     _:匹配一位任意的字符

聚合函数

​ mysql中聚合函数必须用在分组之后,如果没有分组,默认整体就是一组

聚合函数:Max(), Min(), Sum(), Avg(), Count()

级联更新,级联删除

​ 操作外键字段管理数据的时候,书跟出版社是一对多关系

如果要删除的数据所在的表里有外键字段,此时删除该表中字段,会把外键对应的数据也一同删除

如果是修改数据,则外键关联的表中数据,也会一同修改

posted @ 2019-11-28 21:09  simple123  阅读(471)  评论(0编辑  收藏  举报