学习Django的时候在这里写了一点数据库创建查询方法 http://blog.youkuaiyun.com/u013205877/article/details/76768963 但是比较简单,
在这篇文章比较详细的记录下用法,我挑重要的写,方便自己以后查询复习,更详细的参考:https://www.cnblogs.com/ajianbeyourself/p/3604332.html
例子 blog/models.py
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __unicode__(self): # __str__ on Python 3
return self.name
class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
def __unicode__(self): # __str__ on Python 3
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField()
def __unicode__(self): # __str__ on Python 3
return self.headline
1. QuerySet 创建对象的方法
#一共四种方法
from blog.models import Blog,Author,Entry
#第一种
Author.objects.create(name="zhangkun", email="lalalal@qq.com")
#第二种
zk = Author(name="zhangkun", email="lalalal@qq.com")
zk.save()
#第三种
zk = Author()
zk.name="zhangkun"
zk.email="lalalal@qq.com"
zk.save()
#第四种 先读,不存在就创建,防止重复
Author.objects.get_or_create(name="zhangkun", email="lalalal@qq.com")
# 返回值(object, True/False),创建时返回 True, 已经存在时返回 False
2. QuerySet 获取对象的方法 查询方法
#查询所有的
Person.objects.all()
#切面,获取10个,不支持负索引,切片可以节约内存,不支持负索引,后面有相应解决办法,第7条
Persion.objects.all()[:10]
#名称为zhangkun的第一条,多条会报错
Person.object.get(name="zhangkun")
get只是用来获取第一条对象的,如果需要满足条件的一些人,需要用到filter
#名字叫zhangkun的
Person.objects.filter(name="zhangkun")
#名字严格叫zhangkun的(这和上一条有啥区别?黑人问好脸.jpg)
Person.objects.filter(name__exact="zhangkun")
#名字严格叫zhangkun,但是不区分大小写,可以找到Zhangkun,ZHANGKUN,都符合条件
Person.objects.filter(name__iexact="zhangkun")
#名字中包含"zhangkun"的
Persin.objects.filter(name__contains="zhangkun")
#名字中包含"zhangkun"的,但是不区分大小写
Persin.objects.filter(name__icontains="zhangkun")
#正则表达式查询
Person.objects.filter(name__regex="^abc")
#不区分大小写的正则
Person.objects.filter(name__iregex="^abc")
#排除包含WZ的Person对象
Person.objects.exclude(name__contains="WZ")
#找出名称中含有abc但是排除23岁的
Person.objects.filter(name__contains="abc").exclude(age=23)
3.QuerySet 删除符合条件的结果
Person.objects.filter(name__contains="abc").delete() # 删除 名称中包含 "abc"的人
如果写成
people = Person.objects.filter(name__contains="abc")
people.delete()
效果也是一样的,Django实际只执行一条 SQL 语句。
4. QuerySet 更新某个内容
1 .批量更新,适用于.all() .filter() .exclude()等等后面
#名称中包含abc的人都更为xxx
Person.objects.filter(name__contains="abc").update(name="xxx")
#删除所有的Person记录
Person.objects.all().delete()
2.单个的object更新,适用于.get(),get_or_create(),update_or_create()等等得到的obj,和新建很类似
twz = Author.objects.get(name="zhangkun")
twz.name = "studyDjango"
twz.email="learn@qq.com"
twz.save()
5. QuerySet 是可迭代的
#ntry.objects.all() 或者 es 就是 QuerySet 是查询所有的 Entry 条目
es = Entry.objects.all()
for e in es:
print(e.headline)
(1) 如果只是检查Entry中是否有对象,用Entry.objects.all().exits()
(2)QuerySet 支持切片 Entry.objetcs.all()[:10]取出10条,节省内存
(3)用len(Entry.objetcs.all())也能得到Entry的数量,但是推荐使用Entry.objects.count()来查询,因为他用的是SQL:SELECT COUNT(*)
(4)list(Entry.objetcs.all()) 可以强行将QuerySet变成列表
6. QuerySet 是可以用pickle序列化到硬盘再读取出来的
#没看懂,有毛用?
>>> import pickle
>>> query = pickle.loads(s) # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query # Restore the original 'query'.
7. QuerySet 查询结果排序
作者按照名称排序
Author.objects.all().order_by('name')
# 在 column name 前加一个负号,可以实现倒序
Author.objects.all().order_by('-name')
8. QuerySet 支持链式查询
Author.objects.filter(name__contains="zhangkun").filter(email="lalal@qq.com")
Author.objects.filter(name__contains="zhangkun").exclude(email="lalal@qq.com")
#找到名字含有abc,年纪排除23的
Person.objects.filter(name__contains="abc").exclude(age=23)
9. QuerySet 不支持负索引
Person.objects.all()[:10] 切片操作,前10条
Person.objects.all()[-10:] 会报错!!!
#1.使用reverse()解决
Person.objects.all().reverse()[:2]#最后两条
Person.objects.all().reverse()[0]#最后一条
#2.使用order_by,在列名前加一个负号
Author.objects.order_by('-id')[:20]#id最大的20条,相当于从后往前排的20条数据
9. QuerySet 重复的问题,使用 .distinct() 去重
他说,一般的情况下,QuerySet 中不会出来重复的,重复是很罕见的,但是当跨越多张表进行检索后,结果并到一起,可以会出来重复的值,我觉得这可能是设计有问题哈哈哈哈
qs1 = Pathway.objects.filter(label__name='x')
qs2 = Pathway.objects.filter(reaction__name='A + B >> C')
qs3 = Pathway.objects.filter(inputer__name='WeizhongTu')
# 合并到一起
qs = qs1 | qs2 | qs3
这个时候就有可能出现重复的
# 去重方法
qs = qs.distinct()
10.QuerySet 过滤空或者null名称
排除空值和空字符串,首选的方法是链接条件
Author.objects.exclude(name__isnull=True).exclude(name__exact='')
也可以用其他的写法
from django.db.models import Q
Author.objects.exclude(Q(name__isnull=True) | Q(exclude(name__exact=''))
推荐看原文:http://code.ziqiangxuetang.com/django/django-queryset-api.html
下面还有:
Django QuerySet 进阶内容:
http://code.ziqiangxuetang.com/django/django-queryset-advance.html
Django 自定义Field
http://code.ziqiangxuetang.com/django/django-custom-field.html
Django 数据表更改
http://code.ziqiangxuetang.com/django/django-schema-migration.html
二、Django中Q查询及Q()对象
一般我们在Django程序中查询数据库操作都是在QuerySet里进行进行,或者将其组合起来,随着我们的程序越来越复杂,查询的条件也跟着复杂起来,这样简单的通过一个filter()来进行查询的条件将导致我们的查询越来越长。Q()对象就是为了将这些条件组合起来。
from django.db.models import Q
q=Q(name_startswith="zhangkun")
这样就生成了一个Q()对象,我们可以使用符号&或者|将多个Q()对象组合起来传递给filter(),exclude(),get()等函数。当多个Q()对象组合起来时,Django会自动生成一个新的Q()。例如下面代码就将两个条件组合成了一个:
Q(name_startswith="zhangkun") | Q(name_startswith="zhangkun1")
使用上述代码可以使用SQL语句这么理解(SQL通配符%,替代 0 个或多个字符):
WHERE name LIKE "zhangkun%" OR name LIKE "zhangkun1%"
每个接受关键字参数的查询函数(例如filter()、exclude()、get())都可以传递一个或多个Q 对象作为位置(不带名的)参数。如果一个查询函数有多个Q 对象参数,这些参数的逻辑关系为“AND”。
我们可以在Q()对象的前面使用字符“~”来代表意义“非”:
Q(name_startswith="zhangkun") | ~Q(name_="zhangkun2")
对应SQL语句可以理解为:
WHERE name LIKE "zhangkun%" OR name != "zhangkun1%"
也可以传递多个Q()对象给查询函数:
from django.db.models import Q
from biz.volume.models import Volume
Volume.objects.get(Q(name__startswith="EBS"),Q(name="AWS") | Q(name="ali"))
多个Q()对象之间的关系Django会自动理解成“且(and)”关系,Q()对象可以结合关键字参数一起传递给查询函数,不过需要注意的是要将Q()对象放在关键字参数的前面,
Volume.objects.get(Q(name__startswith="EBS"),Q(name="AWS") | Q(name="ali"),name=“zhangkun”)