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)
 
posted @ 2019-05-01 11:18  yw_sun  阅读(365)  评论(0编辑  收藏  举报