八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

环境:

成都创新互联是专业的钟楼网站建设公司,钟楼接单;提供网站建设、成都网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行钟楼网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!

根据关系创建表八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

首先建立django项目,编辑models.py 文件

models.py

from django.db import models

# Create your models here.
class Publish(models.Model):
    # id 如果不写,会自动生成,名字叫做nid,并且自增
    # 数据库不同,可能自动生成的id 名字也不太一样。
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)
    email = models.EmailField()

class Author_details(models.Model):
    phone = models.CharField(max_length=16)
    sex = models.IntegerField

class Author(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)
    # 使用了 OneToOneField 与 ForeignKey,模型表的字段,后面会自动加_id
    # 一对一的关系:OneToOneField
    authordetail_id = models.OneToOneField(to='Author_details', to_field='id')
    def __str__(self):
            return self.name

class Book(models.Model):
    name=models.CharField(max_length=16)
    # 浮点型,共5位,小数部分是2位
    price=models.DecimalField(max_digits=5,decimal_places=2)
    # to= 关联表    to_field= 关联表中的字段 ,一对多的关系使用 ForeignKey
    publish=models.ForeignKey(to=Publish,to_field='id')
    # ManyToManyField 会自动创建第三张表   多对多的关系
    authors=models.ManyToManyField(to=Author)
    def __str__(self):
            return self.name

迁移数据库

makemigrations

migrate

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

在项目中创建Py文件,可以运行在django环境中的代码

test.py

import os
if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pro77_13.settings")
    import django
    django.setup()

    from app01.models import *

一、多表模型创建,一对多的增删改,与多对多增删改

在app01_publish表中添加几条数据

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

一对多新增数据(接上面的继续写)

test.py

# 添加一本北京出版社出版的书
# 第一种方式
# ret=Book.objects.create(name='红楼梦',price=53.4,publish_id=1)
# print(ret.name)

# 第二种方式,存对象Publish=出版社对象,存到数据库是一个id
# pk:主键,是通过主键查找
publish=Publish.objects.filter(pk=2).first()
ret=Book.objects.create(name='红楼梦',price=53.4,publish=publish)
print(ret.name)

app01_book表

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

# 一对多修改数据

test.py

方式一:

book=Book.objects.get(pk=1)
# 解释:book.publish=出版社对象
book.publish_id=2
book.save()

app01_book表:

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

方式二:

# 解释:book=Book.objects.filter(pk=1).update(publish=出版社对象)
book=Book.objects.filter(pk=1).update(publish_id=1)

app01_book表:

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

多对多新增数据

首先需要在app01_author与app01_author_details表中添加数据

app01_author_details表:

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

app01_author表:

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

test.py

# 为红楼梦这本书新增一个叫lqz,egon的作者

方式一:

test.py

lqz=Author.objects.filter(name='lqz').first()
egon=Author.objects.filter(name='egon').first()
book=Book.objects.filter(name='红楼梦').first()
# # add 添加多个对象
book.authors.add(lqz,egon)

这样就可以在中间表里看见(app01_book_authors:中间表)

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

方式二:

# add添加作者id
book.authors.add(1,2)

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

# 删除 remove,可以传对象,可以传id,可以传多个,不要混着用

lqz=Author.objects.filter(name='lqz').first()
egon=Author.objects.filter(name='egon').first()
book=Book.objects.filter(name='红楼梦').first()
book.authors.remove(lqz)
# 也可以
# book.authors.remove(1,2)
# clear清空所有
# book.authors.clear()

set,要传一个列表,列表内可以是 id,也可以是对象

book.authors.set([2,])
# book.authors.set([lqz,])

app01_book_authors表

八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询

总结:

1 创建多表模型(详情见代码)
        #用了OneToOneField和ForeignKey,模型表的字段,后面会自定加_id
        # ManyToManyField会自动创建第三张表
        # *************重点
        # 一对一的关系:OneToOneField
        # 一对多的关系:ForeignKey
        # 多对多的关系:ManyToManyField
        
    2 添加表记录
        1 一对多新增
            -两种方式:
                -publish=对象
                -publish_id=id
        2 一对多删除:同单表删除
        3 一对多修改:两种方式,可以传对象,可以传id
        4 一对一跟一对多一样
        5 多对多:
            -add  ----->可以传对象,可以传id,可以传多个
            -remove  ----->可以传对象,可以传id,可以传多个
            -clear  ---->没有参数
            -set   ----->跟上面不一样,必须传列表,列表里面可以是对象,可以是id

二、基于对象的跨表查询

一对一:
    正向   author---关联字段在author--->authordetail   ------>  按字段
    反向   authordetail------关联字段在author--->author  -----> 按表名小写

正向查询:

lqz = Author.objects.filter(name='lqz').first()
egon = Author.objects.filter(name='egon').first()
book = Book.objects.filter(name='红楼梦').first()
# 查询lqz作者的手机号   正向查询
# author = Author.objects.filter(name='lqz').first()
# authordetail = author.authordetail_id
# print(authordetail.phone)

反向查询:

lqz = Author.objects.filter(name='lqz').first()
egon = Author.objects.filter(name='egon').first()
book = Book.objects.filter(name='红楼梦').first()
# 查询地址是 :手机号 属于哪位作者的   反向查询
authordetail=Author_details.objects.filter(phone='1385469823').first()
author=authordetail.author
print(author.name)

一对多:

    正向   book---关联字段在book--->publish   ------>  按字段
   反向   publish------关联字段在book--->book  -----> 按表名小写_set.all()

正向查询:查询红楼梦这本书的出版社邮箱

book=Book.objects.filter(name='红楼梦').first()
# # book.publish  就是出版社对象
publish=book.publish
print(publish.email)

反向查询:查询地址是北京 的出版社出版的图

publish=Publish.objects.filter(addr='北京').first()
# # publish.book_set.all()  拿出所有的图书
# books=publish.book_set.all()
# # 统计一下条数
books=publish.book_set.all().count()
print(books)

多对多:

正向   book---关联字段在book--->author   ------>  按字段.all()
反向   author------关联字段在book--->book  -----> 按表名小写_set.all()

正向:查询红楼梦这本书所有的作者

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

反向:查询lqz写的所有书

lqz=Author.objects.filter(name='lqz').first()
books=lqz.book_set.all()
print(books)

连续跨表
# 查询红楼梦这本书所有的作者的手机号

book=Book.objects.filter(name='红楼梦').first()
authors=book.authors.all()
for author in authors:
    authordetail=author.authordetail_id
    print(authordetail.phone)

# 基于对象的查询---是子查询也就是多次查询

在终端打印出sql语句

需要要settings.py中配置以下内容

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

test.py

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

对应的sql语句:

SELECT
    `app01_book`.`id`,
    `app01_book`.`name`,
    `app01_book`.`price`,
    `app01_book`.`publish_id` 
FROM
    `app01_book` 
WHERE
    `app01_book`.`name` = '红楼梦' 
ORDER BY
    `app01_book`.`id` ASC 
    LIMIT 1;

在查询结果之后的又一次查询(子查询,也就是多次查询)

print(book.authors.all())

对应的sql语句:

SELECT
    `app01_author`.`id`,
    `app01_author`.`name`,
    `app01_author`.`addr`,
    `app01_author`.`authordetail_id_id` 
FROM
    `app01_author`
    INNER JOIN `app01_book_authors` ON ( `app01_author`.`id` = `app01_book_authors`.`author_id` ) 
WHERE
    `app01_book_authors`.`book_id` = 1 
    LIMIT 21;

总结:

基于对象的跨表查询
        1 一对一
            正向:正向查询按字段
            反向:反向查询按表名小写
        2 一对多
            正向:正向查询按字段
            反向:反向按表名小写_set.all()
        3 多对多
            正向:正向查询按字段
            反向查询:反向按表名小写_set.all()
        4******基于对象的查询,多次查询(子查询)

# 基于双下划线的查询

# 一对一
# 查询lqz作者的手机号   正向查询  跨表的话,按字段
# 以author表作为基表

ret=Author.objects.filter(name='lqz').values('authordetail_id__phone')
print(ret)

# 以authordetail作为基表 反向查询,按表名小写  跨表的话,用表名小写

ret=Author_details.objects.filter(author__name='lqz').values('phone')
print(ret)

# 查询lqz这个作者的手机号
# 正向

ret=Author.objects.filter(name='lqz').values('authordetail_id__phone')
print(ret)

#查询手机号是 1529874130 的作者

ret=Author.objects.filter(authordetail_id__phone='1529874130')
print(ret)

ret=Author_details.objects.filter(phone='1529874130')
print(ret)



网页题目:八、多表模型操作,基于对象的跨表查询,基于双下划线的跨表查询
浏览地址:http://hbruida.cn/article/psgeee.html