我需要將任意數據存儲在多個數據類型的關係數據庫中,所以我想出了一個解決方案,除了存儲數據本身之外,還存儲了什麼是數據的數據類型(str,int等)。這允許在複製時將存儲在db中的字符串轉換爲數據所屬的任何適當的數據類型。爲了存儲數據類型我做了一個自定義模型領域:Django:自定義模型字段不顯示正確的值
class DataType(object):
SUPPORTED_TYPES = {
u'unicode': unicode,
u'str': str,
u'bool': bool,
u'int': int,
u'float': float
}
INVERSE_SUPPORTED_TYPES = dict(zip(SUPPORTED_TYPES.values(), SUPPORTED_TYPES.keys()))
TYPE_CHOICES = dict(zip(SUPPORTED_TYPES.keys(), SUPPORTED_TYPES.keys()))
def __init__(self, datatype=None):
if not datatype:
datatype = unicode
t_datatype = type(datatype)
if t_datatype in [str, unicode]:
self.datatype = self.SUPPORTED_TYPES[datatype]
elif t_datatype is type and datatype in self.INVERSE_SUPPORTED_TYPES.keys():
self.datatype = datatype
elif t_datatype is DataType:
self.datatype = datatype.datatype
else:
raise TypeError('Unsupported %s' % str(t_datatype))
def __unicode__(self):
return self.INVERSE_SUPPORTED_TYPES[self.datatype]
def __str__(self):
return str(self.__unicode__())
def __len__(self):
return len(self.__unicode__())
def __call__(self, *args, **kwargs):
return self.datatype(*args, **kwargs)
class DataTypeField(models.CharField):
__metaclass__ = models.SubfieldBase
description = 'Field for storing python data-types in db with capability to get python the data-type back'
def __init__(self, **kwargs):
defaults = {}
overwrites = {
'max_length': 8
}
defaults.update(kwargs)
defaults.update(overwrites)
super(DataTypeField, self).__init__(**overwrites)
def to_python(self, value):
return DataType(value)
def get_prep_value(self, value):
return unicode(DataType(value))
def value_to_string(self, obj):
val = self._get_val_from_obj(obj)
return self.get_prep_value(val)
因此,這可以讓我做這樣的事情:
class FooModel(models.Model):
data = models.TextField()
data_type = DataTypeField()
>>> foo = FooModel.objects.create(data='17.94', data_type=float)
>>> foo.data_type(foo.data)
17.94
>>> type(foo.data_type(foo.data))
float
所以我的問題是,在Django管理(我我正在使用ModelAdmin),文本框中data_type的值沒有正確顯示。無論何時它是float
(在db中它是以浮點形式存儲的,我選中了),顯示的值是0.0
。對於int
,它顯示0
。對於bool
它顯示False
。而不是顯示data_type的字符串表示,Django實際上調用它,這意味着__call__
被調用時會帶有一個參數,這會導致這些值。例如:
>>> DataType(float)()
0.0
>>> DataType(int)()
0
>>> DataType(bool)()
False
我想通了,通過更換__call__
方法如何猴子修補它下面:
def __call__(self, *args, **kwargs):
if not args and not kwargs:
return self.__unicode__()
return self.datatype(*args, **kwargs)
這顯示在形成正確的價值,但是我覺得這是不是很優雅。有什麼辦法可以讓它變得更好嗎?我無法弄清楚Django在什麼地方稱之爲字段值。
感謝名單
Django代表的模型對象是從模型中驅動的。模型看它的源代碼,看看Django如何做到這一點 –