标签:
Django 中查询数据库需要 Manager 和 QuerySet 两个对象。从数据库里检索对象,可以通过模型的 Manage 来建立 QuerySet,一个 QuerySet 表现为一个数据库中对象的结合,他可以有0个一个或多个过滤条件,在 SQL里 QuerySet 相当于 select 语句用 where 或 limit 过滤。你通过模型的 Manage 来获取 QuerySet。
Manager 对象附在模型类里,如果没有特指定,每个模型类都会有一个 objects 属性,它构成了这个模型在数据库所有基本查询。
Manager 的几个常用方法:
all
:返回一个包含模式里所有数据库记录的 QuerySetfilter
:返回一个包含符合指定条件的模型记录的 QuerySetexclude
:和 filter 相反,查找不符合条件的那些记录card = Card.objects.filter(pk=offline_card_id).get()
card = Card.objects.exclude(pk=offline_card_id).get() 相反的两条语句
get
:获取单个符合条件的记录(没有找到或者又超过一个结果都会抛出异常)order_by
:改变 QuerySet 默认的排序
QuerySet 接受动态的关键字参数,然后转换成合适的 SQL 语句在数据库上执行。
QuerySet 的几个常用方法:
distinct
values
values_list
select_related
filter
:返回一个包含符合指定条件的模型记录的 QuerySetextra
:增加结果集以外的字段
字段查找是指定 SQL 语句的 WHERE 条件从句,通过 QuerySet 的方法 filter()
, exclude()
和 get()
指定查询关键字。
格式为:field__lookuptype=value
。
lookuptype 有以下几种:
gt
: 大于gte
: 大于等于in
: 包含lt
: 小于lte
: 小于等于exact
:iexact
:contains
:包含查询,区分大小写icontains
:不区分大小写startswith
:匹配开头endswith
:匹配结尾istartswith
:匹配开头,不区分大小写iendswith
:匹配结尾,不区分大小写使用 Extra 调整 SQL 用extra可以修复QuerySet生成的原始SQL的各个部分,它接受四个关键字参数。如下: select:修改select语句 where:提供额外的where子句 tables:提供额外的表 params:安全的替换动态参数 增加结果集以外的字段: queryset.extra(select={‘成年‘:‘age>18‘}) 提供额外的 where 条件: queryset.extra(where=["first like ‘%小明%‘ "]) 提供额外的表: queryset.extra(tables=[‘myapp_person‘]) 安全的替换动态参数:
F 关键字参数 前面给的例子里,我们建立了过滤,比照模型字段值和一个固定的值,但是如果我们想比较同一个模型里的一个字段和另一个字段的值,django 提供 F()——专门取对象中某列值的操作。 >>> from django.db.models import F >>> Entry.objects.filter(n_comments__gt=F(‘n_pingbacks‘)) 当然,还支持加减乘除和模计算: >>> Entry.objects.filter(n_comments__gt=F(‘n_pingbacks‘) * 2) >>> Entry.objects.filter(rating__lt=F(‘n_comments‘) + F(‘n_pingbacks‘)) >>> >>> Entry.objects.filter(authors__name=F(‘blog__name‘)) 对于日期类型字段,可以使用 timedelta 方法: >>> from datetime import timedelta >>> Entry.objects.filter(mod_date__gt=F(‘pub_date‘) + timedelta(days=3)) 还支持位操作 .bitand() 和 .bitor(): >>> F(‘somefield‘).bitand(16) 主键查找 Django 支持使用 pk 代替主键: >>> 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 pk 还可以用于其他的查找类型: # 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 Q 关键字参数 QuerySet 可以通过一个叫 Q 的关键字参数封装类进一步参数化,允许使用更复杂的逻辑查询。其结果 Q对 象可以作为 filter 或 exclude 方法的关键字参数。 例子: from django.db.models import Q Q(question__startswith=‘What‘) 支持 & 和 | 操作符: Q(question__startswith=‘Who‘) | Q(question__startswith=‘What‘) 上面的查询翻译成 sql 语句: WHERE question LIKE ‘Who%‘ OR question LIKE ‘What%‘ 取反操作: Q(question__startswith=‘Who‘) | ~Q(pub_date__year=2005) 也可以用在 filter()、exclude()、get() 中: Poll.objects.get( Q(question__startswith=‘Who‘), Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) ) 翻译成 sql 语句为: SELECT * from polls WHERE question LIKE ‘Who%‘ AND (pub_date = ‘2005-05-02‘ OR pub_date = ‘2005-05-06‘) 删除对象 >>>entry = Entry.objects.get(pk=1) >>>entry.delete() >>>Blog.objects.all().delete() >>>Entry.objects.filter(pub_date__year=2005).delete() 关系对象 当对象之间存在映射关系或者关联时,该如何查询呢? 当你在模型里定义一个关系时,模型实例会有一个方便的 API 来访问关系对象。以下分几种映射关系分别描述。 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() 如果关联的对象可以为空,则可以将关联对象职位 None,删除关联: >>> e = Entry.objects.get(id=2) >>> e.blog = None >>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;" 子查询: >>> e = Entry.objects.get(id=2) >>> print(e.blog) # Hits the database to retrieve the associated Blog. >>> print(e.blog) # Doesn‘t hit the database; uses cached version. 也可以使用 select_related() 方法,该方法会提前将关联对象查询出来: >>> e = Entry.objects.select_related().get(id=2) >>> print(e.blog) # Doesn‘t hit the database; uses cached version. >>> print(e.blog) # Doesn‘t hit the database; uses cached version. 你也可以通过 模型_set 来访问关系对象的另一边,在 Blog 对象并没有维护 Entry 列表,但是你可以通过下面方式从 Blog 对象访问 Entry 列表: >>> b = Blog.objects.get(id=1) >>> b.entry_set.all() # Returns all Entry objects related to Blog. # b.entry_set is a Manager that returns QuerySets. >>> b.entry_set.filter(headline__contains=‘Lennon‘) >>> b.entry_set.count() 模型_set 可以通过 related_name 属性来修改,例如将 Entry 模型中的定义修改为: blog = ForeignKey(Blog, related_name=‘entries‘) 上面的查询就会变成: >>> b = Blog.objects.get(id=1) >>> b.entries.all() # Returns all Entry objects related to Blog. # b.entries is a Manager that returns QuerySets. >>> b.entries.filter(headline__contains=‘Lennon‘) >>> b.entries.count() Many-to-many关系 e = Entry.objects.get(id=3) e.authors.all() # Returns all Author objects for this Entry. e.authors.count() e.authors.filter(name__contains=‘John‘) a = Author.objects.get(id=5) a.entry_set.all() # Returns all Entry objects for this Author. One-to-one关系 class EntryDetail(models.Model): entry = models.OneToOneField(Entry) details = models.TextField() ed = EntryDetail.objects.get(id=2) ed.entry # Returns the related Entry object. 当反向查询时: e = Entry.objects.get(id=2) e.entrydetail # returns the related EntryDetail object 这时候如果没有关联对象,则会抛出 DoesNotExist 异常。 并且还可以修改: e.entrydetail = ed 参考资料 Making queries Eclipse的django开发学习笔记(2)--模型(M) Django:模型的使用 django orm总结
参考文章网址:http://blog.javachen.com/2015/01/15/django-orm/
标签:
原文地址:http://www.cnblogs.com/blogofwyl/p/4376474.html