目录
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 缓存查询集
1.2.8 比较对象
1.2.9 删除对象
1.3.1 一次修改多个对象
1.3.2 关系对象
1.3.3 One-to-many关系
1.3.4 Many-to-many关系
1.3.5 One-to-one关系

1.1.1 生成查询
你创建完数据模型,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(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField() def __unicode__(self):
return self.name #目录
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateTimeField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField() def __unicode__(self):
return self.headline

1.1.2 创建对象

用python对象描述数据库表的数据,django使用一个直观的系统,一个模型类描述一个数据表,一个类的实例描述表的一条详细记录。使用模型的save()方法将对象创建到数据库。

from mysite.blog.models import Blog

b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save()

只有执行save方法时,django才会执行sql把对象写入数据库。

1.1.3 保存修改的对象

保存修改仍然使用save()方法

b5.name = 'New name'
b5.save()

1.1.4 保存 ForeignKey 和 ManyToManyField 字段

cheese_blog = Blog.objects.get(name="Cheddar Talk")
entry.blog = cheese_blog #为 ManyToManyField 增加记录
entry.save()
joe = Author.objects.create(name="Joe")
entry.authors.add(joe) #为 ForeignKey 增加记录

1.1.5 检索对象
从数据库里检索对象,可以通过模型的Manage来建立QuerySet,一个QuerySet表现为一个数据库中对象的结合,他可以有0个一个或多个过滤条件,在SQL里QuerySet相当于select语句用where或limit过滤。你通过模型的Manage来获取QuerySet,每个模型至少有一个Manage

1.1.6 检索所有的对象

检索表中所有数据,最简单的方式是用all().

all_entries = Entry.objects.all()

1.1.7 过滤检索特定对象

检索过滤特定查询结果,有两个方法。
filter(**kwargs) 返回一个新的匹配查询参数后的QuerySet
exclude(**kwargs) 返回一个新的不匹配查询参数后的QuerySet

Entry.objects.filter(pub_date__year=2006)

1.1.8 链接过滤

Entry.objects.filter(headline__startswith='What')
.exclude(pub_date__gte=datetime.now())
.filter(pub_date__gte=datetime(2005, 1, 1))

1.1.9 过滤结果集是唯一

每次你完成一个QuerySet,你获得一个全新的结果集,不包括前面的。每次完成的结果集是可以贮存,使用或复用
q1 = Entry.objects.filter(headline__startswith="What")
q2 = q1.exclude(pub_date__gte=datetime.now())
q3 = q1.filter(pub_date__gte=datetime.now())

三个QuerySets是分开的,第一个是headline以"What"单词开头的结果集,第二个是第一个的子集,即pub_date不大于现在的,第三个是第一个的子集 ,pub_date大于现在的

1.2.1 结果集是延迟的

QuerySets是延迟的,创建QuerySets不会触及到数据库操作,你可以多个过滤合并到一起,直到求值的时候django才会开始查询。如:

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

虽然看起来执行了三个过滤条件,实际上最后执行print q的时候,django才开始查询执行SQL到数据库。

1.2.2 其他的QuerySet方法
大多数情况你使用all()、filter()和exclude()

1.2.3 限制 QuerySets

使用python的数组限制语法限定QuerySet,如:
取前5个

Entry.objects.all()[:5]

取第五个到第十个

Entry.objects.all()[5:10]

一般的,限制QuerySet返回新的QuerySet,不会立即求值查询,除非你使用了"step"参数

Entry.objects.all()[:10:2]
Entry.objects.order_by('headline')[0]
Entry.objects.order_by('headline')[0:1].get()

1.2.4 字段查找

字段查找是指定SQL语句的WHERE条件从句,通过QuerySet的方法filter(), exclude()和get()指定查询关键字。
基本查询field__lookuptype=value
例如:

Entry.objects.filter(pub_date__lte='2006-01-01')

转换为SQL:

SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

如果你传了无效的参数会抛异常

数据库API 支持一些查询类型,下面体验一下:
a、exact

Entry.objects.get(headline__exact="Man bites dog")

等价于

SELECT ... WHERE headline = 'Man bites dog';

如果查询没有提供双下划线,那么会默认 __exact=

Blog.objects.get(id__exact=14) # Explicit form
Blog.objects.get(id=14) # __exact is implied

b、iexact——忽略大小写

Blog.objects.get(name__iexact="beatles blog")

blog title会匹配 "Beatles Blog", "beatles blog", 甚至 "BeAtlES blOG".

c、contains——包含查询,区分大小写

Entry.objects.get(headline__contains='Lennon')

转化为SQL

SELECT ... WHERE headline LIKE '%Lennon%';

icontains 不区分大小写

startswith,endswith,istartswith,iendswith
前模糊匹配,后模糊匹配

1.2.5 跨关系查询

Entry.objects.filter(blog__name__exact='Beatles Blog')

这个可以跨越你想要的深度。

反向跨关系查询

Blog.objects.filter(entry__headline__contains='Lennon')

如果跨越多层关系查询,中间模型没有值,django会作为空对待不会发生异常。

Blog.objects.filter(entry__author__name='Lennon');
Blog.objects.filter(entry__author__name__isnull=True);
Blog.objects.filter(
entry__author__isnull=False,
entry__author__name__isnull=True);

1.2.6 过滤器可参考模型字段

目前给的例子里,我们建立了过滤,比照模型字段值和一个固定的值,但是如果我们想比较同一个模型里的一个指端和另一个字段的值,django提供F()——专门取对象中某列值的操作

from django.db.models import F
Entry.objects.filter(n_pingbacks__lt=F('n_comments'))

注:n_pingbacks、n_comments为模型Entry属性

django支持加减乘除和模计算

Entry.objects.filter(n_pingbacks__lt=F('n_comments') * 2)
Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))
Entry.objects.filter(author__name=F('blog__name'))

主键查询捷径

Blog.objects.get(id__exact=14) # Explicit form
Blog.objects.get(id=14) # __exact is implied
Blog.objects.get(pk=14) # pk implies id__exact

不仅限于__exact 查询

# Get blogs entries with id 1, 4 and 7
Blog.objects.filter(pk__in=[1,4,7]) # Get all blog entries with id > 14
Blog.objects.filter(pk__gt=14)

跨越查询

Entry.objects.filter(blog__id__exact=3) # Explicit form
Entry.objects.filter(blog__id=3) # __exact is implied
Entry.objects.filter(blog__pk=3) # __pk implies __id__exact

like语句转义百分号

Entry.objects.filter(headline__contains='%')

转义为

SELECT ... WHERE headline LIKE '%\%%';

1.2.7 缓存查询集

每个QuerySet都包含一个缓存,以尽量减少对数据库的访问。理解他的工作原理很重要,可以写出最高效的代码。
在最新创建的QuerySet里,缓存是空的。在第一次QuerySet被取值,因此数据库查询发生,django把查询结果放入缓存,并返回给请求,随后的查询取值会复用缓存中的结果。

保持缓存的思想习惯,因为如果你不正确使用查询缓存会有麻烦。例如下面例子会创建两个QuerySet

print [e.headline for e in Entry.objects.all()]
print [e.pub_date for e in Entry.objects.all()]

这样意味着数据库查询会执行两次,实际两次数据库加载

为了避免这个问题,简单保存QuerySet复用

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

1.2.8 比较对象

比较两个模型实例,使用python标准的运算符,两个等号==

some_entry == other_entry
some_entry.id == other_entry.id
some_obj == other_obj
some_obj.name == other_obj.name

1.2.9 删除对象

删除方法是很方便的,方法名为delete(),这个方法直接删除对象没有返回值

e.delete()

你也可以批量删除对象,每个QuerySet有一个delete()方法,能删除 QuerySet里所有对象

1.3.1 一次修改多个对象

有时候你想给QuerySet里所有对象的一个字段赋予特定值,你可以使用 update()方法
例如:

# Update all the headlines with pub_date in 2007.
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

这个方法只能用于无关联字段和外键

b = Blog.objects.get(pk=1)
# Change every Entry so that it belongs to this Blog.
Entry.objects.all().update(blog=b)

update()方法不返回任何值,QuerySet不支持save方法,如果要执行save,可以如下:

for item in my_queryset:
item.save()

update也可以使用F()

# THIS WILL RAISE A FieldError
Entry.objects.update(headline=F('blog__name'))

1.3.2 关系对象

当你在model里定义一个关系时,模型实例会有一个方便的API来访问关系对象。用本页上面的模型举个例子,一个Entry
对象可以得到blog对象,访问blog属性e.blog。
django也创建API来访问关系对象的另一边,一个blog对象访问Entry列表b.entry_set.all().

1.3.3 One-to-many关系

如果一个对象有ForeignKey,这个模型实例访问关系对象通过简单的属性

e = Entry.objects.get(id=2)
e.blog # Returns the related Blog object.

你可以凭借外键属性获取和赋值,修改外键值知道执行save()方法才会保存到数据库

e = Entry.objects.get(id=2)
e.blog = some_blog
e.save()

如果ForeignKey 设置了null=True 你可以赋值为None

e = Entry.objects.get(id=2)
print e.blog # Hits the database to retrieve the associated Blog.
print e.blog # 不会在向数据库取; 使用缓存中的值. e = Entry.objects.select_related().get(id=2)
print e.blog # 不会在向数据库取; 使用缓存中的值.
print e.blog # 不会在向数据库取; 使用缓存中的值. b = Blog.objects.get(id=1)
b.entry_set.all() # 返回所有blog的关联对象. # b.entry_set is a Manager that returns QuerySets.
b.entry_set.filter(headline__contains='Lennon')
b.entry_set.count() b = Blog.objects.get(id=1)
b.entries.all() # 返回所有blog的关联对象 # b.entries is a Manager that returns QuerySets.
b.entries.filter(headline__contains='Lennon')
b.entries.count()

add(obj1, obj2, ...) 增加多个关系对象
create(**kwargs) 建立新对象
remove(obj1, obj2, ...) 去除多个关系对象
clear() 清理所有关系对象

b = Blog.objects.get(id=1)
b.entry_set = [e1, e2]

1.3.4 Many-to-many关系

e = Entry.objects.get(id=3)
e.authors.all() # 返回Entry所有authors .
e.authors.count()
e.authors.filter(name__contains='John') a = Author.objects.get(id=5)
a.entry_set.all() # 返回Author所有entry .

1.3.5 One-to-one关系

class EntryDetail(models.Model):
entry = models.OneToOneField(Entry)
details = models.TextField() ed = EntryDetail.objects.get(id=2)
ed.entry # 返回 Entry 对象.

django orm总结的更多相关文章

  1. django orm总结[转载]

    django orm总结[转载] 转载地址: http://www.cnblogs.com/linjiqin/archive/2014/07/01/3817954.html 目录1.1.1 生成查询1 ...

  2. Django ORM - 001 - 外键表查询主表信息

    开始用Django做web开发,我想大家都会遇到同样的问题,那就是如何高效快速的查询需要的数据,MVC都很简单,但是ORM折腾起来就有些费时间,我准备好好研究下Django ORM,所以会有一个系列的 ...

  3. Django ORM 中的批量操作

    Django ORM 中的批量操作 在Hibenate中,通过批量提交SQL操作,部分地实现了数据库的批量操作.但在Django的ORM中的批量操作却要完美得多,真是一个惊喜. 数据模型定义 首先,定 ...

  4. Django ORM 查询管理器

    Django ORM 查询管理器 ORM 查询管理器 对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言 ...

  5. Django ORM模型的一点体会

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁转载. 使用Python的Django模型的话,一般都会用它自带的ORM(Object-relational ma ...

  6. 数据库表反向生成(二) Django ORM inspectdb

    在前一篇我们说了,mybatis-generator反向生成代码. 这里我们开始说如何在django中反向生成mysql model代码. 我们在展示django ORM反向生成之前,我们先说一下怎么 ...

  7. Django ORM那些相关操作

    一般操作 https://docs.djangoproject.com/en/1.11/ref/models/querysets/         官网文档 常用的操作 <1> all() ...

  8. django orm 及常用参数

    一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...

  9. Django ORM中,如何使用Count来关联对象的子集数量

    示例models 解决方法 有时候,我们想要获取一个对象关联关系的数量,但是我们不要所有的关联对象,我们只想要符合规则的那些关联对象的数量. 示例models # models.py from dja ...

  10. Django ORM存储datetime 时间误差8小时问题

    今天使用django ORM 将获取到的时间入库,并未出现问题,但是后来发现时间晚了8小时,经查询Django官方文档发现获取本地时间和UTC时间有差别. 首先科普下:UTC是协调世界时 UTC相当于 ...

随机推荐

  1. 十步图解CSS的position

    CSS的positon,我想做为一个Web制作者来说都有碰到过,但至于对其是否真正的了解呢?那我就不也说了,至少我自己并不非常的了解其内核的运行.今天在Learn CSS Positioning in ...

  2. oracle中rownum和rowid的区别

    rownum和rowid的区别总括: rownum和rowid都是伪列,但是两者的根本是不同的. rownum是根据sql查询出的结果给每行分配一个逻辑编号,所以你的sql不同也就会导致最终rownu ...

  3. alert/confirm/prompt 处理

    webdriver 中处理JavaScript 所生成的alert.confirm 以及prompt 是很简单的.具体思路是使用switch_to_alert()方法定位到alert/confirm/ ...

  4. SQL语句-批量插入表(表数据插表)

    批量插入表(表数据插表) ****1.INSERT INTO SELECT语句语句形式为:Insert into Table2(field1,field2,...) select value1,val ...

  5. PHP安装rrdtool扩展

    首先,我的环境是Centos 6.5 PHP版本是5.51.首先安装rrdtool需要的依赖库文件   yum -y install pango* 2.先服务器安装rrdtool  wget http ...

  6. CSS3--响应式布局

    一.流式布局 不再使用px作为盒模型布局,而是采用百分比布局宽高,定位等. 公式:目标元素宽度/上下文元素宽度=百分比宽度 目标定位/上下文元素宽度或高度=定位距离(保留5位小数点) 用em/rem来 ...

  7. MVC5+EF6 简易版CMS(非接口) 第一章:新建项目

    目录 简易版CMS后台管理系统开发流程 MVC5+EF6 简易版CMS(非接口) 第一章:新建项目 MVC5+EF6 简易版CMS(非接口) 第二章:建数据模型 MVC5+EF6 简易版CMS(非接口 ...

  8. jQuery实现无缝滚动条

    很多时候只看别人的代码时很难看懂.有很多原因,有时候可能是没有耐心,这时候看一下实现的原理就很快明白代码的内容,所以要加些注释,让自己让别人都能看明白:有的时候就是因为知识有限就是不懂,哪怕代码很简单 ...

  9. 如何把android中布局文件(.xml)与相关的类(.java)进行关联?

    eg:把一个布局文件名为page1.xml与MainActivity.java(工程自动生成)进行 1.在存放使用资源的res文件夹下的layout文件夹内新建一个XML布局文件,如命名为:page1 ...

  10. Android.技术站点

    总结Android相关的技术站点和blog 1. http://android-developers.blogspot.com/ 首推这个blog,有时间需要每篇blog读一遍. 2. nlopez ...