django-shop icon indicating copy to clipboard operation
django-shop copied to clipboard

field.get_internal_type() result DecimalField

Open AndyHoang opened this issue 7 years ago • 5 comments

I using generic assign values to django model which contain MoneyField But when I use get_internal_type() it do not return MoneyField I notice we have a migrations https://github.com/awesto/django-shop/pull/344/commits/6a33d48b86aa7a433b8a13e43745b8742fee66ae where we remove that overridden method. I'm not sure is that a mistake or a feature. So how can we determine a field is a MoneyField in our model. Right now i'm using field.__class__.__name__ == 'MoneyField'

AndyHoang avatar Nov 23 '16 10:11 AndyHoang

In the database, amounts are always stored as Decimal types. Reason for this is, that 99% of all shops keep their product prices in one canonical currency and for the remaining 1% is does not make sense to keep the currency side by side with the amount. Therefore if a shop is to return the product price in different currencies, one shall use the get_price() method.

That said, model Cart and Order keep their sub- and totals in the customers preferred currency. However, even then we keep the _total as Decimal, whereas property total returns an amount of type Money in the currency, for which we have another field.

jrief avatar Nov 23 '16 10:11 jrief

For the record, I made bad experiences with systems that store prices without currencies. IMHO, the correct way is to always store the currency along with the decimal value. For example:

amount (Decimal) currency (String)
10.0 EUR

I am ok with django-shop doing it differently as long as I have a good way to override it and hook in my own behaviour, but I would really prefer to store the currency along with the price.

rfleschenberg avatar Nov 23 '16 13:11 rfleschenberg

In that case I would create my own MoneyField, which on the DB-layer is composed of two fields: the amount and the currency. But as said, in 99% of all shops, that additional database column will always contain only one currency.

jrief avatar Nov 23 '16 14:11 jrief

@jrief I agree.

@AndyHoang please provide a reproducible use-case (code / traceback).

rfleschenberg avatar Dec 01 '16 02:12 rfleschenberg

I have function to get all none reference field ob a model

def get_none_reference_field(cls_model):
    return [f for f in cls_model._meta.get_fields() if (not(f.many_to_one or f.related_model))]

a function to assign value by field.name

    def assign_value_by_type(self, field, value):
        try:
            if field.get_internal_type() == 'DateTimeField':
                value = self.parse_time(value)
            elif field.get_internal_type() == 'IntegerField':
                value = int(value)
            elif field.get_internal_type() == 'DecimalField':
                if field.__class__.__name__ == 'MoneyField':
                    splits = value.split()
                    value = Money(splits[0], splits[1])
            elif field.get_internal_type() == 'FloatField':
                if field.__class__.__name__ == 'MeasurementField':
                    cls = field.measurement
                    splits = value.split()
                    value = cls(**{splits[1]: splits[0]})
            elif field.get_internal_type() == 'ArrayField':
                if isinstance(value, str):
                    to_remove = "\"\'"
                    for char in to_remove:
                        value = value.replace(char, "")
                    value = map(lambda v: v.strip(), value.split(','))
            setattr(self, field.name, value)

and have dict with key value that have the same key with model (not using serializer) So that my use case. So basically I would like to check that field like MeasurementField, DateTimeField... (right now it my work around) Am I provide enough info? I'm also new to python, if you have any suggestion, i'm really appreciated

AndyHoang avatar Dec 01 '16 02:12 AndyHoang