2010-01-06 9 views
61

मैं यहां एक प्रतिमान समस्या में भाग रहा हूं। मुझे नहीं पता कि मुझे पैसे को दशमलव() के रूप में स्टोर करना चाहिए, या अगर मुझे इसे स्ट्रिंग के रूप में स्टोर करना चाहिए और इसे दशमलव में परिवर्तित करना चाहिए। मेरा तर्क यह है:Django: मुझे धन मूल्य कैसे स्टोर करना चाहिए?

पेपैल को 2 दशमलव स्थान की आवश्यकता है, इसलिए यदि मेरे पास कोई उत्पाद है जो 49 डॉलर भी है, तो पेपैल 4 9 00 तार में आना चाहता है। Django की DecimalField() दशमलव राशि निर्धारित नहीं करता है। यह केवल अधिकतम दशमलव स्थान राशि संग्रहीत करता है। इसलिए, यदि आपके पास 49 है, और आपके पास फ़ील्ड 2 दशमलव स्थानों पर सेट है, तो यह अभी भी इसे 49 के रूप में संग्रहीत करेगा। मुझे पता है कि Django मूल रूप से कास्टिंग टाइप करता है जब यह डेटाबेस से दशमलव तक वापस deserializes (डेटाबेस के बाद से दशमलव फ़ील्ड नहीं हैं), इसलिए मैं इस समस्या के डिजाइन मुद्दों के साथ जितनी अधिक गति मुद्दों से पूरी तरह से चिंतित नहीं हूं। मैं निष्पादन के लिए सबसे अच्छा क्या करना चाहता हूं।

या, अभी तक बेहतर है, क्या किसी को भी पता है कि django DecimalField() को हमेशा TWO_PLACES स्वरूपण शैली के साथ प्रारूपित करने के लिए कॉन्फ़िगर कैसे करें।

+1

फिर से "डेटाबेस में दशमलव फ़ील्ड नहीं हैं"; माइक्रोसॉफ्ट एसक्यूएल सर्वर में "दशमलव" और "पैसा" डेटा प्रकार दोनों हैं http://msdn.microsoft.com/en-us/library/aa258271%28v=sql.80%29.aspx –

उत्तर

60

आप .quantize() विधि का उपयोग करना चाह सकते हैं। यह स्थानों की एक निश्चित संख्या को दशमलव मान दौर होगा, तर्क उपलब्ध कराने स्थानों की संख्या निर्दिष्ट करता है:

>>> from decimal import Decimal 
>>> Decimal("12.234").quantize(Decimal("0.00")) 
Decimal("12.23") 

यह भी कि तुम क्या दृष्टिकोण गोलाई चाहते निर्दिष्ट करने के लिए एक तर्क ले जा सकते हैं (अलग लेखा प्रणाली विभिन्न चाहते हो सकता है गोलाई)। Python docs में अधिक जानकारी।

नीचे एक कस्टम फ़ील्ड है जो स्वचालित रूप से सही मान उत्पन्न करता है। ध्यान दें कि यह तब होता है जब इसे डेटाबेस से पुनर्प्राप्त किया जाता है, और जब आप इसे स्वयं सेट करते हैं तो आपकी सहायता नहीं करते हैं (जब तक आप इसे डीबी में सहेज नहीं लेते और फिर से इसे पुनः प्राप्त नहीं करते!)।

from django.db import models 
from decimal import Decimal 
class CurrencyField(models.DecimalField): 
    __metaclass__ = models.SubfieldBase 

    def to_python(self, value): 
     try: 
      return super(CurrencyField, self).to_python(value).quantize(Decimal("0.01")) 
     except AttributeError: 
      return None 

[संपादित करें]

__metaclass__ कहा, देख Django: Why does this custom model field not behave as expected?

+0

उत्कृष्ट। धन्यवाद whrde। क्या यह सब आपको पूरी तरह से कार्यात्मक कस्टम मॉडल फ़ील्ड करने के लिए करना है? (यानी, यह प्रारूपण को छोड़कर दशमलव काम के समान ही काम करेगा)। – orokusaki

+1

इसके अलावा, कस्टम फ़ील्ड को संग्रहीत करने के लिए सम्मेलन क्या है? मैं सोच रहा हूं कि मैं इसे रूट प्रोजेक्ट फ़ोल्डर में रखूंगा। – orokusaki

+0

धन्यवाद, मैंने अभी इसका इस्तेमाल किया है। मैंने देखा कि जब भी मैंने मुद्राफिल्ल्ड का उपयोग किया था, तो मुझे max_digits और दशमलव_places विशेषताएँ दोहराना पड़ता था, इसलिए मैंने एक उत्तर पोस्ट किया जो इसे संबोधित करने के लिए आपके ऊपर बनाता है। –

18

मुझे लगता है कि आप एक दशमलव प्रारूप में संग्रहीत और 00.00 प्रारूप लिए यह केवल तो प्रारूप इस तरह, पेपैल के लिए भेज देना चाहिए:

pricestr = "%01.2f" % price 

आप चाहते हैं, तो आप के लिए एक विधि जोड़ सकते हैं अपने मॉडल:

def formattedprice(self): 
    return "%01.2f" % self.price 
+6

इसके अलावा: डेटाबेस को मुद्रा में संग्रहीत करें साथ ही राशि। पैसा सिर्फ एक संख्या नहीं है। –

+0

यह सच है। धन्यवाद श्री शाइन और न्यू – orokusaki

+6

श्री शायनी, आपको निश्चित रूप से डेटाबेस में मुद्रा को स्टोर करने की आवश्यकता नहीं है यदि आप जानते हैं कि सभी मुद्राएं समान होंगी। वास्तव में, अधिकांश अनुप्रयोग एकाधिक मुद्राओं से निपटते नहीं हैं। –

10

मैं भंडारण के साथ मिश्रित प्रतिनिधित्व से बचने का सुझाव देता हूं। डेटा को दशमलव मान के रूप में 2 स्थानों के साथ स्टोर करें।

यूआई परत में, इसे एक ऐसे रूप में प्रदर्शित करें जो उपयोगकर्ता के लिए उपयुक्त है (इसलिए शायद ".00" छोड़ दें)।

जब आप पेपैल को डेटा भेजते हैं, तो इसे इंटरफ़ेस के रूप में प्रारूपित करें।

1

आप इसे दशमलव दशमलव के रूप में संग्रहीत करते हैं और यदि आपको वैल्यू ने बुनियादी प्रारूपण तकनीकों का उपयोग करके कहा है तो मैन्युअल रूप से दशमलव जोड़ें।

आप उत्पाद या लेनदेन मॉडल के लिए एक मॉडल विधि भी जोड़ सकते हैं जो डेसिमलफ़िल्ल्ड को उचित रूप से स्वरूपित स्ट्रिंग के रूप में थूक देगा।

11

पैसा पैसा क्षेत्र है, जो दुर्भाग्य से मौजूद नहीं है में संग्रहित किया जाना चाहिए। चूंकि पैसा दो आयामी मान (राशि, मुद्रा) है।

पायथन-पैसा lib है, जिसमें कई कांटे हैं, फिर भी मुझे एक काम नहीं मिला है।


अनुशंसाएँ:

अजगर-पैसा शायद सबसे अच्छा कांटा https://bitbucket.org/acoobe/python-money

Django-पैसा akumria द्वारा सिफारिश की: http://pypi.python.org/pypi/django-money/ (havent की कोशिश की है कि एक अभी तक)।

+0

का उपयोग करें अकुम्रिया के बजाय https://github.com/reinbach/django-money की सिफारिश करें क्योंकि इसमें कुछ बगफिक्स हैं और पाइप के माध्यम से इंस्टॉल होते हैं। –

3

मेरे अनुभव में और others से, धन मुद्रा के संयोजन और सेंट में राशि के रूप में सबसे अच्छा संग्रहित किया जाता है।

इसे संभालना और इसकी गणना करना बहुत आसान है। @ Will_Hardy के जवाब पर

+0

ध्यान रखें कि यह प्रत्येक मुद्रा के लिए सच नहीं है कि 1 मामूली (उदाहरण के लिए) 0.01 प्रमुख (डॉलर) के बराबर है। – ElmoVanKielmo

+0

मुझे "सेंट" शब्द का उपयोग नहीं करना चाहिए था, लेकिन उस मुद्रा की सबसे छोटी और विभाजित इकाई नहीं थी। –

+0

फिर भी, इस तरह आपका ऐप एक ही समय में प्रमुख और नाबालिग के बीच विभिन्न अनुपात के साथ मुद्राओं का समर्थन नहीं करेगा। – ElmoVanKielmo

4

भवन, यहाँ यह तो आप max_digits निर्दिष्ट करने के लिए नहीं है और हर बार decimal_places:

from django.db import models 
from decimal import Decimal 


class CurrencyField(models.DecimalField): 
    __metaclass__ = models.SubfieldBase 

    def __init__(self, verbose_name=None, name=None, **kwargs): 
    super(CurrencyField, self). __init__(
     verbose_name=verbose_name, name=name, max_digits=10, 
     decimal_places=2, **kwargs) 

    def to_python(self, value): 
    try: 
     return super(CurrencyField, self).to_python(value).quantize(Decimal("0.01")) 
    except AttributeError: 
     return None 
+0

मेरे पास ऐसा फ़ील्ड है, लेकिन मैं 'डिफ़ॉल्ट = {...' और 'defaults.update (** kwargs) 'पैटर्न का उपयोग करता हूं । – orokusaki

13

पार्टी संस्करण है कि दक्षिण माइग्रेशन कहते हैं मेरे देर से।

from decimal import Decimal 
from django.db import models 

try: 
    from south.modelsinspector import add_introspection_rules 
except ImportError: 
    SOUTH = False 
else: 
    SOUTH = True 

class CurrencyField(models.DecimalField): 
    __metaclass__ = models.SubfieldBase 

    def __init__(self, verbose_name=None, name=None, **kwargs): 
     decimal_places = kwargs.pop('decimal_places', 2) 
     max_digits = kwargs.pop('max_digits', 10) 

     super(CurrencyField, self). __init__(
      verbose_name=verbose_name, name=name, max_digits=max_digits, 
      decimal_places=decimal_places, **kwargs) 

    def to_python(self, value): 
     try: 
      return super(CurrencyField, self).to_python(value).quantize(Decimal("0.01")) 
     except AttributeError: 
      return None 

if SOUTH: 
    add_introspection_rules([ 
     (
      [CurrencyField], 
      [], 
      { 
       "decimal_places": ["decimal_places", { "default": "2" }], 
       "max_digits": ["max_digits", { "default": "10" }], 
      }, 
     ), 
    ], ['^application\.fields\.CurrencyField']) 
+0

क्या मेरे प्रोजेक्ट के अनुसार "['^ एप्लिकेशन \ .fields \CurrencyField']" में पथ बदलना है? धन्यवाद – pymarco

संबंधित मुद्दे