Django 数据驱动 Web 应用的总体设计
Django 紧紧地遵循 MVC 模式,可以称得上是一种 MVC 框架。
但是由于 C 由框架自行处理,而 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),Django 也被称为 MTV 框架 。在 MTV 开发模式中:
在 Django 里写一个数据库驱动的 Web 应用的第一步是定义模型 - 也就是数据库结构设计和附加的其它元数据。
M 代表模型(Model),即数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
T 代表模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
V 代表视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你可以把它看作模型与模板之间的桥梁
如果你熟悉其它的 MVC Web开发框架,比方说 Ruby on Rails,你可能会认为 Django 视图view是控制器,而 Django 模板是视图。 很不幸,这是对 MVC 不同诠释所引起的错误认识。 在 Django 对 MVC 的诠释中,视图用来描述要展现给用户的数据;不是数据 如何展现 ,而且展现 哪些 数据。 相比之下,Ruby on Rails 及一些同类框架提倡控制器负责决定向用户展现哪些数据,而视图则仅决定 如何 展现数据,而不是展现 哪些 数据。
系统对app有一个约定: 如果你使用了Django的数据库层(模型),你 必须创建一个Django app。 模型必须存放在apps中。
定义模型和字段
在应用app文件中编辑models.py文件
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
父类 Model 包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。
所有models含有的字段属性方法参考:
类型 | 说明 |
---|---|
AutoField | 一个自动增加的整数类型字段。通常你不需要自己编写它,Django会自动帮你添加字段:id = models.AutoField(primary_key=True),这是一个自增字段,从1开始计数。如果你非要自己设置主键,那么请务必将字段设置为primary_key=True。Django在一个模型中只允许有一个自增字段,并且该字段必须为主键! |
BigAutoField | (1.10新增)64位整数类型自增字段,数字范围更大,从1到9223372036854775807 |
BigIntegerField | 64位整数字段(看清楚,非自增),类似IntegerField ,-9223372036854775808 到9223372036854775807。在Django的模板表单里体现为一个textinput标签。 |
BinaryField | 二进制数据类型。使用受限,少用。 |
BooleanField | 布尔值类型。默认值是None。在HTML表单中体现为CheckboxInput标签。如果要接收null值,请使用NullBooleanField。 |
CharField | 字符串类型。必须接收一个max_length参数,表示字符串长度不能超过该值。默认的表单标签是input text。最常用的filed,没有之一! |
CommaSeparatedIntegerField | 逗号分隔的整数类型。必须接收一个max_length参数。常用于表示较大的金额数目,例如1,000,000元。 |
DateField | class DateField(auto_now=False, auto_now_add=False, **options)日期类型。一个Python中的datetime.date的实例。在HTML中表现为TextInput标签。在admin后台中,Django会帮你自动添加一个JS的日历表和一个“Today”快捷方式,以及附加的日期合法性验证。两个重要参数:(参数互斥,不能共存) auto_now:每当对象被保存时将字段设为当前日期,常用于保存最后修改时间。auto_now_add:每当对象被创建时,设为当前日期,常用于保存创建日期(注意,它是不可修改的)。设置上面两个参数就相当于给field添加了editable=False和blank=True属性。如果想具有修改属性,请用default参数。例子:pub_time = models.DateField(auto_now_add=True),自动添加发布时间。 |
DateTimeField | 日期时间类型。Python的datetime.datetime的实例。与DateField相比就是多了小时、分和秒的显示,其它功能、参数、用法、默认值等等都一样。 |
DecimalField | 固定精度的十进制小数。相当于Python的Decimal实例,必须提供两个指定的参数!参数max_digits:最大的位数,必须大于或等于小数点位数 。decimal_places:小数点位数,精度。 当localize=False时,它在HTML表现为NumberInput标签,否则是text类型。例子:储存最大不超过999,带有2位小数位精度的数,定义如下:models.DecimalField(..., max_digits=5, decimal_places=2)。 |
DurationField | 持续时间类型。存储一定期间的时间长度。类似Python中的timedelta。在不同的数据库实现中有不同的表示方法。常用于进行时间之间的加减运算。但是小心了,这里有坑,PostgreSQL等数据库之间有兼容性问题! |
EmailField | 邮箱类型,默认max_length最大长度254位。使用这个字段的好处是,可以使用DJango内置的EmailValidator进行邮箱地址合法性验证。 |
FileField | class FileField(upload_to=None, max_length=100, **options)上传文件类型,后面单独介绍。 |
FilePathField | 文件路径类型,后面单独介绍 |
FloatField | 浮点数类型,参考整数类型 |
ImageField | 图像类型,后面单独介绍。 |
IntegerField | 整数类型,最常用的字段之一。取值范围-2147483648到2147483647。在HTML中表现为NumberInput标签。 |
GenericIPAddressField | class GenericIPAddressField(protocol='both', unpack_ipv4=False, **options)[source],IPV4或者IPV6地址,字符串形式,例如192.0.2.30或者2a02:42fe::4在HTML中表现为TextInput标签。参数protocol默认值为‘both’,可选‘IPv4’或者‘IPv6’,表示你的IP地址类型。 |
NullBooleanField | 类似布尔字段,只不过额外允许NULL作为选项之一。 |
PositiveIntegerField | 正整数字段,包含0,最大2147483647。 |
PositiveSmallIntegerField | 较小的正整数字段,从0到32767。 |
SlugField | slug是一个新闻行业的术语。一个slug就是一个某种东西的简短标签,包含字母、数字、下划线或者连接线,通常用于URLs中。可以设置max_length参数,默认为50。 |
SmallIntegerField | 小整数,包含-32768到32767。 |
TextField | 大量文本内容,在HTML中表现为Textarea标签,最常用的字段类型之一!如果你为它设置一个max_length参数,那么在前端页面中会受到输入字符数量限制,然而在模型和数据库层面却不受影响。只有CharField才能同时作用于两者。 |
TimeField | 时间字段,Python中datetime.time的实例。接收同DateField一样的参数,只作用于小时、分和秒。 |
URLField | 一个用于保存URL地址的字符串类型,默认最大长度200。 |
UUIDField | 用于保存通用唯一识别码(Universally Unique Identifier)的字段。使用Python的UUID类。在PostgreSQL数据库中保存为uuid类型,其它数据库中为char(32)。这个字段是自增主键的最佳替代品,后面有例子展示。 |
进一步设置字段属性
以字典型数据传参进Field
字段设置选项 | 说明 |
---|---|
null | boolean 值,缺省设置为false。通常不将其用于字符型字段上,比如CharField,TextField上。字符型字段如果没有值会返回空字符串。 |
blank | boolean 值,该字段是否可以为空。如果为假,则必须有值。 注意: null是数据库范畴的概念,blank是表单验证证范畴的 |
choices | 元组值,一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。如SEX_CHOICES=((‘F’,’Female’),(‘M’,’Male’),) |
db_column | string 值,指定当前列在数据库中的名字,不设置,将自动采用model字段名; |
db_index | boolean 值,如果为True将为此字段创建索引; |
default | 给当前字段设定的缺省值,可以是一个具体值,也可以是一个可调用的对象,如果是可调用的对象将每次产生一个新的对象; |
editable | boolean 值,如果为假,admin模式下将不能改写。缺省为真; |
error_messages | 字典,设置默认的出错信息,可覆盖的key 有 null, blank, invalid, invalid_choice, 和 unique。 |
help_text | admin模式下帮助文档 form widget 内显示帮助文本。 |
primary_key | 设置主键,如果没有设置django创建表时会自动加上:id = meta.AutoField(‘ID’, primary_key=True) primary_key=True implies blank=False, null=False and unique=True. Only one primary key is allowed on an object. |
radio_admin | 用于 admin 模式下将 select 转换为 radio 显示。只用于 ForeignKey 或者设置了choices |
unique | boolean值,数据是否进行唯一性验证; |
unique_for_date | 字符串类型,值指向一个DateTimeField 或者 一个 DateField的列名称。日期唯一,如下例中系统将不允许title和pub_date两个都相同的数据重复出现 title = meta.CharField( maxlength=30, unique_for_date=’pub_date’ ) |
unique_for_month / unique_for_year | 用法同上 |
verbose_name | string类型。更人性化的列名。 |
validators | 有效性检查。无效则抛出 django.core.validators.ValidationError 异常。 |
注意: 这些属性并没有unsigned 属性可以设置。 正在寻找原因, 为什么django放弃了这个属性
注意: 对ORM模型的一些字段属性设置不能体现在数据库, 例如default, 只是模型层的限制 参考
调试模型是否创建成功
python manage.py check
;这个命令帮助你检查项目中的问题,并且在检查过程中不会对数据库进行任何操作。
模型迁移事件
注意一个名称叫做: 迁移(migration)
迁移是 Django 对于模型定义(也就是你的数据库结构)的变化的储存形式
即包含目前模型类的改动会给数据库结构带来的改变事件
//生成迁移文件并查看某个应用的模型会带来数据库迁移(migration)事件
python manage.py makemigrations [应用名称]
//查看某次迁移带来数据库结构变化会产生的sql语句执行
python manage.py sqlmigrate [应用名称] [迁移的序列号]
如上图有表明迁移的序列号0001
还有会带来的事件 create model amazen_search
执行migrate使得模型映射数据表结构改变生效
需要注意, 该命令同时会生成setting.py中的注册的需要的系统自带应用
这个命令的前提是前面的迁移事件生成命令makemigrations
有使用
python manage.py migrate
—————————————————————————————————————
模型对象进一步标准化:
给模型增加 __str__()
方法是很重要的,这不仅仅能给你在命令行里使用带来方便,Django 自动生成的 admin 里也使用这个方法来表示对象。
设置模型多种属性
一、设置默认META选项属性
class Meta:
# 定义表名
db_table = "amazon_search"
# 定义在管理后台显示的名称
verbose_name = '亚马逊数据'
# 指定,模型的复数形式
verbose_name_plural = '亚马逊数据集'
# 设置模型属性-默认排序字段
ordering = ['comment_num']
二、关系
一对一模型:关系字段定义在任意一端中
一对多模型:关系字段定义在多的一端中;一对多中,外键对应的是主表的一个对象,而不是一个单纯的id
多对多模型:自动生成第三张表,第三张表为关系表;先实例化对象添加两张表,然后再添加关系
在模型中建立以下关联字段
定义模型关系和关联字段
#学生表与班级是一对多
g = models.ForeignKey(to="Grade", to_field="Grade_id")
#学生信息表与学生表一对一
stu = models.OneToOneField(to="Student", to_field="Student_id")
#课程表与学生表是多对多
stu = models.ManyToManyField(to="Student", to_field="Student_id")
定义好关系后, 可以使用关联查询, 更多关联查询语句使用参考我另一篇文章: [https://www.jianshu.com/p/8be674ae342b)