以下述模型为基础,讨论检索对象的方式方法:
from datetime import datefrom django.db import modelsclass Blog(models.Model):name = models.CharField(max_length=100)tagline = models.TextField()def __str__(self):return self.nameclass Author(models.Model):name = models.CharField(max_length=200)email = models.EmailField()def __str__(self):return self.nameclass 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()mod_date = models.DateField(default=date.today)authors = models.ManyToManyField(Author)number_of_comments = models.IntegerField(default=0)number_of_pingbacks = models.IntegerField(default=0)rating = models.IntegerField(default=5)def __str__(self):return self.headline
比较对象
要比较两个模型实例,使用标准的 Python 比较操作符
,两个等号: ==
。实际上,这比较了两个模型实例的主键值。
示例如下,两个比较是等效的。需要注意的是,有的情况下模型的主键可能不是id
,可能是别的字段名称,但本质都是在比较主键。
>>> some_entry == other_entry>>> some_entry.id == other_entry.id
删除对象
删除单个对象实例
删除方法方便地被命名为delete()
。这个方法立即删除对象并返回被删除的对象数以及一个包含每种对象类型的删除数的字典。
>>> e.delete()(1, {'blog.Entry': 1})
批量删除对象实例
所有 QuerySet
都有个 delete()
方法,它会删除 QuerySet
中的所有成员。
>>> Entry.objects.filter(pub_date__year=2005).delete()(5, {'webapp.Entry': 5})
要删除某个模型的所有对象,要查询得到包含所有对象的 QuerySet
,在QuerySet
上使用 delete()
方法
Entry.objects.all().delete()
如何复制模型实例
新建一个模型实例,保存后,将 pk 设置为 None 并将 _state.adding 设置为 True,再次保存就实现了“复制”。
blog = Blog(name="My blog", tagline="Blogging is easy")blog.save()# blog.pk == 1blog.pk = Noneblog._state.adding = Trueblog.save()# blog.pk == 2
如果模型继承自另一个模型,则还要将id设置为None。
class ThemeBlog(Blog):theme = models.CharField(max_length=200)django_blog = ThemeBlog(name="Django", tagline="Django is easy", theme="python")django_blog.save()# django_blog.pk == 3django_blog.pk = Nonedjango_blog.id = Nonedjango_blog._state.adding = Truedjango_blog.save()# django_blog.pk == 4
如果模型还有 ManyToManyField 关联关系,OneToOneField 关联关系,要重新配置。
批量修改对象
通过 update()
统一设置 QuerySet
中的所有对象的某个字段。注意此方法设置非关联字段和 ForeignKey
字段。要更新非关联字段,请将新值提供为常数。要更新 ForeignKey
字段,请将新值设置为要指向的新模型实例。
# 更新所有pub_date在2007年的Entry,headline修改为"Everything is the same"。Entry.objects.filter(pub_date__year=2007).update(headline="Everything is the same")
update()
方法会立即应用,并返回查询匹配的行数。
对于要更新的 QuerySet
唯一的限制是它只能访问一个数据库表:模型的主表。您可以基于相关字段进行过滤,但只能更新模型的主表中的列。
对于调用 update 的情况,还可以使用 F 表达式 来根据模型中另一个字段的值来更新字段。这在根据当前值增加计数器时特别有用。例如,要增加博客中每篇文章的 pingback 计数:
>>> Entry.objects.update(number_of_pingbacks=F("number_of_pingbacks") + 1)
在更新中使用 F() 对象时,不能引入连接。