django之多表操作

一,创建多表模型

1,用了OneToOneField and ForeignKey,模型的字段,后面会自动加上_id,一般查询的时候,直接查询_id的内容,(如果插入不加_id时,需要插入一个对象)

2,ManyToManyField会自动创建第三张表

3,一对一的关系:OneToOneFiled,(也可以使用ForeignKey,需要添加唯一性约束(unique=True)但是不建议,)

一对多的关系:ForeignKey

多对多的关系:ManyToManyField

from django.db import models


# Create your models here.

class Publish(models.Model):
    # id如果不写会自动添加,名字叫nid,而且会自增,主键
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)
    # 存的依然是varchar类型,对于用户来说没什么用,在app的admin中有用
    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表如果在引用表的上面,则不需要添加引号,如果加上引号则存在就可以
    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>一对多数据添加(一对多数据修改一样)

方式一:(一对多,添加publish_id字段直接添加对应的id即可)
ret = Book.objects.create(name='西游记',price=23,publish_id=1)
print(ret)
方式二:(先根据Id获取其publish对象,然后在添加的时候Publish直接添加对象)
# 可以直接用pk(主键)添加
publish_obj = Publish.objects.grt(id=1)
ret = Book.object.create(name='红楼梦',price=54,publish=publish_obj)
print(ret)

2> 一对多修改

一对多修改数据
    # book=Book.objects.get(pk=1)
    # # book.publish=出版社对象
    # book.publish_id=2
    # book.save()
    # 方式二
    # book=Book.objects.filter(pk=1).update(publish=出版社对象)
    # book=Book.objects.filter(pk=1).update(publish_id=1)

2,一对多数据删除,与一对一数据的处理和单表操作是一样的

3,多对多数据处理一共存在四种方法

# 多对多新增
# 为红楼梦这本书新增一个叫jack,tom的作者
# jack=Author.objects.filter(name='jack').first()
# tom=Author.objects.filter(name='tom').first()
# book=Book.objects.filter(name='红楼梦').first()
# add 添加多个对象
book.authors.add(jack,tom)
# add添加作者id
book.authors.add(1,2)
#删除 remove,可以传对象,可以传id,可以传多个,不要混着用
book.authors.remove(jack)
book.authors.remove(2)
book.authors.remove(1,2)
# clear清空所有
book.authors.clear()
# set,先清空(清空的是该Book的所有链接),在新增,要传一个列表(可迭代对象),列表内可以是, id,也可以是对象
book.authors.set([jack,])
# ********这样不行,因为它打散了传过去了,相当于book.authors.set(jack)
# book.authors.set(*[jack,])

 

三,基于对象的跨表查询

1,一对一

正向:正向查找按字段

# 查询lqz作者的手机号   正向查询
# author=Author.objects.filter(name='jack').first()
# # author.authordetail 就是作者详情的对象
# authordetail=author.authordetail
# print(authordetail.phone)

反向:反向查找按表名小写

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

2,一对多

正向:正向查询按字段

# 正向 查询红楼梦这本书的出版社邮箱
# book=Book.objects.filter(name='红楼梦').first()
# # book.publish  就是出版社对象
# pulish=book.publish
# print(pulish.email)

反向:反向按表名小写_set.all()

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

3,多对多

正向:正向查询按字段,

# 查询红楼梦这本书所有的作者
# book=Book.objects.filter(name='红楼梦').first()
# book.authors.all()  #是所有的作者,是一个queryset对象,可以继续点
# print(book.authors.all())

反向:反向查询按表名小写_set.all()

# 查询lqz写的所有书
# lqz=Author.objects.filter(name='jack').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中

    # 一对一
    # 查询jack作者的手机号   正向查询  跨表的话,按字段
    # 以author表作为基表
    # ret=Author.objects.filter(name='jack').values('authordetail__phone')
    # print(ret)
    # 以authordetail作为基表 反向查询,按表名小写  跨表的话,用表名小写
    # ret=AuthorDetail.objects.filter(author__name='jack').values('phone')
    # print(ret)
    # 查询jack这个作者的性别和手机号
    # 正向
    # ret=Author.objects.filter(name='jack').values('sex','authordetail__phone')
    # print(ret)
    # 查询手机号是13888888的作者性别
    # ret=Author.objects.filter(authordetail__phone='13888888').values('sex')
    # print(ret)
    # ret=AuthorDetail.objects.filter(phone='13888888').values('author__sex')
    # print(ret)

3,基于双下划线一对多的查询

# 基于双下划线一对多查询
    # 例,查询出版社为背景出版社的所有图书的名字,价格
    ret = Publish.objects.filter(name='北京出版社').values('book__name','book__price')
    print(ret)
    ret = Book.objects.filter(publish__name='北京出版社').values('name','price')
    print(ret)
    # 查询北京出版社的价格大于19的书
    ret = Publish.objects.filter(name='北京出版社',book__price__gt=19).values('book__name','book__price')
    print(ret)

4,基于双下划线,多对多的查询

# 基于双下划线多对多的查询
    # 例,查询红楼梦的所有作者的名字
    ret = Book.objects.filter(name='呐喊').values('authors__name')
    print(ret)
    ret = Author.objects.filter(book__name='呐喊').values('name')
    print(ret)
    # 例,查询图书价格大于30的所有作者的名字
    ret = Book.objects.filter(price__gt=30).values('authors__name')
    print(ret)
    ret = Author.objects.filter(book__price__gt=30).values('name')
    print(ret)
    # 更进一步练习--->连续跨表查询
    # 查询北京出版社出版过的所有书籍的名字以及作者的姓名
    ret = Publish.objects.filter(name='北京出版社').values('book__name','book__authors__name')
    print(ret)
    ret = Book.objects.filter(publish__name='北京出版社').values('name','authors__name')
    print(ret)

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值