Django中ORM框架概述

本文旨在对于个人知识的梳理以及知识的分享,如果有不足的地方,欢迎大家在评论区指出


ORM框架的概念

ORM是对象关系映射的简称,由于当下的程序大多采用面向对象的思想,故ORM使我们可以使用面向对象的思想来设计数据库,使得数据库更加的简单


Model层开发流程
  1. 安装数据库驱动: pip install mysqlclient
  2. Django中settings里面数据库的配置修改
    DATABASES = {
    	'default': {
            'ENGINE': 'django.db.backends.mysql',     # 数据库引擎类别
            'NAME': 'xxxx',                     # 数据库名
            'USER': 'xxxx',					    # 用户名
            'PASSWORD': 'xxxx',					# 密码
            'HOST':'localhost' / '127.0.0.1',	# 主机ip
            'PORT':3306,				        # 端口号
        }
    }
    
  3. 创建app: python manage.py startapp app名称
  4. 在生成的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)
    
  5. 生成移植文件: python manage.py makemigrations
  6. 执行迁移操作: 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类为例

  1. 创建数据: User.objects.create()
  2. 删除数据: user = User.object.filter(id=1).first(), user.delete()
  3. 修改数据: user = User.object.filter(id=1).first(), user.username = "pfco", user.save()
  4. 查询数据:
    基本的查询方法:
    • 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指的是忽略大小写
    • 范围查询:
      • in: 返回对应列数据在给定集合的所有行,例如User.objects.filter(age__in=(18, 20))返回的就是年龄为18或20的所有用户
      • range: 返回对应列数据在给定范围的所有行,例如User.objects.filter(age__range(18, 20))返回的就是年龄在[18, 20]之间的所有用户
    • 空值查询: 返回对应字段为空的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的用户

模型中的关联关系
  1. 一对一关系
    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"
    """
    在一对一的关系中,互相都可以通过对方类名的小写调用对方
    """
    
  2. 一对多关系
    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就好了
    """
    
  3. 多对多关系
    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)
上一篇:论文解读《SOLO: Segmenting Objects by Locations》


下一篇:LeetCode - 002_两数相加