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
django在调用save()方法时才操作数据库。
>>> blog1 = Blog(name='blog1', tagline='blog1 tagline')
>>> blog1.save()
修改对象的属性,然后调用save()方法,执行数据库更新操作。
>>> blog1.name = 'b1'
>>> blog1.save()
>>> Blog.objects.all()
<QuerySet [<Blog: b1>]>
更新ForeignKey字段的方式与保存普通字段的方式相同——只需将正确类型的实例分配给相关字段
>>> entry1 = Entry(headline='entry1 headline')
>>> entry1.blog = Blog.objects.get(pk=1)
>>> entry1.save()
在字段上使用 add() 方法为关联关系添加一条记录.
>>> author1 = Author(name='author1')
>>> author2 = Author(name='author2')
>>> author1.save()
>>> author2.save()
>>> entry1.authors.add(author1, author2)
>>> entry1.save()
- 要从数据库检索对象,需要通过模型类的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>]>
>>> 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不会引发数据库操作,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()获取对象时,如果没有满足条件的对象,会引发DoesNotExist异常。
>>> Entry.objects.get(pk=1)
<Entry: entry1 headline>
不支持负索引
>>> Blog.objects.all()[:5]
<QuerySet [<Blog: b1>, <Blog: blog2>]>
通过关键字参数的形式(field__lookuptype=value)传递给QuerySet的filter(),get()等方法。比如:
Entry.objects.get(headline__contains='Lennon')
# 等价于 SELECT ... WHERE headline LIKE '%Lennon%';
- 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>]>
>>> from django.db.models import F
>>> from datetime import timedelta
# 返回所有发布 3 天后被修改的条目
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
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()