美文网首页
03-Django模型

03-Django模型

作者: 郑元吉 | 来源:发表于2018-11-15 15:18 被阅读6次

    一、模型

    Django对各种数据库提供了很好的支持,Django为这些数据库提供了统一的调用API(即不管底层操作哪种数据库,我们只管模型对象操作即可,其实就是屏蔽掉数据库操作的差异性),这就可以根据不同的业务需求选择不同的数据库。

    二、配置数据

    • 在工程目录下init.py文件
    import pymysql
    pymysql.install_as_MySQLdb()
    

    安装链接mysql的驱动: pip install pymysql

    • 在工程目录下settings.py文件中,修改DATABASES
      使用了ORM对象关系映射,使用哪种数据库操作都是一样,就是在设置数据库连接时不一样。
    # Django默认使用SQLine数据库
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
    
    
    # 将项目数据库改为MySql
    DATABASES = {
        'default': {
            # 修改为mysql(驱动)
            'ENGINE': 'django.db.backends.mysql',   
            # 链接数据库,并创建对应的数据库HelloDjango
            'NAME': 'HelloDjango',
            # 用户名
            'USER': 'root',
            # 密码
            'PASSWORD': '123456',
            # 主机
            'HOST': '127.0.0.1',
            # 端口号
            'POST': '3306'
        }
    }
    

    三、模型开发流程

    • 配置数据库(创建对应数据,数据库上述配置)
    默认使用sqlite!
    
    • 定义模型类(一个模型类对应一个表单)
    class Student(models.Model):
      name = models.CharField(max_length=40)
      sex = models.CharField(max_length=10)
      age = models.IntegerField()
      isdelete = models.BooleanField(default=False)
    
    • 生成迁移文件(python manage.py makemigrations)
    $ python manage.py makemigrations
    或
    $ python manage.py makemigrations appname  # 删除迁移目录时,可以使用
    备注: 在migrations目录中生成一个迁移文件,此时数据库中还没生成表单
    
    • 执行迁移文件,生成对应表单(python manage.py migrate)
    $ python manage.py migrate
    备注: 相当于执行了MySQL语句创建了表单(appname_students)
    

    就算是没有创建模型,也是要执行迁移,因为除了自己系统需要在数据库中生成对应的表单!

    • 使用模型类进行增删改查
    # 插入数据
    stu = Student()
    stu.name = 'atom'
    stu.sex = '男'
    stu.age = 18
    stu.save()  # 写入数据库
    

    四、ORM

    • 概述
    O: 对象
    R: 关系
    M: 映射
    
    • 任务
    - 根据对象类型生成表结构;
    - 将对象、列表的操作转换sql语句;
    - 将sql语句查询到的结果转为对象、列表;
    

    五、属性定义

    • 概述
    - Django根据属性的类型确定以下信息:
        当前选择的数据库支持字段的类型;
        渲染管理表单时使用的默认html控件;
        在管理站点最低限度的验证;
    - Django的主键
        会为表增加自增长的主键列,每个模型只能有一个主键列;
        如果使用选项设置某属性为主键列后,则Django不会再生成默认的主键列;
    - 属性命名规则:
        遵循标识符规则;
        由于Django的查询方式,不允许使用连续的下划线;
    
    - 定义属性时
        需要字段类型,字段类型是被定义在django.db.models.fields目录下;
        为了方便使用,被导入到django.db.models中;
    - 使用方式
        导入from django.db import models;
        通过models.field创建字段类型的对象,赋值给属性;
    
    • 逻辑删除
    对于重要数据都做逻辑删除,不做物理删除;
    实现方法是定义isDelete属性,类型为BooleanField,默认值为False;
    
    • 字段类型
    - AutoField
        一个根据实际ID自动增长的IntegerField,通常不指定;
        如果不指定,一个主键字段将自动添加到模型中;
    - CharField(max_length=字段长度)
        字符串,默认的表单样式TextInput;
    - TextField
        大文本字段,一般超过4000使用,默认的表单控件是Textarea;
    - IntegerField
        整数;
    - DecimalField(max_digits=None, decimal_places=None)
        使用python的Decimal实例表示的十进制浮点数;
        DecimalField.max_digits: 位数总数;
        DecimalField.decimal_places: 小数点后的数字位数;
    - FloatField
        用Python的float实例来表示的浮点数;
    - BooleanField
        true/false 字段,此字段的默认表单控制是CheckboxInput;
    - NullBooleanField
        支持null、true、false三种值;
    - DateField([auto_now=False, auto_now_add=False])
        使用Python的datetime.date实例表示的日期;
        DateField.auto_now: 每次保存对象时,自动设置该字段为当前时间,默认是False;
        DateField.auto_now_add: 当对象第一次被创建时自动设置当前时间,它总是使用当前日期,默认是False;
        auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果;
    - TimeField
        使用Python的datetime.time实例表示的时间,参数同DateField;
    - DateTimeField
        使用Python的datetime.datetime实例表示的日期和时间,参数同DateField;
    - FileField
        一个上传文件的字段;
    - ImageField
        继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image;
    
    • 字段选项(通过字段选项,可以实现对字段的约束)
    - null
        如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False;
    - blank
        如果为True,则该字段允许为空白,默认值是 False;
        null是数据库范畴的概念,blank是表单验证证范畴的;
    - db_column
        字段的名称,如果未指定,则使用属性的名称;
    - db_index
        若值为 True, 则在表中会为此字段创建索引;
    - default
        默认值;
    - primary_key
        若为 True, 则该字段会成为模型的主键字段;
    - unique
        如果为 True, 这个字段在表中必须有唯一值;
    
    • 关系
    - ForeignKey:一对多,将字段定义在多的端中
        格式: 对象.模型类小写_set
        示例: grade.students_set
    - OneToOneField:一对一,将字段定义在任意一端中
        格式: 对象.模型类小写
        示例: grade.students
    - 访问id
        格式: 对象.属性_id
        示例: student.sgrade_id
    - ManyToManyField:多对多,将字段定义在两端中
    

    外键: 属于数据库约束

    外键默认是可以重复的,对应另外一张表的主键(一对多)

    六、模型查询之基本使用

    查询集表示从数据库获取的对象集合。
    查询集合可以有多个过滤器。
    过滤器就是一个函数,基于所给的参数限制查询结果。
    从SQL角度来说,查询集合与select等价,过滤器就像where条件。

    • 查询集
    - 在管理器上调用过滤器方法返回查询集;
    - 查询集经过过滤器筛选后返回新的查询集,所以可以写出链式调用;
    - 惰性执行(创建查询集不会带任何数据访问,直到调用数据时才会访问数据)
    
    • 直接访问的情况
    - 迭代
    - 序列化
    - 与if合用
    
    • 过滤器(返回查询集)
    - all() 返回查询集中所有数据(一条数据即一个对象)
        students = Student.objects.all()
    - filter() 返回符合要求的数据
        filter(键=值)
        filter(键=值,键=值)
        filter(键=值).filter(键=值)
        students = Student.objects.filter(s_score=91)
        students = Student.objects.filter(s_score__lt=60)
    - exclude() 过滤掉符合条件的数据
        students = Student.objects.exclude(s_score=91)
    - order_by() 排序
        students = Student.objects.order_by('s_score')  # 升序
        students = Student.objects.order_by('-s_score') # 降序
    - values() 返回查询集中所有数据(一条数据即一个字典),返回一个列表
    

    lt小于、lte小于等于、gt大于、gte大于等于、ne不等于

    • 返回单个数据
    - get() 返回一个满足条件的对象
        如果没有找到符合条件的对象,会引发'DoesNotExist'异常
        如果找到多个对象,会引发'MultipleObjectsReturned'异常
    - count() 返回查询集的对象个数
        students = Student.objects.filter(pk=1)
        if students.count()>0:  # 有数据
            pass
        else:
            pass
    - first() 返回查询集中的第一个对象
        student = students.first()
    - last() 返回查询集中的最后一个对象
        students = students.last()
    - exists() 判断查询集中是否有数据,有数据返回True
        if students.exists():   # 有数据
            pass
        else:
            pass
    

    students = Student.objects.get(pk=91), pk是primary key缩写!

    • 限制查询集(切片)
    查询集返回列表,可以使用下标的方法进行限制,等同于sql语句中的limit语句;
    例如: studentList = Students.objects.all()[0:5]
    注意: 下标不能是负数
    
    • 查询集缓存
    - 每个查询集都包含一个缓存,来最小化的数据访问
    - 在新建的查询集时,缓存首次为空,第一次对查询集求值,会发生数据缓存
    - django会将查询出来的数据做一个缓存,并返回查询结果,以后查询直接使用查询集的缓存
    
    • 元选项
    - 在模型类中定义Mata类,用于设置元信息
    - db_table属性
        定义数据表名,推荐使用小写字母,数据表名默认为项目名小写_类名;
    - ordering属性
        对象的默认排序字段,获取对象的列表时使用;
        ordering = ['id'] 升序
        ordering = ['-id'] 降序
        ordering = ['sage'] 按sage升序
        注意: 排序会增加数据库的开销;
    
    # 学生表students
    class Students(models.Model):
        # 在没有添加主键时,它会在生成时自动添加主键
        # id          = models.IntegerField()
        sname       = models.CharField(max_length=30)
        ssex        = models.CharField(max_length=10)
        sage        = models.IntegerField()
        sbrief      = models.CharField(max_length=50)
        isdel       = models.BooleanField(default=False)
        lastTime = models.DateTimeField(auto_now=True)
        createTime = models.DateTimeField(auto_now=True)
    
        # sclass = models.CharField(max_length=10)
        # 关联外键(学生都会有一个班级)
        sclass = models.ForeignKey('Grades')
    
        def __str__(self):
            return '%s  %s' % (self.sname,self.sclass)
    
    
        # 元选项(元信息)
        class Meta:
            db_table= 'students'
            # ordering = ['id']
            ordering = ['sage']
    

    str内置方法,一般说明类的说明,或者自己定义输出。

    七、模型查询之字段查询

    • 概述
    - 实现了sql中的where语句,作为方法filter()、excluede()、get()的参数
    - 语法
        属性名称__比较运算符=值
    - 外键
        属性名_id
    - 转义
        like语句中使用%为了匹配占位
        filter(sname__contains='%')
    
    • 比较运算符
    - exact 判断(大小写敏感)
        filter(isdel=False)
    - contains 是否包含(大小写敏感)
        studentList = Student.objects.filter(sname__contains='孙')
    - startswith、endswith 以value开头或结尾(大小写敏感)
        studentList = Student.objects.filter(sname__startswith='孙')
    备注: 
        以上四个前面加上i,表示不区分大小写;
        iexact、icontains、istartswith、iendswith
    
    - isnull、isnotnull 是否为空
        filter(sname__isnull=False)
    - in 是否包含在范围内
        studentList = Students.objects.filter(pk__in=[2,3,4,5,6])
    - gt大于、gte大于等于、lt小于、lte小于等于
        studentList = Students.objects.filter(sage__gt=30)
    - year、mouth、day、week_day、hour、minute、second 时间相关
        studentList = Student.objects.filter(lastTime__year=2018)
        
    - 跨关联查询 (处理join查询)
        语法: 模型类名__属性名__比较符
        例如: 学生描述中带有'张三'的学生属于哪个班级
            grade = Grades.objects.filter(students__sbrief__contains='张三')
    - 查询快捷 
        pk 代表主键(因为主键并不一定就是id字段)
        student = Students.objects.get(pk=3)
    
    • 聚合函数
    使用aggregate()函数返回聚合函数的值【sql中的函数使用】
    例如: Avg()、Count()、Max()、Min()、Sum()
    实例: 
        from django.db.models import Max
        maxAge = STudents.objects.aggregate(Max('sage'))
    
    • F对象
    - 可以使用模型的A属性与B属性进行比较.
        例如: Grades.objects.filter(ggirlnum__gt=F('gboynum'))
    
    - 支持F对象的算术运算
        例如: Grades.objects.filter(ggirlnum__gt=F('gboynum')+20)
    
    • Q对象
    - 概述
        查询条件的封装
    - 需求
        进行or查询、进行and查询、进行~查询 【与或非操作】
    - 解决
        使用Q对象
    - 例如
        studentList = Students.objects.filter(Q(pk__lte=3) | Q(sage__gt=50))
        studentList = Students.objects.filter(Q(pk__lte=3)  # 只有一个Q对象就用于匹配
        studentList = Students.objects.filter(~Q(pk__lte=3) # 取反
    

    八、模型成员

    • 类属性
    - objects管理器
        是Manager类型的一个对象,作用是与数据库交互;
        当定义模型类是没有指定管理器,则Django为模型创建一个名为objects的管理器;
    - 自定义管理器
        当为模型指定模型管理器,Django就不在为模型类生成objects模型管理对象;
        studentsObj = models.Manager() # 自定义模型管理器
    - 模型管理器作用
        模型管理器是Django的模型与数据库进行交互的接口;
        一个模型可以有多个模型管理器;
    - 自定义管理器Manager类
        向着管理器中添加额外的方法;
        修改管理器返回的原始查询集(重写get_queryset());
    
    # 自定义管理器后
    # Students.objects.all()  # 默认时
    Students.studentObj.all()   # 自定义管理器为studentObj
    <QuerySet [<Students: 韩俊  python05>, <Students: 申宝静  python05>, <Students: 李嘉熙  python05>, <Students: 小红  python05>, <Students: 阳亚霞  python01>, <Students: 老王  python04>, <Students: 向芳  python01>, <Students: 哈哈  python05>, <Students: 薛延美  python01>, <Students: 孙狮勤  python05>, <Students: 呵呵  python05>, <Students: 萧十一郎  python06>, <Students: 武含  python06>, <Students: 李明志  python04>, <Students: 王子衡  python06>, <Students: 陆彦旭  python01>, <Students: 唐李超  python04>, <Students: 郝路杰  python06>, <Students: 夏明宇  python06>, <Students: 范育宾  python01>, '...(remaining elements truncated)...']>
    
    # 自定义管理器Manager类
    class StudentsManager(models.Manager):
        # 修改管理器返回的原始查询集合
        def all(self):  
            # 调用父类方法,在父类方法基础上进行再次过滤
            return super().all().filter(isdel=False)
    
    
    # 学生表students
    class Students(models.Model):
        # 自定义模型管理器
        studentObj1 = models.Manager()
        # 用到自定义管理器(对数据进行过滤)
        studentObj2 = StudentsManager()
        
    
    # 使用1: Students.studentObj1.all()
    # 使用2: Students.studentObj2.all()
    
    • 创建模型对象
    - 目的
        向数据库中添加数据
    
    - 注意
        当创建对象时,django是不会对数据库进行读写操作;
        当调用save()方法时才会与数据库交互,将对象保存到数据库表单中;
        __init__方法已经在父类models.Model中使用,在自定义的模型中无法使用;
    
    - 在模型类中添加一个类方法(为了创建对象)
        # 学生表students [models.py文件中]
        class Students(models.Model):
            ...
            # 定义一个类方法创建对象
            @classmethod # 这表明就是类方法
            def createStudents(cls,name,sex,age,brief,grade,lastT,createT,isd=False):    # cls就表示Students这个类
                student = cls(sname=name,ssex=sex,sage=age,sbrief=brief,sclass=grade,lastTime=lastT,createTime=createT,isdel=isd)
                return  student
            
        # 调用即快速创建学生对象 [views.py文件中]
        stu = Students.createStudents('测试数据','男',18,'我是测试数据,别太在意.',grade,'2018-05-30','2018-05-29')
    
    - 在定义管理器中添加一个方法(为了创建对象)
        # 自定义管理器Manager类
        class StudentsManager(models.Manager):
            def all(self):  
            # 调用父类方法,在父类方法基础上进行再次过滤
            return super().all().filter(isdel=False)
    
            def createStudent(self,name,sex,age,brief,grade,lastT,createT,isd=False):
                # self.model() 其实就是创建Students对象
                stu = self.model()
                stu.sname = name
                stu.ssex = sex
                stu.sage = age
                stu.sbrief = brief
                stu.sclass = grade
                stu.lastTime = lastT
                stu.createTime = createT
    
                return  stu
                
        # 调用即快速创建学生对象 [views.py文件中]
        stu = Students.studentObj2.createStudent('测试数据','男',18,'我是测试数据,别太在意.',grade,'2018-05-30','2018-05-29')
    

    九、其他

    • 查询数据
    - 根据不同条件,获取对应的数据
    
    • 添加数据
    - 实例化模型对象
    - 设置对象属性
    - 调用对象的save()方法
    
    • 更新数据
    - 查询获取到需要更新的对象
    - 设置对象数据
    - 调用对象的save()方法
    
    • 删除数据
    - 查询获取需要删除出的对象
    - 调用对象的delete()方法
    

    相关文章

      网友评论

          本文标题:03-Django模型

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