Django中的ORM

ORM介绍:object relational mapping 对象关系映射
    1> 把面向对象中的类和数据库表一一对应,通过操作类和对象,对数据表实现数据操作,不需要写sql,由orm框架生成。

    2> Django实现了ORM的一个框架,在项目与数据库之间起桥梁作用。
    
    3> django数据库开发步骤如下:
        a 在models.py定义模型类

        b 生成迁移文件: python manage.py makemigrations  -> 在migrations文件夹生成0001_intial.py

        c 执行迁移生成数据库(默认会用sqite3数据库,生成数据库名为:db.sqlite3)
          python mange.py migrate  -> 在数据库中生成对应的数据 test01_department 等

        d 通过模型类和对象,对数据进行增删改查

模型类设计:
    1> 在应用models.py 中编写模型类,必须继承于models.Model类

    2> 在模型类中,定义属性,生成对应的数据库表字段
       属性名 = models.字段类型(字段选项)

    3> 字段类型(初步了解,models包下的类):只要修改了类型,就需要重新迁移

  • AutoField: 自动增长,通常不需要指定,django自动创建名为id的自动增长属性
  • CharField: 字符串,必须指定的参数: max_length 最大字符个数
  • TextFiled: 大文本字段,一般超过4000个字符
  • IntegerField: 整形
  • BooleanField: 布尔,支持Null,True
  • NullBooleanField: 支持Null,True,False
  • DateFiled: [auto_now=False, auto_now_add=False]
    • auto_now 表示自动设置该字段为最后一次修改的时间,默认为False
    • auto_now_add 表示自动设置该字段为创建时的时间,默认为False
    • 两者互斥,不能同时使用
  • DateTimeField: 日期时间
  • DecimalFiled(max_digits=None, decimal_places=None): 
    • 十进制浮点数,适合用于保存金额,精度较高
    • 必须指定参数,max_digits总位数,decimal_places小数位数
  • FloatField: 浮点数,有误差 
  • FileField: 上传文件字段
  • ImageField: 继承与FileFiled,对上传的内容进行校验,确保是有效地图片
  • ForeignKey: 外键,建立一对多关系

    4> 字段选项:通过选项实现对字段的约束
    
选项默认值描述是否要重新迁移修改表结构
null False 如果为True,数据库中字段允许为空
unique False True表示这个字段在表中必须有唯一值
db_column 属性名称 字段名,如果未指定,则使用属性的名称
primary_key False 若为True,则该字段会成为模型的主键字段,一般作为AutoField的选项使用
default - 默认值
blank False True,html页面后台填写表单验证时字段允许为空
editable True 如果设为False, 这个字段将不会出现在管理后台
choices - True,html页面表单验证时字段允许为空

    choices-下拉列表:
        choices_sex = (
            (0, '男'),
            (1, '女'),
        )
        sex = models.IntegerField(default=0, choices=choices_sex)
    5> 元类class Meta的使用:
        class Meta:
            # 修改表名(需要迁移)
            db_table = 'department'

            # 修改后台的显示的表名
            verbose_name = '部门'
            # 去除复数形式
            verbose_name_plural = verbose_name

修改和添加类:
    from test01.models import *
    from datetime import date
    d = Department()
    d.name = ‘人事部’
    d.create_date = date(2019, 1, 1)
    d.save()

    d.id = None  # 修改id创建新的数据
    d.save()
    
    d.id = 2 
    d.delete()  # 删除id=2 

模型管理器:
    1> 在django创建对象时,都会默认创建一个object属性,是一个manage类,有以下几种方法:

objects管理器中的方法返回类型作用
模型类.objects.get()模型对象返回一个对象,且只能有一个

如果查到多条数据,则报:MultipleObjectsReturned 

如果查询不到数据,则报:DoesNotExist
模型类.objects.all()QuerySet返回所有的对象
模型类.objects.filter()QuerySet返回满足条件的对象
模型类.objects.exclude()QuerySet返回不满条件的对象
模型类.objects.order_by()QuerySet对查询结果集进行排序
模型类.objects.aggregate()字典,例如:

{‘salary__avg’: 9500.0}
进行聚合操作

Sum, Count, Max, Min, Avg
模型类.objects.count()数字返回查询集中对象的数目



get(), all() 和 employee_set.all()方法:

    d = Department.objects.get(id=1)
    print(d.name)
    ----------------------------------------------------------------------
    >>> from test01.models import *
    >>> d = Department.objects.all()
    >>> d
    [<Department: 人事部>, <Department: 人事部>]
    >>> e = Employee()
    >>> e.name = '张三'
    >>> e.age = 20
    >>> e.sex = 0
    >>> e.salary = 100000
    >>> e.comment = '无'
    >>> e.department = Department.objects.get(id=1)  # 设置外键
    >>> e.save()
    >>> e.id = None
    >>> e.name = '李四'
    >>> e.save()
    >>> d = Department.objects.get(id=1) # 重复设置外键
    >>> d.employee_set.all()  # employee_set 为django一对多的时候自动生成的属性
    [<Employee: Employee object>, <Employee: Employee object>]
    ----------------------------------------------------------------------
    # 根据员工查部门   
    >>> e = Employee.objects.get(id=1)
    >>> e.department
    <Department: 人事部>

增删改:
    Employee.objects.filter(id=1).delete()
    Employee.objects.filter(id=1).update(name=‘行政部')

条件查询:
    1> 判等:exact
        # 例:查询id为1的员工
        select * from test01_employee where id = 1;
        Employee.objects.filter(id__exact=1)
        Employee.objects.filter(id=1)

    2> 模糊查询:contains,endswith/startswith
        # 查询包含马的员工
        select * from test01_employee where name = “%马%";
        Employee.objects.filter(name__contains=‘马’)

    3> 空查询:isnull
        # 查询comment 不为空
        select * from test01_employee where comment is not null;
        mployee.objects.filter(comment__isnull=False)

    4> 范围查询:in
        # 查询id为1,3,5
        select * from test01_employee where id in (1, 3, 5);
        Employee.objects.filter(id__in=(1, 3, 5))

    5> 比较查询:gte(>=), lte(<=), gt(>), lt(<) 
        # 查询年龄大于等于30
        mployee.objects.filter(age__gte=30)

    6> 日期查询: year、month、day、week_day、hour、minute、second
        # 查询入职年份为2015
        select * from test01_employee where year(hire_date) = 2015;
        Employee.objects.filter(hire_date__year=2015)
        
        # 查询入职年份在2015-1-1以后
        select * from test01_employee where hire_date >= date(2015-1-1);
        from datetime import date
        Employee.objects.filter(hire_date__gte=date(2015, 1, 1))

    7> exclude:
        # 查询id 不等于 1
        select * from test01_employee where id != 1;
        Employee.objects.exclude(id=1)

关联查询:
    1> 通过对象:
        a. 一对多 departement.employee_set.all()
        b. 多对一 employee.department

    2> 通过模型管理器:
        # 查询部门信息,要求部门中员工名字包含马
        select * from test01.department as d inner join test01.employee as e 
        on d.id = e.department_id where e.name like ‘%马%’;

        Department.objects.filter(employee__name__contains='马’)
        >>> <QuerySet [<Department: 财务部>, <Department: 财务部>]>
        
        # 查询部门为研发部的所有员工信息
        select * from test01.department as d inner join test01.employee as e 
        on d.id = e.department_id where d.name = '研发部’

        Employee.objects.filter(department__name__exact = '研发部’)
        >>> <QuerySet [<Employee: 老李>, <Employee: 老王>, <Employee: 王五>]>
        

F对象:用于比较表中两个字段
     # 查询age 大于四倍 id
     from django.db.models import F
     Employee.objects.filter(age__gt=F('id') * 4)


Q对象:对查询条件进行与或非(&|~)的逻辑操作,多个条件

    # 查询年龄大于30 且 id 大于3
    from django.db.models import Q
    select * from test01_employee where id > 3 and age > 30;
    Employee.objects.filter(id__gt=3, age__gt=30)
    Employee.objects.filter(Q(id__gte=3)&Q(age__gte=30))

    # 查询id不等于3
    Employee.objects.filter(~Q(id=3)) -> 波浪线

order_by 方法:排序方法,降序’-属性名’
    # 统计id 大于等于3,降序排列
    select * from test01_employee where id > 3 order by age desc;  -> [asc升序]
    Employee.objects.filter(id__gt=3).order_by('-age')

aggregate方法:聚合操作,对多行查询结果的一列进行操作
    1> 常用聚合类Sum, Count, Max, Min, Avg,返回字典{‘属性名__聚合函数’: 值}
    
    2> from django.db.models import Count, Avg
        
       # 查询总人数
       select count(*) from test01_employee;
       Employee.objects.aggregate(Count('id’))
       >>> {'id__count': 10}

       # 查询工资平均数
       select avg(salary) from test01_employee;
       Employee.objects.aggregate(Avg('salary’))
       >>> {'salary__avg': 9600.0}

count()方法:统计总数,返回一个数值
       # 查询id大于等于3的人数
       select count(*) from test01_employee where id >= 3;    
       Employee.objects.filter(id__gte=3).count()

QuerySet 查询集:
    1> 为一个数列,下标不能够为负,可以进行切片操作,datas[0:1:-1]

    2> 拥有get(),同objects管理器相同。

    3> 拥有exists(),判断数列中是否有数据

    4> 惰性查询:创建QuerySet的时候不会马上查询数据库,当访问数据的时候才会发起查询操作。

                datas = Department.objects.all()  # 不会查询
    
    5> 缓存:当首次查询时,会缓存,再次查询时会使用之前查询的数据, 但是使用索引或者切片操作,就不会缓存

       datas = Department.objects.all()
       # 首次遍历,缓存数据
       [deps.name for deps in datas]
       # 不会查询数据库
       [deps.name for deps in datas]
    
       datas = Department.objects.all()
       # 会查询数据库
       datas[0]
       # 会查询数据库
       datas[0]



自关联:查询父级和子级目录
    class Area(models.Model):
        title = models.CharField(max_length=20)
        parent = models.ForeignKey(‘self’, on_delete=models.CASCADE, null=True, blank=True)

        def __str__(self):
            return self.title

        +------+-----------------------------------------------+-----------+
        | id   | title                                         | parent_id |
        +------+-----------------------------------------------+-----------+
        |    1 | 中国                                          |      NULL |
        |    2 | 北京市                                        |         1 |
        |    3 | 天津市                                        |         1 |
        +------+-----------------------------------------------+-----------+

    from app01.models import *
    a = Area.objects.get(id=232)

    # 获得父级
    a.parent.title >>> ‘广东省’
    
    # 获得子级
    a.area_set.all()  >>>   ….








  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值