首先来看下如何查询。我们在网页中增加书名的查询链接
后端的查询处理代码:这里由于authors是manytomanyfiled,因此我们这里用r.authors.all().first()来查询符合条件的第一个
def books_inquery_result(request): ret=[] if request.method == 'POST': bookname=request.POST['bookname'] result=Book.objects.filter(title=bookname) for r in result: ret.append(r.authors.all().first()) return HttpResponse(ret)但是当输入书名flask1的时候,我们查出来的确实下面这些代码。这是为什么呢。
我们回头看下之前添加books的操作:
ret3.publisher=Publisher.objects.all()[1] ret3.publish_date=publish_date ret3.save() ret3.authors.add(Author.objects.all()[1])
我们查询对应的Author.objects.all()[1]发现也是同样的结果。
def result2(request): result=Author.objects.all()[1] return HttpResponse(result)但是我们想要到的是书的作者和在网页上输入的对象关联起来。那么我们添加的代码就需要更新如下:这样就把之前的输入给加了进来
ret3=Book() ret3.title=title ret3.publisher=Publisher.objects.get(name=publish) ret3.publish_date=publish_date ret3.save() ret3.authors.add(Author.objects.get(email=email))此时再进行查询,就可以得到正确的结果了。而且我们还可以通过
r.authors.all().first().email r.authors.all().first().first_name r.authors.all().first().last_name 接下来看下如何查询出版商的信息,出版商是ForeignKey的关系。因此查询也很简单,通过下面的方式就可以查出出版商的信息。 r.publisher.address r.publisher. name r.publisher. city r.publisher. state_province r.publisher. country r.publisher. website select_related查询优化,首先我们在setting.py的末尾加上下面的配置: LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } } 这个logging的配置作用是在终端查询的时候自动打印出sql语句,这样我们就能很直观的看到查询的方式。比如前面的Book查询。我们来看下 Python manage.py shell In [1]: from site_prj.models import Publisher,Book,Author In [2]: books=Book.objects().all In [4]: b1=books[0] (0.002) SELECT "site_prj_book"."id", "site_prj_book"."title", "site_prj_book"."publisher_id", "site_prj_book"."publish_date" FROM "site_prj_book" LIMIT 1; args=() In [6]: b1.title Out[6]: u'flask' In [7]: b1.publisher (0.000) SELECT "site_prj_publisher"."id", "site_prj_publisher"."name", "site_prj_publisher"."address", "site_prj_publisher"."city", "site_prj_publisher"."state_province", "site_prj_publisher"."country", "site_prj_ publisher"."website" FROM "site_prj_publisher" WHERE "site_prj_publisher"."id" = 2; args=(2,) Out[7]: <Publisher: æ 我们看到在查询publisher的时候又调用了sql语句,原因在于Book中publisher 和Book的关系是ForeignKey的关系,也就是多对一的关系。可能一本书有多个出版商都在出版,那么我们能不能在查询的时候将这些出版商全都查出来呢。这就需要用到select_related的方法了。 ret2=Book.objects.all().select_related('publisher') #得到所有的文章 r2=ret2[10] #选择第10篇return HttpResponse(r2.publisher.state_province) #得到出版次文章的所有出版商的省份 In [9]: book2=Book.objects.all().select_related('publisher') In [10]: b2=book2[2] (0.000) SELECT "site_prj_book"."id", "site_prj_book"."title", "site_prj_book"."publisher_id", "site_prj_book"."publish_date", "site_prj_publisher"."id", "site_prj_publisher"."name", "site_prj_publisher"."address", "site_prj_publisher"."city", "site_prj_publisher"."state_province", "site_prj_publisher"."country", "site_prj_publisher"."website" FROM "site_prj_book" INNER JOIN "site_prj_publisher" ON ("site_prj_book"."publish er_id" = "site_prj_publisher"."id") LIMIT 1 OFFSET 2; args=() In [11]: b2.publisher.name Out[11]: u'\xe6\x88\x90\xe9\x83\xbd\xe6\x97\xa5\xe6\x8a\xa5' 从下面的调试可以看到,没有再进行SQL查询。那么我们现在来看下发现查询。什么是反向查询呢,之前的查询是引用方查询被引用方
比如在Book中publisher 和Book的关系是ForeignKey的关系,也就是多对一的关系.如果我想查出这本书的作者还写了哪些书。就需要用到反向查询。 代码如下: author=Author.objects.filter(first_name=first,last_name=second)for a in author: ret.append(a.book_set.all().first()) 得到每个作者的对象后用author.book_set.all().first()得到该作者写过的所有书。 同样的通过输入出版商也可以查出该出版商的所有书籍。 publish=Publisher.objects.filter(name=publishname)for p in publish: ret_publish.append(a.book_set.all().first())下面介绍下Values获取字典形式的结果。def result3(request): ret=[]result=Book.objects.values('title','authors','publisher','publish_date') for r in result: ret.append(r) return HttpResponse(ret) 这样能将所有的查询结果以字典的形式呈现出来。我们看到其中publisher和authro都是数字。而不是具体的名称。 我们来看下对应的sql语句:可以看到在sql语句中就是选用的是Publisher和Author的id作为查询条件且使用的是左链接的方式。 SELECT "site_prj_book"."title", "site_prj_book_authors"."author_id", "site_prj_book"."publisher_id", "site_prj_book"."publish_date" FROM "site_prj_book" LEFT OUTER JOIN "site_prj_book_authors" ON ("site_prj_book"."id" = "site_prj_book_authors"."book_id"); args=() 如果不想看字典的形式,而只是想看列表的方式,可以用values_list的方式 result=Book.objects.values_list('title','authors','publisher','publish_date') Annotate进行聚合,计数,平均数,求和等 下面首先来计算作者的个数: 首先引入模块:django.db.models里面包含所有的计算函数 from django.db.models import *def result2(request): result=Author.objects.all().values('email').annotate(count=Count('email')).values('email','count') return HttpResponse(result) 这个函数的作用是统计作者中的email使用总次数。计每个作者的email出现的次数。Annotate代表以某个元素进行聚类的意思。这里是以每个名字的次数进行聚类。返回结果如下。 我们还可以通过聚类求平均,但是目前的表中没有整数字段。我们在Author中添加一个age的字段。添加方法如下,进入python manage.py shell执行如下的语句。 In [1]: from django.db import connection In [2]: cursor=connection.cursor() In [3]: cursor.execute('Alter TABLE Authro add age Integer') In [8]: cursor.execute('Alter TABLE site_prj_Author add age Integer') (0.014) Alter TABLE site_prj_Author add age Integer; args=None Out[8]: <django.db.backends.sqlite3.base.SQLiteCursorWrapper at 0x3050a80> In [3]: print Author.objects.all().query SELECT "site_prj_author"."id", "site_prj_author"."first_name", "site_prj_author"."last_name", "site_prj_author"."email", "site_prj_author"."age" FROM "site_prj_author" 添加后我们就可以通过下面的方式进行作者平均年龄的计算了 result=Author.objects.all().values('age').annotate(average=Avg('age')).values('age','average') 对应的SQL语句: SELECT "site_prj_author"."age", AVG("site_prj_author"."age") AS "average" FROM "site_prj_author" GROUP BY "site_prj_author"."age"; args=() 链式查询: 过滤成都日报出版且城市是成都的出版商 result=Publisher.objects.filter(name='成都日报').filter(city='成都') 过滤成都出版社且城市不是成都出版商 result=Publisher.objects.filter(name='成都日报').exclude(city='成都') 对应的SQL语句: SELECT "site_prj_publisher"."id", "site_prj_publisher"."name", "site_prj_publisher"."address", "site_prj_publisher"."city", "site_prj_publisher"."state_province", "site_prj_publisher"."country", "site_prj_publisher"."website" FROM "site_prj_publisher" WHERE (NOT ("site_prj_publisher"."name" = '成都日报') AND "site_prj_publisher"."city" = '成都'); Defer排除不需要的字段:有些模型的字段太多,我们只想看其中几种可以用defer来排查某些字段 result=Author.objects.all().defer('age').query 对应的SQL:可以看到没有查询age字段 SELECT "site_prj_author"."id", "site_prj_author"."first_name", "site_prj_author"."last_name", "site_prj_author"."email" FROM "site_prj_author" 相对应的only就是选择需要的字段。 result=Author.objects.all().only('age').query 对应的SQL: SELECT "site_prj_author"."id", "site_prj_author"."age" FROM "site_prj_author" 最后补充model的所有类型描述:path:必需参数,一个目录的绝对文件系统路径。 FilePathField 据此得到可选项目。 Example: “/home/images”; match:可选参数, 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名。 注意这个正则表达式只会应用到 base filename 而不是路径全名。 Example: “foo。*\。txt^”, 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif; recursive:可选参数, 是否包括 path 下全部子目录,True 或 False,默认值为 False。
max_digits:总位数(不包括小数点和符号) decimal_places:小数位数。如:要保存最大值为 999 (小数点后保存2位),你要这样定义字段:models.FloatField(…,max_digits=5, decimal_places=2),要保存最大值一百万(小数点后保存10位)的话,你要这样定义:models.FloatField(…,max_digits=19, decimal_places=10)
正小整型字段,类似 PositiveIntegerField, 取值范围较小(数据库相关)SlugField“Slug” 是一个报纸术语。 slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符。它们通常用于URLs。 若你使用 Django 开发版本,你可以指定 maxlength。 若 maxlength 未指定, Django 会使用默认长度: 50,它接受一个额外的参数:
schema_path:校验文本的 RelaxNG schema 的文件系统路径。
转载于:https://www.cnblogs.com/zhanghongfeng/p/7976355.html
相关资源:django queryset 去重 .distinct()说明