Django测试环境搭建及ORM查询(创建外键|夸表查询|双下划线查询)

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

		1.首先连接上我们的数据库 Django有自带一个小型本地数据库Sqlite3
			该数据库功能非常有限 并且针对日期类型的数据兼容性极差 所以我们还是需要连接MySQL数据库
		
		2.Django切换切换MySQL数据库
			找到settings.py文件中找到DATABASES8把里面书记Sqlite3更改为MySQL以及下面的数据库信息
			NAME、HOST、PORT、USER、PASSWORD、CHARSET		(版本区别请查看博主之前文章讲解)
		
		3.定义模型
			class User(models.Model):
				uid = models.AutoField(primary_key=True, verbose_name='编号')
				name = models.CharField(max_length=32, verbose_name='姓名')
				age = models.IntegerField(verbose_name='年龄')
				join_time = models.DateField(auto_now_add=True)
			
			日期字段参数
				auto_now:		每次操作数据并保存都会自动更新当前时间
				auto_now_add:	只在创建数据的那一刻自动获取当前时间 之后如果不人为更改则不变
		
		4.执行数据库迁移命令
			每次输入完关于SQL语句都需要去写入到数据库
				makemigrations	输入完命令之后app里面会自动创建一个py文件记录了创建了那些数据
				migrate 		输入完命令之后真正的执行到数据库里面去创建了
		
		5.模型层测试环境准备
			我们刚创建完我们的模型 但是现在需要查看数据 发现在当前文件下查看无论怎么输入都会报错 所以我们需要创建一个测试环境
			方式1:
				首先需要到自带的文件manage.py中复制前四行代码 到任意空的py文件夹中准备环境
				import os

				def main():						# 前三行
				    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Django003.settings')
				    import django				# 导入模块不能放在上面 否则会报错
				    django.setup()
				
				    from app01 import models
				    print(models.User.objects.filter())
				
				if __name__ == '__main__':		# 运行脚本不能忘
				    main()

			方式2:
				Pycharm提供的测试环境
					Python console命令测试环境

在这里插入图片描述

二、ORM操作相关方法

		我们现在的表格里面没有任何数据 需要去创建 也有三种方式
			方式1: Create()
				    from app01 import models
				    res = models.User.objects.create(name='Lisa', age=20)     
				    print(res)			# create方法有一个返回值 打印出来是一个用户对象 User object (2)
				    print(res.uid)
				    print(res.name)
				    print(res.age)
				    print(res.pk)       # PK是获取当前表格的主键字段 防止有很多张表的时候难以查询 不用查看真正的主键名称 直接PK即可
				    
			方式2:利用类类实例化对象然后调用save方法创建
				    user_ojb = models.User(name='Jack', age=25)  # 仅仅产生一个对象 并不会操作数据库
				    user_ojb.save()     # 用对象调用内置方法 Save才会保存到数据库
				    
			方式3:直接通过Pycharm右侧database创建

		创建Create	更新Update	删除Delete

在这里插入图片描述

三、ORM常见查询关键字

名称语法说明
filterres1 = models.User.objects.filter(name=‘Like’, age=20)筛选数据 返回值是一个QuerySet(可以看成是列表套数据对象)
括号内不写查询条件 默认就是查询所有
括号内可以填写条件 并且支持多个 逗号隔开 默认是and关系
allres2 = models.User.objects.all()查询所有数据 返回值是一个QuerySet(可以看成是列表套数据对象)
firstres3 = models.User.objects.first()获取Queryset中第一个数据对象 如果为空则返回None
lastres4 = models.User.objects.last()获取Queryset中最后一个数据对象 如果为空则返回None
getres5 = models.User.objects.get(pk=2)直接根据条件查询具体的数据对象 但是条件不存在直接报错 不推荐使用
valuesres6 = models.User.objects.values(‘name’, ‘age’)指定查询字段 结果是Queryset(可以看成是列表套字典数据)
values_listres7 = models.User.objects.values_list()指定全部字段 结果是Queryset(可以看成是列表套元组数据)
order_byres8 = models.User.objects.order_by(‘age’) 升序
res8_1 = models.User.objects.order_by(‘-age’, ‘name’)降序
指定字段排序 默认是升序 在字段前加负号则为降序 并且支持多个字段排序
countres9 = models.User.objects.count()统计orm查询之后结果集中的数据格式
distinctres10 = models.User.objects.values(‘name’, ‘age’).distinct()针对重复的数据集进行去重 一定要注意数据对象中的主键
excluderes11 = models.User.objects.exclude()针对括号内的条件取反进行数据查询 QuerySet(可以看成是列表套数据对象)
reverseres12 = models.User.objects.all().order_by(‘age’).reverse()针对已经排了序的结果集做颠倒
existsres13 = models.User.objects.exists()判断查询结果集是否有数据 返回布尔值 但是几乎不用因为所有数据自带布尔值
rawres14 = models.User.objects.raw(‘select * from app01_user’)执行SQL语句
		1.当需要查询数据主键字段值的时候 可以使用pk忽略掉数据字段真正的名字
		2.在模型类中可以定义一个__str__方法 便于后续数据对象被打印展示的是查看方便
		3.Queryset中如果是列表套对象那么直接for循环和索引取值但是索引不支持负数
		4.虽然queryset支持索引但是当queryset没有数据的时候索引会报错 推荐使用first

在这里插入图片描述

四、双下划线查询

			比较运算符
				大于    _ _ gt		res = models.User.objects.filter(age__gt=25)
				小于    _ _ lt		res1 = models.User.objects.filter(age__lt=25)
				大于等于 _ _ gte		res2 = models.User.objects.filter(age__gte=24)
				小于等于 _ _ lte		res3 = models.User.objects.filter(age__lte=24)

在这里插入图片描述

			成员运算符
				在上面里面	 _ _ in			res = models.User.objects.filter(name__in=['Like', 'Lisa', 'Nana'])
			
			范围查询(数字)
				在上面范围内	 _ _ range		res1 = models.User.objects.filter(age__range=(20, 25))
			
			模糊查询
				忽略大写的	 _ _ contains	res2 = models.User.objects.filter(name__contains='l')
				忽略大小写的 	 _ _ icontains	res3 = models.User.objects.filter(name__icontains='l')
			
			日期处理
				年			 _ _ year		res4 = models.User.objects.filter(join_time__year=2022)
				月			 _ _ month		res5 = models.User.objects.filter(join_time__month=9)
				日			 _ _ day		res6 = models.User.objects.filter(join_time__day=5)

在这里插入图片描述

五、ORM底层SQL语句

			我们现在知道了怎么查询数据了但是它的底层语句逻辑是什么呢?
			
			方式1:
				如果是Queryset对象 那么可以直接点Ctrl+左键点击query查看SQL语句
				
			方式2:
				需要到配置文件Settings中找一个空白位置复制一下代码 主要作用打印所有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',
				                },
				            }
				        }

在这里插入图片描述

六、ORM外键字段创建

			一对多
				ORM中外键字段建在多的一方 models.ForeignKey()
			   		会自动添加_id后缀
			多对多
				ORM中有三种创建多对多字段的方式 models.ManyToManyField()
			    	方式1:直接在查询频率较高的表中填写字段即可 自动创建第三张关系表
			       方式2:自己创建第三张关系表
			       方式3:自己创建第三张关系表 但是还是要orm多对多字段做关联
			一对一
				ORM中外键字段建在查询频率较高的表中 models.OneToOneField()
			    	会自动添加_id后缀
			 
			django1.X 针对 models.ForeignKey() models.OneToOneField()不需要on_delete
			django2.X 3.X 则需要添加on_delete参数
			class Book(models.Model):
			    title = models.CharField(max_length=32)
			    price = models.DecimalField(max_digits=8, decimal_places=2)  # 总共可以输入八位 小数点两位
			    publish_time = models.DateTimeField(auto_now=True)      	# 获取当前时间
			
			    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)     # 创建外键出版社 级联删除
			    authors = models.ManyToManyField(to='Author')                           # 多对多 与作者关联
			
			
			class Publish(models.Model):
			    name = models.CharField(max_length=32)
			    email = models.EmailField()
			
			
			class Author(models.Model):
			    name = models.CharField(max_length=32)
			    age = models.IntegerField()
			    author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)   # 一对一 与作者信息关联 级联删除
			
			
			class AuthorDetail(models.Model):
			    phone = models.BigIntegerField()
			    address = models.CharField(max_length=255)  

在这里插入图片描述

七、外键字段数据操作

		models.ForeignKey(to='Publish', on_delete=models.CASCADE)
			方式1:	
				直接给实际字段添加关联数据值	 publish_id = 1
					models.Book.objects.create(title='Python从入门到放弃', price=19999.88, publish_id=1)
				
		  	方式2:
		  		间接使用外键虚拟字段添加数据对象 publish=publish_obj
	  			    publish_obj = models.Publish.objects.filter(pk=2).first()
				    models.Book.objects.create(title='Django从入门到入土', price=28888.99, publish_id=publish_obj)
		
		models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)		# 跟上面方法一样
			方式1:
				直接给实际字段添加关联数据值	 author_detail_id = 1
					models.Author.objects.create(phone=520, address='我爱零',publish_id=4)
			方式2:
				间接使用外键虚拟字段添加数据对象 author_detail=authorDetail_obj
					 detail_obj = models.Author.objects.filter(pk=2).first()
					 models.Author.objects.create(phone=110, address='警察局',publish_id=detail_obj)

		models.ManyToManyField(to='Author')
			方式1:
				先拿到书籍的ID然后添加到第三张表的作者ID
					book_obj = models.Book.objects.filter(pk=1).first()
					book_obj.authors.add(1)
			方式2:
				先拿到作者的ID然后添加到第三张表的书籍ID
					author_obj1 = models.Author.objects.filter(pk=1).first()
					author_obj2 = models.Author.objects.filter(pk=2).first()
					book_obj.author.add(author_obj1,author_obj2)	# 括号内即可以填写数字值也可以填写数据对象 支持多个
		
				remove()删除
					book_obj = models.Book.objects.filter(pk=1).first()
					book_obj.authors.remove(1 )		# 括号内即可以填写数字值也可以填写数据对象 支持多个
				
				set()修改数据
					book_obj = models.Book.objects.filter(pk=1).first()
					book_obj.authors.set([2,])		# 括号内必须是可迭代对象 
				
				clear()清空数据
					book_obj = models.Book.objects.filter(pk=1).first()
					book_obj.authors.clear()			# 删除表中ID为1的书籍 括号内不需要任何参数

八、正反向概念

		正反向的概念核心就在于外键字段在谁手上
		外键在自己手上则是正向查询
		外键在别人手上则是反向查询

		正向查询
			通过书查询出版社 外键字段在书表中
		反向查询
			通过出版社查询书 外键字段不在出版社表中

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

九、基于对象夸表查询(子查询)

	基于对象的正向跨表查询
		
			1.查询主键为1的书籍对应的出版社(书>>>出版社)
				1>先根据条件查询数据对象(先查书籍对象)
					book_obj = models.Book.objects.filter(pk=1).first()
				2>以对象为基准 思考正反向概念(书查出版社 外键字段在书表中 所以是正向查询)
					print(book_obj.publish)		# 通过点的方式就可以拿到外键电影的数据
					
			2.查询主键为3的书籍对应的作者(书>>>作者)
				1>先根据条件查询数据对象(先查书籍对象)
					book_obj = models.Book.objects.filter(pk=3).first()
				2>以对象为基准 思考正反向概念(书查作者 外键字段在书表中 所以是正向查询)
					print(book_obj.authors)  # app01.Author.None
					print(book_obj.authors.all()
			
			3.查询jason的作者详情
				1>先根据条件查询数据对象
					author_obj = models.Author.objects.filter(name='Lisa').first()
				2>以对象为基准 思考正反向概念
					print(author_obj.author_detail)

在这里插入图片描述

	基于对象的反向跨表查询
			4.查询南方出版社出版的书籍
				1>先拿出版社对象
					publish_obj = models.Publish.objects.filter(name='南方出版社').first()
				2>思考正反向
					print(publish_obj.book)				# 报错
					print(publish_obj.book_set)  		# app01.Book.None
					print(publish_obj.book_set.all())	
					
			5.查询Like写过的书
				1>先拿作者对象
					author_obj = models.Author.objects.filter(name='Like').first()
				2>思考正反向
				    print(author_obj.book)				# 报错
				    print(author_obj.book_set)			# app01.Book.None
				    print(author_obj.book_set.all())
			
			6.查询电话是520的作者
				1>先拿作者详情对象
					author_obj = models.AuthorDetail.objects.filter(phone=520).first()
				2>思考正反向
					print(author_obj.author)
			
			'''根据以上6个题目 我们发现规律 多对多会数据需要all()一对一不用 反向需要加-set'''

在这里插入图片描述

十、双下划线夸表查询(连表操作)

	基于双下划线的正向跨表查询
		1.查询主键为1的书籍对应的出版社名称及书名
		    res = models.Book.objects.filter(pk=1).values('publish__name', 'title')
			print(res)
			
		2.查询主键为3的书籍对应的作者姓名及书名
			res1 = models.Book.objects.filter(pk=3).values('authors__name', 'title')
			print(res1)
			
		3.查询Like的作者的电话号码和地址
			res2 = models.Author.objects.filter(name='Like').values('author_detail__phone', 'author_detail__address')
			print(res2)
			
	基于双下划线的反向跨表查询
		4.查询南方出版社出版的书籍名称和价格
			res3 = models.Publish.objects.filter(name='南方出版社').values('book__title', 'book__price')
			print(res3)
			
		5.查询James写过的书的名称和日期
			res4 = models.Author.objects.filter(name='James').values('book__title', 'book__publish_time')
			 print(res4)
			 
		6.查询电话是119的作者姓名和年龄
			res5 = models.AuthorDetail.objects.filter(phone=119).values('author__name', 'author__age')
    		print(res5)
    		
    	7.查询主键为1的书籍对应的作者电话号码
    		res6 = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
		 	print(res6)		# 这一道题涉及到三表查询

		'''连表查询_ _ 表示夸字段 都是先获取到第一个主要信息再去获取后面的次要信息'''

在这里插入图片描述

技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请点点赞收藏+关注谢谢支持 !!!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LoisMay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值