https://www.cnblogs.com/wu-chao/p/8353315.html
1.新建一个py文件
2.代码环境搭建
1 import os 2 3 if __name__ != '__main__': 4 exit() 5 6 # 加载django项目的配置信息 7 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_pro.settings") # 就在manage.py 文件中第8行 8 # 导Django 并 启动Django项目 9 import django 10 django.setup() 11 12 from app01 import models
3.输入需要测试的查询代码
13种查询方法
语法 作用
all() 查询全部
get(字段='xx') 查找指定值的对象 没有结果会报错
filter(条件) 作用同上,没有不会报错 返回列表
exclude(条件) 排除查询,返回不符合条件的所有对象 返回列表
values(字段,) 按字段 返回字段值 返回字典
values_list(字段,) 同上,返回列表,里边是元祖
order_by(字段) 根据指定字段排序
reverse() 反向排序! 前提是已经有顺序才能反序
distinct() 查询结果去重
count() 取查询到的对象 列表个数
first() 第一个
last() 最后一个
exists() 如果返回列表有数据就返回True,否则返回False
实例
1 import os 2 3 # 在py中测试ORM的代码环境搭建: 4 if __name__ == '__main__': 5 # 加载django项目的配置信息 6 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_pro.settings") # 就在manage.py的第六行 7 # 导Django 并 启动Django项目 8 import django 9 django.setup() 10 11 from app01 import models 12 13 # all()查询 14 ret = models.Person.objects.all() 15 print(ret) 16 17 # get查询 (查询没有对应结果时会报错) 取到对象 18 ret = models.Person.objects.get(name='老王') 19 print(ret) 20 21 # filter(**kwargs) 同get但不报错, 取到对象列表,可以批量查询 22 # 对象列表 ,在django叫 QuerySet对象 23 ret = models.Person.objects.filter(id=1) # 查询id1的对象列表 24 print(ret[0]) 25 26 # exclude 排除查询 返回列表 27 ret = models.Person.objects.exclude(id=1) # 取除id=1之外的所有 28 print(ret) 29 30 # values 按字段 来查找返回,该字段的值(列表)里边是字典 31 ret = models.Person.objects.values('id','name') 32 print(ret) # [{'id': 1, 'name': '小张'}, {'id': 2, 'name': '老王'}] 33 34 # values_list 同上,返回列表,里边是元祖 35 ret= models.Person.objects.values_list('id','name') 36 print(ret) # [(1, '小张'), (2, '老王')] 37 38 # order_by 根据指定字段排序 39 ret = models.Person.objects.order_by('id') 40 print(ret) 41 42 # reverse 反向排序! 前提是已经有顺序才能反序 43 ret = models.Person.objects.order_by('id').reverse() 44 print(ret) 45 46 # distinct() 去重 47 48 # count() 取 查询到的对象 列表个数 49 50 # first() 第一个 51 52 # last() 最后一个 53 54 # exists() 如果返回列表有数据就返回True,否则返回False
QuerySet与惰性机制
所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。
QuerySet特点:
<1> 可迭代的
<2> 可切片
<3>惰性计算和缓存机制
1 def queryset(request): 2 books=models.Book.objects.all()[:10] #切片 应用分页 3 books = models.Book.objects.all()[::2] 4 book= models.Book.objects.all()[6] #索引 5 print(book.title) 6 for obj in books: #可迭代 7 print(obj.title) 8 books=models.Book.objects.all() #惰性计算--->等于一个生成器,不应用books不会执行任何SQL操作 9 # query_set缓存机制1次数据库查询结果query_set都会对应一块缓存,再次使用该query_set时,不会发生新的SQL操作; 10 #这样减小了频繁操作数据库给数据库带来的压力; 11 authors=models.Author.objects.all() 12 for author in authors: 13 print(author.name) 14 print('-------------------------------------') 15 models.Author.objects.filter(id=1).update(name='张某') 16 for author in authors: 17 print(author.name) 18 #但是有时候取出来的数据量太大会撑爆缓存,可以使用迭代器优雅得解决这个问题; 19 models.Publish.objects.all().iterator() 20 return HttpResponse('OK')
## 增加和查询操作
* 增
1 def orm(request): 2 orm2添加一条记录的方法 3 单表 4 1、表.objects.create() 5 models.Publish.objects.create(name='浙江出版社',addr="浙江.杭州") 6 models.Classify.objects.create(category='武侠') 7 models.Author.objects.create(name='金庸',sex='男',age=89,university='东吴大学') 8 2、类实例化:obj=类(属性=XX) obj.save() 9 obj=models.Author(name='吴承恩',age=518,sex='男',university='龙溪学院') 10 obj.save() 11 12 1对多 13 1、表.objects.create() 14 models.Book.objects.create(title='笑傲江湖',price=200,date=1968,classify_id=6, publish_id=6) 15 2、类实例化:obj=类(属性=X,外键=obj)obj.save() 16 classify_obj=models.Classify.objects.get(category='武侠') 17 publish_obj=models.Publish.objects.get(name='河北出版社') 18 注意以上获取得是和 book对象 向关联的(外键)的对象 19 book_obj=models.Book(title='西游记',price=234,date=1556,classify=classify_obj,publish=publish_obj) 20 book_obj.save() 21 22 多对多 23 如果两表之间存在双向1对N关系,就无法使用外键来描述其关系了; 24 只能使用多对多的方式,新增第三张表关系描述表; 25 book=models.Book.objects.get(title='笑傲江湖') 26 author1=models.Author.objects.get(name='金庸') 27 author2=models.Author.objects.get(name='张根') 28 book.author.add(author1,author2) 29 30 书籍和作者是多对多关系, 31 切记:如果两表之间存在多对多关系,例如书籍相关的所有作者对象集合,作者也关联的所有书籍对象集合 32 book=models.Book.objects.get(title='西游记') 33 author=models.Author.objects.get(name='吴承恩') 34 author2 = models.Author.objects.get(name='张根') 35 book.author.add(author,author2) 36 #add() 添加 37 #clear() 清空 38 #remove() 删除某个对象 39 return HttpResponse('OK')
根据条件判断,增加 更新
1 根据user=user去查找,如果找到更新 如果没有找到创建defaults={} 中的数据 2 tk = gen_tcoken(username) 3 models.Token.objects.update_or_create(user=user, defaults={'token': tk})
* 删
1 models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据
* 改
1 # 修改方式1 update() 2 models.Book.objects.filter(id=1).update(price=3) 3 4 #修改方式2 obj.save() 5 book_obj=models.Book.objects.get(id=1) 6 book_obj.price=5 7 book_obj.save()
* 查
1 def ormquery(request): 2 books=models.Book.objects.all() #------query_set对象集合 [对象1、对象2、.... ] 3 books=models.Book.objects.filter(id__gt=2,price__lt=100) 4 book=models.Book.objects.get(title__endswith='金') #---------单个对象,没有找到会报错 5 book1 = models.Book.objects.filter(title__endswith='金').first() 6 book2 = models.Book.objects.filter(title__icontains='瓶').last() 7 books=models.Book.objects.values('title','price', #-------query_set字典集合 [{一条记录},{一条记录} ] 8 'publish__name', 9 'date', 10 'classify__category', #切记 正向连表:外键字段___对应表字段 11 'author__name', #反向连表: 小写表名__对应表字段 12 'author__sex', #区别:正向 外键字段__,反向 小写表名__ 13 'author__age', 14 'author__university') 15 16 books=models.Book.objects.values('title','publish__name').distinct() 17 #exclude 按条件排除。。。 18 #distinct()去重, exits()查看数据是否存在? 返回 true 和false 19 a=models.Book.objects.filter(title__icontains='金'). 20 return HttpResponse('OK')
* 连表查询
1 反向连表查询: 2 1、通过object的形式反向连表, obj.小写表名_set.all() 3 publish=models.Publish.objects.filter(name__contains='湖南').first() 4 books=publish.book_set.all() 5 for book in books: 6 print(book.title) 7 通过object的形式反向绑定外键关系 8 authorobj = models.Author.objects.filter(id=1).first() 9 objects = models.Book.objects.all() 10 authorobj.book_set.add(*objects) 11 authorobj.save() 12 13 2、通过values双下滑线的形式,objs.values("小写表名__字段") 14 注意对象集合调用values(),正向查询是外键字段__XX,而反向是小写表名__YY看起来比较容易混淆; 15 books=models.Publish.objects.filter(name__contains='湖南').values('name','book__title') 16 authors=models.Book.objects.filter(title__icontains='我的').values('author__name') 17 print(authors) 18 fifter()也支持__小写表名语法进行连表查询:在publish标查询 出版过《笑傲江湖》的出版社 19 publishs=models.Publish.objects.filter(book__title='笑傲江湖').values('name') 20 print(publishs) 21 查询谁(哪位作者)出版过的书价格大于200元 22 authors=models.Author.objects.filter(book__price__gt=200).values('name') 23 print(authors) 24 通过外键字段正向连表查询,出版自保定的书籍; 25 city=models.Book.objects.filter(publish__addr__icontains='保定').values('title') 26 print(city)
## 高级操作(牛叉的上下划线)
* 利用双下划线将字段和对应的操作连接起来
1 # 获取个数 2 models.Tb1.objects.filter(name='seven').count() 3 4 # 大于,小于 5 models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 6 models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值 7 models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 8 models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值 9 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 10 11 # in 12 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 13 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 14 15 # isnull 16 Entry.objects.filter(pub_date__isnull=True) 17 18 # contains 19 models.Tb1.objects.filter(name__contains="ven") 20 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 21 models.Tb1.objects.exclude(name__icontains="ven") 22 23 # range 24 models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and 25 26 # 其他类似 27 startswith,istartswith, endswith, iendswith, 28 29 # order by 30 models.Tb1.objects.filter(name='seven').order_by('id') # asc 31 models.Tb1.objects.filter(name='seven').order_by('-id') # desc 32 33 # group by 34 from django.db.models import Count, Min, Max, Sum 35 models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) 36 SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" 37 38 # limit 、offset 39 models.Tb1.objects.all()[10:20] 40 41 # regex正则匹配,iregex 不区分大小写 42 Entry.objects.get(title__regex=r'^(An?|The) +') 43 Entry.objects.get(title__iregex=r'^(an?|the) +') 44 45 # date 46 Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) 47 Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) 48 49 # year 50 Entry.objects.filter(pub_date__year=2005) 51 Entry.objects.filter(pub_date__year__gte=2005) 52 53 # month 54 Entry.objects.filter(pub_date__month=12) 55 Entry.objects.filter(pub_date__month__gte=6) 56 57 # day 58 Entry.objects.filter(pub_date__day=3) 59 Entry.objects.filter(pub_date__day__gte=3) 60 61 # week_day 62 Entry.objects.filter(pub_date__week_day=2) 63 Entry.objects.filter(pub_date__week_day__gte=2) 64 65 # hour 66 Event.objects.filter(timestamp__hour=23) 67 Event.objects.filter(time__hour=5) 68 Event.objects.filter(timestamp__hour__gte=12) 69 70 # minute 71 Event.objects.filter(timestamp__minute=29) 72 Event.objects.filter(time__minute=46) 73 Event.objects.filter(timestamp__minute__gte=29) 74 75 # second 76 Event.objects.filter(timestamp__second=31) 77 Event.objects.filter(time__second=2) 78 Event.objects.filter(timestamp__second__gte=31)
## 其他操作
# extra # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) Entry.objects.extra(where=['headline=%s'], params=['Lennon']) Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) # F from django.db.models import F models.Tb1.objects.update(num=F('num')+1) # Q # 方式一: Q(nid__gt=10) Q(nid=8) | Q(nid__gt=10) Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') # 方式二: con = Q() q1 = Q() q1.connector = 'OR' q1.children.append(('id', 1)) q1.children.append(('id', 10)) q1.children.append(('id', 9)) q2 = Q() q2.connector = 'OR' q2.children.append(('c1', 1)) q2.children.append(('c1', 10)) q2.children.append(('c1', 9)) con.add(q1, 'AND') con.add(q2, 'AND') models.Tb1.objects.filter(con) # 执行原生SQL from django.db import connection, connections cursor = connection.cursor() # cursor = connections['default'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone()
## ORM连表操作
我们在学习django中的orm的时候,我们可以把一对多,多对多,分为正向和反向查找两种方式。
正向查找:ForeignKey在 UserInfo表中,如果从UserInfo表开始向其他的表进行查询,这个就是正向操作,反之如果从UserType表去查询其他的表这个就是反向操作。
- 一对多:models.ForeignKey(其他表)
- 多对多:models.ManyToManyField(其他表)
- 一对一:models.OneToOneField(其他表)
正向连表操作总结:
所谓正、反向连表操作的认定无非是Foreign_Key字段在哪张表决定的,
Foreign_Key字段在哪张表就可以哪张表使用Foreign_Key字段连表,反之没有Foreign_Key字段就使用与其关联的 小写表名;
1对多:对象.外键.关联表字段,values(外键字段__关联表字段)
多对多:外键字段.all()
反向连表操作总结:
通过value、value_list、fifter 方式反向跨表:小写表名__关联表字段
通过对象的形式反向跨表:小写表面_set().all()
## 应用场景
一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
多对多:在某表中创建一行数据是,有一个可以多选的下拉框
例如:创建用户信息,需要为用户指定多个爱好