美文网首页
(二) Django模型models

(二) Django模型models

作者: fanhang64 | 来源:发表于2018-03-20 20:56 被阅读41次

    模型models

    一. 配置数据库

    (1) 修改工程目录下的__init__.py, 添加

    import pymysql
    pymysql.install_as_MySQLdb()
    

    (2) 修改settings.py文件, 修改为

    DATABASES = {
        'default': {
            # 'ENGINE': 'django.db.backends.sqlite3',
            # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'day36',  # 数据库名
            'USER': 'fanzone',
            'PASSWORD': '123',
            'HOST': 'localhost',
            'PORT': '3306',
        }
    }
    

    二. 开发流程

    1. 配置数据库
    2. 创建app
    3. 创建模型类
    4. 生成迁移文件
    5. 创建表结构
    6. 对model的增删改查
    7. 找到views.py文件写入控制器(视图函数)
    8. 配置路由 urls.py在工程目录下
    9. 创建模板文件夹
    10. 在settings.py配置模板路径
    11. 在控制器里使用render()方法 访问模板

    三. ORM 对象关系映射

    概述: 对象-映射

    任务:

    1. 根据对象的类型生成表结构
    2. 将对象列表的操作, 转换为SQL语句
    3. 将SQL语句查询到的结果转换为对象和列表

    四. 定义模型

    (1) 模型-属性-表-字段之间的关系

    一个模型类对应数据库中的一个表, 在模型类中定义的属性对应表中的字段名称

    (2) 定义字段属性

    (3) 创建模型类

    在models.py文件中创建类

    (4) 元选项

    在模型类中定义一个Meta类, 用于设置元信息

    db_table: 自定义设置表名 推荐使用小写字母, 数据表名, 默认为 app名称_类名小写

    ordering: 查询数据时, 按照某个字段升序或降序查询, 默认升序

    实例:

    # 学生表
    class Students(models.Model):
         pass
        class Meta:
            db_table = 'student'  # 设置当前表名
            # ordering = ['pk']  # 按照主键升序查询
            ordering = ['-pk']   # 按照主键降序查询,前面带有可选的“-”前缀表示倒序
    

    五. 模型成员

    类属性

    1. objects 管理器

    objects是Manager类型的一个对象, 作用是与数据库进行交互

    当定义模型类的时候, 若没有指定管理器 django会为你默认创建一个名为objects的管理器

    2. 自定义管理器的名称

    # 学生表
    class Students(models.Model):
        stuObj = models.Manager()  # 自定义管理器名称,若指定,则objects不会创建
    

    同时把视图中的代码改为

    def stuShow(request):
        myDict = {}
        # myDict['stu'] = Students.objects.all()
        myDict['stu'] = Students.stuObj.all()  # 新修改的stuObj
    

    3. 自定义管理器Manager类

    一个模型可以有多个模型管理类

    操作:

    重写父类的get_queryset()方法

    实例:

    class StudentsManager(models.Manager):
        def get_queryset(self):  # 重写父类的方法
          return super(StudentsManager,self).get_queryset().filter(isDelete=True)# 过滤,符合条件的要
          #return super(StudentsManager,self).get_queryset().exclude(isDelete=True) # 符合条件的不要
    class Students(models.Model):  # 学生表
        ...
        stuObj2 = StudentsManager()  # 增加了自己过滤的新的manage管理器
    

    六. 创建对象

    (1) 目的

    向数据库中添加数据, 当创建对象的时候django不会对数据库进行读写的操作, 当调用save()时候才与数据库交互

    (2) 实现方法

    1. 在模型类中增加一个类方法

    __init__()方法已经在基类models.Model中使用, 在自定义模型中无法使用重写. # ?

    实例:

    # 学生表
    class Students(models.Model):
       pass
       # 类方法是可以不通过当前对象实例化去调用的,通过当前的类名.类方法([参数])
       # cls 代表Students类,类方法第一个参数为cls
       @classmethod  # 装饰器声明为类方法
       def addStudents(cls, sname, ssex, sage, scontented, sgrade):
           stu = cls(sname=sname,ssex=ssex,sage=sage,scontented=scontented,sgrade=sgrade)
           return stu
    
    

    在视图中的操作

    def addStudents(request):
       # stu = Students()
       # stu.sname ='李四'
       ..
       # 通过类方法添加
       stu = Students.addStudents('赵六', True, 20, '我是赵六', Grades.objects.get(pk=1))
       stu.save()
       return HttpResponse('添加学生成功')
    
    2. 在自定义管理器中添加一个方法

    实例:

    class StudentsManager(models.Manager):
        def get_queryset(self):
           pass
        def addStudents(self, sname, ssex, sage, scontented, sgrade):
            # stu = Students()  # ok
            stu = self.model()  # 同上 当模型类名称发生改变 不需要更改当前类名称
            stu.sname = sname
            stu.ssex = ssex
            stu.sage = sage
            stu.scontented = scontented
            stu.sgrade = sgrade
            return stu
    

    在视图中使用

    def addStudents(request):
        # 通过自定义管理器的方法添加
        stu = Students.stuObj2.addStudents('赵六11', True, 20, '我是赵六11', Grades.objects.get(pk=1))
        stu.save()
        return HttpResponse('添加学生成功')
    

    七. 模型的查询

    概述:

    1. 查询集(queryset)表示从数据库获取对象的集合
    2. 查询集可以有多个过滤器
    3. 过滤器就是一个函数, 基于所给的参数, 去限制查询集
    4. 从SQL角度来说, 查询集合select语句是等价, 过滤器就像where条件

    (1) all() 返回查询集中的所有数据/对象

    实例:

    类名.objects.all()  # 返回所有的数据,列表的形式返回(queryset查询集)
    myDict['stu'] = Students.stuObj.all()[0:2]  # 取两条数据 0 1
    stu = Students.stuObj.all()[-1]  # error 不支持负索引
    

    通过all()和索引取值做分页例子:

    # 学生信息分页
    def stuPage(request, nowPage):
        myDict = {}
        myDict['stu'] = Students.stuObj.all()[(int(nowPage)-1)*2:int(nowPage)*2]  # 分页,每页显示2条数据
        # print(type(nowPage))  # str 接收到的nowPage为字符串类型
        return render(request, 'myApp/stuShow.html', myDict)
    

    url配置:

    url(r'stuPage/(\d+)/', views.stuPage),  # () 子存储取值传递给nowPage
    

    (2) filter() 返回符号条件的数据

    得到的是一个集合的对象, 即queryset

    一个条件的情况:

    filter(键=值)

    Students.objects.filter(sname='张三')  # 返回包含sname为张三的列表
    

    多个条件的情况:

    filter(键=值, 键=值, ...) # 多个条件之间是并且的关系

    myDict['stu'] = Students.stuObj.filter(sname='张三', ssex=False)  # 返回sname='张三',性别为女的列表
    

    (3) exclude() 过滤掉符合条件的数据

    exclude(键=值, 键=值, ...) # 多个条件之间是并且的关系

    myDict['stu'] = Students.stuObj.exclude(sname='张三', ssex=False)  # 返回除了sname='张三',性别为女的对象的查找集
    

    (4) order_by('字段名') 排序

    升序/降序

    格式为:

    类名.objects.order_by('字段名')  # 升序
    类名.objects.order_by('-字段名')  # 添加- 表示降序
    myDict['stu'] = Students.stuObj.filter(ssex=True).order_by('-id') # 查询条件为 性别为True 按照id降序排列
    

    (5) reverse() 对查询查找集进行反转

    格式为: order_by().reverse()

    实例:

    myDict['stu'] = Students.stuObj.all().order_by('-id').reverse()  # ok 为查找集进行反转
    myDict['stu'] = Students.stuObj.all().reverse() # 不起作用, 必须要和order_by配合使用
    

    (6) values() 返回查找集, 以列表的形式返回多个字典, 字典的键为字段的名称

    实例:

    myDict['stu'] = Students.stuObj.values()  # 返回查找集, 返回所有的字段的字典
    myDict['stu'] = Students.stuObj.values('sname','ssex') # 返回sname和ssex字段的查找集, 返回多个字典,字典中的字段名为键
    myDict['stu'] = Students.stuObj.filter(sname='张三').values('sname','ssex')  # 返回姓名为张三的sname和ssex字段
    

    (7) values_list() 以列表形式 返回包含的多个元组(每个元素是一个元组), 只包含值, 不包含字段

    实例:

    # 返回查找集,以列表形式 返回包含的多个元组
    myDict['stu'] = Students.stuObj.filter(sname='张三').values_list('sname','ssex')  # 返回姓名为张三的sname和ssex字段
    

    八. 返回单个数据

    (1) get() 返回一条数据(一个对象)

    实例:

    stu = Students.stuObj.get()  # error 多条数据
    stu = Students.stuObj.get(pk=20) # error 没有找到符号条件
    stu = Students.stuObj.get(pk=1)  # ok  Students object 返回对象
    # 下面这俩中结果一样
    Students.stuObj.filter(sname='李四')[0] <==> Students.stuObj.get(pk=1)  # 为对象
    

    注意:

    1. 如果没有找到符合条件的对象, 会引发模型类的models.DoesNotExist异常错误
    2. 如果查询的数据超过一条, 会引发模型类的models.MultipleObjectsReturned异常

    (2) count() 统计查询结果集中的对象的个数

    格式:

    类名.objects.all().count()  # 统计所有数据的条数
    

    实例:

    Students.objects.all().count()  # 统计所有数据的条数
    Students.objects.filter(ssex=True).count()  # 统计ssex为男的个数
    

    (3) first()/last() 返回查询结果的第一个/最后一个对象

    实例:

    Students.objects.filter(ssex=True).first()  # 第一个对象, filter返回列表,返回列表中的第一个对象
    stu = Students.stuObj.filter(ssex=True).first().sname  # 张三  返回性别为男的第一个对象的name
    Students.objects.filter(ssex=True).last()  # 最后一个对象
    

    (4) exists() 判断queryset是否包含数据 如果包含返回True, 否则为False

    实例:

    Students.objects.filter(ssex=True).exists()  # True
    Students.objects.filter(pk=20).exists()  # False
    

    (5) 字段值的修改

    save() : 更适合单条数据的修改

    update() : 适用于多条数据

    zs = Students.stuObj.get(sname='张三')
    zs.sname = '张三三'
    zs.save()  # 适用于单条数据的修改
    Students.stuObj.get(sname='张三三').update(sname='张三')  # error update为queryset的查询集的方法
    Students.stuObj.filter(sname='张三三').update(sname='张三')  # ok
    Students.stuObj.all().update(isDelete=False)  # ok
    Students.stuObj.all().update(isDelete=False, ssex=False)  # 修改多个字段,
    

    九. QuerySet 字段比较运算符

    (1) 完全匹配运算符

    1. __exact:大小写敏感
    2. __iexact:忽略大小写

    实例:

    Students.stuObj.filter(sname__exact='ab') # 三个结果相同
    Students.stuObj.filter(sname='ab')  # 同上
    Students.stuObj.filter(sname__iexact='ab')  # 同上
    

    (2) 是否包含

    1. __contains: 大小写敏感
    2. __icontains:忽略大小写

    实例:

    Students.stuObj.filter(sname__contains='A')  # ok AB
    Students.stuObj.filter(sname__icontains='A')  # 忽略大小写 aB AB
    

    (3) 以..开头/以..结尾

    1. __startswith:大小写敏感
    2. __istartswith:忽略大小写
    3. __endswith:大小写敏感
    4. __iendswith:忽略大小写

    实例:

    myDict['stu'] = Students.stuObj.filter(sname__startswith='A')  # AB 以A开头
    myDict['stu'] = Students.stuObj.filter(sname__startswith='a')
    myDict['stu'] = Students.stuObj.filter(sname__istartswith='A') # AB ab 忽略大小写
    myDict['stu'] = Students.stuObj.filter(sname__endswith='三')  # 以 '三' 结尾
    

    (4) 是否为空

    1. __isnull:判断为空

    值为: True和False

    实例:

    Students.stuObj.filter(sname__isnull = False)  # 查找sname不为空
    Students.stuObj.filter(sname__isnull = True)  # 查找snmae为空
    

    (5) 在..范围里

    1. __in:

    实例:

    Students.stuObj.filter(pk__in = [1,2,3,10])  # id在1,2,3,10中的
    Students.stuObj.exclude(pk__in = [1,2,3,10])  # id不在1,2,3,10中的
    

    (6) 在..范围内 相当于between..and

    1. __range

    实例:

    Students.stuObj.filter(pk__range = [1,3])  # id为 1-3 范围内的,包括3
    

    (7) 比较

    1. __gt:大于
    2. __gte:大于等于
    3. __lt:小于
    4. __lte:小于等于

    实例:

    myDict['stu'] = Students.stuObj.filter(id__gt=3)  # id大于3的
    myDict['stu'] = Students.stuObj.filter(id__gte=3)  # id大于等于3的
    myDict['stu'] = Students.stuObj.filter(id__lt=3)  # id小于3的
    myDict['stu'] = Students.stuObj.filter(id__lte=3)  # id小于等于3的
    

    (8) 时间

    1. __year
    2. __month
    3. __day
    4. __week
    5. __hour
    6. __minute
    7. __second

    实例:

    Students.stuobj.filter(lasttime__year=2018)  # 返回符合条件的对象列表, 最后修改时间的年份为2018的
    

    (9) 聚合函数

    1. Avg() # 返回所给字段的平均值, 返回类型: float
    2. Count() # 根据所给的关联字段返回被关联 model 的数量
    3. Max() # 返回所给字段的最大值
    4. Min() # 返回所给字段的最小值
    5. Sum() # 计算所给字段值的总和

    导入模块

    from django.db.models import Max,Min
    

    配合函数aggregate() 函数去使用

    实例:

    Students.objects.aggregate(Max('sage')) # 查询年龄最大的值
    

    (10) F对象

    概念: 可以使用模型的A属性与B属性比较

    导入: from django.db.models import F, Q

    实例:

    # f对象的控制器
    def f(request):
        fg = Grades.objects.filter(ggirlnum__gt=F('gboynum'))  # 返回girl数量大于boy数量的集合
        print(fg[0].gname)
        return HttpResponse(fg)
    

    (11) Q对象

    概述: 进行条件的或运算

    可以组合使用 &(and), |(or), ~(not)操作符, 当一个操作符是用于两个Q的对象, 它产生一个新的Q对象。

    导入: from django.db.models import F, Q

    实例:

    s = Students.stuObj.filter(id__gt=3)  # id大于3
    s = Students.stuObj.filter(Q(id__gt=3)|Q(id__lt=3))  # 查询id大于3或id小于3的queryset,不包含3
    # select * from 表名 where id > 3 or id <3;
    s = Students.stuObj.filter(Q(sname='张三'), Q(id__gt=3)|Q(id__lt=3))  # 查询id大于3或id小于3的queryset,不包含3   -------------> filter的逗号进行并操作,可用|进行或操作
    # select * from 表名 where sname = and (id >3 or id <3)
    for i in s:
        print(i.sname)
    return HttpResponse('Q对象')
    

    (12) 删除

    .delete() # 在数据库中删除数据

    实例:

    Students.objects.filter(pk_gt=1).delete()  # 把主键大于1的数据在数据库中删除
    

    注意:

    id/pk/exact, 三种写法结果一样

    Students.objects.filter(id=1)
    Students.objects.filter(pk=1)
    Students.objects.filter(id_exact=1)
    

    相关文章

      网友评论

          本文标题:(二) Django模型models

          本文链接:https://www.haomeiwen.com/subject/jskiqftx.html