• Django-(5)


    内容概览

    • 表查询数据准备及测试环境搭建
    • ORM常见查询关键字
    • 双下划线的查询
    • 查看ORM底层SQL语句
    • ORM外键字段创建
    • 外键字段数据操作
    • 正反向概念
    • 跨表查询

    表查询数据准备及测试环境搭建

    1. django切换为MySQL数据库

    2. 定义模型类

      class User(models.Model):
      	uid = models.AutoField(primary_key=True, verbose_name='编号')
      	name = models.CharField(max_lenght=32, verbose_name='姓名')
      	age = models.IntegerField(verbose_name='年龄')
      	join_time = models.DateField(auto_now_add=True)
      """
      auto_now:每次操作数据并保存都会自动更新为当前时间
      auto_now_add:在创建数据的时候保存当前时间,之后不会自动更改
      """
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    3. 执行数据库迁移命令
      python manage.py makemigrations
      python manage.py migrate

    4. 模型层测试环境准备
      方式1:在任意空的py文件中或自带的测试文件中准备环境

      import os
      def main():
      	os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'day59.settings')
      	import django
      	django.setup()
      	"""在函数内编写测试代码"""
      
      if __name__ == '__main__':
      	main()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      方式2:pycharm提供测试环境
      使用python console命令行测试环境

    ORM常见查询关键字

    """
    先添加三条数据
    models.User.objects.create(name='jason', age=18)
    models.User.objects.create(name='kevin', age=24)
    models.User.objects.create(name='oscar', age=36)
    """
    1. fliter():筛选数据,返回值是Queryset
    	print(models.User.objects.filter())  # , , ]>
    	print(models.User.objects.filter(name='jason'))  # ]>
    	"""
    	括号内不写查询条件则返回所有查询到的数据
    	括号内可以填写多个条件,使用逗号隔开,默认是and关系
    	"""
    2. all():查询所有数据,返回值是Queryset
    	print(models.User.objects.all())  # , , ]>
    3. first():获取Queryset中第一个数据对象,如果为空则返回None
    	print(models.User.objects.all().first())  # User object (1)
    4. last():获取Queryset中最后一个数据对象,如果为空则返回None
    	print(models.User.objects.all().last())  # User object (3)
    5. get():根据条件获取具体的数据对象,如果对象不存在则报错,返回多个条件也会报错
    	print(models.User.objects.get(pk=1))  # User object (1)
    	print(models.User.objects.get(pk=10))  # User matching query does not exist.
    	print(models.User.objects.get())  # get() returned more than one User -- it returned 3!
    6. values():查询指定的字段,结果是Queryset
    	print(models.User.objects.all().values('name'))  # 
    	print(models.User.objects.values('name')  # 也可以直接写values,结果与上边一样
    7. values_list():查询指定的字段,结果是Queryset
    	print(models.User.objects.all().values_list())  # 
    8. order_by():指定字段排序,默认为升序,可以在字段前加负号改为降序,并且支持多个字段排序
    	"""
    	可在models.py的类中重写__str__方法,能够更清晰知道当前返回的对象
    	def __str__(self):
            return f'{self.name}'
    	"""
        print(models.User.objects.order_by('name'))  # , , ]>
        print(models.User.objects.order_by('-name'))  # , , ]>
    9. count():统计orm查询后结果的个数
    	print(models.User.objects.all().count())  # 3
    10. distinct:针对重复的数据集进行去重,查询的结果必须是完全相同
        print(models.User.objects.all().distinct().count())  # 3
    	print(models.User.objects.all().values('join_date').distinct().count())  # 1
    11. exclude:筛选出不符合括号中条件的数据,结果是Queryset
    	print(models.User.objects.exclude(name='oscar'))  # , ]>
    12. reverse():对排过序的结果集做翻转
        print(models.User.objects.all())  # , , ]>
        print(models.User.objects.all().reverse())  # , , ]>
        print(models.User.objects.all().order_by('name'))  # , , ]>
        print(models.User.objects.all().order_by('name').reverse())  # , , ]>
    13. exists():判断查询结果集是否有数据,返回布尔值
    	print(models.User.objects.filter(name='jason').exists())  # True
        print(models.User.objects.filter(name='xxx').exists())  # False
    14. raw():自己编写SQL语句执行
    	print(list(models.User.objects.raw('select * from app01_user')))  # [, , ]
    	
    	"""也可以使用模块"""
    	from django.db import connection
        cursor = connection.cursor()
        cursor.execute("insert into app01_user(name,age, join_date) VALUES ('jerry',12,'2022-9-20')")
        cursor.execute("update app01_user set name='tom' WHERE name='kevin'")
        cursor.execute("delete from app01_user where name='oscar'")
        cursor.execute("select * from app01_user")
        print(cursor.fetchone())
        print(cursor.fetchall())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    双下划线的查询

    1. 比较运算符
    	1. 大于:字段大于指定数据
    		print(models.User.objects.filter(age__gt=25))  # ]>
    	2. 小于:字段小于指定数据
    		print(models.User.objects.filter(age__lt=25))  # , ]>
    	3. 大于等于:字段__gte
    	4. 小于等于:字段__lte
    2. 成员运算符
    	字段__in:字段中是否有指定数据,指定数据值必须为可迭代对象
    		print(models.User.objects.filter(age__in=(18,)))  # ]>
    3. 范围查询
    	字段__range:获取在某个范围之间的数据
    	print(models.User.objects.filter(age__range=(20, 30)))  # ]>
    4. 模糊查询
    	字段__contains:查询数据中包含指定值的,不忽略大小写
    		print(models.User.objects.filter(name__contains='J'))  # 
    	字段__icontains:查询数据中包含指定值的,忽略大小写
    		print(models.User.objects.filter(name__icontains='J'))  # ]>
    5. 日期处理
    	字段__year:获取日期数据中包含指定年份的数据
    		print(models.User.objects.filter(join_date__year=2022))  # , , ]>
    	字段__month:获取日期数据中包含指定月份的数据
    		print(models.User.objects.filter(join_date__month=9))  # , , ]>
    	字段__day:获取日期数据中包含指定天数的数据
    		print(models.User.objects.filter(join_date__day=5))  # , , ]>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    查看ORM底层SQL语句

    1. 如果是却如Queryset对象,那么可以直接使用.query查看SQL语句
    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',
    	        },
    	    }
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    ORM外键字段创建

    一对多
    外键字段建在多的一方
    会自动添加_id后缀
    代码:models.ForeignKey()
    多对多
    外键字段创建多对多关系有三种方式
    1. 直接在查询频率较高的表中填写字段即可,自动创建第三张关系表
    2. 自己创建第三张关系表
    3. 自己创建第三张关系表,但还是使用orm多对多字段做关联
    代码:models.ManyToManyField()
    一对一
    外键字段建在查询频率较高的表中
    会自动添加_id后缀
    代码:OneToOneField()
    ps:django1版本不需要添加on_delete参数

    提前准备:

    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.IntegerField(verbose_name='单价')
        publish_time = models.DateField(auto_now_add=True)
        publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
        authors = models.ManyToManyField(to='Author')
    
        def __str__(self):
            return f'书本:{self.title}'
    
    
    class Publish(models.Model):
        name = models.CharField(max_length=32)
        email = models.EmailField()
    
        def __str__(self):
            return f'出版社:{self.name}'
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
    
        def __str__(self):
            return f'作者:{self.name}'
    
    
    class AuthorDetail(models.Model):
        phone = models.BigIntegerField()
        address = models.CharField(max_length=255)
    
        def __str__(self):
            return f'作者详情:{self.phone}'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    外键字段数据操作

    一对多与一对一:
    	方式1:直接使用实际字段名添加关联数据值
    		models.Book.objects.create(title='Python', price='998', publish_id=1)
    	方式2:先获取需要关联的对象,再用虚拟字段名添加关联数据值
    		publish_obj = models.Publish.objects.filter(pk=1).first()
    	    models.Book.objects.create(title='java', price=888, publish=publish_obj)
    多对多:
    	需要先获取一个对象
    	models.book_obj = models.Book.objects.filter(pk=1).first()
    	add():添加数据,可以填写数据值也可以填写数据对象,支持填写多个,使用逗号隔开
    	    book_obj.authors.add(1)
    	    book_obj.authors.add(2,3)
    		author_obj = models.Author.objects.filter(pk=2).first()
    	    book_obj.authors.add(author_obj)
    	remove():删除数据,可以填写数据值也可以填写数据对象,支持填写多个,使用逗号隔开
    		book_obj.authors.remove(1)
    	    author_obj1 = models.Author.objects.filter(pk=2).first()
    	    author_obj2 = models.Author.objects.filter(pk=3).first()
    	    book_obj.authors.remove(author_obj1, author_obj2)
    	set():修改数据,括号内必须填写可迭代对象(实际上是先删除后添加)
    		book_obj.authors.set([2, 3])
    	clear():清空指定数据,括号内不用填写参数
    		book_obj.authors.clear()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    正反向概念

    正反向的关键就在于外键字段在哪里
    正向查询:通过书籍查询出版社,外键字段在书籍表中
    反向查询:通过出版社查询书籍,外键字段不在出版社表中

    跨表查询

    ORM跨表查询口诀:正向查询按外键字段,反向查询按表名小写

    基于对象(子查询)
    """正向跨表查询"""
    # 1.查询主键为1的书籍对应的出版社(一对多)
    # 1.1.先根据条件查询数据对象(先查书籍对象)
    book_obj = models.Book.objects.filter(pk=1).first()
    # 1.2.以对象为基准 思考正反向概念(书查出版社 外键字段在书表中 所以是正向查询)
    print(book_obj.publish)
    
    # 2.查询主键为3的书籍对应的作者(多对多)
    book_obj = models.Book.objects.filter(pk=1).first()
    print(book_obj.authors)  # app01.Author.None
    print(book_obj.authors.all())  # 在查询结果有多条时需要使用all
    
    # 3.查询jason的作者详情(一对一)
    author_obj = models.Author.objects.filter(name='jason').first()
    print(author_obj.author_detail)
    
    
    """反向跨表查询"""
    # 4.查询南方出版社出版的书籍
    publish_obj = models.Publish.objects.filter(name='南方出版社').first()
    print(publish_obj.book)  # 报错,还需要添加_set后缀
    print(publish_obj.book_set)  # app01.Book.None
    print(publish_obj.book_set.all())  # 有多个结果还是需要使用all
    
    # 5.查询jason写过的书
    author_obj = models.Author.objects.filter(name='jason').first()
    print(author_obj.book_set.all())
    
    # 6.查询电话是110的作者
    uthor_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    print(author_detail_obj.author)  # 针对只有单个数据不需要加_set后缀与all
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    基于双下划线(连表操作)
    """正向跨表查询"""
    # 1.查询主键为1的书籍对应的出版社名称及书名
    res = models.Book.objects.filter(pk=1).values('publish__name', 'title')
    print(res)  # 正向依然是用外键字段,查哪个字段就双下划线加字段名即可
    
    # 2.查询主键为3的书籍对应的作者姓名及书名
    res = models.Book.objects.filter(pk=3).values('authors__name', 'title')
    print(res)
    
    # 3.查询jason的作者的电话号码和地址
    res = models.Author.objects.filter(name='jason').values('author_detail__phone', 'author_detail__address')
    print(res)
    
    """反向跨表查询"""
    # 4.查询南方出版社出版的书籍名称和价格
    res = models.Publish.objects.filter(name='南方出版社').values('book__title', 'book_price')
    print(res)  # 反向也依然使用表名小写
    
    # 5.查询jason写过的书的名称和日期
    res = models.Author.objects.filter(name='jason').values('book__title', 'book__publish_time')
    print(res)
    
    # 6.查询电话是110的作者姓名和年龄
    res = models.AuthorDetail.objects.filter(phone=111).values('author__name', 'author__age')
    print(res)
    
    
    # 7.查询主键为1的书籍对应的作者电话号码(三张表)
    res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
    print(res)
    """先从第一张表通过外键字段名进入第二张表,再直接从第二张表的外键字段名查询到第三张表的数据"""
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    浅谈指针数组
    QT软件开发-基于FFMPEG设计视频播放器-支持软解与硬解(三)
    这几个合成配音软件新手也在用
    Mysql高级——事务(2)
    2.1.1BFS中的Flood Fill和最短路模型
    Composite Patterns :如果想用表达 部分-整体的继承关系,组合模式一定是不二之选了
    P1220 关路灯 ( 区间dp
    Python基础教程:print输出带颜色的方法详解
    Python数据分析学习路线
    【vue设计与实现】挂载和更新 2-正确的设置元素属性
  • 原文地址:https://blog.csdn.net/AL_QX/article/details/126706843