表关系设计,增删改查

1.一对一,一对多,多对多表关系设计

在models.py中创建关系表.

from django.db import models

# Create your models here.


# 作者表
class Author(models.Model):
    name = models.CharField( max_length=32)
    age = models.IntegerField()

    # django2.x版本必须手动指定on_delete=models.CASCADE级联模式
    # au = models.OneToOneField(to="AuthorDetail", to_field="id", on_delete=models.CASCADE)
    # au = models.OneToOneField("AuthorDetail")
    # au = models.IntegerField()
    au = models.OneToOneField("AuthorDetail", db_constraint=False)
    # db_constraint=False取消foreign key的强制约束效果,还可以继续使用orm的提供的属性或者方法来操作关系记录
    # foreign key + unique

# 属性是OneToOneField或者ForeignKey,那么生成的对应字段是  属性名称_id

#作者详细信息表
class AuthorDetail(models.Model):
    birthday=models.DateField()
    telephone=models.BigIntegerField()
    addr=models.CharField(max_length=64)

# 出版社表
class Publish(models.Model):
    name=models.CharField( max_length=32)
    city=models.CharField( max_length=32)


#书籍表
class Book(models.Model):

    title = models.CharField( max_length=32)
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2)

    # publishs=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE)
    publishs=models.ForeignKey("Publish")
    authors = models.ManyToManyField('Author')


# class authortobook(models.Model):
#     book_id = models.ForeignKey('Book')
#     author_id = models.ForeignKey('Author')

2.记录的增删改查操作

增:

    #
    # 一对一关系的添加
    # 先创建作者详细信息表记录
    # ret = models.AuthorDetail.objects.create(
    #     birthday='2000-12-12',
    #     telephone='122',
    #     addr='惠州',
    # )
    #
    #
    # models.Author.objects.create(
    #     name='元涛',
    #     age=18,
    #     # au_id=ret.id,  #如果用的是属性名称_id,那么值为关联记录的id值
    #     au=ret,  #如果写属性名称来添加关系数据,那么值为关联记录的模型类对象
    # )


    # 一对多
    # pub_obj = models.Publish.objects.get(id=1)

    # models.Book.objects.create(
    #     title='白洁2',
    #     price=10,
    #     publishDate='1980-07-07',
    #     # publishs=pub_obj, #如果写属性名称来添加关系数据,那么值为关联记录的模型类对象
    #     publishs_id=2, #如果用的是属性名称_id,那么值为关联记录的id值
    #
    # )

    # 多对多

    # book_obj = models.Book.objects.get(title='金鳞岂是池中物')
    # author1 = models.Author.objects.get(id=1)
    # author2 = models.Author.objects.get(id=2)


    # book_obj.authors.add(author1,author2)
    # book_obj.authors.add(1, 2)

3.删除和更新

    # 删除      # 外键关联到这条作者记录的都会被删除(级联模式下)
    # 一对一
    # models.Author.objects.get(id=1).delete()
    # models.AuthorDetail.objects.get(id=2).delete()

    # 一对多
    # models.Book.objects.get(id=1).delete()
    # models.Publish.objects.get(id=2).delete()


    # 多对多删除
    book_obj = models.Book.objects.get(id=6)
    # book_obj = models.Book.objects.filter(id=5)[0]
    # book_obj.authors.remove(1)  # 4   1  删除第三张表中id为4 并且作者id为1的记录
    # book_obj.authors.clear()  # 清空 第三张表中的书籍id为5的所有记录
    # book_obj.authors.remove(1, 4)  #删除多条
    # book_obj.authors.remove(*[1, 4]) #删除多条


    # 修改
    # 一对一
    # models.Author.objects.filter(id=3).update(
    #     age=38,
    #     # au_id=5,
    #     # au=models.AuthorDetail.objects.get(id=5),
    # )

    # 一对多
    # models.Book.objects.filter(id=4).update(
        # title='白洁1',
        # publishs=models.Publish.objects.get(id=2),
        # publishs_id=2
    # )

    # 多对多

    obj = models.Book.objects.get(id=5)
    obj.authors.set(['1','3'])  #clear + add  跟新,先清空book_id为5的第三张表里的记录,再添加5 1和5 3记录

4.基于对象的跨表查询

    # 基于对象的跨表查询

    # 一对一的
    #  正向查询(关系属性在哪个表里面,通过这个表的数据去查询另外一张表的数据,就是正向查询)
    # 正向查询靠属性,反向查询靠表名小写

    # 查询一下闻哥这个作者的手机号
    # obj = models.Author.objects.get(name='闻哥')
    # obj.au   #这就找到了关联的详细信息表里面的那个记录对象
    # print(obj.au.telephone)

    # 查询手机号为555的作者姓名
    # obj = models.AuthorDetail.objects.get(telephone='555')
    # obj.author   #这就找到了关联的作者表表里面的那个记录对象
    # print(obj.author.name)



    # 一对多
    # 正向查询
    # 查询白洁1这本书是哪个出版社出版的
    # obj = models.Book.objects.get(title='白洁1')
    # obj.publishs   #找到了关联的出版社记录
    # print(obj.publishs.name)

    # 查询闻哥出版社出版了哪些书
    # 反向查询
    # 反向查询在一对多的关系是,使用  表名小写_set
    # obj = models.Publish.objects.get(name='闻哥出版社')
    # obj.book_set.filter()   #类似于objects控制器
    # books = obj.book_set.all()
    # for book in books:
    #     print(book.title)


    # 多对多
    # 查询一下白洁2这本书的作者是谁
    # 正向查询
    # obj = models.Book.objects.filter(title='白洁2').first()
    # obj.authors.all()  #类似objects控制器

    # objs = obj.authors.all()
    # for i in objs:
    #     print(i.name)


    # 查询一下何导写了哪些书
    # 反向查询
    # obj = models.Author.objects.get(name='何导')
    # objs = obj.book_set.all()
    # for i in objs:
    #     print(i.title)

5.基于双下划线的跨表查询

    #####基于双下划线的跨表查询 -- mysql连表查询
    # select app01_authordetail.telephone from app01_author inner join app01_authordetail on app01_author.au_id = app01_authordetail.id;
    # select app01_authordetail.telephone from app01_authordetail inner join app01_author on app01_author.au_id = app01_authordetail.id;
    
    # 正向查询靠属性, 反向查询靠表名小写
    
    # 一对一的
    # 查询一下闻哥这个作者的手机号
    # ret = models.Author.objects.filter(name='闻哥').values('au__telephone')
    # <QuerySet [{'au__telephone': '222'}]>
    # 反向查询
    # ret  = models.AuthorDetail.objects.filter(author__name='闻哥').values('telephone')
    # print(ret)  #<QuerySet [{'telephone': '222'}]>


    # 一对多的
    # 查询白洁1这本书是哪个出版社出版的
    # ret = models.Book.objects.filter(title='白洁1').values('publishs__name')
    # <QuerySet [{'publishs__name': '闻哥出版社'}]>
    # print(ret)

    # ret = models.Publish.objects.filter(book__title='白洁1').values('name')
    # print(ret)  #<QuerySet [{'name': '闻哥出版社'}]>

    # 多对多
    #  查询一下白洁2这本书的作者是谁
    # ret = models.Book.objects.filter(title='白洁2').values('authors__name')
    # <QuerySet [{'authors__name': '闻哥'}, {'authors__name': '何导'}]>
    # print(ret)

    # ret = models.Author.objects.filter(book__title='白洁2').values('name')
    # print(ret) #<QuerySet [{'name': '何导'}, {'name': '闻哥'}]>

6.聚合查询

    # 聚合查询
    # 查询所有书籍的平均价格
    # ret = models.Book.objects.all().aggregate(Avg('price'))
    # ret = models.Book.objects.aggregate(Max('price'),Avg('price'))
    # {'price__max': Decimal('19.00')} 字典类型数据,
    # ret = models.Book.objects.aggregate(m=Max('price'), a=Avg('price'))
    # 
    # print(ret)
    

7.分组查询

    # 分组查询  -- group by
    # 查询一下每个出版社出版书的平均价格
    # 默认是用Publish的id字段值作为分组依据,自动会找book表里面的publishs_id去分组
    # ret = models.Publish.objects.annotate(a=Avg('book__price')).values('a','name','city')
    
    # select t1.name,t1.city,avg(t2.price) from app01_publish as t1 inner join app01_book as t2 on t1.id = t2.publishs_id group by t1.id;(原生sql语句)

    #<QuerySet [{'name': '33期桔色成人出版社', 'city': '沙河', 'a': 12.5}, {'name': '超哥出版社', 'city': '松兰花', 'a': 14.0}, {'name': '牡丹花出版社', 'city': '洛阳', 'a': 13.75}]>


    # ret = models.Book.objects.values('publishs_id').annotate(a=Avg('price'))
    # select avg(price) from app01_book group by publishs_id;
    # print(ret)


    # 每个作者出版书的最高价格
    # 别忘了:  1.检查数据正确性   2.剔除无用数据
    # ret = models.Author.objects.annotate(m=Max('book__price')).values('name','m')
    # <QuerySet [{'name': '苑昊', 'm': None}, {'name': '何导', 'm': Decimal('17.00')}, {'name': '超哥', 'm': Decimal('19.00')}]>
    # print(ret)



    ret = models.Book.objects.values('authors__id').annotate(m=Max('price'))
    # <QuerySet [{'authors__id': '苑昊', 'm': 123},
    # 注意:一定要起别名a=  #结果为Publish模型类对象,对象中有本表字典数据
    # id name city a
    # print(ret)

 

posted @ 2021-04-17 17:28  urls  阅读(122)  评论(0编辑  收藏  举报