Django学习笔记第十二篇--关于自定义数据库字段数据类型

一、需求背景:

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

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

 

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

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

1 from django.db import models
2 
3 class myfiled(models.Filed):
4     pass

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

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

1 from django.db import models
2 
3 class myfield(models.Field):
4     description = "This is my own field!"

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

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

这个函数可以不显性定义

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

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

1 def db_type(self,connection):
2     
3     if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql':
4         return 'datetime'
5     else:
6         return 'timestamp'

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

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

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

1 def get_internal_type(self):
2     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的反序列化是一个比较严重的安全问题。

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

 1 def from_db_value(self,value,expression,connection,content):
 2       if value is None:
 3           return value
 4       try:
 5           return field_function(value)
 6       except Exception:
 7           return value
 8 
 9 def to_python(self,value):
10       if value is None or isinstance(value,xxxx):
11           return value
12       try:
13           return field_function(value)
14       except Exception:
15           return value

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

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

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

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

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

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

1 def get_db_prep_value(self, value, connection, prepared=False):
2     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)

这里值得注意。

转载于:https://www.cnblogs.com/KevinGeorge/p/8465671.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ddl语言自定义数据库字段<br><!--#include virtual="/public/back_top.asp"--><br><html><br><head><br><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><br><link href="member/css/common.css" rel="stylesheet" type="text/css"><br></head><br> <body> <br> <div style="margin-top:15px;"><br> <%<br> sFileName = "alter_manage.asp"<br> tableName = "C_alter"<br> tableName2 = "product"<br> action = Trim(Request.QueryString("action"))<br> %><br> <br> <%<br> Select Case action<br> case ""<br> Call ShowContent()<br> case "add"<br> Call add()<br> case "addsave"<br> Call addsave()<br> case "modify"<br> Call modify()<br> case "modifysave"<br> Call modifysave()<br> case "delall"<br> Call delall()<br> End Select<br> %><br> <br> <%<br> Sub ShowContent()<br> Call gRsClose()<br> sSql = "select * from view_alter"<br> <br> oRs.Open sSql,oConn,1,1<br> <br> %><br> <table width="98%" align=center cellpadding="3" cellspacing=1 bgcolor="#cccccc"><br> <tbody><br> <Form method="post" id="form1" name="form1"><br> <tr bgcolor='#efefef' height='20'><td colspan="5" align='center' style='font-weight:bold;'>字 段 信 息 管 理</td><br> <td align='center' style='font-weight:bold;'><a href="<%=sFileName%>?action=add">添加</a></td><br> </tr><br> <tr bgcolor='#FCFCFC' height='20'><br> <td width="5%" align="center">选择</td><br> <td width="16%" align="center">产品类别</td><br> <td width="14%" align="center">字段类型</td><br> <td width="20%" align="center">字段名称</td><br> <td width="35%" align="center">字段意义</td><br> <td width="10%" align="center">操作</td><br> </tr><br> <%<br> do while not oRs.eof and not oRs.bof <br> select case oRs("a_type")<br> case "nvarchar(255)"<br> a_type = "文本类型"<br> case "int"<br> a_type = "整数类型"<br> case "float"<br> a_type = "浮点类型"<br> case else<br> a_type = "未知类型"<br> end select<br> %><br> <tr bgcolor='#ffffff' height='20'><br> <td width="5%" align="center"><%Response.Write("<input type='checkbox' id='checkzi' name='checkzi' value='" & oRs("a_id") & "'>" & vbCrlf)%></td><br> <td width="16%" align="center"><%Response.Write(oRs("c_name"))%></td><br> <td width="14%" align="center"><%Response.Write(a_type)%></td><br> <td width="20%" align="center"><%Response.Write(oRs("a_name"))%></td><br> <td width="35%" align="center"><%Response.Write(oRs("a_detail"))%></td><br> <td width="10%" align="center"><a href="<%=sFileName%>?action=delall&checkzi=<%=oRs("a_id")%>">删除</a> <a href="<%=sFileName%>?action=modify&a_id=<%=oRs("a_id")%>">修改</a> </td><br> </tr><br> <br> <br> <%<br> oRs.movenext<br> loop<br> %><br> <tr bgcolor='#ffffff' height='20'><br> <td colspan="6" align="center"><br> <%<br> Response.Write("<input type='checkbox' id='checkall' name='checkall' onclick='selectAll();'><font color='#ff0000'><a style='cursor:hand;'>全/反选</a></font>" & vbCrlf)<br> Response.Write("<input type='button' value='删除所选' class='input_submit' onClick=""checkSelect('" & sFileName & "','?action=delall');"">" & vbCrlf)<br> %><br> </td><br> </tr><br> </form><br> </tbody><br> </table><br> <%<br> Call gRsClose()<br> End Sub<br> %><br> <br> <br> <%<br> Sub add()<br> %><br> <Script Language=JavaScript><br> function doSubmit(){<br> if(parseInt(document.getElementById("a_classid").options[document.getElementById("a_classid").selectedIndex].value)==0)<br> {<br> alert("请选择产品类型!");<br> return false;<br> }<br> <br> if(parseInt(document.getElementById("a_type").options[document.getElementById("a_type").selectedIndex].value)==0)<br> {<br> alert("请选择字段类型!");<br> return false;<br> }<br> if(document.getElementById("a_name").value=="")<br> {<br> alert("字段名称不能为空!");<br> document.getElementById("a_name").select();<br> return false;<br> } <br> <br> if(document.getElementById("a_detail").value=="")<br> {<br> alert("请填写该字段的意义!");<br> document.getElementById("a_detail").select();<br> return false;<br> }<br> <br> }<br> </script><br> <table width="58%" border="0" align="center" cellpadding="3" cellspacing="1" bgcolor="#DEDFDE"><br> <form name="myform" method="post" action="<%=sFileName%>?action=addsave" onSubmit="return doSubmit();"><br> <input type="hidden" name="Action" value="AddSave"><br> <tr><br> <td colspan="4" bgcolor="#eeeeee"><div align="center"><strong>字 段 信 息 <br> 添 加</strong></div></td><br> </tr><br> <tr><br> <td bgcolor="#FFFFFF">选择类别:</td><br> <td width="580" colspan="3" nowrap bgcolor="#FFFFFF"><%=gMakeClassSelect("a_classid","p_class",0)%></td><br> </tr><br> <tr><br> <td nowrap bgcolor="#FFFFFF">字段类型:</td><br> <td colspan="3" nowrap bgcolor="#FFFFFF"><label><br> <select name="a_type" class="INPUT" id="a_type"><br> <option value="0" selected>请您选择类型</option><br> <option value="int">整数型</option><br> <option value="nvarchar(255)">文本型</option><br> <option value="float">浮点型</option><br> </select><br> </label></td><br> </tr><br> <tr><br> <td nowrap bgcolor="#FFFFFF">字段名称:</td><br> <td colspan="3" nowrap bgcolor="#FFFFFF"><input name="a_name" type="text" id="a_name" size="80" maxlength="50" class="input_text" > </td><br> </tr><br> <tr><br> <td bgcolor="#FFFFFF">字段意义:</td><br> <td colspan="3" nowrap bgcolor="#FFFFFF"><input name="a_detail" type="text" id="a_detail" size="80" maxlength="50" class="input_text" ></td><br> </tr><br> <br> <tr bgcolor="#efefef" height="30"><br> <td colspan="4" align="center"><br> <input type="submit" name="Submit" value=" 提 交 " class="input_submit" ><br> <input type="reset" name="Submit" value="重 置" class="input_submit"><br> </td><br> </tr><br> </form><br> </table><br> <%<br> End Sub<br> %><br> <br> <br> <%<br> Sub addsave()<br> a_classid = GetSafeStr(Trim(Request.Form("a_classid")))<br> a_name = GetSafeStr(Trim(Request.Form("a_name")))<br> a_detail = GetSafeStr(Trim(Request.Form("a_detail")))<br> a_type = GetSafeStr(Trim(Request.Form("a_type")))<br> a_regtime = now() <br> '判断主表中要添加的字段是否存在<br> eSql = "select * from syscolumns where id=object_id('"& tableName2 &"') and name='"& a_name &"'"<br> Call gRsClose() <br> oRs.Open eSql,oConn,1,3<br> if not oRs.EOF then<br> Call ErrorMsg(sFileName,"主表中字段已经存在在,三秒后返回",1)<br> end if<br> Call gRsClose() <br> <br> '将字段相关信息添加到从表<br> sSql = "select * from "& tableName &" where 1=1"<br> Call gRsClose() <br> oRs.Open sSql,oConn,1,3<br> oRs.AddNew()<br> oRs("a_classid") = a_classid<br> oRs("a_name") = a_name<br> oRs("a_detail") = a_detail<br> oRs("a_type") = a_type<br> oRs("a_regtime") = a_regtime<br> oRs.Update()<br> <br> '添加字段<br> <br> oConn.Execute("ALTER TABLE "& tableName2 &" ADD "& a_name &" "& a_type &"")<br> Call ErrorMsg(sFileName,"添加字段成功,三秒后返回",1)<br> Call gRsClose() <br> End Sub<br> %><br> <br> <br> <br> <%<br> Sub modify()<br> %><br> <Script Language=JavaScript><br> function doSubmit(){<br> if(parseInt(document.getElementById("a_classid").options[document.getElementById("a_classid").selectedIndex].value)==0)<br> {<br> alert("请选择产品类型!");<br> return false;<br> }<br> <br> if(parseInt(document.getElementById("a_type").options[document.getElementById("a_type").selectedIndex].value)==0)<br> {<br> alert("请选择字段类型!");<br> return false;<br> }<br> if(document.getElementById("a_name").value=="")<br> {<br> alert("字段名称不能为空!");<br> document.getElementById("a_name").select();<br> return false;<br> } <br> <br> if(document.getElementById("a_detail").value=="")<br> {<br> alert("请填写该字段的意义!");<br> document.getElementById("a_detail").select();<br> return false;<br> }<br> <br> }<br> </script><br> <%<br> Call gRsClose()<br> a_id = Trim(Request.QueryString("a_id"))<br> sSql = "select * from view_alter where a_id = "& a_id<br> oRs.Open sSql,oConn,1,1<br> If not oRs.eof and not oRs.bof Then<br> a_classid = oRs("a_classid")<br> a_name = oRs("a_name")<br> a_detail = oRs("a_detail")<br> a_type = oRs("a_type")<br> End If<br> Call gRsClose()<br> %><br> <table width="58%" border="0" align="center" cellpadding="3" cellspacing="1" bgcolor="#DEDFDE"><br> <form name="myform" method="post" action="<%=sFileName%>?action=modifysave&a_id=<%=a_id%>" onSubmit="return doSubmit();"><br> <input type="hidden" name="Action" value="AddSave"><br> <tr><br> <td colspan="4" bgcolor="#eeeeee"><div align="center"><strong>字 段 信 息 <br> 添 加</strong></div></td><br> </tr><br> <tr><br> <td bgcolor="#FFFFFF">选择类别:</td><br> <td width="580" colspan="3" nowrap bgcolor="#FFFFFF"><%=gMakeClassSelect("a_classid","p_class",a_classid)%></td><br> </tr><br> <tr><br> <td nowrap bgcolor="#FFFFFF">字段类型:</td><br> <td colspan="3" nowrap bgcolor="#FFFFFF"><label><br> <select name="a_type" class="INPUT" id="a_type"><br> <option value="0" <%If a_type="" Then Response.Write("selected")%>>请您选择类型</option><br> <option value="int" <%If a_type="int" Then Response.Write("selected")%>>整数型</option><br> <option value="nvarchar(255)" <%If a_type="nvarchar(255)" Then Response.Write("selected")%>>文本型</option><br> <option value="float" <%If a_type="float" Then Response.Write("selected")%>>浮点型</option><br> </select><br> </label></td><br> </tr><br> <tr><br> <td nowrap bgcolor="#FFFFFF">字段名称:</td><br> <td colspan="3" nowrap bgcolor="#FFFFFF"><input name="a_name" type="text" class="input_text" id="a_name" value="<%=a_name%>" size="80" maxlength="50" > </td><br> </tr><br> <tr><br> <td bgcolor="#FFFFFF">字段意义:</td><br> <td colspan="3" nowrap bgcolor="#FFFFFF"><input name="a_detail" type="text" class="input_text" id="a_detail" value="<%=a_detail%>" size="80" maxlength="50" ></td><br> </tr><br> <br> <tr bgcolor="#efefef" height="30"><br> <td colspan="4" align="center"><br> <input type="submit" name="Submit" value=" 修 改 " class="input_submit" ><br> <input type="reset" name="Submit" value="重 置" class="input_submit"><br> </td><br> </tr><br> </form><br> </table><br> <%<br> End Sub<br> %><br> <br> <%<br> Sub modifysave()<br> a_classid = GetSafeStr(Trim(Request.Form("a_classid")))<br> a_name = GetSafeStr(Trim(Request.Form("a_name")))<br> a_detail = GetSafeStr(Trim(Request.Form("a_detail")))<br> a_type = GetSafeStr(Trim(Request.Form("a_type")))<br> a_regtime = now()<br> a_id = Trim(Request.QueryString("a_id"))<br> <br> <br> '将字段相关信息添加到从表<br> sSql = "select * from "& tableName &" where a_id = "& a_id <br> Call gRsClose() <br> oRs.Open sSql,oConn,1,3<br> <br> aname = oRs("a_name")<br> atype = oRs("a_type")<br> on error resume next<br> oRs("a_classid") = a_classid<br> '判断主表中是否有相同的字段(保持主从表中的数据一致)<br> set rs1=oConn.Execute("select 1 from syscolumns where id=object_id('"& tableName2 &"') and name='"& a_name &"'")<br> If rs1.eof and rs1.bof Then<br> oRs("a_name") = a_name<br> End If<br> rs1.close()<br> oRs("a_detail") = a_detail<br> oRs("a_type") = a_type<br> oRs.Update()<br> <br> If a_name<>aname Then<br> '修改字段名称(判断主表中是否有相同的字段)<br> oConn.Execute("if not exists(select 1 from syscolumns where id=object_id('"& tableName2 &"') and name='"& a_name &"') EXEC sp_rename '"& tableName2 &".["& aname &"]', '"& a_name &"', 'COLUMN'")<br> End If<br> If a_type<>atype Then<br> '修改字段类型<br> oConn.Execute("ALTER TABLE "& tableName2 &" ALTER COLUMN "& a_name &" "& a_type &"")<br> End If<br> <br> Call ErrorMsg(sFileName,"修改字段成功,三秒后返回",1)<br> Call gRsClose()<br> End Sub<br> %><br> <br> <%<br> Sub delall()<br> checkzi = Trim(Request("checkzi"))<br> If checkzi <> "" Then<br> <br> Dim z1<br> z1 = tableName<br> Dim temp_id,last_id<br> last_id="("<br> temp_id = Split(Request("checkzi"),",")<br> <br> For i=0 To UBound(temp_id)<br> last_id = last_id & Trim(temp_id(i)) & ","<br> Next<br> last_id = Left(last_id,Len(last_id)-1)<br> last_id = last_id & ")"<br> 'last_id为最终要删除的记录ID<br> <br> '取出要删除的对应字段<br> sSql = "select a_name from "& z1 &" where a_id in " & last_id<br> Call gRsClose()<br> oRs.Open sSql,oConn,1,1<br> dim a_names<br> a_names = ""<br> jj=1<br> do while not oRs.eof and not oRs.bof<br> If jj <> oRs.recordcount Then<br> a_names = a_names & oRs("a_name") &","<br> Else<br> a_names = a_names & oRs("a_name")<br> End If<br> oRs.movenext<br> jj = jj + 1<br> loop<br> Call gRsClose()<br> <br> '删除主表对应字段<br> a_name = Split(a_names,",")<br> for i=0 to Ubound(a_name)<br> oConn.Execute("ALTER TABLE "& tableName2 &" DROP COLUMN "& a_name(i) &"")<br> next<br> <br> '删除从表中字段的意义信息<br> sSql = "delete from " & z1 & " where a_id in " & last_id<br> oConn.Execute(sSql)<br> Call ErrorMsg(sFileName,"成功删除所选记录,三秒后将返回……",1)<br> End If<br> End Sub<br> %><br> </div><br> </body><br></html><br><!--#include virtual="/public/back_bottom.asp"-->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值