十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名注册、雅安服务器托管、营销软件、网站建设、贺州网站维护、网站推广。
目录
queries:...1
exclude():...3
关联对象查询:...3
反向查询对
复杂查询:...4
保存ForeignKey和ManyToMany字段:...5
QuerySet链式过滤:...5
lookup,高级条件过滤:...5
跨关联关系查询:...6
限制返回个数:...6
查询对象比较...7
不常用查询API:...7
事务:...10
自定义管理器:...11
user.groups.set(groups)
user.groups.all()
group.user_set.all() #反查会加上_set
Author.objects.exclude(name='jowin')
Entry.objects.get(id=1).blog #一对多,前向查询,通过属性访问关联的(外部)对象
Blog.objects.get(id=1).entry_set.all() #一对多,反向查询,模型中有fk,该fk所指的模型实例可通过一个管理器返回前一个模型的所有实例,默认这个管理器的名字是
例:
class Group(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
class User(models.Model):
name = models.CharField(max_length=20)
groups = models.ManyToManyField(Group) #ManyToMany会自动生成中间表publish_user_groups
def __str__(self):
return self.name
>>> from publish.models import Group,User
>>> user = User.objects.create(name='jowin')
>>> group1 = Group.objects.create(name='magedu1')
>>> group2 = Group.objects.create(name='magedu2')
>>> user = User.objects.first()
>>> groups = Group.objects.all()
>>> type(groups)
>>> user.groups.set(groups) #将用户为'jowin'加入多个组里
>>> user.groups.all()
>>> group = Group.objects.get(id=1)
>>> group.user_set.all() #反查会加上_set
例,多对多,自己加中间表:
class Group(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
class User(models.Model):
name = models.CharField(max_length=20)
# groups = models.ManyToManyField(Group)
def __str__(self):
return self.name
class UserGroupRelation(models.Model): #多对多,自己加中间表
user = models.ForeignKey(User)
group = models.ForeignKey(Group)
sqlite> .schema publish_usergrouprelation
CREATE TABLE IF NOT EXISTS "publish_usergrouprelation" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "group_id" integer NOT NULL REFERENCES "publish_group
" ("id"), "user_id" integer NOT NULL REFERENCES "publish_user" ("id"));
CREATE INDEX "publish_usergrouprelation_group_id_e393f98c" ON "publish_usergrouprelation" ("group_id");
CREATE INDEX "publish_usergrouprelation_user_id_0e041f81" ON "publish_usergrouprelation" ("user_id");
sqlite> .schema publish_group
CREATE TABLE IF NOT EXISTS "publish_group" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(20) NOT NULL);
sqlite> .schema publish_user
CREATE TABLE IF NOT EXISTS "publish_user" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(20) NOT NULL);
例:
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
def __str__(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.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField()
def __str__(self):
return self.headline
例:
与filter相反:
>>> b = Blog(name='beatles blog', tagline='all the latest beatles news')
>>> b.save()
>>> a1 = Author.objects.create(name='jowin',email='jowin@ane56.com')
>>> a2 = Author.objects.create(name='mage',email='mage@ane56.com')
>>> Author.objects.exclude(name='jowin')
>>> e = Entry(blog=Blog.objects.get(id=1),headline='test',body_text='test',pub_date=timezone.now(),n_comments=20,n_pingbacks=50,rating=100)
>>> e.save()
>>> e = Entry.objects.get(id=1)
>>> e.blog #一对多,前向查询,通过属性访问关联的(外部)对象
>>> e.authors.set(Author.objects.all())
>>> e.authors.all()
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() #一对多,反向查询,模型中有fk,该fk所指的模型实例可通过一个管理器返回前一个模型的所有实例,默认这个管理器的名字是
>>> b.entry_set.filter(headline__contains='test')
>>> b.entry_set.count()
1
class Entry(models.Model):
blog = models.ForeignKey(Blog, related_name='entries')
使用时用entries_set;
filter中的关键字参数默认是AND的关系;
若用OR的关系,得用Q对象(from django.db.models import Q),Q对象用于封装一组关键字参数;
查询函数get、filter、exclude中可混合使用Q对象和关键字参数,所有提供给查询函数的参数都将AND在一起,注意Q对象要在关键字参数前,如Poll.objects.get(Q(question__startswith='who'),Q(pub_date=date(2019,1,8)|Q(pub_date=date(2019,1,2)),Poll.objects.get(Q()|Q(),question__startswith='who');
推荐用符号&和|;
>>> from django.db.models import Q
>>> Author.objects.filter(Q(name='jowin')|Q(name='mage'))
>>> e = Entry.objects.create(blog=b,headline='test2',body_text='test2',pub_date=timezone.now(),n_comments=30,n_pingbacks=60,rating=90)
>>> e.blog
>>> e.blog = b
>>> a3 = Author.objects.create(name='mage2',email='mage2@magedu.com')
>>> a4 = Author.objects.create(name='jowin2',email='jowin2@magedu.com')
>>> e.authors = [a3]
>>> e.save()
>>> e.authors.add(a3,a4) #e.authors.set([])清空
>>> e.save()
>>> e.authors.create(name='mage3',email='mage3@magedu.com') #查询创建fk的value
Entry.objects.filter(headline__startswith='what').exclude(pub_date__gte=datetime.date.today()).filter(pub_date__gte=datetime(2019,1,8))
使用
gt、gte、lt、lte
contains #包含
exact #精确匹配,默认
startswith #开始于
endswith #结束于
regex #RE
icontains、iexact、istartswith、iendwith、iregex #忽略大小写
in #在列表中
range #范围之内
date、year、month、day #时间日期类型
>>> Entry.objects.filter(pub_date__gt='2018-12-31')
>>> Blog.objects.get(name__iexact='beatles blog')
>>> Blog.objects.filter(pk__in=[0,2,4])
>>> Entry.objects.filter(pub_date__range=(datetime.date(2018,12,31),datetime.date(2019,1,9)))
>>> Entry.objects.get(body_text__regex=r'^test2') #
>>> Entry.objects.filter(blog__name='beatles blog')
>>> Blog.objects.filter(entry__headline__contains='test') #反向
>>> Blog.objects.filter(entry__authors__name__isnull=True) #多层
>>> Blog.objects.filter(entry__authors__isnull=False,entry__authors__name__isnull=True) #多个过滤条件
>>> from django.db.models import F #模型字段查询F,通常是将模型字段与常量比较,或比较2个字段值
>>> Entry.objects.filter(n_pingbacks__gt=F('n_comments')) #点赞数大于评论数
>>> Entry.objects.filter(rating__gt=F('n_comments') + F('n_pingbacks'))
>>> Entry.objects.all()[:3] #同limit 5
>>> Entry.objects.all()[1:2] #同offset 1 limit 1
查询对象比较,用==,在后台比较的是2个模型主键的值:
some_entry == other_entry #some_entry.id == other_entry.id
https://docs.djangoproject.com/en/2.1/ref/models/querysets/
annotate():
添加注释属性,与聚合函数一起使用,返回聚合值;
>>> from blog.models import Blog,Author,Entry
>>> from django.db.models import Count
>>> q = Blog.objects.annotate(Count('entry'))
>>> q
>>> q[0].name
'beatles blog'
>>> q[0].entry__count
1
>>> qs = Blog.objects.annotate(entry_num=Count('entry'))
>>> for q in qs:
... print(q.entry_num)
...
1
1
aggregate():
聚合函数,返回是字典;
>>> qs = Blog.objects.aggregate(Count('entry'))
>>> qs
{'entry__count': 2}
>>> qs = Blog.objects.aggregate(entry_num=Count('entry'))
>>> qs
{'entry_num': 2}
聚合类函数:
from django.db.models import Avg,Count,Max,Min,StdDev(标准除),Sum,Variance(方差)
聚合类函数配合聚合函数aggregate()或注释函数annotate()使用;
distinct():
去重;
>>> Author.objects.distinct()
>>> Entry.objects.order_by('blog')
>>> Entry.objects.order_by('pub_date')
values():
返回是字典(列表套字典),而不是模型实例对象;
>>> Blog.objects.filter(name__startswith='beatles')
>>> Blog.objects.filter(name__startswith='beatles').values()
>>> Blog.objects.values()
>>> Blog.objects.values('id','name') #可指定显示某些字段
values_list():
返回列表套元组;
>>> Entry.objects.values_list('id')
>>> Entry.objects.values_list('id').order_by('id')
>>> Entry.objects.values_list('id',flat=True) #可指定显示某些字段;flat扁平,若元组中仅1个元素用flat会将元组脱掉,结果为列表
>>> Entry.objects.values_list('id',flat=True).order_by('id')
defer()、only():
若模型包含一些含有大量数据的类型,通常模型会将数据库取出的数据转换为py对象,有时可不需要浪费这样的性能,用defer排队、only仅转换指定的(将指定的字段转为可用属性方式访问);
>>> Entry.objects.defer('headline')
>>> Entry.objects.only('headline')
using():
使用哪个数据库;
在一主多从情况下,将查询指定到从库上,在settings.py中配;
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db0.sqlite3'),
},
'backup': {...},
}
>>> Entry.objects.all()
>>> Entry.objects.using('default') #Entry.objects.using('backup')
select_for_update():
返回一个queryset,会锁定相关行直到事务结束,在支持的数据库上产生一个select ... for update语句;
>>> Entry.objects.select_for_update().filter(authors=Author.objects.get(id=1))
raw():
执行原始sql;
>>> for s in Blog.objects.raw('select * from blog_blog'):
... print(s)
...
beatles blog
test2
get_or_create()、update_or_create():
能查到,返回;查不到,创建;
obj, created = Person.objects.get_or_create(
first_name='John',
last_name='Lennon',
defaults={'birthday':date(2019,1,8)},
)
等价于
try:
obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
obj = Person(first_name='John',last_name='Lennon',birthday=date(2019,1,8))
obj.save()
bulk_create():
批量创建;
>>> Blog.objects.bulk_create([Blog(name='test3',tagline='test3'),Blog(name='test4',tagline='test4')])
[
in_bulk():
将主键封装成列表,返回指定主键的记录;
>>> Blog.objects.in_bulk([3,4])
{3:
>>> Blog.objects.in_bulk([1,3])
{1:
latest()、earliest、first()、last():
>>> Entry.objects.latest('pub_date')
>>> Entry.objects.earliest('pub_date')
get_lastest_by()经常用,在Meta中指定;
事务是在view中实现,在函数执行完后才统一commit,默认是autocommit;
例:
from django.db import transaction
@transaction.atomic
def my_view(request):
do_stuff()
@transaction.atomic
def viewfunc(request):
do_stuff()
1、添加额外管理器,是为类增加“表级”功能的首选方式,可返回你想要的任何数据,而不是返回一个查询集;
如果要添加行级功能,如只对某个模型的实例起作用,应使用模型方法,而不是管理器方法;
2、添加自定义管理器:
from django.utils.translation import ugettext as _
class AuthorManager(models.Manager):
def get_queryset(self):
return super(AuthorManager, self).get_queryset().filter(role='A')
class EditorManager(models.Model):
def get_queryset(self):
return super(EditorManager, self).get_queryset().filter(role='E')
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
role = models.CharField(max_length=1, choices=(('A', _('Author'), ('E',_('Editor')))))
people = models.Manager()
authors = AuthorManager()
editors = EditorManager()