本文旨在对于个人知识的梳理以及知识的分享,如果有不足的地方,欢迎大家在评论区指出
ORM框架的概念
ORM是对象关系映射的简称,由于当下的程序大多采用面向对象的思想,故ORM使我们可以使用面向对象的思想来设计数据库,使得数据库更加的简单
Model层开发流程
- 安装数据库驱动:
pip install mysqlclient
- Django中settings里面数据库的配置修改
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 数据库引擎类别 'NAME': 'xxxx', # 数据库名 'USER': 'xxxx', # 用户名 'PASSWORD': 'xxxx', # 密码 'HOST':'localhost' / '127.0.0.1', # 主机ip 'PORT':3306, # 端口号 } }
- 创建app:
python manage.py startapp app名称
- 在生成的app的models.py文件中定义model类
from django.db import models class User(models.Model): name = models.CharField(max_length=30) password = models.CharField(max_length=30)
- 生成移植文件:
python manage.py makemigrations
- 执行迁移操作:
python manage.py migrate
ORM中的模型字段
字段类型 | 说明 |
---|---|
SmallIntegerField |
2字节 |
IntegerField |
4字节 |
BigIntegerField |
8字节 |
FloatField |
double |
DecimalField |
max_digits=a, decimal_places=b,指的是该小数除小数点外一共a位,其中小数点后有b位 |
CharField |
max_length=a,表示最大长度为a |
TextField |
相当于mysql中的text |
BooleanField |
相当于mysql中的tinyint |
DatetimeField |
相当于mysql中的datetime |
DateField |
auto_now_add=True表示该字段取决于该行数据首次添加的时间,auto_now=True表示该字段取决于该行数据修改的时间 |
ForeignKey |
ForeignKey(to="对方的类或类名", on_delete = 级联选项) 表示外键一对多 |
OneToOneField |
OneToOneField(to="对方的类或类名", on_delete = 级联选项) 表示外键一对一 |
ManyToManyField |
ManyToManyFiled(to="对方的类或类名") 表示外键多对多 |
ORM中的字段参数
-
null
: 默认为False
表示不能为空 -
default
: 表示该字段的默认值,例:name = models.CharField(max_length=20, default="FfFJ")
-
primary_key
: 定义当前列为主键 -
unique
: 当前列是否唯一 -
db_column
: 自定义列名,默认与定义的变量名相同 -
db_index
: 是否在某列上建立索引 -
blank
: 用于前端的form验证,表示在前端中该字段可以为空 -
meta
:class MyModel(models.Model): salary = models.DecimalField(...) ..... age = models.xxx name = models.xxx class Meta: db_table = "表名" # 设置表名,修改Django默认的表名 unique_together = ((), ()) # 设置联合索引 ordering = ['列名']或['列名1', '列名2'] # 规定表内数据的排序方式
Model-API的增删改查
这里以User这个model类为例
- 创建数据:
User.objects.create()
- 删除数据:
user = User.object.filter(id=1).first(), user.delete()
- 修改数据:
user = User.object.filter(id=1).first(), user.username = "pfco", user.save()
- 查询数据:
基本的查询方法:- all(): 返回QuerySet中的所有model对象
User.object.all()
- get(): 返回一个model对象
User.object.get(id=1)
返回指定的一条数据,如果没有,则报错 - filter(): 返回QuerySet对象,
User.object.filter(id=1)
- count(): 返回QuerySet集合中的对象个数
User.object.filter(age=12).count()
- exclude(): 返回不满足条件的QuerySet对象,
User.object.exclude(age=12)
,这行代码的意思是返回age不为12的所有用户 - first(): 返回QuerySet中的第一个数据
- last(): 返回QuerySet中的最后一个数据
- exists(): 判断当前Model类对应数据库表中是否有数据
- order_by(‘列名’): 将查询到的QuerySet集合按照列名进行升序排列,如果要降序在列名前加’-’
- lt, lte, gt, gte: 分别代表
<、<=、>、>=
,例如我们要找年龄大于等于18的所有用户,则对应的查询语句为User.objects.filter(age__gte=18)
- 模糊查询:
- contains, icontains: 返回包含某个指定字符的所有数据,icontains指的是忽略大小写,
User.objects.filter(name__contains="s")
,就是返回名字中包含s的所有用户 - startswith, istartswith: 返回以某个指定字符开头的所有数据,istartswith指的是忽略大小写
- endswith, iendswith: 返回以某个指定字符结尾的所有数据,iendswith指的是忽略大小写
- contains, icontains: 返回包含某个指定字符的所有数据,icontains指的是忽略大小写,
- 范围查询:
- in: 返回对应列数据在给定集合的所有行,例如
User.objects.filter(age__in=(18, 20))
返回的就是年龄为18或20的所有用户 - range: 返回对应列数据在给定范围的所有行,例如
User.objects.filter(age__range(18, 20))
返回的就是年龄在[18, 20]之间的所有用户
- in: 返回对应列数据在给定集合的所有行,例如
- 空值查询: 返回对应字段为空的QuerySet集合,
User.objects.filter(age__isnull=True)
表示age字段为空的所有用户 - 日期查询:
year: 年份 month: 1-12 月份 day: 一年中的第几天 hour: 一年中的第几个小时 minute: 一年中的第几分钟 second: 一年中的第几秒 week: 一年中的第几周 1-52or53 week_day: 周几 周日=1, 周六=7
- values(“列名1”, “列名2” … ): 返回符合条件的QuerySet集合中指定的列,这样每一个model对象都对应一个小字典
- 聚合函数(aggregate):
from django.db.models import Count, Max,Avg,Min,Sum User.objects.aggregate(Max("pk"), Min("Salary")) # 获得用户表中的最大id以及最少的薪水
- 分组查询(annotate):
# 分组查询是以values中的列作为分组条件 # 将所有的用户以age进行分组,并在每一组中找到最大id User.objects.values("age").annotate(Max("pk")) # 将所有的用户以age进行分组,并找到所有组中id最大值大于15的所有组 User.objects.values("age").annotate(p = Max("pk")).filter(p__gt=15)
- F()函数: 当当前的查询需要使用到表中另外的列时,使用F函数,例如
User.objects.filter(id__gt=F("age"))
就是找到id大于年龄的所有用户 - Q()函数: 当需要使用|或者~逻辑的时候,可以使用Q函数,例如
User.objects.filter(Q(id__gt=15)|Q(id__lt=10))
就是找到所有id大于15或者id小于10的用户
- all(): 返回QuerySet中的所有model对象
模型中的关联关系
- 一对一关系
class Passport(models.Model): note = models.CharField(max_length=20) person = models.OneToOneField(to="Person",on_delete=models.CASCADE,null=True) #关系属性 class Meta: db_table="t_passport" class Person(models.Model): name = models.CharField(max_length=20) age = models.IntegerField() class Meta: db_table="t_person" """ 在一对一的关系中,互相都可以通过对方类名的小写调用对方 """
- 一对多关系
class Category(models.Model): title = models.CharField(max_length=20) note = models.CharField(max_length=20) class Meta: db_table="t_category" class Goods(models.Model): title = models.CharField(max_length=20,unique=True) price = models.FloatField() cate = models.ForeignKey(to=Category,on_delete=models.CASCADE) class Meta: db_table = "t_goods" """ 在一对多的关系中,例如对于商品的分类而言,其中的某个对象我们假设为category,那么要获得 该分类下的所有商品的方法为category.goods_set,而要获得某个商品对象的分类的方式就是直 解good.cate就好了 """
- 多对多关系
class Student(models.Model): name = models.CharField(max_length=20) age = models.IntegerField() class Meta: db_table="t_student" class Course(models.Model): title = models.CharField(max_length=30) expire = models.SmallIntegerField() stu = models.ManyToManyField(to=Student) #关系属性 class Meta: db_table="t_course" """ 在多对多的关系中,有对方属性的一方可以直接调用,没有的则需要加_set,例如上面的例子,当我们 获得当前学生对象为student,那么获得他所学的课程的方式就是student.course_set,而当我获得 当前课程对象为course时,获得学习该课程的所有学生的方式就是course.stu """
在有关联关系的表中增加数据的方式为(这里以一对多的关系为例):
cate = Category.objects.create(xxxxx)
good = Goods.objects.create(xxxxx, cate=cate)
在有关联关系的表中删除数据的时候,需要给外键指定它的级联方式,主要有一下几种:
#如果要删除主,所有从的外键置null (重要)
per = models.OneToOneField(to=Person,on_delete=models.SET_NULL,null=True)
#如果要删除主,所有从一起删除
per = models.OneToOneField(to=Person,on_delete=models.CASCADE,null=True)
#如果要删除主,django什么也不做,有数据库决定是否合法
per = models.OneToOneField(to=Person,on_delete=models.DO_NOTHING,null=True)
#如果要删除主,所有从的外键置为6 (重要)
cate = models.ForeignKey(to="Category",on_delete=models.SET(6))
#如果要删除主,所有从的外键置为默认值5 (重要)
cate = models.ForeignKey(to="Category",on_delete=models.SET_DEFALUT,default="5")
#如果要删除主,如果有从数据存在,不允许删除
cate = models.ForeignKey(to="Category",on_delete=models.PROTECT)