Django框架(十)—— 多表操作:一对一、一对多、多对多的增删改查

多表操作:一对一、一对多、多对多的增删改查

一、创建多表模型

一对一:OneToOneField

一对多:ForeignKey

多对多:ManyToManyField

  • 创建表时,会自动添加一个nid字段,并且自增,所以id可以不用手动创建

  • OneToOneField和ForeignKey会自动在后面加上" _id "

  • ManyToManyField会自动创建第三张表

  • 创建表的类,OneToOneField、ForeignKey和ManyToManyField中的to后的主表,
    1、如果用双引号包裹,那么创建主表的类在上在下都可以

    2、如果不用双引号包裹,那么创建主表的类就必须在从表的上方

二、一对多增删改表记录

class Publish(models.Model):
    # id如果不写,会自动生成,名字叫nid,并且自增
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)
    email = models.EmailField()


class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    # 数字类型
    sex = models.IntegerField()
    # to='AuthorDetail'  加引号,这个表能找到就可以,不用引号,类必须在上面定义
    authordetail = models.OneToOneField(to='AuthorDetail', to_field='id')

    def __str__(self):
        return self.name


class AuthorDetail(models.Model):
    id = models.AutoField(primary_key=True)
    phone = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)


class Book(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish = models.ForeignKey(to=Publish, to_field='id')

    authors = models.ManyToManyField(to=Author)

    def __str__(self):
        return self.name

1、一对多添加记录

(1)通过 _id 来添加记录

models.Book.objects.create(name='红楼梦',price=20.0,publish_id=1)

(2)通过对象添加记录

# pk 表示主键,一旦主键改变,还是会找到对应的主键来获取对象
publish = models.Publish.objects.filter(pk=1).first()
models.Book.objects.create(name='红楼梦',price=34.5,publish=publish)

2、一对多删除记录

删除记录同单表删除记录一样

models.Book.objects.filter(name='红楼梦').first().delete()

3、一对多修改记录

(1)通过queryset对象的update方法修改

# 方式一:通过 _id 修改
models.Book.objects.filter(pk=1).update(name='西游记',publish_id=1)

# 方式二:通过对象修改
publish = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=1).update(name='西游记',publish=publish)

(2)通过对象的属性修改,调用对象的save()方法保存

# 方式一:通过 _id 修改
book = models.Book.objects.filter(pk=1).first()
book.publish_id = 2
book.save()

# 方式二:通过对象修改
publish = models.Publish.objects.filter(pk=2).first()
book.publish = publish
book.save()

三、一对一增删改记录

一对一的增删改记录和一对多的方法相同,参考一对多的增删改记录

四、多对多增删改记录

1、多对多增加记录

add()    # 可以传对象,可以传id,可以传多个

(1)通过对象添加记录

# 为红楼梦这本书添加一个作者
tom = models.Author.objects.filter(name='tom').first()
book = models.Book.objects.filter(name='红楼梦').first()
tony = models.Author.objects.filter(name='tony').first()
jack = models.Author.objects.filter(name='jack').first()
book.authors.add(tom)
# 一次添加两个作者,中间用逗号隔开
book.authors.add(tony,jack)

(2)通过 id 添加记录

book = models.Book.objects.filter(name='红楼梦').first()
book.authors.add(1)
# 一次添加两个作者,中间用逗号隔开
book.authors.add(1,2)

2、多对多删除记录

remove()    # 可以传对象,可以传id,可以传多个

(1)通过对象删除记录

# 删除红楼梦作者名字是tom的作者
tom = models.Author.objects.filter(name='tom').first()
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.remove(tom)

(2)通过id删除记录

# 删除红楼梦作者id是1、2的两个作者
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.remove(1,2)

3、多对多清空记录

clear()    # 没有参数
# 清除红楼梦的所有作者
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.clear()

4、多对多修改记录

set()    # 先清空在增加,必须传列表,列表里面可以是对象,可以是id

(1)通过对象修改记录

# 修改红楼梦作者名字为tom
tom = models.Author.objects.filter(name='tom').first()
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.set([tom,])

(2)通过id修改记录

# 修改红楼梦作者为作者id是1、2的作者
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.set([1,2])

五、基于对象的跨表查询--多次查询、子查询

正向查询和反向查询

正向查询:关联字段在从表,由从表查询主表中的数据    -----> 按字段查询
反向查询:关联字段在从表,由主表查询从表中的数据    -----> 按表名小写查询

1、一对一基于对象的跨表查询

正向:正向查询按 字段
反向:反向查询按 表名小写
# 1.查询tom作者的手机号   正向查询
author=Author.objects.filter(name='tom').first()
    # author.authordetail 就是作者详情的对象
authordetail=author.authordetail
print(authordetail.phone)

# 2. 查询地址是山东的作者名字   反向查询
authordetail=AuthorDetail.objects.filter(addr='山东').first()
    # authordetail.author  这是作者对象
author=authordetail.author
print(author.name)

2、一对多基于对象的跨表查询

正向:正向查询按 字段
反向:反向按 表名小写_set.all()
# 1.正向 查询红楼梦这本书的出版社邮箱
book=Book.objects.filter(name='红楼梦').first()
    # book.publish  就是出版社对象
pulish=book.publish
print(pulish.email)

# 2.反向  查询地址是北京的出版社出版的图书
publish=Publish.objects.filter(addr='北京').first()
    # publish.book_set.all()  拿出所有的图书
books=publish.book_set.all()
    # 统计一下条数
books=publish.book_set.all().count()
print(books)

3、多对多基于对象的跨表查询

正向:正向查询按 字段
反向:反向按 表名小写_set.all()
# 1.查询红楼梦这本书所有的作者
book=Book.objects.filter(name='红楼梦').first()
book.authors.all()  # 是所有的作者,是一个queryset对象,可以继续点
print(book.authors.all())

# 2.查询lqz写的所有书
lqz=Author.objects.filter(name='lqz').first()
books=lqz.book_set.all()
print(books)

六、基于双下划线的跨表查询

1、连表查询

# 查询红楼梦这本书所有的作者的手机号
    book=Book.objects.filter(name='红楼梦').first()
    authors=book.authors.all()
    for author in authors:
        authordetail=author.authordetail
        print(authordetail.phone)

2、一对一的基于双下划线的跨表查询

正向:按 字段,跨表可以在filter,也可以在values中
反向:按 表名小写,跨表可以在filter,也可以在values中
# 1.查询lqz作者的手机号   正向查询  跨表的话,按字段
   # 以author表作为基表
    ret=Author.objects.filter(name='lqz').values('authordetail__phone')
    print(ret)
    
# 2.以authordetail作为基表 反向查询,按表名小写  跨表的话,用表名小写
    ret=AuthorDetail.objects.filter(author__name='lqz').values('phone')
    print(ret)

猜你喜欢

转载自www.cnblogs.com/linagcheng/p/9953252.html