本文讲解Django在数据库方面的基本使用。
基本查询
有时候,我们查询数据时并不需要该数据的全部字段,这个时候可以使用values
或values_list
,它们的区别在于:
values
方法可以获取指定字段的字典列表values_list
方法获取指定字段的元组列表,当加上参数flat=True
时,可以获取指定字段的值列表
使用示例:
YourModel.objects.values('field1', 'field2')
YourModel.objects.values_list('field', flat=True)
当对象与另一个对象存在一对一的关系时,如果想同时查找到关联对象,可以使用select_related(*fields)
方法。
下面是官方文档的说明:
# Hits the database.
e = Entry.objects.get(id=5)
# Hits the database again to get the related Blog object.
b = e.blog
# Hits the database.
e = Entry.objects.select_related('blog').get(id=5)
# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog
filter() 和 select_related() 的顺序不重要。下面两个语句是等价的。
Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog')
Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now())
F() 对象
一个 F() 对象表示一个模型属性的值。
不使用F()对象时,可能是这样:
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1
reporter.save()
但是使用F()对象后,就变成:
from django.db.models import F
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()
这种方法是在数据库层面操作的,因此不需要把stories_filed的值载入内存再进行运算。
使用这种方法后,要想获得保存后的新值,需重新载入:
reporter.refresh_from_db()
除了应用在单个实体上,F() 也可以用在多个实体上:
Reporter.objects.all().update(stories_filed=F('stories_filed') + 1)
Q对象
使用django的Q对象可以做一些复杂查询。例如,下面的语句表示LIKE查询:
from django.db.models import Q
Q(question__startswith='What')
Q对象之间可以使用 & 和 | 进行组合。同时,当Q对象前面有 ~ 符号时,表示否定。
查询函数可以同时使用Q对象和关键字参数,但是Q对象必须在关键字参数前面。
比如,下面做法是正确的:
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who',
)
但是下面的代码就不正确了:
# INVALID QUERY
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
自定义SQL
Django可以使用如下方法执行自定义SQL:
Manager.raw(raw_query, params=None, translations=None)
这个方法执行一个原始SQL(raw_query),返回一个RawQuerySet
实例。
raw方法自动映射查询中的字段到模型字段,因此查询中的字段的顺序是无所谓的。
你也可以执行模型中没有包含的字段的查询,查询依然可以成功,并且可以访问到该字段,如下:
people = Person.objects.raw('SELECT *, age(birth_date) AS age FROM myapp_person')
for p in people:
print("%s is %s." % (p.first_name, p.age))
向raw
传递参数的方式如下:
lname = 'Doe'
Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])
分页查询
要进行分页查询时,可以使用django.core.paginator.Paginator
,如下:
models = Model.objects.all()
paginator = Paginator(models, pagesize)
result = paginator.page(page) # page从1开始,代表第几页
paginator还有其他一些属性,比如paginator.count
表示总记录数,paginator.num_pages
表示总页数
要向客户端返回result的json结果时,可以使用如下方式:
from django.core import serializers
from django.http import JsonResponse
import json
response = {}
services = SystemService.objects.all()
paginator = Paginator(services, pageSize)
response['total'] = paginator.count
try:
result = paginator.page(page)
except PageNotAnInteger:
result = paginator.page(1)
except EmptyPage:
result = paginator.page(paginator.num_pages)
response['result'] = json.loads(serializers.serialize("json", result.object_list))
return JsonResponse(response)
实体更新
Django更新一个model的做法非常简单,首先将要更新的属性及其新值写在一个dict
中,然后调用model.__dict__.update(**data)
,最后调用save
方法保存到数据库中即可,示例如下:
data = {
'name': 'test'
}
old = MyModel.objects.get(id=1)
old.__dict__.update(**data)
old.save()