骄傲的赛亚人

day7-django数据库操作

数据库操作

为了方便调试,django开发了一个命令shell,通过python manage.py shell 进入解释器,它会自动的导入当前项目的所有环境变量

注意:要安装ipython方便调试

 

创建对象

模型类代表数据表,模型实例代表数据表中的一条记录

所有创建一个对象,用关键字初始化,然后调用save()就是保存到数据库

1 from crm.models import Student
2 s = Student(name='xinlan', age=18)
3 s.save()

这里幕后,django执行INSERTSQL语句。Django在你显示的调用save()的时候才会操作数据库。

更行对象

要将修改保存至数据库中某个已存在的对象,使用save()

s.age = 19
s.save()

 

指定要更行的字段

默认情况下save方法执行update的时候会全字段更新,效率不高

可以传递一个字段列表给关键字参数update_fields,那么只有列表中指定的字段才会被更新,当只更新一个对象上的一个或几个字段的时候,可以使用这个字段。有轻微的性能优势

s.age=19

s.save(update_fields=["age"])  # 指定只更新age字段

 

一次更新多个字段

想要一次更新多个字段,需要再查询集上调用updae,例如

Student.objects.all()update(sex=0) --------慎用

注意:update不会调用对象上的save()方法,如果对象多个对象,又想执行save,可以迭代每个对象,分别调用save,update是一条语句

什么时候是插入,什么时候是更新

当对象有pk属性的时候,这时调用save就是更新,否则就是插入


 

 

查询对象

管理器

要从数据库去检索对象,需要通过模型类的Manage构建一个QuerySet。每个模型至少有一个管理器,默认名称是objects,例如:

Student.objects

注意:通过模型对象不能直接访问管理器

QuerySet(查询集)

一个QuertSet代表来自数据库中对象的一个集合,它可以被迭代,切片,可以正整数索引(不支持负索引),可以通过list转换为列表。在sql层面对应的是一条select语句

检索全部对象

在管理器上调用all方法

s=Student.objects.all()

方法all()返回一个包含数据库表所有对象的QuerySet对象

过滤

在管理器上调用下面两个方法,可以对queryset进行过滤

filter(**kwargs)

  返回一个新的queryset,包含的对象满足给定的查询参数

 

exclude(**kwargs)

  返回一个新的queryset,包含的对象不满足给定的查询参数

例如:

查询名字叫tom的

  qs = Student.objects.filter(name="tom")  

  第二种写法:qs = Student.objects.filter(name="tom")

查询名字不叫tom的

  qs = Student.objects.exclude(name="tom")

检索单个数据

这些方法都是返回queryset,即使只有一个对象,也是返回queryset。如果要获取单个好需要进行索引

get(**kwargs)

  获取一个对象,如果对象不存在会报错,存在多个对象也会保存。一般用pk这个条件

s = Student.objects.get(pk=1)

s = Student.objects.get(name="tom")

first()

  Student.objects.first()

  返回查询集的第一个对象

last()

  Student.objects.last()

  返回查询集的最后一个对象

排序

默认情况下,django会按照主键进行排序,可以通过在模型的Meta属性中定义默认排序

class Student(models.Model):  # 必须继承
    ......
    
    class Meta:
        ......
        ordering = ["age"]  # 根据年龄排序从小到大   [-age]从大到小

模型中的排序是默认的,在查询集上可以主动调用排序

order by(*fields)

根据给定的字段进行排序,字段名字前加负号表示desc,

  Student.objects.all().order_by("-age","name")

查询年龄最小的学生

  StudentStudent.objects.all().order_by("age").first()

切片

使用序列的切片语法来获取查询集的部分数据,它等价于sql中的limit,offset子句

获取前5条

  StudentStudent.objects.all()[:5]

获取3,4条数据

  StudentStudent.objects.all()[2:5]   # 等价于limit 3 offset 2

queryset惰性计算

查询集为了多次过滤,需要提高性能,它是惰性计算,也就意味着只是取值的时候才回去数据库中查询数据

  1. 迭代queryset
  2. 对queryset进行索引
  3. 在命令行输出
  4. print

注:一个查询集在进行上面的操作时,才会去数据库获取数据

选择字段查询

在上面的查询中,都是查询所有的字段

  • values(fields):

   返回一个queryset,这个queryset返回的是字典列表,而不是数据对象,参数fields指定在select语句中想要查询的字段,返回的字段会包含指定的字段,如果不指定字段,会返回所有字段

Student.objects.values("name")

 

  • only(fields):

  返回一个queryset,这个queryset返回的是对象列表。fields指定我们在select语句中想要查询的字段,即使不指定主键字段,对象中也一定包含主键字段

Student.objects.only("name")

 

  • defer(fields):

  它的机制和only相同,只是筛选逻辑相反,参数fields指定在select语句中想要排除的字段,对象中也一定会包含主键

Student.objects.defer("name")

 

条件查询

在filter、exclude、get中可以接受参数实现各种比较条件的查询

  • exact精确匹配,在字段后面加 __exact
Student.objects.filter(name__exact="tom")
Student.objects.filter(namet="tom")  #  exact一般会省略掉
  • iexact:不区分大小写
Student.objects.filter(level__iexact="A")   #  匹配level为a和A的学生
  • gt:大于
Student.objects.filter(age__gt=18) # 查询年龄大于18的学生 
  • lt:大于
Student.objects.filter(age__lt=18) # 查询年龄小于18的学生
  • gte:大于等于
Student.objects.filter(age__gte=18) # 查询年龄大于等于18的学生
  • lte:大于等于
Student.objects.filter(age__lte=18) # 查询年龄小于等于18的学生
  • range:范围
Student.objects.filter(age__range=(18,30))  # 查询年龄大于18小于30的学生,等价于between  and
  • in:离散范围
Studetn.objects.filter(age__in=(18,20,22,30))  # 查询年龄在18,20,22,30范围内的学生

:更多内容见官方文档 https://docs.djangoproject.com/zh-hans/3.2/ref/models/querysets/#field-lookups

 

条件组合

  • AND

  使用sql AND操作符将两个QuerySet组合起来

# 查询18岁以上的男生
#  第一种
Student.objects.filter(sex=1,age__gt=18)
#  第二种
Student.objects.filter(sex=1) & Student.objects.filter(age__gt=18)
#  第三种
from django.db.models from Q
Student.objects.filter(Q(sex=1)) & Q(age__gt=18)
  • OR

  使用sql OR操作符将两个QuerySet组合起来

#  查询大于18岁,或者小于13岁的学生
# 第一种
Student.objects.filter(age__gt=18) | Student.objects.filter(age__lt=13)
# 第二种
from django.db.models import Q
Student.objects.filter(Q(age__gt=18)) | Q (age__lt=13)

聚合查询

  • count

  在查询集上直接使用count方法,会返回记录的条数

# 查询女生的人数
Student.objects.filter(sex=0).count()
  • avg

  使用平均值函数,需要在查询集上调用aggregate方法

# 计算学生的平均年龄
from django.db.models import Avg
Student.objects.all().aggregate(Avg("age"))
#  输出:{'age__avg': 19.0}
Student.objects.all().aggregate(ageavg=Avg("age"))  # 通过关键字指定字段名
#  输出:{'ageavg':19.0}
  • max
from django.db.models import Max
# 查询年龄最大的学生
Student.objects.all().aggregate(Max('age'))
# 输出:{'age_max':19}
  • min
from django.db.models import Min
# 查询年龄最小的学生
Student.objects.all().aggregate(Min('age'))
  • sum
from django.db.models import Sum
# 查询所有人年龄的总和
Student.objects.all().aggregate(Sum('age'))

分组

  • annotate

  上面的聚合是不分组聚合,要在每个对象上增加聚合字段,需要利用分组

  按字段分组需要用valuesannotate配合

# 查询男女生各有多少人
Student.objects.values('sex').annotate(Count('sex'))
Student.objects.values('sex').annotate(Count('sex')).order_by()
# 查询男女生的平均年龄
Student.objects.values("sex").annotate(Avg("age")).order_by()
# 查询男女生年龄最大的人
Student.objects.values("sex").annotate(Max("age")).order_by()

注意:排序会有影响,如果模型有了排序后,需要在命令后面加上order_by()去掉排序

 

posted on 2022-06-10 10:36  骄傲的赛亚人  阅读(111)  评论(0编辑  收藏  举报

导航