Django学习笔记(5):QuerySet

Django学习笔记(5):QuerySet

在模型中只讲到了一些基本的查询和创建方法,这里专门来讲与数据库操作相关的接口。

从数据库中查询出来的结果一般是一个集合,称为QuerySet。

基于这个blog/models.py作讲解:

 from django.db import models
    
    
    class Blog(models.Model):
        name = models.CharField(max_length=50)
        tagline = models.TextField()
    
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        name = models.CharField(max_length=50)
        email = models.EmailField()
    
        def __str__(self):
            return self.name
    
    
    class Entry(models.Model):
        blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
        headline = models.CharField()
        body_text = models.TextField()
        pub_date = models.DateField()
        mod_date = models.DateField()
        authors = models.ManyToManyField()
        n_comments = models.IntegerField()
        n_pingbacks = models.IntegerField()
        rating = models.IntegerField()
    
        def __str__(self):
            return self.headline

在Django中,对数据库的增删查改操作是通过ORM(Object Relational Mapping,对象关系映射)来操作的。ORM减少了SQL语句的重复率,性能损耗小,使用灵活并具有可移植性。

常用字段类型:

  • CharField:字符串类型,映射到数据库中会转换成varchar类型,使用时必须传入max_length限定最大长度。
  • EmailField:同样是varchar类型,在验证表单的时候会起作用。
  • URLField:varchar类型,不过只能用来存url格式的字符串。
  • FloatField:浮点数类型,映射到数据库会变成double类型
  • IntegerField:整数类型,映射到数据库变成11位int类型
  • BigIntegerField:大整型。值的区间是-9223372036854775808到9223372036854775807。
  • PositiveIntegerField:正整型。值的区间是0到2147483647。
  • SamllIntegerField:小整型。值的区间是-32768到32767。
  • PositiveSmallIntegerField:正小整型。值的区间是0到32767。
  • BooleanField:布尔类型,映射到数据库中会变成长度只有1位的tinyint类型。
  • AutoField:自增长类型,映射到数据库中是11位整数,使用时必须传入peimary_key=True。一个模型不能有两个自增长字段。
  • DateTimeField:日期时间类型,映射到数据库是datetime类型。
  • DateField:日期类型,映射到数据库为date类型。
  • TimeField:时间类型,映射到数据库为time类型。
  • FileField:文件类型。
  • ImageField:图片文件类型。
  • TextField:大量的文本类型。

常用配置:

  • null:标识是否为空,默认为false。
  • blank:标识在表单验证时,该字段是否可以为空,默认为false。
  • db_column:该字段在数据库中的名字。没有设置这个参数的话将会使用模型中属性的名字。
  • db_index:标识这个字段是否为索引字段。
  • default:默认值。可以为一个值或者一个函数。
  • primary_key:是否为主键。默认为false。
  • unique:在表中的字段是否唯一。
  • choice:在一个范围内选出一项。

创建对象

# 方法一
Author.objects.create(name="Marcus",email="[email protected]")

# 方法二
tmp = Author(name="Marcus",email="[email protected]")
tmp.save()

# 方法三
tmp = Author()
tmp.name = "Marcus"
tmp.email = "[email protected]"
tmp.save()

# 方法四
Author.objects.get_or_create(name="Marcus",email ="[email protected]")
# 返回值(object,True/False)

当有一对多,多对一,或者多对多关系的时候,先把相关的对象查询出来。

from blog.models import Entry
entry = Entry.objects.get(pk=1)
cheese_blog = Blog.objects.get(name="Cheddar Talk")
entry.save()

获取对象

Person.objects.all() # 查询所有
Preson.objects.all()[:10] # 切片操作,获取十个人
Person.objects.get(name="Marcus") # 名为Marcus的一条,多条会报错

Person.objects.filter(name="abc") # 名称为(严格等于)abc的人
Person.objects.filter(name__iexact="abc") # 名称为abc,但不区分大小写

Person.objects.filter(name__contains="abc") # 名称中包含abc的人
Person.objects.filter(name__icontains="abc") # 名称中包含abc,但不区分大小写

Person.objects.filter(name__regex="abc") # 正则表达式查询 
Person.objects.filter(name__iregex="abc") # 正则表达式不区分大小写

Person.objects.exclude(name__contains="Marcus") # 排除名字中包含Marcus的对象
Person.objects.filter(name__contains="Marcus").exclude(age=23) # 找出名字中有Marcus,但是排除年龄为23岁

删除对象

Person.objects.filter(name__contains="abc").delete()

# 等于下面的写法
people = Person.objects.filter(name__contains="abc")
people.delete()

更新对象

# 批量更新
Person.objects.filter(name__contains="abc").update(name="xxx")
Person.objects.all().delete()

# 单个Object更新
tmp = Author.objects.get(name="Marcus")
tmp.name = "xxx"
tmp.email = "[email protected]"
tmp.save()

QuerySet特性

QuerySet是可迭代的

es = Entry.objects.all()
for e in es:
		print(e.headline)

注意:

  • 如果只是检查,应使用exist方法
  • QuerySet支持切片操作
  • 推荐使用Entry.objects.count()查询数量
  • list(es)可以强行把QuerySet转换成列表

QuerySet可以通过pickle序列化到硬盘

import pickle
query = pickle.loads(s)
qs = MyModel.objects.all()
qs.query = query

QuerySet查询结果排序

Author.objects.all().order_by('name') # 作者按照名称排序
Author.objects.all().order_by('-name') # 加上负号,实现倒序排序

QuerySet支持链式查询

Author.objects.filter(name__contains="Marcus").filter(email="[email protected]")

Person.objects.filter(name__contains="abc").exclude(age=23)

QuerySet不支持负索引

Person.objects.all()[:10] # 切片操作
Person.objects.all()[-10:]  # 报错

# 解决方法
# 1. 使用reverse()方法
Person.objects.all().reverse()[:2]
Person.objects.all().reverse()[0]

# 2. 使用order_by
Author.objects.order_by('-id')[:20]

QuerySet使用.distinct()去重

你可能感兴趣的:(python,django)