2017-02-13 16 views
0

當我在列表模板或詳細(只讀)模板中顯示金額時,我希望能夠顯示包含貨幣符號的字段值的漂亮版本:「$ 100.00」如何用列表模板中的貨幣符號和簡單的十進制代表Django貨幣字段進行編輯?

但是,當正在編輯記錄,我想在沒有任何貨幣符號的情況下在TextInput框中顯示「100.00」。

我做了一個自定義models.DecimalField類和forms.DecimalField類來表示在我的Django應用程序中的錢。

所以我試圖想出一種方法來在模板中有一個替換版本的字段的值是漂亮的(即正確格式化的查看,但不理想的編輯)。我知道有模板過濾器可以讓你完成這個任務,但我相信這會阻止我遍歷表單中的字段並顯示它們的值。

如果我可以添加一個漂亮的屬性到我的自定義字段類,我可以檢查它是否存在於模板中並顯示它。到目前爲止,我嘗試這樣做:

class MoneyFormField(forms.DecimalField): 
    def __init__(self, *args, **kwargs): 
     # I plan to add symbol localization code here 
     self.symbol= '$' 

    def prepare_value(self, value): 
     # assign pretty value to an attribute that template can access 
     self.pretty = self.pretty_value(value)    
     try: 
      return round(Decimal(value),2) 
     except: 
      return 0 

    def pretty_value(self, value): 
     if not value: 
      value = 0 
     return self.symbol + str(round(Decimal(value),2)) 

的問題是,爲了在模板中訪問美麗的價值,我必須先訪問原始值,以便prepare_value()被調用。

如果我試圖在這樣的一個模板打印漂亮值...

{% for field in payment_form %} 
    {{ field.field.pretty }} {{ field.value }} {{ field.field.pretty }} 
{% endfor %} 

那麼第一個漂亮被忽略,但最後漂亮的照片。

如果我能得到這個工作,那麼我會顯示一個模板一個漂亮的值(或者漂亮不存在默認值)是這樣的:

{% if field.field.pretty %} 
    {{ field.field.pretty}} 
{% else %} 
    {{ field.value }} 
{% endif %} 

沒有人有做的任何建議可用於模板的字段的替代表示?

TL; DR-如何訪問表單字段init中的字段值?

回答

0

我想出了一個解決方案,但由於我是新來的Django和python我可能會使事情不必要的過度複雜。所以我很樂意聽到任何反饋!

總結:我希望我的金錢領域有一個「漂亮」的版本,可以在列表和只讀細節等特定模板中顯示金額爲「$ 100.00」而不是「100.00」。

我創建了一個指定我的自定義表單域款車型領域,MoneyFormField:

class MoneyField(models.DecimalField): 
    def __init__(self, *args, **kwargs): 
     kwargs['max_digits'] = 13 
     kwargs['decimal_places'] = 4 
     kwargs['default'] = 0 

    def formfield(self, **kwargs): 
     defaults = {'form_class': MoneyFormField} 
     defaults.update(kwargs) 
     return super(MoneyField, self).formfield(**defaults)   

這裏是我的MoneyFormField表單字段。注意調用「get_bound_field」:

class MoneyFormField(forms.DecimalField): 
    def __init__(self, *args, **kwargs): 
     self.widget = MoneyTextInput() # custom widget I'm experimenting with 
     self.prefix = '$'    
     super(MoneyFormField, self).__init__(*args, **kwargs) 

    def get_bound_field(self, form, field_name): 
     return MoneyBoundField(form, self, field_name)   

    def prepare_value(self, value): 
     try: 
      return round(Decimal(value),2) 
     except: 
      return 0 

MoneyBoundField是什麼使可用的「漂亮」的版本字段的模板:

class MoneyBoundField(BoundField): 
    def pretty(self): 
     return self.field.prefix+str(self.value()) 

如果我只是做了這個話,我可以打印很值首先檢查是否相當值的存在,如果沒有,打印原始值是這樣的:

{% for somefield in payment_form %} 
    {% if somefield.pretty %} 
     {{ somefield.pretty }} 
    {% else %} 
     {{ somefield.value }} 
    {% endif %}  
{% endfor %} 

但我寧願只是做這樣的事情:

{% for somefield in payment_form %} 
    {{ somefield.pretty }} 
{% endfor %} 

所以我不得不通過增加兩行漂亮添加到主Django的綁定列類boundfields.py:

boundfield.py 
class BoundField(object): 
... 
    def pretty(self): 
     # return default value. Let descendant classes override this function where desired 
     return self.value() 
0

這裏的另一種方法,我拿了。我現在只是使用模板過濾器來使字段變得非常漂亮,而不是在boundfield.py中使用主要的django BoundField類定義。該過濾器將執行以下操作:

  • 如果該字段是一個選擇字段,將其轉換選擇索引值描述字符串
  • 如果字段的自定義formfield,一個自定義的BoundField,有一個叫功能「漂亮」它調用該函數並返回值。
  • (註釋掉)如果適用,您可以嘗試調用自定義formfield類中的特定方法。這樣就無需在formfield類
  • 定義一個BoundField如果這些不應用它只是返回該字段的值不進行修改

這是我app_filters.py代碼:

from django.forms.fields import ChoiceField 

@register.filter 
def pretty_filter(field): 
    # is this a better way to get the field's value? 
    # field_value = field.form.initial[field.name] 

    # get the field's value (for choice fields, this is the integer index used to look up the verbose string in the choices dict) 
    field_value = field.value() 
    if field_value is None: 
     return '' 
    # the the field has 'choices' then return the verbose string for the choice 
    if isinstance(field.field, ChoiceField): 
     for (choices_index, description) in field.field.choices: 
      if choices_index == field_value: 
       return description 
     return '' # no match found 

    # # if your model.field's formfield has a function called 
    # # another_custom_function() you can call it this way: 
    # try: 
    #  return field.field.another_custom_function() 
    # except: 
    #  pass 

    # attempt to return pretty value if field has th 
    try: 
     return field.pretty() 
    except: 
    # else return default value 
     return field_value 

我也做了更改我的自定義字段的錢漂亮的功能,所以它增加了一個逗號(這可以改變處理本地化):

class MoneyBoundField(BoundField):  
    def pretty(self): 
     # return $12,345.67 
     return "{}{:,.2f}".format(self.field.prefix,self.value()) 

class MoneyFormField(forms.DecimalField): 
    def __init__(self, *args, **kwargs): 
     self.widget = MoneyTextInput() 
     self.prefix = '$' 
     super(MoneyFormField, self).__init__(*args, **kwargs) 

    def get_bound_field(self, form, field_name): 
     return MoneyBoundField(form, self, field_name)  

然後在我的模板,我用它是這樣的:

{% load app_filters %} 

{% for item in payment_form %} 
    {{item|pretty_filter}} 
{% endfor %}     

大部分的濾波代碼是從用戶Simple10複製在這裏: https://code.djangoproject.com/ticket/10427#comment:18

請分享任何想法或意見!