【Django】数据库(ORM)各种关系表操作方法

目录

  • 1、一对一(OneToOneField)
  • 2、一对多或多对一(ForeignKey)
  • 3、多对多
  •   3.1 ManyToManyField
  •   3.2 第三张表
  •   3.3 第三张表+ManyToManyField
  • 4、事务
  • 5、MVC和MTV

 

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)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值