一、django的orm的13种基本的查询方法

1、all方法,查询某张表中的所有的数据

  1. user_obj_list = models.Person.objects.all()

  

返回的结果是queryset对象,也就是一个对象的集合

  1. <QuerySet [<Person: 人的对象小黑9>, <Person: 人的对象小黑8>, <Person: 人的对象小黑7>, <Person: 人的对象小黑6>, <Person: 人的对象小黑5>, <Person: 人的对象小黑4>, <Person: 人的对象小黑3>, <Person: 人的对象小黑2>, <
  2. Person: 人的对象小黑19>, <Person: 人的对象小黑18>, <Person: 人的对象小黑17>, <Person: 人的对象小黑16>, <Person: 人的对象小黑15>, <Person: 人的对象小黑14>, <Person: 人的对象小黑13>, <Person: 人的对象小黑12>, <Pers
  3. on: 人的对象小黑11>, <Person: 人的对象小黑10>, <Person: 人的对象小黑1>, <Person: 人的对象小黑0>]>

  

2、filter方法,查询符合某个条件的所有的数据

  1. user_objs = models.Person.objects.filter(name="小黑7")

返回的结果也是一个queryset对象,也就是一个对象的集合

  1. <QuerySet [<Person: 人的对象小黑7>]>

  

3、get方法,返回的单个对象

  1. user_obj = models.Person.objects.get(name="小黑7")

  

返回的是单个对象

  1. 人的对象小黑7

  

  1. # 返回的时候某一个具体的对象,如果这个条件的对象不存在,会报错

4、exclude方法,对条件取反

  1. user_obj = models.Person.objects.exclude(id__gte=4)

  

返回的是一个queryset对象的

  1. exclude方法 <QuerySet [<Person: 人的对象小黑2>, <Person: 人的对象小黑1>, <Person: 人的对象小黑0>]>

  

5、values方法,查询一个queryset对象的值

  1. user_obj = models.Person.objects.exclude(id__gte=4).values("id","name","birthday_1")

  

返回的是一个一个queryset的对象集合,是一个大的列表,每个列表的元素又是每个对象的小字典

  1. <QuerySet [{'id': 3, 'name': '小黑2', 'birthday_1': datetime.datetime(2016, 12, 6, 0, 0)}, {'id': 2, 'name': '小黑1', 'birthday_1': datetime.datetime(2016, 5, 13, 0, 0)}, {'id': 1, 'name': '小黑0', 'birthday_1':
  2. datetime.datetime(2016, 3, 5, 0, 0)}]>

  

6、values_list,查询一个queryset对象的值

  1. user_obj = models.Person.objects.exclude(id__gte=4).values_list("id", "name", "birthday_1")

  

返回的是一个queryset对象,这个对象是一个列表,列表中的每个元素是每个对象的元组信息

  1. <QuerySet [(3, '小黑2', datetime.datetime(2016, 12, 6, 0, 0)), (2, '小黑1', datetime.datetime(2016, 5, 13, 0, 0)), (1, '小黑0', datetime.datetime(2016, 3, 5, 0, 0))]>

  

7、order_by,根据某个字段排序,如果字段加一个负号,则是逆序排序,如果不加,则则是正序排列

  1. user_obj = models.Person.objects.exclude(id__gte=4).order_by("-id")

  

返回的结果也是一个queryset对象

  1. <QuerySet [<Person: 人的对象小黑2>, <Person: 人的对象小黑1>, <Person: 人的对象小黑0>]>

  

  1. user_obj = models.Person.objects.exclude(id__gte=4).order_by("id")

  

返回的结果也是一个queryset对象

  1. <QuerySet [<Person: 人的对象小黑0>, <Person: 人的对象小黑1>, <Person: 人的对象小黑2>]>

  

8、reverse方法,对一个有序的queryset对象,做反转操作

  1. user_obj = models.Person.objects.exclude(id__gte=4).order_by("-id").reverse()

  

返回的结果

  1. <QuerySet [<Person: 人的对象小黑0>, <Person: 人的对象小黑1>, <Person: 人的对象小黑2>]>

  

9、distance方法,对返回的数据去重,在外键中用的比较多

10、count方法,统计查询到的数据的个数

11、first方法,在queryset对象中返回查询到的第一条数据

12、last方法,在queryset对象中返回查询到的最后一条数据

13、exists方法,判断用指定的过滤条件查询是否有值

二、单表查询中的双下划线查询

  1. _exact 精确等于 like 'aaa'
  2.  
  3. __iexact 精确等于 忽略大小写 ilike 'aaa'
  4.  
  5. __contains 包含 like '%aaa%'
  6.  
  7. __icontains 包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains
  8.  
  9. __gt 大于
  10.  
  11. __gte 大于等于
  12.  
  13. __lt 小于
  14.  
  15. __lte 小于等于
  16.  
  17. __in 存在于一个list范围内
  18.  
  19. __startswith 以...开头
  20.  
  21. __istartswith 以...开头 忽略大小写
  22.  
  23. __endswith 以...结尾
  24.  
  25. __iendswith 以...结尾,忽略大小写
  26.  
  27. __range 在...范围内
  28.  
  29. __year 日期字段的年份
  30.  
  31. __month 日期字段的月份
  32.  
  33. __day 日期字段的日
  34.  
  35. __isnull=True/False
  36.  
  37. 例子:
  38.  
  39. >> q1 = Entry.objects.filter(headline__startswith="What")
  40.  
  41. >> q2 = q1.exclude(pub_date__gte=datetime.date.today())
  42.  
  43. >> q3 = q1.filter(pub_date__gte=datetime.date.today())
  44.  
  45. >>> q = q.filter(pub_date__lte=datetime.date.today())
  46.  
  47. >>> q = q.exclude(body_text__icontains="food")

  

  1. models.test_orm.objects.filter(id__in=[12,34,21])
  2. models.test_orm.objects.filter(id__gt=12)
  3. models.test_orm.objects.filter(name__icontains="aaaa")
  4. models.test_orm.objects.filter(name__iendswith="aaa")

  

三、一对多的查询

1、先看正向查询,有两种方式,方式1,先在多表中找到某个对象,然后通过外键的字段找到一表中的对象

  1. book_obj = models.Book.objects.all().last()
  2.  
  3. print(book_obj.book_publish)
  4.  
  5. print(book_obj.book_publish.name)

  

2、正向查询的方式2,在values和values_list中利用外键字段的双下划线进行跨表查询

  1. # 通过双下划线在values中进行跨表查询,需要通过外键的字段
  2. publist_obj = models.Book.objects.filter(id=3).values("id","book_name","book_publish","book_publish__name")
  3.  
  4. print(publist_obj)
  5.  
  6. # 通过双下划线在values_list中进行跨表查询,需要通过外键的字段
  7. publist_obj = models.Book.objects.filter(id=3).values_list("id","book_name","book_publish","book_publish__name")
  8.  
  9. print(publist_obj)

  

3、在看反向查询

我们先来介绍一下外键中的related_name字段,如果,如果设置了这个值,则反向查询的时候用related_name的值,如果没有设置这个值,则通过“多表的名称_set”进行反向查询

首先我们看下不设置related_name的反向查询

首先外键是这样设置的

  1. book_publish = models.ForeignKey(to="Publisher")

  

然后进行反向查询,这里要记住,如果使用values或者values_list方法,则里面的参数和正向查询是一样的

  1. publist_obj = models.Publisher.objects.all().first()
  2.  
  3. print(publist_obj.book_set.all())
  4. print(publist_obj.book_set.values_list("id","book_name","book_publish","book_publish__name"))

  

然后我们在看下在外键中设置related_name的方向查询,下面的例子,我们设置了ralated_name,所以反向查询则要使用PubToBook进行反向查询

  1. book_publish = models.ForeignKey(to="Publisher", related_name="PubToBook")

  

同样,在values和values_list方法中,则里面的参数和正向查询是一样的

  1. print(publist_obj.PubToBook.all())
  2. print(publist_obj.PubToBook.values_list("id", "book_name", "book_publish", "book_publish__name"))

  

这里要注意,如果要调用values和values_list方法,则必须要用queryset对象

如果要使用点,则必须要单个对象

四、多对多操作

1、create操作

  1. # 1、方法1,create
  2.  
  3. # 我们的manytomant字段在book表中,我们可以调用book表中的某个对象的create方法,去创建一个auther对象,创建成功后,会自动把这个book对象和
  4. # 和我们新创建的出版社关联起来
  5.  
  6. # book_obj = models.Book.objects.get(id=2)
  7.  
  8. # book_obj.book_auther.create(
  9. # auther_name = "大学作者10",
  10. # )

  

2、add操作

  1. # 2、add方法
  2. # 1、由于manytomany字段在book表中,我们可以先查到某个或者某几个auther表中的对象,某个book对象通过manytomany字段
  3. # 为某本书添加和多个auther表的关联,这里还可以传递一个列表对象,则需要用*列表对象传递进去,可以添加一个对象,也可以
  4. # 添加多个对象,也可以传递一个列表进去
  5. #
  6. # auther_1 = models.Auther.objects.all().first()
  7. # auther_2 = models.Auther.objects.get(id=2)
  8. #
  9. # models.Book.objects.all().last().book_auther.add(
  10. # auther_1,auther_2
  11. # )
  12.  
  13. # add的方法也可以直接传递一个id的值进去

  

3、remove操作

  1. # 3、remove方法
  2. # 先在book表中找到某个对象,然后通过多对多字段进行remove操作,删除这个book和作者的关系
  3.  
  4. # book_obj = models.Book.objects.all().first()
  5.  
  6. # 3_1、可以直接传递一个id进去
  7. # book_obj.book_auther.remove(11)
  8.  
  9. # 3_2、传递一个对象进去
  10.  
  11. # del_auther_obj = models.Auther.objects.get(id=5)
  12. #
  13. # book_obj.book_auther.remove(del_auther_obj)

  

4、clear方法

  1. # 4、clear方法
  2.  
  3. book_obj = models.Book.objects.all().first()
  4.  
  5. book_obj.book_auther.clear()

  

五、聚合查询

  1. from django.db.models import Avg
  2. from django.db.models import Max
  3. from django.db.models import Min
  4. from django.db.models import Sum

  

  1. ret = models.Book.objects.all().aggregate(Sum("book_price"))
  2. print(ret)
  3.  
  4. ret = models.Book.objects.all().aggregate(Avg("book_price"))
  5. print(ret)
  6.  
  7. ret = models.Book.objects.all().aggregate(Max("book_price"))
  8. print(ret)
  9.  
  10. ret = models.Book.objects.all().aggregate(Min("book_price"))
  11. print(ret)

  

结果如下

  1. {'book_price__sum': Decimal('468.98')}
  2. {'book_price__avg': 46.898}
  3. {'book_price__max': Decimal('99.43')}
  4. {'book_price__min': Decimal('14.43')}

  

六、分组查询

  1. from django.db.models import Avg
  2. from django.db.models import Max
  3. from django.db.models import Min
  4. from django.db.models import Sum

  

先通过values方法进行分组,然后求每个分组下的最大值,平均值,最小值,和,通过表中的所有字段都可以做分组查询

  1. ret = models.Book.objects.all().values("book_publish").annotate(Sum("book_price"))
  2. print(ret)
  3.  
  4. ret = models.Book.objects.all().values("book_auther").annotate(Min("book_price"))
  5. print(ret)
  6.  
  7. ret = models.Book.objects.all().values("book_name").annotate(Max("book_price"))
  8. print(ret)

  

结果

  1. <QuerySet [{'book_publish': 10, 'book_price__sum': Decimal('102.93')}, {'book_publish': 15, 'book_price__sum': Decimal('88.86')}, {'book_publish': 16, 'book_price__sum': Decimal('48.84')}, {'book_publish': 17, 'bo
  2. ok_price__sum': Decimal('34.49')}, {'book_publish': 18, 'book_price__sum': Decimal('99.43')}, {'book_publish': 19, 'book_price__sum': Decimal('94.43')}]>
  3. <QuerySet [{'book_auther': None, 'book_price__min': Decimal('34.23')}, {'book_auther': 1, 'book_price__min': Decimal('14.43')}, {'book_auther': 2, 'book_price__min': Decimal('34.41')}, {'book_auther': 3, 'book_pri
  4. ce__min': Decimal('14.43')}, {'book_auther': 4, 'book_price__min': Decimal('32.43')}, {'book_auther': 7, 'book_price__min': Decimal('34.49')}, {'book_auther': 8, 'book_price__min': Decimal('56.43')}, {'book_auther
  5. ': 9, 'book_price__min': Decimal('94.43')}, {'book_auther': 10, 'book_price__min': Decimal('94.43')}]>
  6. <QuerySet [{'book_name': '大学体育1', 'book_price__max': Decimal('34.23')}, {'book_name': '大学体育2', 'book_price__max': Decimal('56.43')}, {'book_name': '跟周雍博学玩游戏', 'book_price__max': Decimal('14.43')},
  7. {'book_name': '跟妈妈学做饭', 'book_price__max': Decimal('34.47')}, {'book_name': '跟小妹学哭鼻子', 'book_price__max': Decimal('34.49')}, {'book_name': '跟崔洪艳学会计', 'book_price__max': Decimal('34.41')}, {'boo
  8. k_name': '跟崔皓然学爬楼梯', 'book_price__max': Decimal('32.43')},, {'book_name': '跟爷爷学木匠', 'book_price__max': Decimal('94.43')}, {'book
  9. _name': '跟爸爸学开车', 'book_price__max': Decimal('34.23')}]>

  

分组查询的高级用法,求每个作者出的book的总价格

  1. ret = models.Auther.objects.all().annotate(book_price_sum=Sum("book__book_price")).values_list("auther_name","book_price_sum")
  2. print(ret)

  

结果如下

  1. <QuerySet [('大学作者0', Decimal('266.42')), ('大学作者1', Decimal('133.84')), ('大学作者2', Decimal('83.31')), ('大学作者3', Decimal('200.50')), ('大学作者4', None), ('大学作者5', None), ('大学作者6', Decimal('12
  2. 8.92')), ('大学作者7', Decimal('56.43')), ('大学作者8', Decimal('94.43')), ('大学作者9', Decimal('94.43')), ('大学作者10', None)]>

  

下面来解释一下上面的代码

先拿到所有的作者,然后求出每个作者的书的总价格,然后赋值给一个变量book_price_sum,赋值给的这个变量后,也就是在数据库中会临时多一个字段,这个字段就是book_price_sum,然后通过values_list方法打印出作者名称和book_price_sum的值,由于作者表中没有manytomany字段,需要用表明+下划线的方法做跨表查询

下面这段代码更好理解,实现的效果和上面的一样

  1. ret = models.Auther.objects.all().values("auther_name").annotate(book_price_sum=Sum("book__book_price")).values_list("auther_name",
  2. "book_price_sum")
  3. print(ret)

  

7、F查询

  1. from django.db.models import F
  2. from django.db.models import Q
  3.  
  4. # 当我们需要对表中的 数字字段做比较或者操作的时候加减乘除等数学运算的时候可以用到F查询
  5.  
  6. print("F查询".center(100,"*"))
  7.  
  8. # 过滤出来kucun字段大于卖出字段的值
  9. ret = models.Book.objects.filter(kucun__gt=F("maichu"))
  10. print(ret)
  11.  
  12. # 为库存字段+2
  13. models.Book.objects.all().update(kucun=F("kucun")+2)

  

8、Q查询

append的方法需要传递一个tuple

  1. q_obj = Q()
  2.  
  3. q1 = Q()
  4. q2 = Q()
  5.  
  6. q1.connector = "AND"
  7.  
  8. q1.children.append(("id__gte",3))
  9.   
  10. q1.children.append(("kucun__gte",1000))
  11.  
  12. q2.connector = "OR"
  13.  
  14. q2.children.append(("maichu__lte",3000))
  15.  
  16. q_obj.add(q1,"AND")
  17. q_obj.add(q2,"AND")
  18.  
  19. # 过滤条件1:id大于等于3,库存大于等于1000的,两个条件是AND的关系
  20. # 过滤条件2:卖出小于等于3000的,如果在q2中继续添加条件,他是or的关系
  21. # 最后过滤条件1和过滤条件2是AND的关系
  22.  
  23. ret = models.Book.objects.filter(q_obj).values("id","kucun","maichu")
  24. print(ret)

  

结果如下

  1. <QuerySet [{'id': 4, 'kucun': 1012, 'maichu': 299}, {'id': 9, 'kucun': 4010, 'maichu': 19}]>

  

9、一对一操作

我们可以把一张表中不常用的字段,或者不重要的字段放在另外一张表中,比如我们通过qq去登录第三方的网站,这个时候就可以把一些不重要的字段暴露给第三方网站,而不用把很重要的信息暴漏给第三方网站

先看下我们设计的表

  1. class partent(models.Model):
  2. id = models.AutoField(primary_key=True)
  3. name = models.CharField(max_length=32)
  4. pwd = models.CharField(max_length=32)
  5. details = models.OneToOneField(to="details_info",related_name="reverse_look_partent")
  6.  
  7. class Meta:
  8. unique_together = ("name","pwd")
  9.  
  10. def __str__(self):
  11. return self.name
  12.  
  13. class details_info(models.Model):
  14. sex = models.CharField(max_length=32)
  15. addr = models.CharField(max_length=64,null=True)
  16. phone = models.PositiveIntegerField(unique=True)
  17.  
  18. def __str__(self):
  19. return self.phone

  

如果我们要给表中增加数据,则需要先给details_info表中插入数据,然后在为parent表中插入数据

为details_info表中插入数据

  1. import random
  2. for i in range(5):
  3. models.details_info.objects.create(
  4. sex = "man",
  5. addr = "深圳" + str(random.randint(1,10000)),
  6. phone = random.randint(100000000,900000000)
  7. )

  

在为parent表中插入数据

  1. for i in models.details_info.objects.all().values_list("id"):
  2.  
  3. models.partent.objects.create(
  4. name = "小黑" + str(i[0]),
  5. pwd = "password" + str(random.randint(100000000,900000000)),
  6. details_id = int(i[0]),
  7.  
  8. )

  

最后我们看下一对一的正向和反向查询

分别验证通过对象和query_set对象进行查询

  1. p_obj = models.partent.objects.all().last()
  2.  
  3. print("一对一的正向查询1",p_obj.details.phone)
  4.  
  5. i = models.partent.objects.all().first().id
  6.  
  7. p_obj = models.partent.objects.filter(id=i)
  8.  
  9. print("一对一的正向查询2",p_obj.values("id","name","details__phone"))

  

在看下反向查询

  1. d_obj = models.details_info.objects.all().first()
  2.  
  3. print("一对一的反向查询1",d_obj.reverse_look_partent.name)
  4.  
  5. i = models.details_info.objects.all().last().id
  6.  
  7. d_obj = models.details_info.objects.filter(id=i)
  8.  
  9. print("一对一的反向查询2",d_obj.values("reverse_look_partent__id","reverse_look_partent__name","reverse_look_partent__pwd","sex","addr","phone"))

  

我们重点看下通过query_set对象进行反向查询这里

10、多对多的其他方式,手动创建第三张表的方式,之前学的时候由django为我们创建的第三张表,下面我们我们介绍下由我们自己创建第三张表时间多对多的方式

先看下数据库的表结构,用两个外键来实现多对多

  1. class Student(models.Model):
  2. name = models.CharField(max_length=64)
  3. age = models.PositiveSmallIntegerField()
  4.  
  5. class Meta:
  6. unique_together = ("name","age")
  7.  
  8. def __str__(self):
  9. return self.name
  10.  
  11. class Role(models.Model):
  12. role_name = models.CharField(max_length=63,unique=True)
  13.  
  14. def __str__(self):
  15. return self.role_name
  16.  
  17. class Student2Role(models.Model):
  18. to_student = models.ForeignKey(to="Student")
  19. to_role = models.ForeignKey(to="Role")

  

如果要进行跨表查询,只能去第三张表通过表名去查询

  1. def manytomany(request):
  2. ret = models.Student2Role.objects.filter(to_student_id=1).values_list("to_role")
  3.  
  4. print(ret)
  5.  
  6. ret = [i[0] for i in ret]
  7.  
  8. ret = models.Role.objects.filter(id__in=ret).values_list("role_name")
  9. print(ret)
  10.  
  11. return HttpResponse("manytomany")

  

Django的model操作中一些常用的小点的更多相关文章

  1. django的Model 模型中常用的字段类型

    常用的字段类型: AutoField:自增长字段,通常不用,如果未在Model中显示指定主键,django会默认建立一个整型的自增长主键字段 BooleanField:布尔型,值为True或False ...

  2. 提高django model效率的几个小方法

    django的model效率不是很高,特别是在做大量的数据库操作的时候,如果你只用django来开企业站或者外包项目的话,那可以小跳过下,而你恰巧是效率狂或者说是对程序的效率要求比较高的话,那就要注意 ...

  3. Django之Model操作

    Django之Model操作 本节内容 字段 字段参数 元信息 多表关系及参数 ORM操作 1. 字段 字段列表 AutoField(Field) - int自增列,必须填入参数 primary_ke ...

  4. Python之路【第二十二篇】:Django之Model操作

    Django之Model操作   一.字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bi ...

  5. Django之Model组件

    Model组件在django基础篇就已经提到过了,本章介绍更多高级部分. 一.回顾 1.定义表(类) ##单表 from django.db import models class user(mode ...

  6. Django 07 Django模型基础2 (常用查询和多表关联)

    Django 07 Django模型基础2 (常用查询和多表关联) 一.常用查询 #查找数据 def search_user(request): #获取 rs = User.objects.first ...

  7. django (四) model模型

    models模型 1. models 定义属性 概述 django根据属性的类型确定以下信息 ·当前选择的数据库支持字段的类型 ·渲染管理表单时使用的默认html控件 ·在管理站点最低限度的验证 dj ...

  8. ES6中常用的小技巧,用了事半功倍哦

    ES6中常用的小技巧,如果能在实际项目中能使用到,必定事半功倍: 1. 强制要求参数 ES6提供了默认参数值机制,允许你为参数设置默认值,防止在函数被调用时没有传入这些参数. 在下面的例子中,我们写了 ...

  9. Django的Model上都有些什么

    Django的Model上都有些什么 modelinfo= ['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__' ...

随机推荐

  1. UI5-学习篇-18-云端UI5应用部署到Fiori Launchpad

    UI5应用发布SCP 选择UI5应用项目,右键 Deploy - Deploy to SAP Cloud Platform 输入云平台子账号,项目名称,应用名称,如下图所示: 点击Open the r ...

  2. curator 实现分布式一致性锁

    最近准备在项目中引入分布式锁,故而研究基于zookeeper的curator框架. 网上资料不多,自己研究其源码发现,这个框架已经帮我做了很多现成的实现. 下面介绍下锁的实现: 通过源码中Lockin ...

  3. html lesson one

    Review Congratulations on completing the first lesson of HTML & CSS! You are well on your way to ...

  4. sql中优化查询

    1.在大部分情况下,where条件语句中包含or.not,SQL将不使用索引:可以用in代替or,用比较运算符!=代替not. 2.在没有必要显示不重复运行时,不使用distinct关键字,避免增加处 ...

  5. UGUI的text赋值问题-速度

    仅是简单的给一个ugui.text组件不断的赋值字符串,就会带来很高的CPU消耗,约0.5MS左右. 这个过程主要是消耗在字体的MESH顶点重建. 在游戏中变化的字体一般不多,聊天面板虽然变化,刷新率 ...

  6. 今天折腾phantomjs+selenium的笔记

    1.debian8里安装phantomjs的方法: 参照:http://www.cnblogs.com/lgh344902118/p/6369054.html a.去https://bitbucket ...

  7. echarts.js制作中国地图

    一.准备 1.  打开sublime,新建一个echarts文件夹,新建echarts.html文件 2.  在echarts.html文件中,为ECharts准备一个Dom(id是china-map ...

  8. 修改Http消息的消息头Host

    在 HttpURLConnection 类中直接使用如下代码无法修改Host的值: connection.setRequestProperty("Host", host); 需要在 ...

  9. 阿里支付宝java接口

    网上关于Java支付宝接口的文章很多,都大同小异,但是具体到代码中,还是不太一样,对于以前没有调试的新手来说还是很费解的,这是通过调试认为比较有用的版本,贴在这里供大家参考. 1.从本站提交到支付宝: ...

  10. 10. Lambda表达式.md

    为了简化匿名内部类的代码,具体定义: 例如将9.内部类中的匿名内部类例子: 原来代码: //Main.java public class Main { public static void main( ...