2012-06-28 132 views
0

我需要將任意數據存儲在多個數據類型的關係數據庫中,所以我想出了一個解決方案,除了存儲數據本身之外,還存儲了什麼是數據的數據類型(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在什麼地方稱之爲字段值。

感謝名單

+0

Django代表的模型對象是從模型中驅動的。模型看它的源代碼,看看Django如何做到這一點 –

回答

0

WRT爲什麼你的數據類型被調用,這樣說的:https://docs.djangoproject.com/en/1.4/topics/templates/#accessing-method-calls

乾淨的解決方案可能是簡單地呼叫重命名爲更加明確。

+0

我想這可能是問題,但不會Django Admin使用ModelForm哪些字段使用小部件來渲染表格。因此,該值的實際呈現不會發生在模板中,而是發生在小部件中。在調試過程中,我正在逐步完成小部件,並且小部件渲染函數會得到錯誤的值。 – miki725

相關問題