Skip to content

Latest commit

 

History

History
204 lines (186 loc) · 6.44 KB

查询.md

File metadata and controls

204 lines (186 loc) · 6.44 KB

1.模型

from django.db import models
import datetime
class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField()

    def __str__(self):
        return self.name

class Entry(models.Model):
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField(default=datetime.datetime.now())
    mod_date = models.DateField(default=datetime.datetime.now())
    authors = models.ManyToManyField(Author)
    number_of_comments = models.IntegerField(default=0)
    number_of_pingbacks = models.IntegerField(default=0)
    rating = models.IntegerField(default=0)

    def __str__(self):
        return self.headline

1.创建对象

django在调用save()方法时才操作数据库。

>>> blog1 = Blog(name='blog1', tagline='blog1 tagline')
>>> blog1.save()

2.执行更新

修改对象的属性,然后调用save()方法,执行数据库更新操作。

>>> blog1.name = 'b1'
>>> blog1.save()
>>> Blog.objects.all()
<QuerySet [<Blog: b1>]>

保存 ForeignKey 和 ManyToManyField 字段

ForeignKey

更新ForeignKey字段的方式与保存普通字段的方式相同——只需将正确类型的实例分配给相关字段

>>> entry1 = Entry(headline='entry1 headline')
>>> entry1.blog = Blog.objects.get(pk=1)
>>> entry1.save()

ManyToManyField

在字段上使用 add() 方法为关联关系添加一条记录.

>>> author1 = Author(name='author1')
>>> author2 = Author(name='author2')
>>> author1.save()
>>> author2.save()
>>> entry1.authors.add(author1, author2)
>>> entry1.save()

3.检索对象

  • 要从数据库检索对象,需要通过模型类的Manager构建一个QuerySet
  • 一个QuerySet代表来自数据库中对象的集合。
  • QuerySet对应select语句,filter对应where条件语句。
  • 每个模型至少拥有一个Manager,默认名称是objects。

检索全部对象

>>> Entry.objects.all()
<QuerySet [<Entry: entry1 headline>]>
>>> Blog.objects.all()
<QuerySet [<Blog: b1>, <Blog: blog2>]>

通过过滤器检索指定对象

  • filter():返回一个QuerySet,其中包含的对象满足指定的查询条件。
  • exclude():返回一个QuerySet,其中包含的对象 不满足指定的查询条件。
>>> Entry.objects.all().filter(pub_date__year=2020)
<QuerySet [<Entry: entry1 headline>]>

链式过滤:QuerySet过滤的结果还是QuerySet,所以可以串联执行过滤。

>>> Entry.objects.all().filter(pub_date__year=2020).filter(pk=1)
<QuerySet [<Entry: entry1 headline>]>

每个QuerySet都是唯一的,之间互不影响。

>>> q1 = Entry.objects.filter(headline__startswith="What")
>>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
>>> q3 = q1.filter(pub_date__gte=datetime.date.today())

每个QuerySet都是惰性的

创建QuerySet不会引发数据库操作,django只会在QuerySet被计算的时候执行查询操作,如下,实际只在print(q)的时候,才通过数据库操作计算出QuerySet

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

使用get()检索单个对象

使用get()获取对象时,如果没有满足条件的对象,会引发DoesNotExist异常。

>>> Entry.objects.get(pk=1)
<Entry: entry1 headline>

限制QuerySet条目数

不支持负索引

>>> Blog.objects.all()[:5]
<QuerySet [<Blog: b1>, <Blog: blog2>]>

字段查询(where语句)

通过关键字参数的形式(field__lookuptype=value)传递给QuerySet的filter(),get()等方法。比如:

Entry.objects.get(headline__contains='Lennon')
# 等价于 SELECT ... WHERE headline LIKE '%Lennon%';
常用的lookuptype:
  • exact:完全匹配。
  • iexact:不区分大小写的完全匹配。
  • contains:等价于like语句。
  • in:等价于in语句。
Entry.objects.filter(id__in=[1, 3, 4])
# SELECT ... WHERE id IN (1, 3, 4);
inner_qs = Blog.objects.filter(name__contains='Cheddar')
entries = Entry.objects.filter(blog__in=inner_qs)
# 等价 SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')
  • gt: 大于。
  • gte: 大于或等于。
  • lt: 小于。
  • lte: 小于或等于。
  • startswith:同python str.startswith(),区分大小写。
  • istartswith: 同python str.startswith(),不区分大小写。
  • endswith/iendswith: 原理同上。
  • range:
import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))
  • 其他date,year,month,week,day等。

跨关系查询

# 通过blog的条件查询指定的entry
>>> Entry.objects.filter(blog__name='b1')
<QuerySet [<Entry: entry1 headline>]>
# 通过entry的条件反向查找blog
>>> Blog.objects.filter(entry__headline='entry1 headline')
<QuerySet [<Blog: b1>]>

同一个模型中不同字段比较(F())

>>> from django.db.models import F
>>> from datetime import timedelta
# 返回所有发布 3 天后被修改的条目
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

通过Q对象完成复杂查询

from django.db.models import Q
Q(question__startswith='Who') | Q(question__startswith='What')
# 等价 WHERE question LIKE 'Who%' OR question LIKE 'What%'

Poll.objects.get(
    Q(question__startswith='Who'),
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
# 等价 SELECT * from polls WHERE question LIKE 'Who%' AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

删除对象

Entry.objects.filter(pub_date__year=2005).delete()

更新对象

Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

一对多关联查询

# 若模型有个 ForeignKey
>>> e = Entry.objects.get(id=2)
>>> e.blog

# 模型中没有 ForeignKey 反向查找
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all()