2012-09-25 36 views
-1

我想使自己的字段在單個貨幣中進行一些計算,並且我無法在數據庫中使用小數數據類型,這就是我到目前爲止。我真的只是在學習自定義字段類型,並不確定我做錯了什麼。我如何強制Django將小數點保存到浮點數據庫列中

class MoneyField(models.DecimalField): 
    """ 
    """ 

    __metaclass__ = models.SubfieldBase 

    def __init__(self, verbose_name=None, name=None, max_digits=10, decimal_places=2, seperator=',', dp='.', pos='', neg='-', trailneg='', **kwargs): 
     models.DecimalField.__init__(self, verbose_name, name, decimal_places=2, max_digits=10, **kwargs) 

    def get_internal_type(self): 
     return models.DecimalField.__name__ 

    def pre_save(self, model_instance, add): 
     value = getattr(model_instance, self.attname) 
     if self.decimal_places > 0: 
      dp_modifier = Decimal(1/Decimal(pow(10, self.decimal_places))) 
     else: 
      dp_modifier = Decimal(1) 
     if value != None: 
      value = Decimal(str(value)) 

     print value 
     print type(value.quantize(Decimal(dp_modifier))) 
     return value.quantize(Decimal(dp_modifier)) 

    def to_python(self, value): 
     try: 
      if self.decimal_places > 0: 
       dp_modifier = Decimal(1/Decimal(pow(10, self.decimal_places))) 
      else: 
       dp_modifier = Decimal(1) 
      if value != None: 
       value = Decimal(str(value)) 
      return super(MoneyField, self).to_python(value).quantize(Decimal(dp_modifier)) 
     except AttributeError: 
      return None 

    def get_db_prep_save(self, value, connection): 
     return float(value) 

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

例外:

Environment: 


Request Method: GET 
Request URL: http://127.0.0.1:8001/appdata/joinery/costing/cost-boughtin-by-item/glass/1A346B0F-0705-11E2-9E84-7071BCB8D2AB/ 

Django Version: 1.3.1 
Python Version: 2.6.2 
Installed Applications: 
['django.contrib.auth', 
'django.contrib.contenttypes', 
'django.contrib.sessions', 
'django.contrib.sites', 
'django.contrib.admin', 
'appdata.generic', 
'appdata.contacts', 
'appdata.dashboard', 
'appdata.scheduler', 
'appdata.financial', 
'appdata.work', 
'appdata.boughtin', 
'appdata.bespoke', 
'appdata.joinery', 
'appdata.home', 
'appdata.globaltags', 
'appdata.importdata', 
'appdata.database', 
'appdata.ads', 
'appdata.workshop', 
'appdata.transfer', 
'appdata.setup', 
'appdata.languages', 
'appdata.machine_output', 
'appdata.machine_output.modules', 
'appdata.printing', 
'django_cpserver', 
'appdata.djangologdb', 
'raven.contrib.django'] 
Installed Middleware: 
('django.middleware.common.CommonMiddleware', 
'django.contrib.sessions.middleware.SessionMiddleware', 
'django.middleware.locale.LocaleMiddleware', 
'django.contrib.auth.middleware.AuthenticationMiddleware', 
'appdata.middleware.UserAgent', 
'appdata.middleware.SiteLogin', 
'appdata.middleware.RequestIdent', 
'appdata.middleware.ProfilerMiddleware', 
'django.middleware.transaction.TransactionMiddleware', 
'djangologdb.middleware.LoggingMiddleware', 
'raven.contrib.django.middleware.Sentry404CatchMiddleware') 


Traceback: 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\core\handlers\base.py" in get_response 
    111.       response = callback(request, *callback_args, **callback_kwargs) 
File "C:\JoinerySoft\Development\working folder\appdata\joinery\costing.py" in cost_boughtin 
    202.   net_cost, charge_out, xml = calc_model.objects.cost_by_item(item,get_xml=True) 
File "C:\JoinerySoft\Development\working folder\appdata\joinery\models.py" in cost_by_item 
    719.   return self._cost_component_list(item_list, costbook, get_xml, item=item) 
File "C:\JoinerySoft\Development\working folder\appdata\joinery\models.py" in _cost_component_list 
    699.    calc_data = self._cost_components(calc_item_list, costbook) 
File "C:\JoinerySoft\Development\working folder\appdata\joinery\models.py" in _cost_components 
    688.    calc_item.apply_cost(cost_item, item_cache) 
File "C:\JoinerySoft\Development\working folder\appdata\joinery\models.py" in apply_cost 
    1024.   calc_component.save() 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\db\models\base.py" in save 
    460.   self.save_base(using=using, force_insert=force_insert, force_update=force_update) 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\db\models\base.py" in save_base 
    526.       rows = manager.using(using).filter(pk=pk_val)._update(values) 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\db\models\query.py" in _update 
    491.   return query.get_compiler(self.db).execute_sql(None) 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\db\models\sql\compiler.py" in execute_sql 
    869.   cursor = super(SQLUpdateCompiler, self).execute_sql(result_type) 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\db\models\sql\compiler.py" in execute_sql 
    725.    sql, params = self.as_sql() 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\db\models\sql\compiler.py" in as_sql 
    834.     val = field.get_db_prep_save(val, connection=self.connection) 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\db\models\fields\subclassing.py" in inner 
    28.    return func(*args, **kwargs) 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\db\models\fields\__init__.py" in get_db_prep_save 
    786.   return connection.ops.value_to_db_decimal(self.to_python(value), 
File "C:\JoinerySoft\Development\working folder\lib\site-packages\django\db\models\fields\__init__.py" in to_python 
    761.    return decimal.Decimal(value) 
File "C:\JoinerySoft\Development\working folder\lib\decimal.py" in __new__ 
    653.        "First convert the float to a string") 

Exception Type: TypeError at /appdata/joinery/costing/cost-boughtin-by-item/glass/1A346B0F-0705-11E2-9E84-7071BCB8D2AB/ 
Exception Value: Cannot convert float to Decimal. First convert the float to a string 
+3

那麼,怎麼了? –

+0

我想知道如何強制django像浮場一樣保存。目前它正試圖保存一個小數位字段,並且它不起作用 – Jharwood

+0

您是否會遇到異常?怎麼了? – miki725

回答

1

我想你可能接近從錯誤的方向問題。而不是試圖將db中的Decimal字段保存爲float,您應該嘗試從float字段獲取Decimal值。

嘗試一些在這種性質:

class MoneyField(models.FloatField): 
    __metaclass__ = models.SubfieldBase 

    def to_python(self, value): 
     t_value = type(value) 

     if t_value is Decimal: 
      return value 

     elif t_value is float: 
      return Decimal.from_float(value) 

     elif t_value in (str, unicode,): 
      return Decimal(value) 

     else: 
      raise TypeError('Unsupported value type: %s' % str(t_value)) 

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

那麼這樣做是它的工作原理一樣浮領域,因此是用分貝浮點字段兼容。但是,無論何時獲取值,它都會確保返回浮點數的十進制版本。當試圖保存該字段時,它將其轉換爲浮動。

還沒有測試過,所以不確定是否100%正確,但我認爲這應該讓你在正確的方向。最重要的是,你可以執行所有的錢...

+0

python 2.6,我覺得你不能用from_float – Jharwood

相關問題