第十八 django及ORM操作
一、项目及ORM操作
1.添加新项目
python manage.py startapp blog
2.配置数据库类 models.py
from django.db import models # Create your models here. class Blog(models.Model): name = models.CharField(max_length=100) tag_line = 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() mod_date = models.DateField() authors = models.ManyToManyField(Author) n_comments = models.IntegerField() n_pingbacks = models.IntegerField() rating = models.IntegerField() def __str__(self): return self.headline
3.配置settings
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', #'app01.apps.App01Config', 'blog', ]
4.运行创建数据库py文件
运行报错,是因为url里面路径,涉及到以前的项目,应该注释
4.2.运行创建数据库py文件
4.3.运行创建表
4.4.查看数据库
5.blog 的项目
二、ORM 相关操作
1.通过命令插入blog项
1.1.原内容
1.2.通过命令插入新的
from blog.models import Blog b = Blog(name="美发品",tag_line='再也没有一天,是曾经的某一天') b.save()
1.3.查看结果
2.修改外键关联的表
2.1.查看原始内容
2.2.将“冬天会下雪”改掉
from blog.models import Entry entry = Entry.objects.get(pk=1) ckl_blog = Blog.objects.get(name="美发品") entry.blog = ckl_blog entry.save()
2.3.查看结果
没看出结果,呜呜呜~~~~
3.修改多对多关联的表
3.1.修改内容,添加作者
from blog.models import Author ckl = Author.objects.create(name='wukaka') entry.authors.add(ckl)
3.2.查看作者
4.单表内容查询
all_entry = Entry.objects.all() #查询所有
print(all_entry)
<QuerySet [<Entry: 春天花会开>, <Entry: 冬天会下雪>, <Entry: 暴雪将至>, <Entry: 天晴脚疼>]>
Entry.objects.filter(pub_date__year=2016) #查询出版年份在2016年 <QuerySet [<Entry: 暴雪将至>, <Entry: 天晴脚疼>]>
Entry.objects.all().filter(pub_date__year=2017) #同上查询出版年在2017年 <QuerySet [<Entry: 春天花会开>, <Entry: 冬天会下雪>]>
Entry.objects.all()[:3] #查询前3条数据
<QuerySet [<Entry: 春天花会开>, <Entry: 冬天会下雪>, <Entry: 暴雪将至>]>
Entry.objects.all()[2:3] #查询区间
<QuerySet [<Entry: 暴雪将至>]>
Entry.objects.order_by('headline')[0] #排序,查询第一个
<Entry: 冬天会下雪>
Entry.objects.get(pk=1) #查询一条值,主键为1
<Entry: 春天花会开>
Entry.objects.filter(pub_date__lte='2017-01-01') #查询日期小于2017-01-01
<QuerySet [<Entry: 暴雪将至>, <Entry: 天晴脚疼>]>
Entry.objects.get(headline__exact="冬天会下雪") #查询标题等于这个
<Entry: 冬天会下雪>
Entry.objects.get(headline__iexact="冬天会下雪") #同上,不区分大小写
<Entry: 冬天会下雪>
Entry.objects.get(body_text__contains='虚幻') #查询内容匹配'虚幻'的
<Entry: 暴雪将至>
5.联合查询
5.1.配置显示内容
修改admin
from django.contrib import admin from blog import models # Register your models here. class BlogAdmin(admin.ModelAdmin): list_display = ('blog','headline','body_text','pub_date','mod_date','n_comments','n_pingbacks') admin.site.register(models.Author) admin.site.register(models.Blog) admin.site.register(models.Entry,BlogAdmin)
5.2.查看内容
5.3.查询Entry所属板块包含“风雨中”
#!/usr/bin/env python # -*- coding: utf-8 -*- import os from django.core.wsgi import get_wsgi_application os.environ["DJANGO_SETTINGS_MODULE"] = "dj16.settings" import django django.setup() from blog import models from django.db.models import F obj = models.Entry.objects.get(blog__name__contains="风雨中") print(obj)
结果:
暴雪将至
5.4.查询所有的“n_comments”小于"n_pingbaks"
#!/usr/bin/env python # -*- coding: utf-8 -*- import os from django.core.wsgi import get_wsgi_application os.environ["DJANGO_SETTINGS_MODULE"] = "dj16.settings" import django django.setup() from blog import models from django.db.models import F # obj = models.Entry.objects.get(blog__name__contains="风雨中") # print(obj) objs = models.Entry.objects.filter(n_comments__lt=F("n_pingbacks")) print(objs)
查询结果:
<QuerySet [<Entry: 暴雪将至>, <Entry: 不想就是不想>]>
6.Caching and QuerySet
s
每个QuerySet都包含一个缓存来最小化数据库访问。 了解它的工作原理将允许您编写最高效的代码。
在新创建的QuerySet中,缓存是空的。 第一次对QuerySet进行评估 - 并因此发生数据库查询 - 查询结果将存储在QuerySet的缓存中,并返回已经明确请求的结果(例如,如果正在迭代QuerySet,则返回下一个元素)。 QuerySet的后续评估将重新使用缓存的结果。
记住这个缓存行为,因为它不能正确使用。 例如,下面将创建两个QuerySets,对它们进行评估,然后将其丢弃:
print([e.headline for e in Entry.objects.all()]) print([e.pub_date for e in Entry.objects.all()])
这意味着相同的数据库查询将执行两次,有效地加倍你的数据库负载。 此外,这两个列表可能会添加到相同的数据库记录中,因为它们可以添加到第二个或第二个请求中。
为了避免这个问题,只需保存QuerySet并重用:
queryset = models.Entry.objects.all() print([p.headline for p in queryset]) print([p.headline for p in queryset])
结果:
['我的欲望很多', '回忆中', '暴雪将至', '时间和雨蛙', '不想就是不想'] ['我的欲望很多', '回忆中', '暴雪将至', '时间和雨蛙', '不想就是不想']
当QuerySets没有被缓存时
查询集并不总是隐藏他们的结果。 当仅评估部分查询集时,将检查缓存,但未填充,则不会缓存查询返回的项目。 具体来说,这意味着将查询集限制为数组切片或索引将不会填充缓存。
例如,重复获取查询集中的某个索引
queryset = models.Entry.objects.all() print(queryset[4]) print(queryset[4])
查询结果:
不想就是不想
不想就是不想
但是,如果整个查询集已经被评估,缓存将被检查:
queryset = models.Entry.objects.all() [entry for entry in queryset] print(queryset[4]) print(queryset[4])
结果:
不想就是不想
不想就是不想
7.Complex lookups with Q
objects(复杂查询)
关键字参数查询 - 在filter()等 - “和”在一起。 如果您需要执行更复杂的查询(例如,使用OR语句的查询),则可以使用Q对象。
Q对象(django.db.models.Q)是一个用来封装关键字参数集合的对象。 这些关键字被指定为上面的“字段查找”。
7.1.例如,这个对象封装了一个LIKE查询:
#!/usr/bin/env python # -*- coding: utf-8 -*- import os from django.core.wsgi import get_wsgi_application os.environ["DJANGO_SETTINGS_MODULE"] = "dj16.settings" import django django.setup() from blog import models from django.db.models import F from django.db.models import Q obj = models.Entry.objects.filter( Q(blog__name__contains="过去岁月") ) print(obj)
查询结果:
<QuerySet [<Entry: 回忆中>, <Entry: 不想就是不想>]>
7.2. and 查询
#!/usr/bin/env python # -*- coding: utf-8 -*- import os from django.core.wsgi import get_wsgi_application os.environ["DJANGO_SETTINGS_MODULE"] = "dj16.settings" import django django.setup() from blog import models from django.db.models import F from django.db.models import Q obj = models.Entry.objects.filter( Q(n_comments__lt=F("n_pingbacks")),Q(pub_date__gt="2017-03-05") ) print(obj)
查询结果:
<QuerySet [<Entry: 不想就是不想>]>
7.2. or 查询
#!/usr/bin/env python # -*- coding: utf-8 -*- import os from django.core.wsgi import get_wsgi_application os.environ["DJANGO_SETTINGS_MODULE"] = "dj16.settings" import django django.setup() from blog import models from django.db.models import F from django.db.models import Q obj = models.Entry.objects.filter( Q(n_comments__lt=F("n_pingbacks")) | Q(pub_date__gt="2017-09-05") ) print(obj)
结果:
<QuerySet [<Entry: 我的欲望很多>, <Entry: 回忆中>, <Entry: 暴雪将至>, <Entry: 不想就是不想>]>
8.更新数据
原数据:
n_pingbacks 自增1:
#!/usr/bin/env python # -*- coding: utf-8 -*- import os from django.core.wsgi import get_wsgi_application os.environ["DJANGO_SETTINGS_MODULE"] = "dj16.settings" import django django.setup() from blog import models from django.db.models import F from django.db.models import Q obj = models.Entry.objects.update(n_pingbacks=F("n_pingbacks")+1)
查看结果:
9.复合查询
#!/usr/bin/env python # -*- coding: utf-8 -*- import os from django.core.wsgi import get_wsgi_application os.environ["DJANGO_SETTINGS_MODULE"] = "dj16.settings" import django django.setup() from blog import models from django.db.models import F from django.db.models import Q from django.db.models import Avg,Min,Max,Sum,Count print(models.Entry.objects.all().aggregate( Avg('n_pingbacks'),Sum('n_pingbacks'),Min('n_pingbacks'),Max('n_pingbacks') )) from fly import models as book_model pub_obj = book_model.Publisher.objects.last() print(pub_obj.name,pub_obj.book_set.select_related()) #反向关联查询 pub_objs = book_model.Publisher.objects.annotate(book_num=Count('book')) for publisher in pub_objs: print(publisher.book_num)
查询结果:
{'n_pingbacks__avg': 6.8, 'n_pingbacks__sum': 34, 'n_pingbacks__min': 4, 'n_pingbacks__max': 10} 猫狗出版社 <QuerySet [<Book: <梦的奥秘>>, <Book: <陳の夏休み>>, <Book: <老毛上山>>]> 4 1 3 3