Django学习笔记第十二篇--关于自定义数据库字段数据类型
一、需求背景:
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学习笔记第十二篇--关于自定义数据库字段数据类型的更多相关文章
- Python框架之Django学习笔记(十二)
Django站点管理 十一转眼结束,说好的充电没能顺利开展,反而悠闲的看了电视剧以及去影院看了新上映的<心花路放>.<亲爱的>以及<黄金时代>,说好的劳逸结合现在回 ...
- 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 ...
- VSTO 学习笔记(十二)自定义公式与Ribbon
原文:VSTO 学习笔记(十二)自定义公式与Ribbon 这几天工作中在开发一个Excel插件,包含自定义公式,根据条件从数据库中查询结果.这次我们来做一个简单的测试,达到类似的目的. 即在Excel ...
- 汇编入门学习笔记 (十二)—— int指令、port
疯狂的暑假学习之 汇编入门学习笔记 (十二)-- int指令.port 參考: <汇编语言> 王爽 第13.14章 一.int指令 1. int指令引发的中断 int n指令,相当于引 ...
- Binder学习笔记(十二)—— binder_transaction(...)都干了什么?
binder_open(...)都干了什么? 在回答binder_transaction(...)之前,还有一些基础设施要去探究,比如binder_open(...),binder_mmap(...) ...
- Egret入门学习日记 --- 第十二篇(书中 5.1节 内容)
第十二篇(书中 5.1节 内容) 昨天把 第4章完成了. 今天来看第5章. 接下来是 5.1节 的内容. 总结一下 5.1节 的重点: 1.如何制作一个公用按钮皮肤. 跟着做: 重点1:如何制作一个公 ...
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- MySQL数据库学习笔记(十二)----开源工具DbUtils的使用(数据库的增删改查)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- Android学习笔记(十二)——实战:制作一个聊天界面
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 运用简单的布局知识,我们可以来尝试制作一个聊天界面. 一.制作 Nine-Patch 图片 : Nine-Pa ...
随机推荐
- C#中byte类型转换为double类型
// Initialize unmanged memory to hold the array. int size = Marshal.SizeOf(bytes[0]) * bytes.Length; ...
- vue $http请求服务
vue中的$http服务 需要引入一个叫vue-resource.js的文件,因为vue.js中没有$http服务.如果需要使用这个服务去百度下载vue-resource.js 然后引进项目即可. ...
- Decoration4:分页展示
现在我们实现前台List的分页展示,这也是最基本的要求 先看现在的Rest数据格式,在spring的默认返回中,分页用到的元素都已经在page节点中返回了,只要在前台合理利用就足够了 { " ...
- js基本知识1
Javascript 作用 1. 网页特效 2. 用户交互 3. 表单验证 Js 就是可以用来控制 结构 和 样式 . 1.2 体验js 认识常用的三个输出语句. 都属于 js 内置对象 . 大家买手 ...
- JAVA第一个窗体小程序
import java.awt.*;public class Day1015_Frame{ public static void main(String[] args) { ...
- [C++]在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include StdAfx.h”
问题现象:在写好的.cpp文件后,编译报错.提示"你建立的工程使用了预编译功能, cpp最前边要留一行这样的内容:#include "StdAfx.h"问题原因:网上说是 ...
- web.config中的connectionString里面应该怎么写?
2009-09-16 10:19信欣玛利 | 浏览 6068 次 网络 就是具体格式.. 谁能举个例子? asp.net 3.5的. 2009-09-16 10:40 提问者采纳 这是用来连 ...
- 跟着百度学习之ThinkPHP的认识/初窥
MVC全称(Model View Controller) Model:模型(可以理解位数据库操作模型) View:视图(视图显示) Controller:(控制器) 简单的说框架就是一个类的集合.集合 ...
- java 读取Zip文件进行写入
直接读取ZIp文件读取写入到别的文件中. package jp.co.misumi.mdm.batch; import java.io.BufferedReader; import java.io.F ...
- eclipse不能自动编译生成class文件的解决办法
最近在项目项目开发过程中遇到eclipse不能自动编译生成class文件,当时很纳闷,每次修改代码后运行都是修改前的效果,没辙了,只好反编译原来的class文件,结果发现,class文件里并没有看到修 ...