Django之ORM跨表操作
1、一对一(OneToOneField)
class Author(models.Model): name = models.CharField(max_length=32) authorinfo = models.OneToOneField(to="AuthorInfo") class AuthorInfo(models.Model): addr = models.CharField(max_length=32) # 查 # 正向查询:.字段名.关联表的字段 # 需求:查看每个作者的地址 authors = models.Author.objects.all() for author in authors: print(author.name, author.authorinfo.addr) # 反向查询:.关联表名.关联表字段 # 需求:查看住在上海的作者姓名 authors_info = models.AuthorInfo.objects.filter(addr="上海") for author_info in authors_info: print(author_info.author.name) # 在ORM操作方法内使用跨表查询,主要方法filter,values, values_list等 # 正向查询:字段名__关联表字段 # 需求:直接拿到作者sun的住址 author_addr = models.Author.objects.filter(name="sun").values("authorinfo__addr") print(author_addr) # 结果:<QuerySet [{'authorinfo__addr': 'aaaaaa'}]> # 反向查询:关联表名__字段名 # 需求:查看住在上海的作者姓名 authors_name = models.AuthorInfo.objects.filter(addr="上海").values("author__name")
# 删除 # 由于是关联表,所以删除主表记录,从表相关记录也会删除 models.AuthorInfo.objects.filter(pk=6).delete() # pk是主键primary key
# 添加(修改也一样)把create换成update # 先添加主表AuthorInfo,再添加Author # 第一种方法: author_info = models.AuthorInfo.objects.create(addr="上海浦东新区") author = models.Author.objects.create(name="sun", authorinfo=author_info) # 第二种方法: author_info = models.AuthorInfo(addr="上海浦东新区") author_info.save() author = models.Author(name="sun", authorinfo=author_info) author.save()
2、一对多或多对一(ForeignKey)
class Book(models.Model): name = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) publish = models.ForeignKey(to='Publish') class Publish(models.Model): name = models.CharField(max_length=32) email = models.EmailField() # 查 # 正向查询:.表字段.关联表字段 # 需求:查找每本书的出版社名 books = models.Book.objects.all() for book in books: print(book.name, book.publish.name) # 反向查询:.关联表名_set # 查询id为1的出版社出版的书的书名 publish = models.Publish.objects.filter(id=1).first() # publish 是表对象 books = publish.book_set.all() # books是QuerySet对象 for book in books: print(book.name) # 在ORM操作方法内使用跨表查询,主要方法filter,values, values_list等 # 正向查询:.字段名__关联表字段 # 需求:查找每本书的出版社名 books = models.Book.objects.values("publish__name") print(books) # 反向查询:关联表名__字段名 # 查询id为1的出版社出版的书的书名 book_name = models.Publish.objects.filter(id=1).values("book__name") print(book_name)
# 删除 # 由于是关联表,所以删除主表记录,从表相关记录也会删除 models.Publish.objects.filter(pk=4).delete() # pk是主键primary key
# 添加(修改也一样)把create换成update # 先添加主表Publish,再添加Book # 第一种方法: publish = models.Publish.objects.create(name="xxx出版社", email="123@123.com") models.Book.objects.create(name="三体", price=35, publish=publish) # 或 publish = models.Publish.objects.filter(name="xxx出版社").first() models.Book.objects.create(name="三体", price=35, publish_id=publish.pk) # 第二种方式: publish = models.Publish(name="xxx出版社") publish.save() book = models.Book(name="三体",price=35, publish=publish) book.save()
3、多对多
3.1 ManyToManyField
class Book(models.Model): name = models.CharField(max_length=32) authors = models.ManyToManyField(to='Author') class Author(models.Model): name = models.CharField(max_length=32) # 创建表时,会自动创建第三张表"app01_book_authors", # 跨表查询时,就相当于隐藏了第三张表,直接到跨到另外张表,然后查询 # 查 # 正向查询:.表字段(得到QUerySet对象) # 查看id为1的书籍都有哪些作者 book = models.Book.objects.filter(pk=1).first() print(book.authors.all()) 结果:<QuerySet [<Author: Author object>, <Author: Author object>]> # 反向查询:.关联表名_set # 查看id=1的作者写了哪些书 author = models.Author.objects.filter(pk=1).first() print(author.book_set.all()) # 结果:<QuerySet [<Book: Book object>, <Book: Book object>]> # 在ORM操作方法内使用跨表查询,主要方法filter,values, values_list等 # 正向查询:.字段名__关联表字段 # 查看id为1的书籍都有哪些作者 authors = models.Book.objects.filter(pk=1).values("authors__name") print(authors) # 结果:<QuerySet [{'authors__name': 'sss'}, {'authors__name': 'aaa'}]> # 反向查询:关联表名__字段名 # 查看id=4的作者写了哪些书 books = models.Author.objects.filter(pk=1).values("book__name") print(books) #结果:<QuerySet [{'book__name': '三体'}, {'book__name': '白夜行'}]>
# 对ManyToManyField字段的增删改的方法 # 表内的其他字段按照正常的方法操作 # 添加 add # 特点: # 1. 无返回值 # 2. 如果数据存在,则不插入 # 正向插入:表对象.字段名.add() # 可以直接添加关联表的id,(如果添加一个不存在的id,也能添加上去) # add(2)、add(2,4)、add(*[2,4]) book = models.Book.objects.filter(id=1).first() book.authors.add(2) # 也可以添加对象,(必须插入关联表内已有的数据记录对应的对象) # add(obj)、add(obj1, obj2)、add(*[obj1, obj2]) book = models.Book.objects.filter(id=1).first() authors = models.Author.objects.filter(id__in=[2,3,4]) book.authors.add(*authors) # 反向插入:表对象.关联表名_set.add() author = models.Author.objects.filter(id=1).first() author.book_set.add(2) author = models.Author.objects.filter(id=1).first() books = models.Book.objects.filter(id__in=[3,4]) author.book_set.add(*books) # 删除 remove (用法同add) # 正向删除:表对象.字段名.remove() # 反向删除:表对象.关联表名_set.remove() # 清空 clear # 正向清空:表对象.字段名.clear() # 反向清空:表对象.关联表名_set.clear() book = models.Book.objects.filter(id=1).first() book.authors.clear() # 修改 set # 说明:1. 必须传入可迭代对象,列表,元组 # 正向修改:表对象.字段名.set() book = models.Book.objects.filter(id=1).first() author = models.Author.objects.filter(id=1).first() book.authors.set([author]) # 正向修改:表对象.关联表名_set.set() book = models.Book.objects.filter(id=2).first() author = models.Author.objects.filter(id=3).first() author.book_set.set([book])
3.2 第三张表
class Book(models.Model): name = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) class Book2Author(models.Model): """书籍和作者多对多关系表""" book = models.ForeignKey(to="Book") author = models.ForeignKey(to="Author") # 表的增删改查和一对多的操作一样,这里的主表是Book2Author, 从表是Book和Author
# 但跨表查询方法有很多:
# 示例 # 需求:找到《三个》书本都有哪些作者 # 第一种方式:先找书籍,反向查询到第三章表book2author, 在正向查询作者名 book = models.Book.objects.filter(name="三个").first() b_as = book.book2author_set.all() for b_a in b_as: print(b_a.author.name) # 第二种方式:操作第三张表筛选书本条件,然后正向查到作者姓名 book = models.Book.objects.filter(name="三个").first() b_as = models.Book2Author.objects.filter(book=book).all() for b_a in b_as: print(b_a.author.name) # 或者:(使用神奇的双下划线) b_as = models.Book2Author.objects.filter(book__name="三个").all() for b_a in b_as: print(b_a.author.name) # 第三种方式:直接在作者表查询,通过下划线跨两次表查询 authors = models.Author.objects.filter(book2author__book__name="三个").values("name") # 说明: # book2author__:跨到第三张表 # book2author__book__:通过第三张表的book字段跨到book表
3.3 第三张表+ManyToManyField
class Book(models.Model): name = models.CharField(max_length=32 authors = models.ManyToManyField(to='Author', through="Book2Author", through_fields=("book", "author")) class Book2Author(models.Model): """书籍和作者多对多关系表""" book = models.ForeignKey(to="Book") author = models.ForeignKey(to="Author") class Author(models.Model): name = models.CharField(max_length=32) # 说明: # 1. 查询时可隐藏第三章表,如:Book.objects.first().authors.all() # 2. 可以使用clear清空,但不能使用set,和remove,add # 3. 添加,修改,删除使用一对多的方法操作
4、事务
from django.db import transaction with transaction.atomic(): # ORM 操作 pass
5、MVC和MTV
MTV(django):
M: models
T: templates
V: views
MVC:
M: models
V: views
C: controller (urls+views)