linRichielinRichie
前端
Python
Linux
ChatGPT
  • B 站
  • 500px
前端
Python
Linux
ChatGPT
  • B 站
  • 500px
    • Python学习指南
  • 快速开始

    • Python: 输入与输出 (I/O)
    • Python: 异常处理 try-except
    • Python: List深入概述
    • Python: 面向对象编程(OOP)
  • Python 语法库函数

    • 语法库目录
    • 库

      • library目录
      • argparse:解析命令行参数
      • difflib:比较序列并生成差异信息
      • dnspython: DNS处理库
      • IPy:IP地址处理库
      • logging:记录和管理日志信息
      • os:访问和操作操作系统
      • psutil:系统性能信息库
      • re:正则表达式库
      • smtplib:邮件发送库
    • 函数

      • function目录
      • any() 函数
      • input 函数
      • lambda 和 map 函数
      • reversed()函数
      • zip()函数
    • 语句

      • statement目录
      • import 语句
      • Try/Exception 异常
    • 概念

      • concept目录
      • 深拷贝与浅拷贝
      • 列表、字典与元组
      • 文件读写
      • IO: 输入与输出
      • 逻辑判断与条件语句
      • OOP 面向对象:class
      • OOP: 面向对象编程
  • SQLAlchemy

    • 获取insert或者update的id
  • Pandas

    • Pandas目录
    • Pandas:基础操作
    • Pandas:数据处理与转换
    • Pandas: 数据写入 excel 表格
  • Python前端框架

    • Flask

      • 1. Flask简介
      • 2. Flask程序基本结构
      • 3. Flask请求-响应循环
      • 4. flask案例: 框架网页查询IP
      • Python: Flask中的GitHub OAuth
    • Django

      • chapter-01:Django框架认识

        • 1.1 Django的产生背景
        • 1.2 MTV设计模式
        • 1.3 Django 主要功能模块
      • chapter-02:开发环境配置

        • 2.1 Python的安装与配置
        • 2.2 虚拟环境安装与配置
        • 2.3 Django安装与配置
        • 2.4 MySQL安装配置
      • chapter-03:项目框架搭建

        • 3.1 Django管理工具-创建项目骨架
        • 3.2 修改项目的默认配置
        • 3.3 初始化项目环境
      • chapter-04:ORM应用与原理剖析

        • 4.1 构建POST应用需要的数据集
        • 4.2 Model相关的概念和使用方法
        • 4.3 Model的查询操作API
        • 4.4 ORM实现原理
      • chapter-05:Django管理后台

        • 5.1 将Model注册到管理后台
        • 5.2 管理后台实现原理
      • chapter-06:视图

        • 6.1 视图基础
        • 6.2 视图的高级特性和快捷方法
        • 6.3 基于类的通用视图
      • chapter-07:模板系统

        • 7.1 模板系统基础
        • 7.2 模板语言
      • chapter-08:表单系统

        • 8.2 使用表单系统实现表单: ModelForm
      • chapter-09:用户认证系统

        • 9.1 用户与身份认证
        • 9.2 权限管理
        • 9.3 用户认证系统应用
      • chapter-10:Django路由系统

        • 10.1 路由系统基础
      • chapter-11:Django中间件

        • 11.1 中间件基础
  • Python例子

    • Python: Linux的Shell命令
    • Python: PEP8自动格式化代码
    • Python: pip操作
    • Python: 业务服务监控
    • Python: 从文件逐行读取数据
    • 将链表转换为字符串
    • Python: 检查URL是否能正常访问
    • Python: 爬取网易云音乐
    • Python: 读取目录下的所有内容
    • 案例研究:文本统计
  • Python爬虫

    • 数据解析工具:Xpath
  • 算法题

    • 02:两数相加
    • 09:回文数
    • 13:罗马数值转换为整数
    • 14:最长公共前缀

4.2 Model相关的概念和使用方法

  • 4.2 Model相关的概念和使用方法
    • 4.2.1 Model的组成部分
      • django.db.models.Model
      • Meta内部类声明元数据
      • 定义数据表项的Field实例
      • __str__方法
    • 4.2.2 Meta元数据类属性说明
    • 4.2.3 Field的通用字段选项
    • 4.2.4 基础字段类型
      • django.db.models.Field
        • db_type(connection)
        • get_prep_value(value)
        • from_db_value(value,expression,connection)
      • 常用的基础字段类型
      • 自定义一个字段类型
    • 4.2.5 三种关系字段类型
      • 多对一关系类型
      • 一对一关系类型
      • 多对多关系类型
    • 4.2.6 Model的继承模型
      • 抽象基类
      • 多表继承
      • 代理模型

  • Model是Django ORM的核心,有许多特性(继承模型,元数据)
  • 需要遵守一些规则:字段类型必须是Field类型

4.2.1 Model的组成部分

通常包含四个部分

  • 继承自:django.db.models.Model
  • Model元数据声明(Meta内部类)
  • 若干个Field类型的字段
  • __str__方法

django.db.models.Model

通过类之间的继承,Django主要对自定义的Model添加了两个属性

  • id:每一个Model必须有且仅有一个Field字段的primary_key属性设置为True,即必须要有主键,通常在定义Model的时候不需要关注主键字段,基类会自动添加一个auto-incrementing id 作为主键
  • objects:是Manager(django.db.models.Manager)类的实例,称为查询管理器,是数据库查询的入口

Meta内部类声明元数据

Meta是一个类容器,Django会将容器中的元数据选项定义附加到Model中
常见的元数据定义有:数据表名称,是否是抽象类,权限定义,索引定义等
Meta定义的元数据相当于Model的配置信息,可以直接在shell环境中打印

from post.models imoprt
Topic
Topic.Meta
Topic.Meta.__dict__
  • Meta内部类可选,用户的Model没有需要完全可以不定义Meta,Django会自动应用默认的元数据到Model上

定义数据表项的Field实例

  • Model中的每个字段都是Field(django.db.models.fields.Field)类型的实例,根据Field的实际类型确认下面的信息
    • 数据库中的列类型
    • 渲染表单时使用的默认HTML部件
    • 管理后台与自动生成的表单中的数据验证

__str__方法

  • __str__方法是为print这样的打印函数设计的,此方法不定义,打印对象会显示对象的内存地址

4.2.2 Meta元数据类属性说明

  • Meta类不数据Model的字段,但可以用来标识一些属性
  • 一些重要的元数据和含义以及使用方法
    • abstract:布尔类型的变量

      • True:标识当前的Model是抽象基类,这个元选项不具备传递性,只对当前声明的类有小
    • proxy:布尔类型的变量

      • False:默认值
      • True;表示为基类的代理模型
    • db_table:用于指定数据表的名称

      • 默认会使用Django的表名生成规则
      • 例子:db_table='topic'
      • 对抽象基类是无效的,不应该在抽象基类中去声明它,因为抽象基类可以被多个子类继承,如果数据表名也可以继承,会在数据库创建数据表的时候抛出异常错误
    • ordering:指定获取对象列表时的排序规则,是一个字符串的列表或元组对象

      • 每一个字符串都是Model中定义的字段名,前面加上-,代表逆序,默认正序
      • 例子
        • ordering = ['created_time']: 正序
        • ordering = ['-created_time']: 逆序
        • ordering = ['created_time','-last_modified']: 先按照created_time正序,然后按last_modified逆序
        • 建议当所有的查询都需要按照特定的规则排序时,才设置这个元选项,否则,可以在特定的查询中指定排序规则
    • managed:布尔类型的变量

      • True:默认值。代表Django会管理数据库的生命周期,即可利用Django提供的工具完成创建和删除数据表
      • False:Django不会管理这些Model所对应的数据表

      当在执行migrate命令之前那已经在数据库中创建了数据表,此时就需要把managed设置为False,让用户自己去管理 需要注意下面的问题

      1. 当Model中没有声明主键,即使managed设置为False,Django也会自定添加列为id的自增主键
      2. 如果Model中包含ManyToManyField类型的字段,且指向的Model也是自管理的(managed=False),那Django不会给这种关系创建中间表,需要主动创建中间表,并使用ManyToManyField.through指定关联关系
      • indexes:列表类型的元数据

      • 定义Model的索引

      • 列表中的每个元素都是index(django.db.models.indexes.Index)类型的实例

      • Index类的定义

        • class Index(field()=[], name=None, db_tablespace=None)
          • field: 列表对象,指定索引的字段,必填项,至少包含一个字段
          • name:索引的名称
          • db_tablespace:表空间,用于优化数据库性能(用于PostgreSQL,Oracle)
      • 例子

        from django.db import models
        indexs = {
            models.Index(fields=['title']),
            models.Index(fields=['title','is_online'], name='title_is_online_idx')
        }
        
    • unique_together:常见的元组类型元选项

      • 包含多个元组对象,标识联合唯一约束,在数据库表现为联合唯一索引
      • 优点:将数据取值的限制抽离出业务逻辑,放在框架和数据库层面处理
      • 例子
        • unique_together = (('title','is_online'),('title','content'))
        • unique_together = ('title','is_online')

      ManyToManyField类型的字段不能包含在unique_together中

    • verbose_name 和 verbose_name_plural

      • 两个元选项用于给Model类起一个方便阅读的名称,主要用在管理后台上的展示
    • default_permissions

      • 默认会给每一个定义的Model设置三个权限:add,change,delete
    • permissions

      • 此元选项给Model添加额外的权限。permissions是一个包含二元组的元组或者列表

        • 格式:(权限代码,权限名称)
        • 例子:
        permissions = (
            ("can_read_topic", "可以阅读话题"),
            ("can_discuss_topic", "可以评论话题")
        )
        

4.2.3 Field的通用字段选项

  • blank:数据验证相关字段,体现在管理后台录入数据的校验规则
    • 默认值:False,不允许输入空值
    • True:允许输入空值
  • unique:数据库级别的选项,表明必须是唯一的;对ManyToManyField和OneToOneField关系类型不起作用
    • 默认值:False
    • 设置为True,就不需要对这个字段加上索引选项了
  • null:影响表字段属性,规定字段的数据是否可以是空值
    • 默认值:False
    • True:会在数据库中将空值存储为NULL
    • 对于CharField和TextField的字符串类型,null字段应用总是设置为False,
      • 如果设置为True,对于“空数据”会有两个概念:空字符串和NULL
      • 例外:当CharField同时设置了unique=True和blank=True,则需要设置null=True,防止保存多个空白值时违反唯一性约束
  • db_index:索引属性
    • 默认值:False
    • True:会为字段创建数据库索引
  • db_column:设置数据库表字段的名称
  • default:给字段设置默认值
    • lambda表达式不可以作为default的参数值,因为不能被migrations命令序列化
    • 对于ForeignKey的字段,默认值设置的应该是主键而不应该是Model对象实例
  • primary_key:主键属性
    • 默认值:False
    • True:成为Model的主键字段,且不允许其他的字段再次将该选项设置为True
    • 特性:
      • 在数据库层面:primary_key=True 意味着对应的字段唯一且不能是NULL
      • 主键字段是只读的
  • choices:
    • 给字段设置可以选择的值,是一个可迭代的对象(列表或者元组),每一个元素都是一个二元组(A,B),A是选择的对象(作为字段值使用),B是A的描述信息

    • choices字段在管理后台的显示上会有文本框变成选择框,框中的可选值就是choices中的元组

    • Django建议将choices定义在Model的内部,是代码更加规整

    • 例如

      from django.db import models
      class People(models.Model):
          MALE = 'm'
          FEMALE = 'f'
          GENDER_CHOICES = (
              (MALE,"男性"),
              (FEMALE,"女性")
          )
      
    • 但在数据库中还是会遵循Field类型对应的数据表字段类型

  • help_text:显示字段的提示信息
  • verbose_name:给字段设置可读性更高的名称

4.2.4 基础字段类型

Django内置的字段类型,按照与其他的Model存在关联分为两类

  • 基础字段类型:字符串,数字,时间,二进制等
  • 关系字段类型:只有三个

django.db.models.Field

对于Field,只需要关注三个方面:

  • 映射到数据表的列类型(db_type)
  • 将Python对象映射到数据表(get_prep_value)
  • 从数据库返回python对象(from_db_value)

db_type(connection)

  • 根据所配置的数据库后端返回Field对应的数据库列类型
  • 对这个方法重载,需要考虑不同的数据库后端列类型兼容的问题
  • 此方法只会在Django为Model生成创建表语句的时候调用一次,其他任何时候都不会使用。
  • 此方法实现较为复杂,但不会影响系统性能

get_prep_value(value)

  • 参数value是Model属性的当前值
  • 该方法对value操作,最终返回用作数据库查询的参数
  • Model对象保存到数据库中的时候,也会将该方法的返回值作为该列数据保存

from_db_value(value,expression,connection)

  • 与get_prep_value的作用相反,将从数据库中返回的数据转换为Python对象

常用的基础字段类型

  • IntegerField
    • SmallIntegerField: 小整数
    • BigIntegerField: 64位整数
    • PositiveIntegerField: 只允许存储大于等于0的整数
  • AutoField:根据ID自增的IntegerField
    • BigAutoField:使用的是8个字节的存储空间
  • CharField:
    • 有必填参数:max_length,且取值只能是大于0的整数
  • TextField
  • BooleanField:布尔类型
    • 某个字段的取值只能是True或False的情况
  • DateField和DateTimeField
    • DateField是日期,以Python的datetime.date实例表示
    • DateTime是日期时间,以Python的达特time.datetime实例表示
    • 都有两个特殊的参数选项可以设置
      • auto_now:此选项应用在对象保存的时候,会自动设置为当前时间
      • auto_now_add:此选项应用在首次创建对象的时候,会自动将字段设置为当前时间
    • auto_now,auto_now_add,default是互斥的,不能组合在一起使用
  • EmailField
    • 存储字符串类型的数据,是专门用来存储邮箱地址
    • 内部有使用EmailValidator验证器对输入的字符串进行校验

自定义一个字段类型

  • GenericIPAddressField:存储IP地址
  • URLField:存储URL
  • FloatField:存储浮点数的字段类型

4.2.5 三种关系字段类型

  • 多对一(ForeignKey)
  • 一对一(OneToOneField)
  • 多对多(ManyToManyField)

多对一关系类型

  • 在数据库中体现为:外键关联关系
  • 可以和其他Model建立关联,也可和自己建立关联,描述多对一的关系
  • ForeignKey的定义方法:class django.db.models.ForeignKey(to, on_delete, **options)
  • 两个必填的参数
    • to:指定所关联的Model,取值可以是直接引用其他的Model,也可以是Model对应的字符串名称,要创建递归的关联关系,即Model自身存在多对一的关系,可以设置为字符串self
    • on_delete:删除关联表的数据时,此参数决定Django会执行什么样的SQL约束,可选值
      • CASCADE:级联删除,大部分应该选择的约束
      • PROTECT:删除被引用对象时,会抛出ProtectedError异常
      • SET_NULL:设置删除对象所关联的外键字段为null,前提是设置了选项null为True
      • SET_DEFAULT:将外键字段设置为默认值,但前提是设置了default选项,且指向的对象是存在的
      • SET(value):删除被引用对象时,设置外键字段为value。value如果是一个可调用对象,那么就会被设置为调用后的结果
      • DO_NOTHING:不做任何处理。但是,由于数据表之间存在引用关系,删除关联数据,会造成数据库抛出异常
  • 可选参数
    • to_field:关联对象的字段名称。默认情况下,Django使用关联对象的主键(大部分情况下是id),如果需要修改成其他字段,可以设置这个参数。但是,需要注意,能够关联的字段必须有unique=True的约束
    • db_constraint:默认值是True,它会在数据库中创建外键约束,维护数据完整性
    • related_name:这个字段设置的值用于反向查询,默认不需要设置,Django会设置其为“小写模型名_set”。如果不想创建反向关联关系,可以将它设置为“+”或者以“+”结尾
    • related_query_name:这个名称用于反向过滤。如果设置了related_name,那么将用它作为默认值,否则Django会把模型的名称作为默认值

一对一关系类型

  • 类似于unique=True的ForeignKey

  • 与ForeignKey的差别在于:反向查询上

    • ForeignKey反向查询返回的是一个对象实例列表
    • OneToOneField:返回的是一个对象实例
  • OneToOneField的定义:class models.OneToOneField(to, on_delete, parent_link=False, **options)

  • parent_link参数:

    • True:表示在继承另一个非抽象的Model中使用时,该字段会变成指向父类实例的应用
  • 例子:关联对象的字段名称。默认情况下,Django使用关联对象的主键(大部分情况下是id),如果需要修改成其他字段,可以设置这个参数。但是,需要注意,能够关联的字段必须有unique=True的约束

    from django.db import models
    from django.contrib.auth.models import User
    
    
    class CusTomUser(models.Model):
        user = models.OneToOneField(to=User, on_delete=models.CASCADE)
        sign = models.CharField(max_length=255, help_text=u'用户签名')
    

多对多关系类型

  • 此关系类型Django会通过中间表来进行维护

  • 定义格式:class django.db.models.ManyToManyField(to, **option)

  • 重要的可选参数:

    • related_name:用于反向查询
    • db_table:用于指定中间表的名称
    • through:用于指定中间表
  • 例子:针对Author和Book之间的多对多关系

    from django.db import models
    
    
    class Book(models.Model):
        title = models.CharField(max_length=64, help_text=u'书名')
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32, help_text=u'作者')
        books = models.ManyToManyField(to=Book)
    

4.2.6 Model的继承模型

  • 三种继承模型
    • 抽象基类
    • 多表继承
    • 代理模型

抽象基类

抽象Model专门设计为被其他的子类继承,它将子Model中通用的元素聚合到一起,以便子Model不用多次重复定义这些通用的部分,且对于修改也只需要操作基类

  • 定义Meta内部类,并将abstract设置为True,就可把当前的Model定义为抽象基类了
  • 抽象基类,不能被实例化,所以Django不会为它创建数据表和查询管理器

Model的元数据继承关系的几个原则

  • 抽象基类中定义的元数据,子类中没有定义,子类会继承基类中的元数据。
  • 抽象基类中定义的元数据,子类也定义了,子类优先级更高。
  • 子类可以定义自己的元数据,即不出现在抽象基类中的元数据。

多表继承

继承方式的效果是父Model和子Model都会有数据库表,且Django会自动给子Model添加一个OneToOneField类型的字段指向父Model,而这个字段会成为子Model数据表的主键

  • 例子

    from django.db import models
    
    class CategortTopic(Topic):
        """
        分类 Topic
        """
        category = models.CharField(max_length=32, help_text='类别')
    
  • 与抽象基类的显著不同点是Meta的继承

    • 子类不会继承父类的Meta定义
    • 但是有两个Meta元选项会被子类继承:ordering,get_latest_by

代理模型

  • 使用场景:需要给原始的Model添加一些方法或者修改它的Meta选项,但是不需要修改原始Model的字段定义

  • 创建方法:将Meta中的proxy选项设置为True

  • 例如:需要给Topic添加title的校验方法且查询记录按照id的顺序返回

    class ProxyTopic(Topic):
        """
        代理 Topic
        """
    
        class Meta:
            ordering = ['id']
            proxy = True
    
        def id_topic_valid(self):
            return 'django' in self.title
    
  • 代理模型只能继承自一个非抽象的基类,并且不能同时继承多个非抽象基类

最近更新时间:
Prev
4.1 构建POST应用需要的数据集
Next
4.3 Model的查询操作API