首页 > 编程语言 >进入python的世界_day53_Django模型层的外键建立、连表查询

进入python的世界_day53_Django模型层的外键建立、连表查询

时间:2022-12-15 21:13:51浏览次数:60  
标签:__ obj name python 外键 Django models 查询

一、ORM执行SQL语句

1.raw()

models.表名.objects.raw('sql语句')
# 注意,sql语句内的表,要用应用+表名 才是真正能查到的表

2.运用模块

​ 不会提示,要自己手敲,就是类似以前搞的pymysql,产生游标啊,游标发SQL语句,接收啊之类的

from django.db import connection  
cursor = connection.cursor()  
cursor.execute('SQL语句')
cursor.fetchone()  
cursor.fetchall()
cursor.fetchmany()
print(xxx)

=二、ORM之神奇的双下线查询==

​ 昨天的学习中,发现等于号是可以用的,我们再试试直接写大于小于号之类的,发现没法使用

​ ORM中,有特殊的语法

  • 补充:

    ​ 如果查询后的结果是QuerySet对象,还可以继续点方法

1.比较运算符

res = models.User.objects.filter(age__gt=30)
print(res)

字段__gt  	大于
字段__lt		小于
字段__gte		大于等于
字段__lte		小于等于

2.成员运算__in

age__in=(32, 48) # 年龄为32或者48的
name_in=[ ]

3.范围运算__range

# 顾头顾尾
age__range=(20,25)

4.模糊查询__contains

name__contains='卡' # 名字里有卡的,无论位置
name__contains='K'  # 名字里有大写K的,ORM区分大小写,mysql不区分

字段__icontains  忽略大小写

5.日期筛选

# 常用的
字段__year
字段__month
字段__day

三、ORM外键字段的创建

​ Mysql的外键相关知识:

https://www.cnblogs.com/wznn125ml/p/16923272.html#autoid-h2-2-0-7

主要就是mysql中多对多需要建立第三张关系表来搭线
ORM则可以不用自己主动建,待会就知道
1.一对多——models.ForeignKey()
ORM 中外键字段建在 多的一方 models.Foreignkey(to='xxx表',级联申明)
2.多对多——models.ManyToManyField()
ORM 中外键字段建在某张查询频率较高的,自动创建第三章表
当然,也能自己创建第三张关系表 但是还是要orm多对多字段做关联
3.一对一——models.OneToOneField()
ORM 中外键字段建在某张查询频率较高的

!!! 另外要注意
#django1.x版本外键字段默认都是级联更新删除 django2.x及以上需要自己申明  on_delete=models.XXX

​ 外键设立好后,记得那两句同步数据库数据代码!

​ 设立的外键字段,会自动加上_id,所有我们就不要在多对多的外键昵称上加上id,并且多对多的外键不会在设立表中展示,而是在虚拟的第三张表

四、外键字段的操作***

​ 写在开头,录入数据时,有多对多外键的那张表不能先录入数据,建议最后录入

# 表准备
from django.db import models


# Create your models here.
class Book(models.Model):
    """图书表"""
    title = models.CharField(max_length=32, verbose_name='书名')
    price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='价格')
    publish_time = models.DateField(auto_now_add=True, verbose_name='出版日期')

    # 创建书籍与出版社的一对多外键字段
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    '''django1.x版本外键字段默认都是级联更新删除 django2.x及以上需要自己申明  on_delete=models.XXX '''
    # 创建书籍与作者的多对多外键字段
    authors = models.ManyToManyField(to='Author')
    '''多对多字段为虚拟字段 用于告诉ORM自动创建第三张表'''

    def __str__(self):
        return f'数据对象:{self.title}'


class Publish(models.Model):
    """出版社表"""
    name = models.CharField(max_length=32, verbose_name='名称')
    address = models.CharField(max_length=64, verbose_name='地址')

    def __str__(self):
        return f'出版社对象:{self.name}'


class Author(models.Model):
    """作者表"""
    name = models.CharField(max_length=32, verbose_name='姓名')
    age = models.IntegerField(verbose_name='年龄')
    # 创建作者与作者详情的一对一外键字段
    author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)

    def __str__(self):
        return f'作者对象:{self.name}'


class AuthorDetail(models.Model):
    """作者详情表"""
    phone = models.BigIntegerField(verbose_name='手机号')
    address = models.CharField(max_length=64, verbose_name='家庭住址')

    def __str__(self):
        return f'详情对象:{self.address}'

# 数据自己看着加,可以直接用pycharm操作

1.给一对多外键字段添加 关联数据值

  • 创建的时候直接填写被关联表数据的主键值,不能超过范围!不然会报错,比如class_id=1

  • 直接填被关联表中相对应的对象(如果前面已经拿到了这个对象),直接用不带_id的键等于这个对象即可,比如class=class_obj

2.一对一同理

  • 创建的时候直接填写被关联表数据的主键值,不能超过范围!不然会报错,比如class_id=1

  • 直接填被关联表中相对应的对象(如果前面已经拿到了这个对象),直接用不带_id的键等于这个对象即可,比如class=class_obj

3.多对多***

​ 只需要拿到一个需要添加多对多外键值的对象,然后点一下外键字段,add添加即可(因为是多对多,所以可以添加好多个嘛)

book_obj = models.Book.objects.filter(pk=6).first()
book_obj.authors.add(1)
# 比如上面这个,先是拿到了主键为6的书对象,然后给虚拟的多对多的表,添加了一行,让主键为6的书对应了主键为1的作者,如果是add()多个,就是多行
# 同理add()内也可以是对象,一个或者多个
# 上面代码同等与如下
book_obj = models.Book.objects.filter(pk=6).first()
author_obj = models.Author.objects.filter(pk=1).first()
book_obj.authors.add(author_obj)

​ 如果要修改,可以用set( ) 里面套列表或者小元组都行,当然,对象也可以传,如果是空(),意思就是移除所有关联数据

book_obj = models.Book.objects.filter(pk=6).first()
book_obj.authors.set((1, 3))
# 意思是把多对多虚拟表中的原书表主键号为6的书对应的作者绑定关系换成1和3,每个对应关系一行,所以就是两行,该书如果绑了其他编号作者,一律删除行

​ 如果要移除,可以用remove( ) 来实现,其实也能用set()实现,也能用对象,这个倒是不用括号内再套

book_obj = models.Book.objects.filter(pk=7).first()
book_obj.authors.remove(1)

​ 如果要暴力一键移除,也可以用clear() ,不用填写东西进入括号,能一键删除多对多表中的该对象的所有数据

book_obj = models.Book.objects.filter(pk=6).first()
book_obj.authors.clear()

# 其实也等于set(())啦

五、正反向概念

​ 其实很简单,牢记一句话,外键字段在谁手里,就按这个点来判断

比如说,A和B两张表有关联,外键在A中,如果我想基于A的某个数据去查B的对应的数据,那么我就是正向查询,如果我是基于B的某个数据去查询A的对应的数据,那么我就是反向查询,主要注意外键位置和出发点就行

# 口诀
正向查询按外键字段,反向查询按表名小写(后面 还要跟_set)

比如说现在主键在书表
# 我想查询主键是1的作者,出版的书名——反向
author_obj = models.Author.objects.filter(pk=1).first()
print(author_obj.book_set.all().values('title')) # filter也行

# 我想查询主键是6的书的,作者名字————正向
book_obj = models.Book.objects.filter(pk=6).first()
print(book_obj.authors.filter().values_list('name')[0][0])

六、跨表查询***

# 复习一下
在mysql中,跨表查询有两个查询方法:
1.子查询
	将第一次查询的结果作为一张表,继续用于第二次查询,可以一直叠加,不过得自己理清

2.连表查询
	通过inner join 或者 left/right join 链接
    基于连接词将俩张表(如A和B)的列组合到一起产生新的结果表
    

1.一对多,两表

  • 主键在出发点:

​ 拿到对象后直接点外键即可站在被关联表内随意点数据

  • 主键不在出发点:

    拿到对象后,要用点被关联表的小写_set.all()就拿到了QS对象列表,可以按valus()取值了

author_obj = models.Author.objects.filter(name='东野奎吾').first()
res = author_obj.book_set.all()
for i in res:
    print(i.title)
>>>
幻夜
白夜行
嫌疑人X的献身
# 就举一个例子吧,上面代码是找到东野奎吾写的书的名字

2.一对一,两表

  • 主键在出发点

​ 拿到对象后直接点外键即可站在被关联表内随意点数据

  • 主键不在出发点:

    拿到对象后,要用点被关联表的小写即可拿到一对一的关联对象,然后点即可拿到要的数据,意思就是当结果可能是多个就要用_set,因为一对一是不可能对上多个的,所以八竿子都打不着set.all()

# 查询电话号码是123的作者的姓名
obj = models.AuthorDetail.objects.filter(phone=123).first()
print(obj.author.name)
>>>
东野奎吾

七、基于双下方法正反向查询

​ 只要可以做筛选的地方,都能正反查询

1.第一次正筛

# 查询主键为4的书的出版社名称———正向
obj = models.Book.objects.filter(pk=4).first()
print(obj.publish.name)

#————————————————————————————————
# 上述代码也可以这样写
obj = models.Book.objects.filter(pk=4).values_list('publish__name')
print(obj[0][0])
# 查询清华社出版过的书籍名称和价格————反向
    obj = models.Publish.objects.filter(name='清华社').values_list('book__title','book__price')
    for i in obj:
        print(f'书名:{i[0]} 价格:{i[1]}')
    
>>>
书名:白夜行 价格:555.00
书名:幻夜 价格:666.00
书名:嫌疑人X的献身 价格:56.78

2.第一次反筛(其实有点搞人)

obj = models.Publish.objects.filter(book__pk=4).values_list('name')
print(obj[0][0])
# 意思是查询,出版了,主键为1的书籍的出版社的名字

八、多表(2表以上)查询

	支持连续跨表,依旧是看正向反向,以及双下方法的使用,结果产生于最后一对一表,直接两次[0]拿,如果结果产生于最后的一对多表,结果for循环拿

​ 如果熟练使用,随便从哪个表入手,反正找关系就行了

# 查询主键为4的书籍的作者的姓名和电话号码
obj = models.Book.objects.filter(pk=6).values_list('authors__name','authors__author_detail__phone')
print(obj)

我查你,外键在我手,正向查询

我查你,外键在你手,反向查询

每日单词

equal 等于
DecimalField 小数字段 
max_digits 最大位数 
decimal_places小数位数

重点知识:多对多添加外键,修改外键
.set_all()

标签:__,obj,name,python,外键,Django,models,查询
From: https://www.cnblogs.com/wznn125ml/p/16986015.html

相关文章