注册 登录
  • 欢迎访问"运维那点事",推荐使用Google浏览器访问,可以扫码关注本站的"微信公众号"。
  • 如果您觉得本站对你有帮助,那么可以扫码捐助以帮助本站更好地发展。

Django模型(Model)

Python框架 彭东稳 420次浏览 已收录 0个评论

Django模型是与数据库相关的,与数据库相关的代码一般写在models.py中,Django支持sqlite3、MySQL、PostgreSQL等数据库,只需要在settings.py中配置即可,不用更改models.py中的代码,因为ORM封装了底层,并且提供了丰富的API极大的方便了使用。

一、ORM介绍

对象-关系映射(OBJECT/RELATION MAPPING,简称ORM),是随着面向对象的软件开发方法发展而产生的。

一个关系数据库中都有什么?没错,简单来说,就是一张张表。表中又有什么?行和列,一行就是一条记录,一列就代表着一条记录的某个属性。举例来说,一个学 籍数据库可能包含一张学生信息表,表中每行记录着一个学生的信息,由很多列组成,每一列表示学生的一个属性,比如姓名、年龄、入学时间……

有没有觉得和python中的类、实例对象以及成员属性的概念有某种映射关系呢?哈,没错,orm其实就是把表映射成了类,它包含一些成员属性,相当于一个模板,通过这个模板,我们给相应的属性填上一个值,可以创建一个实例对象也就是一条记录。然后把常用的一些SQL操作封装成对应的方法,比如select封装为get方法,这样就实现了一个ORM。

简单来说就是使用Python的方法、数据结构访问数据库,并且数据库返回的数据类型也是Python数据类型;使用ORM还有一个好处就是不用关心底层数据库类型,通过ORM都给统一输出了API。

二、设置数据库

Django默认数据库使用sqlite3,SQLite是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中,甚至在iOS和Android的App中都可以集成。

Python就内置了SQLite3,所以,在Python中使用SQLite,不需要安装任何东西,直接import导入使用即可。

当你上生产时可能需要更改数据库为MySQL,只需要在settings.py中配置即可,如下:

三、编写Model

下面在models.py中创建一个问题表和一个选择表:

常见字段说明:

CharField:表示数据库中varchar数据类型,max_length属性用来设置varchar长度。

DateTimeField:表示数据库中datetime数据类型。

TimeField:表示数据库中的time数据类型。

FloatField:表示数据库中的float,存储浮点数。

TextField:表示数据库中的text字段,最大存储65535 bytes。

BinaryField:存储二进制数据类型。

EmailField:表示邮件类型,Django自己封装的。

ForeignKey:表示数据库中Foreign Key外键约束,Django中只需要指定表,不需要指定关联表字段,因为默认会关联主键。on_delete必须指定,表示当外键删除时Django应该怎么做?另外related_name参数用来指定反查管理器的名称,可以不用指定。

IntegerField:表示数据库中int数据类型,default属性用来设置默认值。

BigIntegerField:表示数据库中bigint数据库类型。

ImageField:用来存储图片的。

GenericIPAddressField:用来存储IP地址的。

URLField:用来存储URL的。

FilePathField:存储文件路径的。

FileField:存储文件的。

BooleanField:用来表示布尔关系的。

ManyToManyField:多对一关系。

OneToOneField:一对一关系。

常见属性说明:

每个字段都接受一组与字段有关的属性,例如,CharField需要max_length参数来指定VARCHAR数据库字段的大小。还有一些适用于所有字段的通用参数,这些参数在参考中有详细定义,这里我们只简单介绍一些最常用的:

max_length:用来设置varchar长度。

null:表示是否将数据库中的字段设置为允许将空字段存储为NULL,默认为False。

blank:用来设置此字段是否可以为空值,默认为False。

primary_key:用来设置主键,默认未False。

default:用来设置字段的默认值,可以是一个值或者可调用对象,如果可调用,每个新对象被创建它都会被调用。

choices:由二项元组构成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices中的选项。

unique:用来设置唯一索引约束。

help_text:表单部件额外显示的帮助信息,即使字段不在表单中使用,它对生成文档也很有用。

更多参考官方文档:https://docs.djangoproject.com/en/1.11/topics/db/models

四、Model Migrate

编写完数据模型后需要应用到数据库,Django为了能跟踪表结构的变化,增加了migrations版本控制功能。如果没有该功能,每次表结构变化,就需要重新生成表结构,重新导入数据,非常麻烦。

通过 python manage.py makemigrations生成数据库迁移文件,如下:

如果不带App名称,会给所有App创建迁移文件。

通过查看migrations目录,看见增加了一个SQL生成语句的文件:

可以使用下面命令进行查看:

从创建表的语句可以看出:

1. 字段默认不允许为空(NOT NULL)。

2. 默认ORM会帮我们创建一个字段名为id的自增主键。

3. 创建外键约束默认会以表的主键作为关联字段,并且会重写字段名。

4. 一个class代表一张表,多对多会产生额外一张关系表,比如用户表和组表就是多对多。

5. 表名默认为$(app_name)_$(calss_name)。

五、应用数据库

通过结果我们可以看出,当我们编写完model并应用时,会把默认要装载的admin、auth、sessions等模块的model也一同应用了。此时查看sqlite3数据库会发现创建了很多表,包括polls应用的表。

进入sqlite数据库(使用sqlite3命令跟上数据库文件即可):

或者使用 python manage.py dbshell命令进入数据库,以SQL的方式操作数据库。

六、操作数据库

一旦你建立好数据模型,Django会自动为你生成一套数据库抽象的API(查询集方法),可以让你创建、检索、更新和删除对象。

Django使用一种直观的方式把数据库表中的数据表示成Python对象:一个模型类代表数据库中的一个表,一个模型类的实例代表这个数据库表中的一条特定的记录。使用关键字参数实例化模型实例来创建一个对象,然后调用save()把它保存到数据库中。

使用 python manage.py shell命令可以进入到Python交互式窗口,跟你执行Python直接进入交互式窗口是不同的,前者会加载一些环境变量。

django.utils提供了一些模块,比如我们这里要使用的timezone,Django默认开启了I18N(I18n是internationalization的缩写,意思指i和n之间有18个字母。是用来支持国际化信息显示。就是支持多种字符集的转换,避免出现乱码。),只能使用timezone,而不能使用python自带的datetime模块之类的,不支持timezone。另外可以看出,通过ORM取的数据都是Python类型,并且都是格式化好的,使用起来很方便。

操作对象(增删改查)

通过模型中的管理器构造一个查询集,来从你的数据库中获取对象。

查询集表示从数据库中取出来的对象的集合,它可以含有零个、一个或者多个过滤器过滤器基于所给的参数限制查询的结果。 从SQL的角度,查询集SELECT语句等价,过滤器是像WHERELIMIT一样的限制子句。你可以从模型的管理器那里取得查询集,每个模型都至少有一个管理器,它默认命名为objects通过模型类来直接访问它。

增加

删除

修改

查询

对于查询有一点要说明,其中不管是 objects.all()还是 objects.filter()从数据库中查询出来的结果一般是一个列表集合,这个集合在Django中叫做QuerySet,是一个可迭代对象。如下:

可以看出所有对象都在一个列表中,既然是可迭代,那么就可以遍历了,如下:

如果使用 objects.get()方式从数据库中查询结果是一个对象,如下:

主要区别在于,QuerySet必须迭代才能打印结果,而对象通过实例化之后可以直接获取到实例属性。

七、给带外键的表插入数据

给带外键的表插入数据时可能跟普通表插入数据不同,

我给id=6的“What sport do you like?”问题增加三个选项,现在貌似增删改查都没有问题了,但是对于一个投票系统,最常见的需求就是通过问题查询相关的选项值。这个在Django中当然也提供了相关的方式,称之为“反查询”(内部就是多表join操作),意思就是根据问题查出对象的选项。

反查的相关方法跟单表方法都差不多,比如filter、order_by等等,可以多多尝试。

另外对于choice_set是Django ORM帮我们自动生成的一个管理器,就跟objects管理器相同,它默认名称为“表名_set”,也可以自定义名称,创建外键时指定related_name参数即可。

八、给Model增加方法

在model编程中,其实跟我们基于类编程操作都是一样的,比如可以给类增加一些专有方法以及普通方法,比如给Question类增加一个 __str__专有方法,以及普通方法。

在没有 __str__之前,我们不管插入数据还是直接get数据,返回的都是一个对象,不方便调试(也是新手和老手的区别)。操作结果如下:

增加一个 __str__专有方法:

当我们给类定义了 __str__专有方法之后,再次插入或者get数据时,返回的直接就是self.question_text内容,这是Python解释器内置的特殊方法,类似这种特殊方法还有很多。

然后也可以定义一个普通方法,比如我们定义一个查看是否有最近发布的问题,我这里定义为1天,也就是说只要这一天之类有发布的,就返回真,否则则为假。

需要注意一点,如果是Python2这里需要使用unicode格式化一下,而Python3则不需要。

然后重新执行 python manage.py shell看一下效果:

九、在View中使用Model

简单完成了View以及Model的学习,下面在View中使用Model。简单的需求就是列出最近3个问题:

很简单,就是先从数据库中取数据,然后排个序取出最近前三个问题。然后使用join把从数据库取出的问题以’,’分隔拼接成一个字符串,最后返回到页面即可。

插入三条新数据:

使用curl访问一下,看看结果:

完美!!!

接下来可以多写几个简单的View,比如问题详情页面、支持投票功能、显示投票结果等:

然后可以尝试分别访问一下这三个URL,结果如下:

由结果可以看出,正常带参数的View跟URL简单运行起来是没有问题了。目前View中只是简单的打印一些字符,后面在此基础之上扩展,“Django表单(Form)”。

需要说一下的就是其中URL部分的 r'^(?P<question_id>[0-9]+)/$正则匹配也可以简单写成 r'^([0-9]+)/$'这个样子。前者是使用命名组方式,其到函数中的表现形式为detail(request, question_id=5),而后者没有使用命名组其在函数中的表现形式为detail(request,5),就这点区别。

另外需要说明一点的是,Django从URL中捕获到的参数永远是string类型的,不管你输入的是数值还是字符。所以如果需要其它类型,需要自己接收时转换。


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (0)or分享 (0)
关于作者:

您必须 登录 才能发表评论!