接着上一篇的分享,我们继续学习Django,本篇将从CURD深度解析、F和Q的使用方法、原声SQL语句查询、模型类、app内部模块等几个方面讲述。
为了更好的学习,我专门创建了一个技术交流,有兴趣的可以加WX(19524662948),我拉大家入群,一起探寻程序人生。
目录
一、CURD深度解析
1.1 模型类的objects
1.2 filter和exclude查询
1.3QuerySet对象
1.4 聚合函数类
二、F和Q的用法
三、原生SQL语句查询
4、模型类
4.1 显性创建模型类
4.2 一对一关系
4.3 一对多、多对一的关系
4.4 多对多关系
五、app内部模板
六、结束语
一、CURD深度解析 1.1 模型类的objects
正常情况下,我们可以不用在模型类中创建objects对象。因为默认情况,django.db.models.Manager这个已经帮我创建好了,如果字段中实在有objects,那我们必须创建objects为Manager对象,Manager类实际是QuerySet类的子类。如下:
class Test(models.Model):
test_name = models.CharField(max_length=20)
test_info = models.CharField(max_length=20)
objects = models.Manager() # 正确的写法
1.2 filter和exclude查询
通过filter和exclude可以筛选出我们想要的数据集合,从而满足业务需求。用法如下:
Test.objects.filter(属性名__条件=条件值)
Test.objects.filter(属性名=条件值)
Test.objects.filter(属性名__时间属性__条件=条件值)
查询中的条件如下:
gt:大于 lt:小于 gte:大于等于 lte:小于等于
contains:包含xx字符串 (i)startswith:是否以x字符串开头 (i)endswith:是否以x字符串结尾
isnull:是否为空 isnotnull是否不为空
in:是否在xxx里面(xxx可以是字符串、列表、字典等等)
查询中的时间属性如下:
1.3QuerySet对象年月日时分秒:year、month、day、hour、minute,second
QuerySet对象字面意思级查询集合,其目的就是创建我们的模型类(class Test)在元类中创建django.db.models.Manager类的对象,即为QuerySet。QuerySet是可以被迭代的。
返回QuerySet的对象的方法有:
1.4 聚合函数类filter exclude all values order_by():分组查 count():统计数据个数 exists():判断数据是否存在
其实在1.3中count的用法也可以归为聚合函数类的使用,其原理是django.db.models.聚合函数与QuerySet中的aggregate()组合使用。举例:
Test.objects.aggregate(Min(test_score)) # 查询测试分数最低的一条数据,结合aggregate使用
二、F和Q的用法
F的作用就是筛选出有计算的,或者是数字更新的数据,原理是django.db.models.F,举例:
# 将测试分数更新为四舍五入
Test.objects.update(test_score=round(F('test_score'),2))
Q的作用可以用来解决多个条件之间的逻辑关系,与或非,原理是django.db.models.Q,举例:
# 查询分数低于50的,或高于90的测试用例
test_q = Test.objects.filter(Q(test_score__lte=50) | Q(t_score=90)).values()
三、原生SQL语句查询
大家可以发现,今天前面三张主要就是学习怎么筛选得到我们想要的数据。为什么这一块的方法很发杂很多呢,就是因为我们的数据库里面存在各种各样的数据,为了最终的数据是我们想要的数据,就要应对不同数据的特性,学习解决这一类数据方法,从而提高开发效率。下面我们就学习原生SQL语句查询我们想要的数据。
原生SQL语句查询主要针对复杂的查询,通过QuerySet以及上面两章的介绍已经无法查询的时候,则使用原生SQL查询,不过一般情况下,上面的两个基本就可以解决百分之八十的查询问题。
这里插播一曲,说道原生SQL那肯定离不开SQL语句了。我将在后面几天巩固一下Mysql方面的知识,顺便更新几篇Mysql的博客,感兴趣的朋友们可以持续关注,等待文章的产出。
QuerySet提供两种原生SQL语句查询:
QuerySet.raw()
条件:查询的字段必须是模型类中声明的字段,且必须存在主键列 。查询的结果是RawQuerySet类对象,可以迭代,元素类型是模型类对象。
raw_queryset = Test.objects.raw('select id, name,test_score from tb_test where test_score < %s order by test_score DESC LIMIT %s, 10', (10, 0))
for raw in raw_queryset:
print(raw)
QuerySet.extra()
条件:extra()扩展查询, 针对QuerySet查询结果集中,额外增加查询条件或排序等相关 *** 作。返回结果还是QuerySet对象
qs1 = Test.objects.extra(where=['test_score < %s'], params=['10'])
qs2 = Test.objects.extra(where=['test_score < %s or test_name like %s'], params=['20', 'agv'])
4、模型类 4.1 显性创建模型类扩展:使用django.db.connection数据库连接对象进行原生SQL查询(这种方法感兴趣的朋友也可持续关注我,后面有时间分享并讲解)
class TestManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(Test.Q(test_score>50))
4.2 一对一关系
通过models.OneToOneField(联系的模型类, on_delete=models.CASCADE)这样去建立
class RealProfile(models.Model):
# 声明一对一的关联关系
user = models.OneToOneField(User,
verbose_name='账号',
on_delete=models.CASCADE)
real_name = models.CharField(max_length=20,
verbose_name='真实姓名')
number = models.CharField(max_length=30,
verbose_name='证件号')
real_type = models.IntegerField(verbose_name='证件类型',
choices=((0, '身份z'),
(1, '护照'),
(2, '驾驶证')))
image1 = models.ImageField(verbose_name='正面照',
upload_to='user/real')
image2 = models.ImageField(verbose_name='反面照',
upload_to='user/real')
以上是我们辅表:实名认证表 主表为User表,通过user字段联系起一对一之间的关系。当我们联系起这样的关系后,就可以通过辅表找到主表的数据了。
u = RealProfile.objects.filter(real_name='xx').first()
u.user.phone # 直接访问主表对象的数据
4.3 一对多、多对一的关系
# 声明水果商品与购物车的关系表
class FruitCartEntity(models.Model):
cart = models.ForeignKey(CartEntity,
on_delete=models.CASCADE,
verbose_name='购物车')
fruit = models.ForeignKey(FruitEntity,
on_delete=models.CASCADE,
verbose_name='水果名')
cnt = models.IntegerField(verbose_name='数量',
default=1)
def __str__(self):
return self.fruit.name +':'+self.cart.no
@property
def price1(self):
# 属性方法在后台显示时没有verbose_name, 如何解决?
return self.fruit.price # 从获取主的对象属性
@property
def price(self):
# 属性方法在后台显示时没有verbose_name, 如何解决?
return round(self.cnt*self.fruit.price, 2)
class Meta:
db_table = 't_fruit_cart'
verbose_name_plural = verbose_name = '购物车详情表'
通过Meta类申明我们当前商品表与购物车详情表之间的关系。每个用户购物车只有一个,但是购物车里面的商品可以有多个。
# 主读取多个从对象的信息
login_u = User.objects.get(pk=1)
# 查询当前用户的购物车中的所有商品及数量相关的信息
cart_fruits = login_u.cartentity.fruitcartentity_set.all()
for fruit_cart in cart_fruits:
print(fruit_cart.fruit.name, fruit_cart.fruit.price, fruit_cart.cnt)
首先登陆进来的用户login_u,每个用户都有一个购物车 login_u.cartentity,因为购物车和水果商品在模型类中存在一对多的关系,所以在购物车详情表里就可以通过fruitcartentity_set联系起水果商品表,从而对水果商品表数据进行交互。例如买卖数量的加减,金额的确定等。
4.4 多对多关系通过models.ManyToManyField(联系的模型类,db_table:被联系起的表别名,related_name:联系的主外键,verbose_name:被联系的表名),需要第三方表的外键来实现。
需求:用户收藏商品, 需要建立第三方表,完成用户收藏多个商品, 或一个商品被多位用户收藏。
在水果商品表中,添加如下关联关系:
# 默认情况下,反向引用的名称是当前类的名称(小写)_set
# 可以通过related_name 来指定
# db_table='t_collect' 使用第三张表建立fruit和user的多对多关系
users = models.ManyToManyField(UserEntity,
db_table='t_collect',
related_name='fruits',
verbose_name='收藏用户列表')
通过水果商品表,联系起User表和收藏表之间的关系。根据需求我们可以知道,用户可以收藏多个商品,每个商品也可以被多个用户收藏,其中间的桥梁就是商品,所以在水果商品表申明多对多的字段,其联系起User表,被联系表别名 t_collect,联系的主外键关系fruits(收藏表中肯定有fruits这个字段最为水果商品表的外键),被联系的表名verbose_name。下面我们模拟用户收藏商品:
u1 = User.objects.get(pk=1)
u1.fruits.add(FruitEntity.objects.get(pk=1))
u1.fruits.add(FruitEntity.objects.get(pk=2))
五、app内部模板
到这一步基本上后端Django的一些知识点就已经讲完了,分享的不是很细致。但是大体的学习思路和还是罗列的非常清晰的。我们在开发web项目的时候,不仅仅是需要后端开发,还需要前端的开发。Django作为一个MTV模式的开发框架,自然有对T的开发,但是如果是都写在pycharm里面,也就是说整个项目MTV都在同一个项目包下,我们把这种开发模式叫做前后端不分离,不推荐使用,这里做一个简单介绍,介绍各模块中的T,也就是我们的模板。
每个app下都可以增加templates目录,存放它自己的模板文件
内部的模板templates目录,不需要在settings.py中设置
如果app模块之外存在templates目录,且在settings.py中已设置,则加载模板时,则优先从此目录中加载模板文件。
我还是推荐大家使用前后端分离的开发方式,后端用某个框架去搭建,前端用前端的框架去搭建。管理项目也十分方便。
注意:在进行项目是前后端分离的开发方式的时候,我们要具备的技能有以下几点:
1.熟悉一个后端框架
2.熟悉一个前端框架
3.熟悉网络协议、特别是请求和响应的过程
为了方便学习,我将我自己总结好的资源将放在下一篇博客中,感兴趣的可以下载查看。内容主要是:
1.Django入门
2.Vue入门
3.交互前后端HTTP协议
4.前后端的交互流程
宏观性的了解了这样的交互流程之后,学起来可能会更加轻松一些。
六、结束语Django的分享到这里也就结束了,可能分享的不是很好。因为我自我也能感觉到,有很多细枝末节的知识点没有整理出来,但是目前来说,还没有一个好的思路去总结那些细小的知识点。因为真的知识点太多太多了,后面有时间,遇到问题的话会当方面的拿一些知识点来总结。创作不易,记得点赞收藏,给博主一个小小的支持吧。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)