双下查询,ORM创建外键,多表查询

双下划线查询方法

比较运算

# 关键字:
    大于:		__gt
    小于:		__lt
    大于等于:		__gte
    小于等于:		__lte
# 举例:
    res = models.User.objects.filter(age__gt=18)
    print(res)   # 年龄大于18
    res1 = models.User.objects.filter(age__lt=18)
    print(res)   # 年龄小于18
    res2 = models.User.objects.filter(age__gte=18)
    print(res2)  # 年龄大于等于18
    res3 = models.User.objects.filter(age__lte=18)
    print(res3)   # 年龄小于等于18

在某一数据集内:

# 关键字:__in=['数据集']

# 举例:
    res = models.User.objects.filter(age__in=[10,20,30,40])
    print(res)

在某一范围内:

# 关键字:__range=[]
# 举例:
    res = models.User.objects.filter(age__range=[19,40]) # 包含19和40
    print(res)

模糊查询:

# 关键字:__contain=''  区分大小写
	 __icontain=''  不区分大小写
# 举例:
查询姓名中包含字母k的用户
    res = models.User.objects.filter(name__contains='k')
    print(res)
    res1 = models.User.objects.filter(name__icontains='k')
    print(res1)

以什么开头/结尾:

# 关键字:__startwith=''  以什么开头
	 __endswith=''	 以什么结尾
    	 __istartwith=''  不区分大小写
         __iendswith=''   不区分大小写
# 举例:
models.User.objects.filter(name_ _startswith="n" )

models.User.objects.filter(name_ _endswith="n" )

按照日期查询:

# 关键字:
    __month='1'   # 按照月份取
    __year='2020'  # 按照年份
    __day='29'    # 按照天筛选

# 举例:
    res = models.User.objects.filter(register_time__month='01')
    print(res)
    res1= models.User.objects.filter(register_time__day='02')
    print(res1)
    res3 = models.User.objects.filter(register_time__year='2022')
    print(res3)
    res4 = models.User.objects.filter(register_time__year='2022',register_time__month='02')
    print(res4)

ORM创建外键

以书籍,出版社,作者,作者信息这4张表为例

书籍和出版社的关系:
  一本书籍只能由一个出版社出版,一个出版社可以出版多本书。
  关系为:一对多(ForeignKey),书籍是多所以外键创建在书籍表中。

书籍和作者的关系:
  一本书可以由多个作者创作,一个作者同样也可以创作多本书。
  关系为:多对多(ManyToManyField),需要创建第三张表来表示关系

作者和作者信息的关系:
  一条信息对应一个作者,一个作者对应一条信息。
  关系为:一对一(OneToOneField),外键应创建在查询频率较高的表中。
  
一对多外键关系  
    """在orm中 外键字段建在多的一方"""
多对多外键关系
    """在orm中 可以直接写在查询频率较高的表中(自动创建第三张表)"""
一对一外键关系
    """在orm中 直接写在查询频率较高的表中"""


"""
ManyToManyField不会在表中创建实际的字段 而是告诉django orm自动创建第三张关系表
ForeignKey、OneToOneField会在字段的后面自动添加_id后缀 如果你在定义模型类的时候自己添加
了该后缀那么迁移的时候还会再次添加_id_id 所以不要自己加_id后缀

ps:三个关键字里面的参数
    to用于指定跟哪张表有关系 自动关联主键
    to_field\to_fields  也可以自己指定关联字段
"""
#书籍
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    # 一对多
    publish = models.ForeignKey(to='Publish')
    # 多对多
    authors = models.ManyToManyField(to='Author')  # 自动创建书籍和作者的第三张关系表

#出版
class Publish(models.Model):
    title = models.CharField(max_length=32)

#作者
class Author(models.Model):
    name = models.CharField(max_length=32)
    # 一对一
    author_detail = models.OneToOneField(to='AuthorDetail')

#作者信息
class AuthorDetail(models.Model):
    addr = models.CharField(max_length=32)
    phone = models.BigIntegerField()

ORM外键字段操作

一对一,一对多(OneToOneField,ForeignKey)

添加外键字段值:
    #第一种方法
    models.Book.objects.create(title='JAVA',price=123456,publish_id=1) # 直接填写关联数据的主键值
    #第二种方法
    publish_obj = models.Publish.objects.filter(pk=2).first() # 获取外键对象
    models.Book.objects.create(title='JS',price=11111,publish=publish_obj)

修改外键字段值:
    #第一种方法
    models.Book.objects.filter(pk=1).update(publish_id=2) # 直接修改publish_id的值
    #第二种方法
    publish_obj = models.Publish.objects.filter(pk=2).first() # 先获取对象,这里是修改出版社那么要先获取对应出版社对象
    models.Book.objects.filter(pk=1).update(publish=publish_obj) # 修改publish

多对多(ManyToManyField)

 # 添加关系
    #第一种方法
    book_obj = models.Book.objects.filter(pk=2).first() # 先获取对应书籍对象
    book_obj.authors.add(1)  # 然后给书籍对象的authors字段传入作者的id # 在第三张关系表中添加数据
    book_obj.authors.add(1, 3)  #可以直接填写数据主键值
    #第二种方法
    author_obj1 = models.Author.objects.filter(pk=3).first() # 先获取作者对象
    author_obj2 = models.Author.objects.filter(pk=4).first()
    book_obj.authors.add(author_obj1)
    book_obj.authors.add(author_obj1,author_obj2) # 会在第三张表中添加2条数据(2,3)(2,4)
    #修改关系
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.set([3, ])
    book_obj.authors.set([1, 2])
    author_obj1 = models.Author.objects.filter(pk=3).first()
    author_obj2 = models.Author.objects.filter(pk=4).first()
    book_obj.authors.set([author_obj1, ])
    book_obj.authors.set([author_obj1, author_obj2])
    #移除关系
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.remove(3)
    book_obj.authors.remove(3,4)
    author_obj1 = models.Author.objects.filter(pk=1).first()
    author_obj2 = models.Author.objects.filter(pk=2).first()
    book_obj.authors.remove(author_obj1)
    book_obj.authors.remove(author_obj1,author_obj2)
    #清空关系
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.clear()
  1.第三张关系表创建数据
	book_obj = models.Book.objects.filter(pk=1).first()
  	book_obj.authors.add()
  	括号内可以放主键值也可以放数据对象 并且都支持多个
  2.第三张关系表修改数据
  	book_obj.authors.set()
    	括号内必须是一个可迭代对象 元素同样支持主键值或者数据对象
  3.第三张关系表删除数据
  	book_obj.authors.remove()
    	括号内可以放主键值也可以放数据对象 并且都支持多个
  4.第三张关系表清空指定数据
  	book_obj.authors.clear()
    	括号内无需传值 直接清空当前表在第三张关系表中的绑定记录

正向查询和反向查询

  如果一张表有外键字段,并且是从这张表开始查询的,那么就叫作正向查询。
  相反的,如果从关联表开始查询的,就叫反向查询。

  由书籍查询出版社 外键字段在书籍表中 那么书查出版社就是'正向'
  由出版社查询书籍 外键字段不在出版社表 那么出版社查书就是'反向'

	"""
 	查询口诀
 		正向查询按外键字段名
 		反向查询按表名小写
 	"""

多表查询

表信息

#书籍
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    # 一对多
    publish = models.ForeignKey(to='Publish')
    # 多对多
    authors = models.ManyToManyField(to='Author')  # 自动创建书籍和作者的第三张关系表

#出版
class Publish(models.Model):
    title = models.CharField(max_length=32)

#作者
class Author(models.Model):
    name = models.CharField(max_length=32)
    # 一对一
    author_detail = models.OneToOneField(to='AuthorDetail')

#作者信息
class AuthorDetail(models.Model):
    addr = models.CharField(max_length=32)
    phone = models.BigIntegerField()

基于对象的跨表查询(子查询)

正向查询
1.查询Python编程书籍对应的出版社
  (1)先获取书籍对象
        book_obj = models.Book.objects.filter(title='Python编程').first()
  (2)进行跨表查询,从书籍找到出版社是正向查询,使用外键字段名
        res = book_obj.publish # 返回的是对应的出版社对象
        print(res.title) # 上海出版社
    
2.查询python编程书籍创作的作者
    # 首先先获取书籍对象
    book_obj = models.Book.objects.filter(title='Python编程').first()
    # 进行跨表查询,从书籍找到出版社是正向查询,使用外键字段名
    # res = book_obj.authors
    # print(res) # app01.Author.None # 此时返回none,如果返回有多个还需要加all()
    res = book_obj.authors.all() # 返回多个对象
    print(res) # <QuerySet [<Author: Author object>, <Author: Author object>]>

反向查询
3.查询上海出版社出版的书籍
#首先获取出版社对象
    publish_obj = models.Publish.objects.filter(title='上海出版社').first()
    #进行跨表查询,从出版社找到书籍是反向查询(外键不在出版社表中),使用表名小写
    # res = publish_obj.book_set # 反向查询时表名小写还需要加上 _set
    # print(res) # app01.Book.None
    #由于一个出版社可以出版多本书籍,返回结果可能是多个,还需要加上 all()
    res = publish_obj.book_set.all() #返回多个书籍对象
    print(res) # <QuerySet [<Book: Book object>, <Book: Book object>]>

4.查询电话为1的作者(在一对一关系中的反向查询表名小写后不要跟 _set)
    author_detail_obj = models.AuthorDetail.objects.filter(phone=1).first()
    res = author_detail_obj.author # 返回作者对象
    print(res.name)  # 张三

基于双下划线的跨表查询(多表连接查询)

1.查询Python编程书籍对应的出版社名称
      res = models.Book.objects.filter(title='Python编程').values('publish__title')
      print(res) # <QuerySet [{'publish__title': '上海出版社'}]>

2.查询作者张三的手机号和地址
      res = models.Author.objects.filter(name='张三').values('author_detail__phone','author_detail__addr')
      print(res) # <QuerySet [{'author_detail__phone': 1, 'author_detail__addr': '上海'}]>

双下划线查询扩展

1.查询Python编程书籍对应的出版社名称
    方法一:
    res = models.Publish.objects.filter(book__title='Python编程') # 返回出版社对象<QuerySet [<Publish: Publish object>]>
    print(res[0].title) # 上海出版社
    方法二:
    res = models.Publish.objects.filter(book__title='Python编程').values('title')
    print(res) # <QuerySet [{'title': '上海出版社'}]>
    print(res[0].get('title')) # 上海出版社
    方法三:
    res = models.Publish.objects.filter(book__title='Python编程').first()
    print(res.title) # 上海出版社

2.查询作者王五的手机号和地址
    res = models.AuthorDetail.objects.filter(author__name='王五').values('phone','addr')
    print(res) # <QuerySet [{'phone': 3, 'addr': '北京'}]>
    print(res[0].get('phone')) # 3
    print(res[0].get('addr')) # 北京

'''连续跨表操作'''
1.查询python编程书籍对应的作者的手机号
    res = models.Book.objects.filter(title='PYthon编程').values('authors__author_detail__phone')
    print(res) # <QuerySet [{'authors__author_detail__phone': 1}, {'authors__author_detail__phone': 2}]>

如何查看SQL语句

方式1:如果结果集对象是queryset 那么可以直接点query查看
方式2:配置文件固定配置
  	适用面更广 只要执行了orm操作 都会打印内部SQL语句
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level': 'DEBUG',
        },
    }
}
posted @ 2022-05-17 21:26  春游去动物园  阅读(68)  评论(0编辑  收藏  举报