django-多表操作

#######多表操作########

多表操作和单表其实差不多,都是对数据库的增删查改

1、在models创建表就不多写了,就写写三种关系,
    一对一:OneToOneField(),括号还有参数,其实它就是ForeignKey(unique=True),外键不唯一
    一对多:ForeignKey(),外键
    ## 上面着两种你在数据库创建表的时候,会在对应的字段下加_id
    多对多:ManyToManyField,创建表的时候,自动会创建第三张表。

2、多表操作的增删改,查单独拿出来写。
    呃呃,那我把表都写出来吧,万一不写表,都不知道在写什么。

class Publish(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    address = models.CharField(max_length=64)
    email = models.EmailField()


class Authorinfo(models.Model):
    phone = models.IntegerField()
    email = models.EmailField()
    address = models.CharField(max_length=64)


class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    sex = models.IntegerField()  # 1男 2女 3其他
    authorinfo = models.OneToOneField(to='Authorinfo')  # 作者表和作者详情表一对一


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)
    create_time = models.DateField()
    publish = models.ForeignKey(to='Publish')  # 和出版社一对多关系
    author = models.ManyToManyField(to='Author')  # 和作者多对多关系

先写一对一的增删改:
    上面创建的表中,就Author和Authorinfo是一对一关系
    首先我们必须先要有Authorinfo,这样才能写Author它的记录,对吧!
    ret = models.Authorinfo.objects.create(phone=1787878,[email protected],address='重庆')
    第一种方法:
        zhuyu = models.Author.objects.create(name='朱宇',sex=1,authorinfo=ret)
    第二种方法:
        zhanghao = models.Author.objects.create(name='张昊',sex=1,authorinfo_id=2)
    上面的两种方法唯一不一样的就是authorinfo和authorinfo_id,
        authorinfo = Authorinfo对象
        authorinfo_id = Authorinfo对象的id
    authorinfo_id你在创建表之后,因为一对一关系嘛,它自动加了_id在后面,这样写你就直接将Authorinfo对象的id写上

    删除修改就不写了,和单表的一样
    models.Authorinfo.objects.filter(address='重庆').delete()
    # 你执行上面这行代码后,你的Authorinfo对应的记录会删除,还有就是Author中authorin_id相对应的也会删除。

继续写一对多的增删改
    上面创建的表中,Publish和Book是一对多的关系,首先我手动创建几条Publish表的记录,先不管Book表下面的author
    增:
        publish = models.Publish.objects.filter(pk=1).first()
        models.Book.objects.create(name='红楼梦',price='33.50',create_time='2017-11-11',publish=publish)
        models.Book.objects.create(name='西游记',price='59.50',create_time='2017-11-02',publish_id=2)
        # 对了,你通过实例的方法也行,再调用save方法
    删除,修改:
        models.Book.objects.filter(name='红楼梦').delete()
        models.Book.objects.filter(name='红楼梦').update(publish_id=2)

写多对多的增删改
    上面创建的表中,Book和Author是多对多的关系。
    # 添加
        # 红楼梦这本书添加两位作为,叫朱宇(id=4),张昊(id=5)
        zhuyu = models.Author.objects.filter(name='朱宇').first()
        zhanghao = models.Author.objects.filter(name='张昊').first()
        models.Book.objects.filter(name='红楼梦').first().author.add(zhuyu,zhanghao)  # 方式一
        models.Book.objects.filter(name='红楼梦').first().author.add(4,5)  # 方式二
        # add方法,可以传多个参数,可以是对象,也可以是id值
        # 首先找到红楼梦这本书,这书下面不是有author对象嘛?再调用add方法,传参就好了。
        # id为4,5,我是直接再数据库看到的,只是为了方便

    # 删除
        # 删除红楼梦这本书的两名作者,叫张昊(id=5),朱宇(id=4)
        zhuyu = models.Author.objects.filter(name='朱宇').first()
        zhanghao = models.Author.objects.filter(name='张昊').first()
        models.Book.objects.filter(name='红楼梦').first().author.remove(zhanghao,zhuyu)    # 方式一
        models.Book.objects.filter(name='红楼梦').first().author.remove(4,5)  # 方式二

    # 清空
        # 删除完红楼梦这本书的作者
        models.Book.objects.filter(name='红楼梦').first().author.clear()

    # 修改
        修改无非就添加新的作者,添加也分情况,1、在原有基础上添加(add方法可以实现),2、在空的情况下添加(set方法)
        # 红楼梦这本书的作者只设置为朱宇,张昊两个人
        # 分析一下,只设置为这两个人,万一之前这书有其他作者,你用add方法完全不行,那就先clear,然后add再添加
        models.Book.objects.filter(name='红楼梦').first().author.clear()
        models.Book.objects.filter(name='红楼梦').first().author.add(4,5)
        # 这样写是不是太麻烦了,直接用set方法就好,运行步骤差不多一致吧(猜测)
        models.Book.objects.filter(name='红楼梦').first().author.set([4,5])
        # set()里面参数必须是可迭代的,你直接记传列表就好了

下面就主要写查了。
    再写查之前,我先写写正向,反向的概念,以下面这两个表为例哈
class Authorinfo(models.Model):
    phone = models.IntegerField()
    email = models.EmailField()
    address = models.CharField(max_length=64)
class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    sex = models.IntegerField()  # 1男 2女 3其他
    authorinfo = models.OneToOneField(to='Authorinfo')

    通过(Author表)朱宇的作者对象,想要查找(Authorinfo表)他的电话(phone) ---->这就是正向查找
    通过Authorinfo表)电话(phone)为18716754,查找(Author表)哪位作者   ---->这就是反向查找
    疑问:你说凭什么通过Author表,查到到Authorinfo表 就是正向查找呢?
    解答:因为Author表关联一对一关系的字段就在Author表里,没有为什么。
    结论:关联表之间关系的字段在哪个表中,那么从那个表查找到被关联表的字段,就是正向查找,反过来就是反向查找

好了,继续写一对一的查找
    正向:直接查询字段
    反向:查询表名的小写
    # 查询作者叫朱宇的手机号码(phone)  这是正向对吧
    zhuyu = models.Author.objects.filter(name='朱宇').first()
    phone = zhuyu.authorinfo.phone

    # 查询电话号码为2147483647的作者名字  反向
    phone = models.Authorinfo.objects.filter(phone=2147483647).first()
    name = phone.author.name

    ### 记住上面正向按照什么查询,反向又按照什么查询

一对多的查看
    正向:按照字段查询
    反向:按照表名小写_set.all(),all()只是把所有数据取了出来,是一个queryset对象
    # 一对多关系就只有publish和book,
    # 查询红楼梦这本书出版社的名字    book--->publish 关联关系字段在book表中,所以正向吧!
    book = models.Book.objects.filter(name='红楼梦').first()
    name = book.publish.name

    # 查询重庆大学出版社出版所有书籍名字 publish--->book 反向吧
    publish = models.Publish.objects.filter(name='重庆大学出版社').first()
    book_name = publish.book_set.all().values('name')

多对多查找
    正向:按照字段查询
    反向:按照表名小写_set.all(),all()只是把所有数据取了出来,是一个queryset对象
    # 多对多的关系就是author和book表了
    # 查询红楼梦这本书作者的名字
    book = models.Book.objects.filter(name='红楼梦').first()
    authors = book.author.all().values('name')

    # 查询作者朱宇,出版的书籍名字
    zhuyu = models.Author.objects.get(name='朱宇')
    books = zhuyu.book_set.all().values('name')

# 上面这些其实是基于对象跨表查询,子查询,就是说拿着上一条命令的结果,执行下一条
# 完成一个指定的要求,执行了几条sql语句


既然有基于对象跨表查询,那么就有不基于对象的跨表查询,就是基于双下划线跨表查询

一对一:(author,authorinfo表)
    # 查询作者名字叫朱宇的手机号
    方式一:phone = models.Author.objects.filter(name='朱宇').values('authorinfo__phone')
    方式二:phone = models.Authorinfo.objects.filter(author__name='朱宇').values('phone')
    # 为什么这么写?
    # 首先看题目,作者名字为朱宇,筛选条件已经告诉你了,所有filter肯定是朱宇
    # models.Author.objects.filter(),写在这里的时候,你再想,我以Author为基表,找Authorinfo里的字段
    # 作者名字是不是在基表里?对在,那就直接filter(name='朱宇'),我想要找到Authorinfo里的phone字段,
    # 跨表查询就用表名__字段名就行。

    # 那我们再看看方式二,一样的思考方式,基表是谁?对就是Authorinfo,那作者名字那字段是不是不在基表里,跨表查询
    # 就用表名__字段名,所有filter(author__name='朱宇'),phone在基表里吧,直接values('phone')。

    # 其实你了解到了这个方法,一对多,多对多都是一样。

一对多:(publish、book表)
    # 查询红楼梦这本书的出版社的名字
    方式一:name = models.Publish.objects.filter(book__name='红楼梦').values('name')
    方式二:name = models.Book.objects.filter(name='红楼梦').values('publish__name')

多对多:(book,author表)
    # 查询红楼梦这本书的作者名字
    name = models.Book.objects.filter(name='红楼梦').values('author__name')
    name = models.Author.objects.filter(book__name='红楼梦').values('name')

猜你喜欢

转载自www.cnblogs.com/zhuchunyu/p/9954538.html