一、需求背景:

django的models模块提供了很多数据字段的数据类型field,但是总有写奇葩需求不能依靠默认字段满足,所以需要自定义数据数据库数据字段类型。所有的自定义field应该在app路径下的fields.py文件里面定义。

二、自定义数据库数据类型字段:

1、知识点1->继承自filed类型

所以所有自定义类型都应该如下编写:

 from django.db import models

 class myfiled(models.Filed):
pass

第一行引入继承的父类所在的models模块,然后定义自定义field类型,定义时候继承models.field类。

2、可以创建一个描述变量

 from django.db import models

 class myfield(models.Field):
description = "This is my own field!"

3、初始化实例的构造函数

 class myfield(models.Field):
def __init__(self,*args,**kwargs):
kwargs['max_length'] = 100
super(myfield,self).__init__(*args,**kwargs)

这个函数可以不显性定义

4、对于1.7之前版本的django的自定义field迁移到1.7以及之后的版本,需要自定义deconsturct函数,但这里不在本文的介绍访问之内。

5、实现db_type方法,作用是返回其本身说属于的数据库中的字段数据类型,例如你自定义了一个时间类型,那么对应在MySQL中就是datetime类型。

 def db_type(self,connection):

     if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql':
return 'datetime'
else:
return 'timestamp'

这里的connection.setting_dict是一个保存着连接配置的字典数据结构,其中ENGINE表示的是数据库类型,django.db.backends.mysql就是mysql,其实,这里就相当于定义了你自定义数据字段类型说依赖的数据库数据字段类型,如果对长度要限制,则可以在实例化出事函数中,传入max_length值给属性,self.max_length属性,然后,在db_type里面初始化,完成动态构造。

 class myfield(models.Field):
def __init__(self,max_length,*args,**kwargs):
self.max_length = max_length
super(myfield,self).__init__(*args,**kwargs)
def db_type(self):
return 'int(%s)'%self.max_length

6、如果需要自定义某个column,最好还是去数据库中使用sql语句创建或其他方式,请在db_type函数中返回None,通知migerate创建数据库表的时候跳过这个字段,因为migerate就是利用这个返回值来创建数据库表的。当然有些时候也可以使用另外一个函数:get_internal_type

 def get_internal_type(self):
return 'CharField'

7、增删改查时候需要用到的几个API:

(1)将值转换为python对象:

这里有两个api需要实现from_db_value()和to_python()

引用官方文档中的一段内容来解释一下:

如果您的自定义Field类处理比字符串,日期,整数或浮点数更复杂的数据结构,则可能需要覆盖from_db_value()to_python()

如果存在于字段子类,则在从数据库加载数据(包括在聚合和values()调用)的所有情况下将调用from_db_value()

to_python()通过反序列化和从表单使用的clean()方法调用。

作为一般规则,to_python()应优雅地处理以下任何参数:

  • 正确类型的实例
  • 字符串
  • None(如果字段允许null=True

尤其请注意to_python通过反序列化和表单中的clean方法调用,这个要注意反序列化的问题,python的反序列化是一个比较严重的安全问题。

所以一般的这两个函数一般的定义范式:

 def from_db_value(self,value,expression,connection,content):
if value is None:
return value
try:
return field_function(value)
except Exception:
return value def to_python(self,value):
if value is None or isinstance(value,xxxx):
return value
try:
return field_function(value)
except Exception:
return value

当然field_function是对value的处理函数,需要自己定义。

(2)将python对象转换为查询值:

当重写to_python的时候,必须重写get_prep_value函数,基本上是field_function函数的逆向操作

 def get_prep_value(self,value):
return do_something(value)

(3)将查询值转换为数据库值:

也就是类似像这一类操作的转换过程(p.s.日期存在数据库中是unix时间戳,后台处理是2018-01-01 11:07:23.123),都写在get_db_prep_value函数中

 def get_db_prep_value(self, value, connection, prepared=False):
return do_something(value)

(4)此外还有很多API方法,详情请参考http://python.usyiyi.cn/documents/django_182/ref/models/fields.html

8、与表单相关可以覆盖重写formfield,此处不再展开。

9、关于序列化,这里要展开引一段官方文档:

转换字段数据以进行序列化

要自定义序列化程序如何序列化值,您可以覆盖value_to_string()。调用Field._get_val_from_obj(obj)是获取值序列化的最佳方式。例如,由于我们的HandField使用字符串作为其数据存储,我们可以重用一些现有的转换代码:

class HandField(models.Field):
# ... def value_to_string(self, obj):
value = self._get_val_from_obj(obj)
return self.get_prep_value(value)

这里值得注意。

Django学习笔记第十二篇--关于自定义数据库字段数据类型的更多相关文章

  1. Python框架之Django学习笔记(十二)

    Django站点管理 十一转眼结束,说好的充电没能顺利开展,反而悠闲的看了电视剧以及去影院看了新上映的<心花路放>.<亲爱的>以及<黄金时代>,说好的劳逸结合现在回 ...

  2. MyCat 学习笔记 第十二篇.数据分片 之 分片事务处理

    1 环境说明 VM 模拟3台MYSQL 5.6 服务器 VM1 192.168.31.187:3307 VM2 192.168.31.212:3307 VM3 192.168.31.150:  330 ...

  3. VSTO 学习笔记(十二)自定义公式与Ribbon

    原文:VSTO 学习笔记(十二)自定义公式与Ribbon 这几天工作中在开发一个Excel插件,包含自定义公式,根据条件从数据库中查询结果.这次我们来做一个简单的测试,达到类似的目的. 即在Excel ...

  4. 汇编入门学习笔记 (十二)—— int指令、port

    疯狂的暑假学习之  汇编入门学习笔记 (十二)--  int指令.port 參考: <汇编语言> 王爽 第13.14章 一.int指令 1. int指令引发的中断 int n指令,相当于引 ...

  5. Binder学习笔记(十二)—— binder_transaction(...)都干了什么?

    binder_open(...)都干了什么? 在回答binder_transaction(...)之前,还有一些基础设施要去探究,比如binder_open(...),binder_mmap(...) ...

  6. Egret入门学习日记 --- 第十二篇(书中 5.1节 内容)

    第十二篇(书中 5.1节 内容) 昨天把 第4章完成了. 今天来看第5章. 接下来是 5.1节 的内容. 总结一下 5.1节 的重点: 1.如何制作一个公用按钮皮肤. 跟着做: 重点1:如何制作一个公 ...

  7. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  8. MySQL数据库学习笔记(十二)----开源工具DbUtils的使用(数据库的增删改查)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  9. Android学习笔记(十二)——实战:制作一个聊天界面

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 运用简单的布局知识,我们可以来尝试制作一个聊天界面. 一.制作 Nine-Patch 图片 : Nine-Pa ...

随机推荐

  1. 摘:常用函数(包括:宽字符函数、普通C函数 )

    只要看见“W”就是宽的意思,左边wchar_t,右边char 字符分类: 宽字符函数            普通C函数            描述 iswalnum()             isa ...

  2. 函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例

    一.适配器 三种类型的适配器: 容器适配器:用来扩展7种基本容器,利用基本容器扩展形成了栈.队列和优先级队列 迭代器适配器:(反向迭代器.插入迭代器.IO流迭代器) 函数适配器:函数适配器能够将仿函数 ...

  3. ASP.NET Identity & OWIN 学习资料

    有关 ASP.NET Identity 的更多细节: http://www.asp.net/identity 从一个空项目中添加 ASP.NET Identity 和 OWIN 支持: http:// ...

  4. python--迭代器的实现

    #!/usr/local/python/bin/python3 """ 一个迭代器的例子 """ class exsample(object ...

  5. django Models cross file ---- 跨app引用文件

    一.django 的跨app引用文件是通过import 来实现的,但是import 的路径查找和标准的import 不太一样,django里面更加方便了 二.例子 1.project 结构说明 [ji ...

  6. jquery判断元素的子元素是否存在

    jquery判断元素的子元素是否存在的示例代码. jquery判断子元素是否存在 一.判断子元素是否存在 //一级子元素 if($("#specialId>img").len ...

  7. Netty的ByteBuf

    https://blog.csdn.net/thinking_fioa/article/details/80795673  netty的ByteBuf知识点

  8. HTTP协议各个参数详解

    HTTP消息是由普通ASCII文本组成.消息包括消息头和数据体部分.消息头以行为单位,每行以CRLF(回车和换行)结束,消息头结束后,额外增加一个CRLF,之后内容就是数据体部分了. http请求: ...

  9. IP地址欺骗

    1.什么是IP地址欺骗按照IP网络协议,数据包头包含来源地和目的地信息,而IP地址欺骗,就是通过伪造数据包爆头,使显示的信息源不是实际的来源,就像这个数据包是从另一台计算机上发送的. 2.IP地址欺骗 ...

  10. js prototype 理解

    简单理解:prototype对象是实现面向对象的一个重要机制.每个函数也是一个对象,它们对应的类就是 function,每个函数对象都具有一个子对象prototype.Prototype 表示了该函数 ...