Task6.5 了解元类
又又又又到了喜闻乐见的吃水不忘挖井人环节https://www.cnblogs.com/ellisonzhang/p/10513238.html
关键概念: 元类是创造类的类,在Python中万物皆可对象,对象是类的实例化可以由类来创建,所以类可以由源类来实例化
Python创建类的方法 type, 一个古老而强大函数,在类的创建中被调用,用来创建出一个类
# type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值)) 用法
# 覆写一个魔术方法
>>> def __str__(self):
... return self.name
...
# 用Student源类(None)新建一个类,并赋值和方法
>>> Studentss = type('Student',(),{'name':None,'School':'第二实验小学','__str__':__str__})
# 赋值name
>>> students2 = Studentss()
>>> students2.name = '小可爱'
# 上面覆写了魔术方法,可以直接打印self.name
>>> print(students2)
小可爱
由此我们可以看出,Type可以是所有类的源类
我们不仅可以用type使用源类,也可以在类的定义的时候使用魔术方法定义源类,如:写一个类的时候为其添加__metaclass__属性,定义了__metaclass__就定义了这个类的元类
但是问题是,我们在______metaclass______中放什么代码合适,说到底既然一个类是被实例化出来的,那他的元类应该咋写
实际上我们刚刚已经见到了一个万类元类:Type, 我们的metaclass,也就是元类只要放置type, type的子类或能调用type的类即可(return 为type)
我们可以用含type的函数做元类, 用type的子类做元类, 但是这里我用Python3还原博客写的源类的实例代码时结果完全不一致,不知道是不是因为Python3和Python2的结果有如此的大病
那为什么要学这个呢,因为在Django中Model的API是基于元类设计的,唉。不过搞懂了元类,你就能理解Model的源码(Model是由元类ModelBase创建的,ModelBase元类你就可以理解了)
Task7 了解模型类中的objects是啥
课程链接放出来,这一段确实挺抽象的:https://www.bilibili.com/video/BV1UE411L7Fy?p=3
默认情况下: 模型类会创建一个django.db.models.manager.Manage类的对象,赋给objects。。Manage类是BaseManage.from_queryset(QuerySet) 也就是一个查询结果集对象, 也是QuerySet的子/孙类 。可以从QuerySet中拿到数据库记录。
因此我们在模型中可以覆写objects(必须是manager类型,不然。。)
# models.py
objects = models.Manager()
但是objects能干什么?刚刚我们说过Manager是一个查询结果集对象,因此我们可以在模型类中利用objects进行查询,objects可以进行几乎所有的查询
# models.py
class Player(models.Model):
virture_name = models.CharField(default = 'GodForever')
objects = models.Manager() # 正确的写法
Task8 objects过滤器
# views 完成一个Player等级的过滤
def find_level(request:HttpRequest):
# 通过等级来过滤玩家
level_judge = request.Get.get('level',20)
level_judge = int(level_judge)
# 设置过滤条件, 大于等于: classname__gte,小于等于_lte, 更多过滤法则请移步官网
Player = PlayerEntity.objects.filter(level__gte=level_judge,
level__lte = 25).all()
return render(request,'object_fliter1.html',locals())
# 自己设置一下路由,咱就不写了直接开冲
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
可以看到筛选出10到25级的范围了
过滤器有两种,一种是fliter 就是上面用的选择 * 范围之内的, 一种是 exclude, 选择 * 范围之外的。注 :Django的object支持链式查找,及支持 PlayerEntity.objects.filter(a).exclude(b).filter©.filter(d)的写法
# object还可以直接用raw 插入sql语句条件
Player = PlayerEntity.objects.raw('Select * from player_Inform Where level>20')
# 需要注意,此时返回的对象为RawQuerySet 本身就是set集合,不需要all
# 同时我们也可已使用orderby进行排序,还有些其他参数可以自己去官网或随便试试,目录叫做:QuerySet方法
Player = PlayerEntity.objects.filter(level__gte=level_judge,
level__lte = 25).all().order_by('level')
Task9 F与Q的用法
首先了解我们的F与Q是什么
F对象,可以将自己的属性作为条件值,主要用于模型类的 A 字段属性与 B 字段属性两者的比较。简单来说,F就是拿到当前属性的某一字段值, 并且支持运算.eg.F
from django.db.models import F
# views.py
# 比如这样的应用场景,因为游戏的更新维护或者说系统崩掉了,表示步长给全体玩家等级加15级
def Jiangli(request:HttpRequest):
PlayerEntity.objects.update(level= F('level')+15)
Player = list(PlayerEntity.objects.all().values())
print(Player)
return render(request,'F_try.html',locals())
# 没错我又又又又没有把定义子路由的细节给你们
效果如图,成功自增
Q 对象相比 F 对象更加复杂一点,它主要应用于包含逻辑运算的复杂查询(and:& or:| 非:~ )。Q 对象把关键字参数封装在一起,并传递给 filter、exclude、get 等查询的方法。
在filter中虽然可以做很多约束,不过级联查询条件都是and 而不是or ,Q对象可以做到all查询。举个例子就很好理解
from django.db.models import Q
# 我们的目标是找一些资深玩家,指伊西俄老玩家和新秀玩家,游玩时间长或等级高的玩家
def Special_Player(request:HttpRequest):
Super_Player = list(PlayerEntity.objects.filter(Q(level__gte = 20)|Q(play_valu__gte =20)).values())
print(Super_Player)
# 因为不想再新建html模板直接print了,虽然浏览器有无reponse的报错但是可以再输出看到,成功
[{'id': 1, 'virture_name': 'Son_Bitch', 'level': 26, 'play_valu': 38.7, 'profile_picture': None}, {'id': 2, 'virture_name': 'MyLover', 'level': 23, 'play_valu': 14.4, 'profile_picture'
: None}, {'id': 3, 'virture_name': "'小可爱'", 'level': 44, 'play_valu': 13.8, 'profile_picture': 't11.png'}]