一:多表操作之增、删、改
1.1:增:
一对多:
方式1:
publish_obj=Publish.objects.get(nid=1)
book_obj=Book.objects.create(title="海尔兄弟",publishDate="2012-12-12",price=100,publish=publish_obj)
方式
2:
book_obj=Book.objects.create(title="海尔兄弟",publishDate="2012-12-12",price=100,publish_id=1)
多对多:
# 当前生成的书籍对象 book_obj=Book.objects.create(title="追风筝的人",price=200,publishDate="2012-11-12",publish_id=1) # 为书籍绑定的做作者对象 yuan=Author.objects.filter(name="yuan").first() # 在Author表中主键为2的纪录 egon=Author.objects.filter(name="alex").first() # 在Author表中主键为1的纪录 # 绑定多对多关系,即向关系表book_authors中添加纪录 book_obj.authors.add(yuan,egon) # 将某些特定的 model 对象添加到被关联对象集合中。
1.2:删
book_obj.authors.remove() # 将某个特定的对象从被关联对象集合中去除。 ====== book_obj.authors.remove(*[])
book_obj.au
thors.clear()
#清空被关联对象集合
1.3:改
set会先清空在设置:
new_list = [obj1, obj2, obj3]
e.related_set = new_list
注意:对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。
1.4:补充:
clear() :从关联对象集中移除一切对象。
b
=
Blog.objects.get(id=1)
b.entry_set.clear()
注意这样不会删除对象
——
只会删除他们之间的关联。
就像remov
e()
方法一样,clear()只能在
nul
l=True的ForeignKey上被调用。
add(obj1[, obj2, ...])
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
二:多表操作之查询
正向查询按字段,反向查询按表明
2.1:基于对象查询
一对多正向查询:按字段,publish
# 查询主键为1的书籍的出版社所在的城市 book_obj=Book.objects.filter(pk=1).first() # book_obj.publish 是主键为1的书籍对象关联的出版社对象 print(book_obj.publish.city)
一对多反向查询:按表名_set(book_set)
publish=Publish.objects.get(name="苹果出版社") #publish.book_set.all() : 与苹果出版社关联的所有书籍对象集合 book_list=publish.book_set.all() for book_obj in book_list: print(book_obj.title)
多对多正向查询:正向查询按字段
# python所有作者的名字以及手机号 book_obj=Book.objects.filter(title="python").first() authors=book_obj.authors.all() for author_obj in authors: print(author_obj.name,author_obj.authorDetail.telephone)
多对多反向查询:反向查询按表名_set
# 查询egon出过的所有书籍的名字 author_obj=Author.objects.get(name="yjp") book_list=author_obj.book_set.all() #与yjp作者相关的所有书籍 for book_obj in book_list: print(book_obj.title)
2.2:基于双下划线查询
正向查询按字段,反向查询按表名
多对多正向查询:正向查询按字段
# 正向查询 按字段:authors: queryResult=Book.objects.filter(authors__name="yjp").values_list("title")
多对多反向查询:反向查询按字段
# 反向查询 按表名:book queryResult=Author.objects.filter(name="yuan").values("book__title","book__price")
values和values_list区别:
values():返回QuerySet对象
values_list():返回list
注意:
反向查询时,如果定义了related_name ,则用related_name替换表名,例如:
publish = ForeignKey(Blog, related_name='bookList')
#反向查询 不再按表名:book,而是related_name:bookList queryResult=Publish.objects .filter(name="人民出版社") .values_list("bookList__title","bookList__price")
三:聚合查询和分组查询
3.1:聚合查询
from django.db.models import Sum,Avg,Max,Min # 导入分组函数 # 计算所有图书的平均价格,返回{'price__avg': 34.35} Book.objects.all().aggregate(Avg('price')) #计算所有图书的价格,和,最大值,最小值 #返回字典 Book.objects.aggregate(Sum('price'), Max('price'), Min('price'))
3.2:分组查询
from django.db.models import Count #导入分组函数 # 标签列表 通过mldels进行跨表查询,并通过'article_tags'进行分组 # 返回值中 c 就是分组后的值
tag_list=UserInfo.objects.filter(username=username).values(c=Count('article__tags')).values_list('c','article__tags__title')
四:F查询,Q查询,extra
4.1:F查询:可以引用当前表内的字段
在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
# 查询评论数大于收藏数的书籍 from django.db.models import F Book.objects.filter(commnetNum__lt=F('keepNum'))
Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
# 查询评论数大于收藏数2倍的书籍 Book.objects.filter(commnetNum__lt=F('keepNum')*2)
4.2:Q查询:可对查询条件进行 & | ~ 与 或 非 操作
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象
查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。
#与 bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon")) #与和非 bookList=Book.objects.filter(Q(authors__name="yuan") & ~Q(publishDate__year=2017)).values_list("title") #混合使用 bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017), title__icontains="python" )
4.3:extra: django提供的sql语句不能进行复杂的操作,extra可以对现有的操作函数进行扩展
extra源码:
def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None): """ Adds extra SQL fragments to the query. """ assert self.query.can_filter(), "Cannot change a query once a slice has been taken" clone = self._clone() clone.query.add_extra(select, select_params, where, params, tables, order_by) return clone
extra用法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
## select提供简单数据 # SELECT age, (age > 18) as is_adult FROM myapp_person; Person.objects.all().extra(select={'is_adult': "age > 18"}) # 加在select后面 ## where提供查询条件 # SELECT * FROM myapp_person WHERE first||last ILIKE 'jeffrey%'; Person.objects.all().extra(where=["first||last ILIKE 'jeffrey%'"]) # 加一个where条件 ## table连接其它表 # SELECT * FROM myapp_book, myapp_person WHERE last = author_last Book.objects.all().extra(table=['myapp_person'], where=['last = author_last']) # 加from后面 ## params添参数 # !! 错误的方式 !! first_name = 'Joe' # 如果first_name中有SQL特定字符就会出现漏洞 Person.objects.all().extra(where=["first = '%s'" % first_name]) # 正确方式 Person.objects.all().extra(where=["first = '%s'"], params=[first_name])