模型中的属性介绍
一,类属性概述
1. Django工具属性的类型确定以下信息
- 当前选择的数据库支持的字段类型
- 渲染管理表单时使用的默认html控件
- 在管理站点最低限度的验证
2. Django的主键
- 会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则Django不会再生成默认的主键列
3. 属性命名限制
- 不能是Python的保留关键字
- 由于Django的查询方式,不允许使用连续的下划线
二,库
1.库的定义
- 定义属性时,需要字段类型,字段类型被定义在django.db.models.fields 目录下,为了方便使用,被导入到django.db.models中
2. 使用方式
- 导入 from django.db import models
- 通过models.Field创建字段类型的对象,赋值给属性
三,逻辑删除
对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False
四,字段类型
1. AutoField
- 介绍:一个根据实际ID自动增长的IntergerField,通常不指定,如果不指定,一个主键字段将自动添加到模型中
2. CharField(max_length=字符长度)
- 介绍:字符串,默认的表单样式是TextInput
3. TextField
- 介绍:大文本字段,一般超过4000字节使用,默认的表单控件是Textarea
4. IntergerField
- 介绍:整数
5. DecimalField(max_digits=None,decimal_places=None)
- 介绍:使用Python的Decimal实例表示的十进制浮点数
- 参数说明:
- DecimalField.max_digits – 位数总数
- DecimalField.decimal_places – 小数点后的数字位数
6. FloatField
- 介绍:用Python的float实例来表示的浮点数
7. BooleanField
- 介绍:true/false 字段,此字段的默认表单控制是CheckboxInput
8. NullBooleanField
- 介绍:支持null,true,false三种值
9.DateField(auto_now=False,auto_now_add=False)
- 介绍:使用Python的datetime.date实例表示的日期
- 参数说明:
- DateField.auto_now 每次保存对象时,自动设置该字段为当前时间,用于“最后一次修改”的时间戳,他总是使用当前日期,默认为False
- DateField.auto_now_add 当对象第一次被创建时自动设置当前时间,用于创建的时间戳,他总是使用当前日期,默认为False
- 说明:该字段默认对应的表单控件是一个TextInput,在管理员站点添加了一个JavaScript写的日历控件,和一个“Today”的快捷按钮,包含了一个额外的invalid_date错误消息键
- 注意:auto_now,auto_now_add,and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果
10. TimeFiled
- 介绍:使用Python的datetime.time 实例表示的时间,参数同DateField
11. DateTimeField
- 介绍:使用Python的datetime ,datetime 实例表示的日期和时间,参数同DateField
12. FileField
- 介绍:一个上传文件的字段
13. ImageField
- 介绍:继承了FileField 的所有属性和方法,但对上传的对象进行校验,确保它是一个有效的image
五,字段选项
1. 概述:
- 通过字段选项,可以实现对字段的约束
- 在字段对象时通过关键字参数指定
2. 字段值
- null:如果为True,Django将空值以NULL 存储到数据库中,默认值是False
- blank:如果为True,则该字段允许为空白,默认值是False
注意:null是数据库范畴的概念,blank是表单验证范畴的 - db_column:字段的名称,如果未指定,则使用属性的名称
- db_index:若值为True,则在表中会为此字段创建索引
- default:默认值
- primary_key:若为True,则该字段会成为模型的主键字段
- unique:若为True,这个字段在表中必须有唯一值
六,关系
1. 分类:
- ForeignKey:一对多,将字段定义在多的端中
- ManyToManyField:多对多,将字段定义在两端中
- OneToOneField:一对一,将字段定义在任意一端中
2. 访问方式
- 用一访问多:
格式:对象.模型类小写_set
示例:grade.students_set - 用一访问一:
格式:对象.模型类小写
示例:grade.students - 访问id:
格式:对象.属性_id
示例:student.sgrade_id
七,元选项
1. 定义
在模型类中定义Meta类,用于设置元信息
2. 示例代码:
class Meta:
# 定义数据表名,推荐使用小写,默认为项目小写_类名小写
db_table = 'students'
# 对象的默认排序字段,获取对象的列表时使用
ordering = ['id'] # 升序
# ordering = ['-id'] # 降序
# 注意:排序会增加数据库开销
模型成员
一,类属性
1. 自定义的类属性
详见上方“模型中的属性介绍”
2. objects:
- 是Manager类型的一个对象,作用是与数据库进行交互
- 当定义模型类时没有指定管理器,则Django为模型创建一个名为objects的管理器
3. 自定义模型管理器:
- 当为模型指定模型管理器,Django就不再为模型类生成objects模型管理器
- 示例代码:
class Student(models.Model): StudentObj = models.Manager()
4. 自定义管理器Manager() 类
- 概念介绍:模型管理器是Django的模型与数据库进行交互的接口,一个模型可以有多个模型管理器
- 作用:
- 向管理器中添加额外的方法
- 修改管理器返回的原始查询集 --> 重写get_queryset()方法
- 代码示例:
class StudentManager(models.Manager):
# 代码逻辑删除后,返回未被删除的数据
def get_queryset(self):
return super(StudentManager,self).get_queryset().filter(isDelete=False)
class Student(models.Model):
# 自定义模型管理器,当自定义模型管理器,Django就不再为模型类生成objects模型管理器
StudentObj = models.Manager()
StudentObj2 = StudentManager()
二,创建对象
1. 目的
向数据库中添加数据,在models中创建对象时,Django不会对数据库进行读写操作,只有调用save() 方法时才与数据库交互,将对象的数据保存到数据库
2. 注意:__init__方法已经在父类models.Model 中使用,在自定义的模型中无法使用
3. 方法:
1. 在模型类中增加一个类方法:
- \Django\MyDjango\project\MyApp\models.py 文件中增加以下内容
class Student(models.Model):
# 自定义模型管理器,当自定义模型管理器,Django就不再为模型类生成objects模型管理器
StudentObj = models.Manager()
StudentObj2 = StudentManager()
objects = None
studentName = models.CharField(max_length=64)
studentAge = models.IntegerField(max_length=64)
studentGender = models.BooleanField(default=False)
#grade = models.IntegerField(max_length=64)
# 关联外键
grade = models.ForeignKey("Grade",on_delete=models.DO_NOTHING) # 删除关联数据,什么也不做
isDelete = models.BooleanField(default=False)
# 不需要定义主键,在生成时会自动增加
def __str__(self):
return self.studentName
# 在模型类中定义Meta类,用于设置元信息
class Meta:
# 定义数据表名,推荐使用小写,默认为项目小写_类名小写
#db_table = 'myapp_'
# 对象的默认排序字段,获取对象的列表时使用
ordering = ['id'] # 升序
# ordering = ['-id'] # 降序
# 注意:排序会增加数据库开销
# 类方法,创建数据库对象
@classmethod
def AddStudents(cls,Name,Age,Grade,IsDelete,Gender):
StuOBJ = cls(studentName = Name,studentAge = Age,grade = Grade,isDelete = IsDelete,studentGender = Gender)
return StuOBJ
- \Django\MyDjango\project\MyApp\views.py 文件中增加以下内容,调用models.py 中的数据库类方法,实现向数据库添加数据
def AddStudent(requset):
GradeId = Grade.objects.get(pk = 2)
stu = Student.AddStudents("刘亦菲","22",GradeId,False,True)
stu.save()
return HttpResponse("保存成功")
- \Django\MyDjango\project\MyApp\urls.py 文件中添加路由信息
urlpatterns = [
url(r"^AddStudent/$",views.AddStudent), # 关联添加学生
]
- 重启服务,访问http://127.0.0.1:8000/AddStudent,即可实现添加学生功能
2. 在定义管理器中添加一个方法:
- \Django\MyDjango\project\MyApp\models.py 文件中增加以下内容
class StudentManager(models.Manager):
def get_queryset(self):
return super(StudentManager,self).get_queryset().filter(isDelete=False)
def CreateStudent(self,Name,Age,Grade,IsDelete,Gender):
Stu = self.model()
Stu.studentName = Name
Stu.studentAge = Age
Stu.grade = Grade
Stu.isDelete = IsDelete
Stu.studentGender = Gender
print("Grade的类型:", type(Grade))
return Stu
- \Django\MyDjango\project\MyApp\views.py 文件中增加以下内容,调用models.py 中自定义管理器的对象,实现向数据库添加数据
def AddStudent2(requset):
GradeId = Grade.objects.get(pk = 2)
stu = Student.StudentObj2.CreateStudent("黎明8","33",GradeId,False,True)
stu.save()
return HttpResponse("AddStudent2,保存成功")
- \Django\MyDjango\project\MyApp\urls.py 文件中添加路由信息
urlpatterns = [
url(r"^AddStudent2/$", views.AddStudent2) # 关联添加学生
]
- 重启服务,访问http://127.0.0.1:8000/AddStudent2,即可实现添加学生功能
模型查询
一,概述
1.查询集
- 查询集表示从数据库获取的对象集合
- 查询集可以有多个过滤器,过滤器是一个函数,基于所给的参数限制查询集结果
二,查询集使用方法
1. 管理器上调用过滤器方法
在管理器上调用过滤器方法返回查询集,详见下方代码
class StudentManager(models.Manager):
def get_queryset(self):
return super(StudentManager,self).get_queryset().filter(isDelete=False)
2. 链式调用
查询集经过过滤器筛选后返回新的查询集,所以可以写成链式调用
3. 惰性执行
创建查询集不会带来任何数据的访问,直到调用数据时,才会访问数据
4. 直接访问数据的情况
- 迭代
- 序列化
- 与if合用
5. 返回查询集的方法称为过滤器
1. all()
返回查询集的所有数据
2. filter()
返回符合条件的数据
- filter(键=值) --> 单一条件过滤
- filter(键=值 键=值) --> 复合条件过滤,且关系
- filter(键=值).filter(键=值) --> 复合条件过滤,且关系
3. exclude()
返回不符合条件的数据
4. order by()
排序
5. values()
一条数据是一个对象(字典),返回一个列表
6. 返回一条数据
1. get()
- 返回一个满足条件的对象
- 注意:
- 如果没有找到符合条件的对象,会引发"模型类.DoesNotExist"异常
- 如果找到多条符合条件的对象,会引发"模型类.MultipleObjectsReturned"异常
2. count()
返回当前查询集中的对象个数
3. first()
返回查询集中的第一个符合条件的对象
4. last()
返回查询集中的最后一个符合条件的对象
5. exists()
判断查询集中是否有数据,如果有数据返回True
7. 限制查询集
1. 介绍
查询集返回列表,可以使用下标的方式进行限制,等同于sql中的limit语句
2. 注意
下标不能为负数
8. 查询集的缓存
1. 概述
- 每个查询集都包含一个缓存,来最小化的对数据库访问
- 在新建的查询集中, 缓存首次为空,会发生数据缓存,Django会将查询出来的数据做一个缓存,并返回查询结构,以后的查询直接使用查询集的缓存。
9. 字段查询
1. 概述
- 实现了SQL中的where 语句,作为方法filter(),exclude(),get()的参数
- 语法
- 属性名称_比较运算符=值
- 例如:StudentAge__>20
- 外键
- 属性名_id
- 转义
- SQL语句中的like 使用 % 是为了匹配占位,匹配数据中的%(where like ‘%’)
- Django 中不需要转义
def StudentSearchName(request):
StudentList = Student.StudentObj2.filter(studentName__contains="%")
return render(request,"MyApp/students.html",{"studentsHtml":StudentList})
2. 比较运算符
- exact
- 概述:判断,大小写敏感,如果是iexact,则不区分大小写
- 例如:filter(isDelete=False)
- contains
- 概述:是否包含,大小写敏感,如果是icontains,则不区分大小写
- 例如:
def StudentSearchName(request):
StudentList = Student.StudentObj2.filter(studentName__contains="明")
return render(request,"MyApp/students.html",{"studentsHtml":StudentL
- startswith,endswith
- 概述:以 value 开头或结尾,大小写敏感,如果是istartswith,iendswith,则不区分大小写
- 例如:
def StudentStartswithName(request):
StudentList = Student.StudentObj2.filter(studentName__startswith="张")
return render(request,"MyApp/students.html",{"studentsHtml":StudentList})
- isnull,isnotnull
- 概述:是否为空
- filter(StudentName__isnull=False)
- in
- 概述:是否包含在范围内
- 示例代码
def StudentIn(request):
StudentList = Student.StudentObj2.filter(pk__in=[2,4,5,7])
return render(request,"MyApp/students.html",{"studentsHtml":StudentList})
- gt,gte,lt,lte
- 概述:gt表示大于,gte表示大于等于,lt表示小于,lte表示小于等于
- 示例代码
def StudentAgeGt(request,Age):
StudentList = Student.StudentObj2.filter(studentAge__gt=Age)
return render(request,"MyApp/students.html",{"studentsHtml":StudentList})
- year,month,day,week_day,hour,minute,second
- 示例代码
StudentList = Student.StudentObj2.filter(lastTime__year=2017)
- 跨关联查询
- 处理join查询
- 语法:模型类名(小写)__属性名__比较运算符
- 示例代码
- 处理join查询
# 查询学生名字中包含“亦菲”的班级
def GetNameContainsOfGrade(request):
GradeList = Grade.objects.filter(student__studentName__contains="亦菲")
return render(request,"MyApp/grades.html",{"gradesHtml":GradeList})
- 查询快捷
pk:代表主键
3. 聚合函数
- 使用aggregate() 函数返回聚合函数的值
- Avg
- Count
- Max
- Min
- Sum
- 示例代码
from django.db.models import Max
def GetStudentMaxAge(request):
MaxAge = Student.StudentObj2.aggregate(Max("studentAge"))
print(MaxAge)
StudentList = Student.StudentObj2.filter(studentAge__gt=30)
return render(request,"MyApp/students.html",{"studentsHtml":StudentList})
4. F对象
- 概述:可以使用模型的A属性与B属性进行比较
- 示例代码
# 列出女生比男生人数多的班级
from django.db.models import F,Q
def GetGirlNumGTBoyNumOfGrades(request):
GradesList = Grade.objects.filter(girlNum__gt=F('boyNum'))
return render(request, 'MyApp/grades.html', {"gradesHtml": GradesList})
- 支持F对象的算术运算
# F对象的boyNum属性加20后,再与girlNum属性相比较
from django.db.models import F,Q
def GetGirlNumGTBoyNumOfGrades(request):
GradesList = Grade.objects.filter(girlNum__gt=F('boyNum')+20)
return render(request, 'MyApp/grades.html', {"gradesHtml": GradesList})
5.Q对象
- 概述:过滤器方法中的关键字参数,条件为and模式
- 示例代码
# 获取年龄大于30或小于20的学生列表
from django.db.models import Q
def GetAgeGTThrityOrLTTwentyOfStudent(request):
StudentssList = Student.StudentObj2.filter(Q(studentAge__gt=30)|Q(studentAge__lt=20))
return render(request, 'MyApp/students.html', {"studentsHtml": StudentssList})
- 过滤条件中只有一个Q对象,就是用于匹配的
# 获取年龄大于30的学生列表
from django.db.models import Q
def GetAgeGTThrityOrLTTwentyOfStudent(request):
StudentssList = Student.StudentObj2.filter(Q(studentAge__gt=30))
return render(request, 'MyApp/students.html', {"studentsHtml": StudentssList})
- 取反
# 获取年龄小于等于30的学生列表
from django.db.models import Q
def GetAgeGTThrityOrLTTwentyOfStudent(request):
StudentssList = Student.StudentObj2.filter(~Q(studentAge__gt=30))
return render(request, 'MyApp/students.html', {"studentsHtml": StudentssList})