ORM之多表操作

1、添加记录

外键字段

#方式一
#publish_id=2,另一个关联的表的主键id号
Book.objects.create(name='python',price=77,pub_date='2019-01-05',public_id=2)

#方式二
#publish=object
Book.objects.create(name='python',price=77,pub_date='2019-01-05',publish=publish_obj)

#### 多对多字段
book_obj=Book.objects.create(title="追风筝的人",publishDate="2012-11-12",price=69,pageNum=314,publish_id=1)
 
author_yuan=Author.objects.create(name="yuan",age=23,authorDetail_id=1)
author_tom=Author.objects.create(name="tom",age=32,authorDetail_id=2)

book_obj.author.add(author_tom,author_yuan) #将某个特定的 model 对象添加到被关联对象集合中。   =======    book_obj.authors.add(*[])
book_obj.authors.create()      #创建并保存一个新对象,然后将这个对象加被关联对象的集合中,然后返回这个新对象。

2、查询记录

一对多查询(Publish与Book)

#正向查询(按字段:publish):
#查询nid=1的书籍的出版社所在的城市
book_obj=Book.objects.get(nid=1)
print(book_obj.publish.city)  #  book_obj.publish是nid=1的书籍对象关联的出版社对象

#方向查询(按表名:book_set)
#查询 人民出版社出版过的所有书籍
publish=Publish.object.get(name='人民出版社')
book_list=publish.book_set.all() #与人民出版社关联的所有对象的集合

for book-obj in bool_list:
    print(book_obj.title)

多对多查询(Author与Book)

正向查询(按字段:authors):
#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)

注意:

你可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Article model 中做一下更改: publish = ForeignKey(Blog, related_name='bookList'),那么接下来就会如我们看到这般:

# 查询 人民出版社出版过的所有书籍
 
   publish=Publish.objects.get(name="人民出版社")
 
   book_list=publish.bookList.all()  # 与人民出版社关联的所有书籍对象集合

#### 双下划线的跨表查询
1、查询人民出版社出版过的所有书籍的名字与价格(一对多)
   #正向查询 按字段:publish
    ret=Book.objects.filter(publish__name='人民出版社' ).values_list("title","price")
    
   #反向查询,按表名:book
    ret1=Publish.objects.filter(name='人民出版社').values('book__title',"book__price")
    
2、查询tom出过的所有书籍的名字(多对多)
   #正向查询 按字段:author
    ret=Book.objects.filter(author__name="yuan").vaules("title")
    
   #反向查询 按表名:book
	ret1=Author.objects.filter(name='yuan').values("book__title")
 
3、手机号以151开头的作者出版过的所有书籍名称以及出版社名称
        ret=Book.objects.filter(authors__authorDetail__telephone__regex="151").values_list("title","publish__name")

注意:

反向查询时,如果定义了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")

#### F查询

Django提供F查询来对两个字段的值作比较,F()的实例可以在查询中引用字段,来比较同一个model实例中两个不同字段的值

#查询评论数大于收藏数的书籍
from django.db.models import F
Book.objects.filter(commentNum__lt=F('keepNum'))

# 查询评论数大于收藏数2倍的书籍
Book.objects,filter(commentNum__lt=F('keepNum')*2)

#将每一本书的价格提高30元
Book.objects.all().update(price=F("price")+30)

Q查询

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象

from django.db.models import Q
Q(title__startswith='Py')

Q 对象可以使用&| 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。

bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="tom"))

等同于下面的SQL WHERE 子句:

WHERE name ="yuan" OR name ="tom"

你可以组合&| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:

bookList=Book.objects.filter(Q(authors__name="yuan") & ~Q(publishDate__year=2017)).values_list("title")

查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如:

    bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017),
                                  title__icontains="python"
                                 )
posted @ 2019-04-04 22:12  Dandelion-L  阅读(119)  评论(0)    收藏  举报