django 数据库查询

class Poll(models.Model):

slug = models.SlugField(unique_for_month=‘pub_date‘)
question = models.CharField(maxlength=255)
pub_date = models.DateTimeField()
expire_date = models.DateTimeField()

def __repr__(self):
return self.question

class Meta:
get_latest_by = ‘pub_date‘

class Choice(models.Model):
poll = models.ForeignKey(Poll, edit_inline=models.TABULAR,
num_in_admin=10, min_num_in_admin=5)
choice = models.CharField(maxlength=255, core=True)
votes = models.IntegerField(editable=False, default=0)

def __repr__(self):
return self.choice

及下面的简单会话:

>>> from datetime import datetime
>>> p1 = Poll(slug=‘whatsup‘, question="What‘s up?",
... pub_date=datetime(2005, 2, 20), expire_date=datetime(2005, 4, 20))
>>> p1.save()
>>> p2 = Poll(slug=‘name‘, question="What‘s your name?",
... pub_date=datetime(2005, 3, 20), expire_date=datetime(2005, 3, 25))
>>> p2.save()
>>> Poll.objects.all()
[What‘s up?, What‘s your name?]

查询如何运作

Django 的数据查询基于构建结果集及对结果集进行取值. 结果集是独立于数据库的符合某个查询条件的一组数据对象的集合.这是一个惰性集合:在对该集合取值之前,无法知道该集合有哪些成员.

要生成一个满足你需求的结果集,首先要得到一个描述给定类型的所有对象的初始结果集.这个初始结果集可以通过一系列函数进行更精细的优化处理.当经 过处理后的结果集符合你的要求时, 就可以对它进行取值操作(使用迭代操作,slicing操作,或一系列其它技术), 以得到一个你需要的对象或对象的列表.
获得初始结果集

每个 Django model 都有一个与生俱来的管理器对象 objects, 管理器最重要的角色就是作为初始结果的来源. 一个管理器就是一个描述给定类型所有对象的特殊的初始结果集. Poll.objects 就是包含所有 Poll 对象的一个初始结果集. 它唯一特殊之处在于它不能被取值. 要克服此限制, 管理器对象有一个 all() 方法. 该方法生成一个 可以 被取值的初始结果集的拷贝:

all_polls = Poll.objects.all()

参阅 Model API 的 Managers 小节以了解管理器的定位及创建细节.
优化定制结果集

管理器提供的初始结果集描述了给定类型的所有对象.不过通常你只需要这个对象集合中的一小部分(一个子集).

要生这样一个结果集,你需要对初始结果集进行优化定制处理, 增加一些限制条件直到描述的子集满足你的需要.最常用的两个定制结果集的方法是:

filter(**kwargs)
返回一个匹配查询参数的新的结果集.
exclude(**kwargs)
返回一个不匹配查询参数的新的结果集.

参数格式在下面 "字段查询" 小节有描述.

这两个方法的返回值都是结果集对象,因此结果集可以进行链式处理:

Poll.objects.filter(
question__startswith="What").exclude(
pub_date__gte=datetime.now()).filter(
pub_date__gte=datetime(2005,1,1))

...以一个初始结果集作为参数, 然后进行过滤, 再进行排除, 再进行另一个过滤. 这样得到的最终结果就一个问题开头单词是 "What", 发布日期在 2005年1月1日至今的所有民意测验的集合.

每个结果集都是一个独一无二的对象. 以上操作的每一步都生成了一个新的结果集:

q1 = Poll.objects.filter(question__startswith="What")
q2 = q1.exclude(pub_date__gte=datetime.now())
q3 = q1.filter(pub_date__gte=datetime.now())

这三步生成了三个结果集; 一个初始结果集包含所有的以"What"开头的民意测验, 两个初始结果集的子集(一个排除条件,一个过滤条件).对原始结果集的改进过程并没有影响到原始的结果集.

值得注意的是结果集的创建根本没有访问数据库.只有当对结果集取值时才会访问数据库.
字段查询

以 field__lookuptype (注意是双下线)形式进行基本的字段查询,举例来说:

polls.objects.filter(pub_date__lte=datetime.now())

该查询翻译成SQL就是:

SELECT * FROM polls_polls WHERE pub_date <= NOW();

实现细节

Python 能够在定义函数时接受任意的 name-value(names和values均可以在运行时通过计算得到)参数. 要了解更多信息,参阅官方 Python 教程中的 关键字参数 .

DB API 支持下列查找类型:

类型 描述
exact 精确匹配: polls.get_object(id__exact=14).
iexact 忽略大小写的精确匹配: polls.objects.filter(slug__iexact="foo") 匹配 foo, FOO, fOo, 等等.
contains 大小写敏感的内容包含测试: polls.objects.filter(question__contains="spam") 返回question 中包含 "spam" 的所有民意测验.(仅PostgreSQL 和 MySQL支持. SQLite 的LIKE 语句不支持大小写敏感特性. 对Sqlite 来说, contains 等于 icontains.)
icontains 大小写不敏感的内容包含测试:
gt 大于: polls.objects.filter(id__gt=4).
gte 大于等于.
lt 小于.
lte 小于等于.
ne 不等于.
in 位于给定列表中: polls.objects.filter(id__in=[1, 3, 4]) 返回一个 polls 列表(ID 值分别是 1或3或4).
startswith 大小写敏感的 starts-with: polls.objects.filter(question__startswith="Would").(仅PostgreSQL 和MySQL支持. SQLite 的LIKE 语句不支持大小写敏感特性. 对Sqlite 来说,``startswith`` 等于 istartswith)
endswith 大小写敏感的 ends-with. (仅PostgreSQL 和 MySQL)
istartswith 大小写不敏感的 starts-with.
iendswith 大小写不敏感的 ends-with.
range 范围测试: polls.objects.filter(pub_date__range=(start_date, end_date)) 返回 pub_date 位于 start_date 和 end_date (包括)之间的所有民意测验
year 对 date/datetime 字段, 进行精确的 年 匹配: polls.get_count(pub_date__year=2005).
month 对 date/datetime 字段, 进行精确的 月 匹配:
day 对 date/datetime 字段, 进行精确的 日 匹配:
isnull True/False; 做 IF NULL/IF NOT NULL 查询: polls.objects.filter(expire_date__isnull=True).

如果未提供查找类型, 系统就认为查找类型是 exact . 下面两个语句是等价的:

Poll.objects.get(id=14)
Poll.objects.get(id__exact=14)

查询允许多个条件参数, 逗号分隔的多个条件参数会被 "AND" 起来使用:

polls.objects.filter(
pub_date__year=2005,
pub_date__month=1,
question__startswith="Would",
)

...得到2005年1月公布的带有一个"Would"开头的问题的所有民意测验.

为了使用更加方便, 还提供有一个 pk 查找类型, 可以翻译成 (primary_key)__exact. 在这个民意测试的例子里, 下面两个语句是等价的.:

polls.get_object(id__exact=3)
polls.get_object(pk=3)

pk 也可以通过连接进行查询. 在这个民意测试的例子里, 下面两个语句是等价的:

choices.objects.filter(poll__id__exact=3)
choices.objects.filter(poll__pk=3)

如果传递的关键字参数非法, 将引发 TypeError 异常.
OR 查询

关键字参数查询的各个条件都是 "AND" 关系. 如果你需要一个复杂的查询(举例来说,你需要一个 OR 语句), 你需要使用 Q 对象.

Q 对象是 django.core.meta.Q 的实例, 用来装载一系列关键字参数. 这些关键字参数就象指定给 get() 和 filter() 函数的关键字参数一样. 举例来说:

Q(question__startswith=‘What‘)

Q 对象可以使用 & 和 | 运算符进行组合. 当两个Q对象进行 & 或 | 运算时,会生成一个新的Q对象.举例来说语句:

Q(question__startswith=‘Who‘) | Q(question__startswith=‘What‘)

... 生成一个新的 Q 对象表示这两个 "question__startswith" 查询条件的 "OR" 关系. 等同于下面的 SQL WHERE 子句:

... WHERE question LIKE ‘Who%‘ OR question LIKE ‘What%‘

通过对多个 Q 对象的 & 和 | 运算你能得到任意复杂的查询语句. 也可以使用圆括号分组.

查询函数可以接受一个或多个 Q 对象作为参数.如果提供有多个 Q 对象参数, 它们将被 "AND" 到一起. 举例来说:

polls.get_object(
Q(question__startswith=‘Who‘),
Q(pub_date__exact=date(2005, 5, 2)) | Q(pub_date__exact=date(2005, 5, 6))
)

... 翻译成 SQL 就是这样:

SELECT * from polls WHERE question LIKE ‘Who%‘
AND (pub_date = ‘2005-05-02‘ OR pub_date = ‘2005-05-06‘)

如果需要,查询函数可以混合使用 Q 对象参数和关键字参数. 所有提供给查询函数的参数(不管是关键字参数还是Q对象)都被 "AND" 到一起. 如果提供了 Q 对象作为参数,它就必须在其它关键字参数(如果有的话)的前面. 举例来说:

polls.get_object(
Q(pub_date__exact=date(2005, 5, 2)) | Q(pub_date__exact=date(2005, 5, 6)),
question__startswith=‘Who‘)

... 这是一个合法的查询, 等价于前一个例子,不过:

# INVALID QUERY
polls.get_object(
question__startswith=‘Who‘,
Q(pub_date__exact=date(2005, 5, 2)) | Q(pub_date__exact=date(2005, 5, 6)))

... 这个查询则不符合我们的规则,会引发异常.

Q 对象也可以以 complex 关键字参数的形式使用. 举例来说:

polls.get_object(
complex=Q(question__startswith=‘Who‘) &
(Q(pub_date__exact=date(2005, 5, 2)) |
Q(pub_date__exact=date(2005, 5, 6))
)
)

参阅 OR 查询示例 以阅读更多实例.
从结果集中取值

只有通过取值操作才能得到结果集包含的对象.取值操作可以通过迭代,切片,或其它专门的函数来实现.

一个结果集就是一个可迭代对象.因此,可以通过一个循环来取出它的值:

for p in Poll.objects.all():
print p

将使用 Poll 对象的 __repr__() 方法打印出所有的 Poll 对象.

一个结果集也可以被切片, 使用数组符号操作:

fifth_poll = Poll.objects.all()[4]
all_polls_but_the_first_two = Poll.objects.all()[2:]
every_second_poll = Poll.objects.all()[::2]

结果集对象是惰性对象 - 也就是说,他们不是 真正的 包含他们表示对象的集合 (或列表). Python 的协议魔法让结果集看起来是一个可迭代,可切片的对象. 事实上在幕后, Django 使用了缓存技术..

如果你真的需要一个列表, 你可以强制对一个惰性对象取值:

querylist = list(Poll.objects.all())

不过,最好不要这么做,尤其当一个结果集相当大时. 由于 Django 要创建每一个对象的内存表示,这将占用相当大的内存.
结果集及其缓存行为

每个结果集都包含一个 cache. 对一个新创建的结果集来说, 缓存区是空的.当一个结果集第一次被取值, Django 会进行一次数据库查询,并将查询结果放入缓存中, 之后返回用户需要的数据. 后面的取值操作会使用缓存中的数据而不用再次访问数据库.

必须时刻记住:结果集具有缓存行为. 下面两行语句生成了两个临时的结果集,并进行了取值,之后舍弃:

print [p for p in Poll.objects.all()] # Evaluate the Query Set
print [p for p in Poll.objects.all()] # Evaluate the Query Set again

对一个小型的,低流量的站点来说,这不会造成严重问题.不过,对一个高访问量的站点来说,它双倍增加了数据库服务器的负担.另外,由于在两次操作之间可能有其它的用户增加或删除了投票,因此这两次操作得到结果可能并不相同.

要避免这个问题, 保存这个结果集并在后面重用该结果集:

queryset = Poll.objects.all()
print [p for p in queryset] # Evaluate the query set
print [p for p in queryset] # Re-use the cache from the evaluation

专门的结果集取值函数

下面这些函数也可以用来从一个结果集中取值.不同于迭代及切片操作,这些方法不具有缓存行为.每次使用这些函数,都会访问数据库.
get(**kwargs)

以下文描述的 "字段查询" 格式返回匹配查找参数的对象.如果没有找到符合给定参数的对象,会引发一个模块级的 DoesNotExist 异常. 如果找到不止一个对象,引发 AssertionError 异常.
count()

返回结果集的行数.``count()`` 永远不会引发异常.

根据你使用的数据库引擎 (比如 PostgreSQL vs. MySQL), 它可能返回一个长整数而不是普通整数.
in_bulk(id_list)

接受一个 ID 列表作为参数, 返回一个字典(每个ID映射一个具有给定ID的对象实例). 也接受可选的关键字查询参数(参数格式在下面 "字段查询" 小节有描述),这里有一个例子,使用上面定义的 Poll model.

>>> Poll.objects.in_bulk([1])
{1: What‘s up?}
>>> Poll.objects.in_bulk([1, 2])
{1: What‘s up?, 2: What‘s your name?}
>>> Poll.objects.in_bulk([])
{}

latest(field_name=None)

根据 model 的 ‘get_latest_by‘ 选项或可选的字段名参数返回最新的对象. 例子:

>>> Poll.objects.latest()
What‘s up?
>>> Poll.objects.latest(‘expire_date‘)
What‘s your name?

关系 (连接)

当你在 model 中定义了一个关系字段(也就是,一个ForeignKey, OneToOneField, 或 ManyToManyField). Django 使用关系字段的名字为 model 的每个实例添加一个 描述符. 在访问对象或关联对象时, 这个描述符就象一个常规属性. 举例来说, mychoice.poll 会返回 Choice 实例对象关联的 Poll 对象.

通过下面的关系,连接可以以非显式的方式进行: choices.objects.filter(poll__slug="eggs") 得到一个 Choice 对象列表, 这些对象关联的 Poll 对象的 slug 字段值为 eggs. 允许多级连接.

通过一个对象实例的便利函数(convenience functions)就可直接查询该对象的关联对象. 举例来说, 如果 p 是一个 Poll 实例, p.choice_set() 将返回所有关联的 Choice 对象列表. 聪明的读者会注意到它等价于 choices.objects.filter(poll__id=p.id), 只是更加清晰.

每一种关系类型会为关系中的每个对象自动创建一系列便利方法(类似 choice_set() 这样的方法).这些方法被双向创建, 这样被关联的对象就不需要明确的定义反向关系, 这一切都是自动完成的.
One-to-one relations

one-to-one 关系中的每个对象拥有一个 get_relatedobjectname() 方法. 举例来说:

class Place(meta.Model):
# ...

class Restaurant(meta.Model):
# ...
the_place = meta.OneToOneField(places.Place)

在上面的例子里, 每个 Place 会自动拥有一个 get_restaurant() 方法, 且每个 Restaurant 会自动拥有一个 get_the_place() 方法.
Many-to-one relations

在 many-to-one 关系中, 关联对象(Many)会自动拥有一个 get_relatedobject() 方法. 被关联的对象(one)会自动拥有 get_relatedobject(), get_relatedobject_list(), 和 get_relatedobject_count() 方法 (功能与模块级的 get_object(), filter(), 和 get_count() 相同).

在上面的民意测试例子里, 一个 Poll 对象 p 自动拥有下列方法:

p.get_choice()
p.get_choice_list()
p.get_choice_count()

Choice 对象 c 则自动拥有下面的方法:

c.get_poll()

Many-to-many 关系

Many-to-many 关系类似`Many-to-one relations`_, 它生成同样的方法集.例外的是关联对象的 get_relatedobject_list() 方法返回一个实例的列表而不是一个仅一个实例.因此,若 Poll 和 Choice 是 many-to-many 关系, choice.get_poll_list() 将返回一个列表.
专门的结果集

除 filter 和 exclude() 之外, Django 提供了一系列结果集处理方法, 修改结果的类型, 或修改 sql 查询在数据库执行的方式.
order_by(*fields)

根据 model 中提供 ordering tuple, 结果集会被自动排序. 不过, 排序也可以通过 order_by 方法显式的进行:

Poll.objects.filter(pub_date__year=2005,
pub_date__month=1).order_by(‘-pub_date‘, ‘question‘)

结果集将按降序排列 pub_date, 然后按升序排列 question."-pub_date" 中的负号表示降序(递减).要取随机序,使用"?", 象下面这样:

Poll.objects.order_by=(‘?‘)

要按另一个表中的字段排序, 添加另一个表的名字和一个句点,象下面这样:

Choice.objects.order_by=(‘Poll.pub_date‘, ‘choice‘)

无法指定排序是否大小写敏感, 不管你的数据库后端如何排序, Django都会以大小写敏感的方式重新排序结果集.. (这样是不是会降低效率? 不能关掉这个特性么?)
distinct()

默认的, 一个结果集不会自动除去重复的行. 尤其当你进行跨关系查询时, 很容易出现重复的行.

distinct() 返回一个除去了重复行的新的结果集,它等价于 SELECT DISTINCT SQL 语句.
values(*fields)

类似 filter(), 不过它返回一个字典的列表而不是 model 实例对象的列表.

它接受一个可选参数: fields, 这是一个字段名列表或tuple.如果你没有指定 fields, 每个字段都会返回.否则就只返回你指定的字段名和值.这里有一个例子,使用上面定义的 Poll model

>>> from datetime import datetime
>>> p1 = Poll(slug=‘whatsup‘, question="What‘s up?",
... pub_date=datetime(2005, 2, 20), expire_date=datetime(2005, 3, 20))
>>> p1.save()
>>> p2 = Poll(slug=‘name‘, question="What‘s your name?",
... pub_date=datetime(2005, 3, 20), expire_date=datetime(2005, 4, 20))
>>> p2.save()
>>> Poll.objects.all()
[What‘s up?, What‘s your name?]
>>> Poll.objects.values()
[{‘id‘: 1, ‘slug‘: ‘whatsup‘, ‘question‘: "What‘s up?", ‘pub_date‘: datetime.datetime(2005, 2, 20), ‘expire_date‘: datetime.datetime(2005, 3, 20)},
{‘id‘: 2, ‘slug‘: ‘name‘, ‘question‘: "What‘s your name?", ‘pub_date‘: datetime.datetime(2005, 3, 20), ‘expire_date‘: datetime.datetime(2005, 4, 20)}]
>>> Poll.objects.values(fields=[‘id‘, ‘slug‘])
[{‘id‘: 1, ‘slug‘: ‘whatsup‘}, {‘id‘: 2, ‘slug‘: ‘name‘}]

当你知道你要取得哪些字段的值时并且你不需要那些 model实例对象的功能时,使用 values() 函数.

时间: 2024-11-10 14:53:24

django 数据库查询的相关文章

django 数据库查询 ORM

单表操作: 添加记录: # 方式1: #obj=Book.objects.create(title="python",publishDate="2012-12-12",price=100) 注意:Book.objects.create()的返回值是当前添加的记录对象这种方式不需要save() # 方式2: book_obj=Book(title="python2",publishDate="2012-12-12",price=

八、Python Django数据库添加查询

Python Django数据库添加查询 对数据进行操作 一.创建记录 # pwd /root/csvt03 # ipython manage.py shell In [1]: from blog.models import Employee #(第一种方法) In [2]: Employee Out[2]: blog.models.Employee In [3]: emp = Employee() In [4]: emp.name = 'Alen' In [5]: emp.save() #(第

Django中的数据库查询

web应用需要经常向数据库查询相关的数据,Django语言也不例外.了解Django中的数据查询操作,对于优化应用的性能,有着重要的意义. 基础信息 Django中,model通过Manager获取QuerySet,每个model至少有objects这个 Manager . QuerySet 可以有一个或多个 filter , filter 根据传入的参数返回 QuerySet 结果. 用SQL来对比, QuerySet 相当于 SELECT , filter 相当于 WHERE 或者是 LIM

django 数据库操作详解

你创建完数据模型,django会自动提供给你数据库抽象的API,可以创建,获取,修改,删除对象.本篇文档讲解如何使用API,包括外键相关查询以及多对多模式的操作等 我们参考下面模型,一个weblog: class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def __unicode__(self): return self.name class Author(m

django orm查询方法详解

目录 1.1.1 生成查询 1.1.2 创建对象 1.1.3 保存修改的对象 1.1.4 保存 ForeignKey 和 ManyToManyField 字段 1.1.5 检索对象 1.1.6 检索所有的对象 1.1.7 过滤检索特定对象 1.1.8 链接过滤 1.1.9 过滤结果集是唯一 1.2.1 结果集是延迟的 1.2.2 其他的QuerySet方法 1.2.3 限制 QuerySets 1.2.4 字段查找 1.2.5 跨关系查询 1.2.6 过滤器可参考模型字段 1.2.7 缓存查询集

Django数据库

数据库 ORM框架 O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思.在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据.ORM框架还有一个功能,它可以根据我们设计的类自动帮我们生成数据库中的表格,省去了我们自己建表的过程. django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作. 使用dj

Django 分页查询并返回jsons数据,中文乱码解决方法

一.引子 Django 分页查询并返回 json ,需要将返回的 queryset 序列化, demo 如下: # coding=UTF-8 import os from django.core import serializers from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.shortcuts import render from django.http import

(转)Django 数据库

转:https://blog.csdn.net/ayhan_huang/article/details/77575186 一.数据库框架 数据库框架是数据库的抽象层,也称为对象关系映射(Object-Relational Mapper, ORM),它将高层的面向对象操作转换成低层的数据库指令,比起直接操作数据库引擎,ORM极大的提高了易用性.这种转换会带来一定的性能损耗,但ORM对生产效率的提升远远超过这一丁点儿性能降低. Django中内置的SQLAlchemy ORM就是一个很好的数据库框架

python 数据库查询条件`不等于`

1.python 数据库查询条件不等于 当在做数据库查询的时候,想根据业务需求进行条件的筛选或过滤, 但是django封装的数据库语句中没有 '不等于' 查询操作. 2.例如:通过以下语句进行'不等于查询' data = User-objects.filter(id != '1').values('id','name','age') 此语句会报错 3.解决方案: from django.db.models import Q data = User.objects.filter(~Q(id= '1