Esempio n. 1
0
def _expand_money_args(model, args):
    """
    Augments args so that they contain _currency lookups - ie.. Q() | Q()
    """
    for arg in args:
        if isinstance(arg, Q):
            for i, child in enumerate(arg.children):
                if isinstance(child, Q):
                    _expand_money_args(model, [child])
                elif isinstance(child, (list, tuple)):
                    name, value = child
                    if isinstance(value, Money):
                        clean_name = _get_clean_name(name)
                        arg.children[i] = Q(*[
                            child,
                            (get_currency_field_name(clean_name),
                             smart_unicode(value.currency))
                        ])
                    if isinstance(value, BaseExpression):
                        field = _get_field(model, name)
                        if isinstance(field, MoneyField):
                            clean_name = _get_clean_name(name)
                            arg.children[i] = Q(*[
                                child,
                                ('_'.join([clean_name, 'currency']),
                                 F(get_currency_field_name(value.name)))
                            ])
    return args
Esempio n. 2
0
def _expand_money_args(model, args):
    """
    Augments args so that they contain _currency lookups - ie.. Q() | Q()
    """
    for arg in args:
        if isinstance(arg, Q):
            for i, child in enumerate(arg.children):
                if isinstance(child, Q):
                    _expand_money_args(model, [child])
                elif isinstance(child, (list, tuple)):
                    name, value = child
                    if isinstance(value, Money):
                        clean_name = _get_clean_name(name)
                        arg.children[i] = Q(*[
                            child,
                            (get_currency_field_name(clean_name), smart_unicode(value.currency))
                        ])
                    if isinstance(value, BaseExpression):
                        field = _get_field(model, name)
                        if isinstance(field, MoneyField):
                            clean_name = _get_clean_name(name)
                            arg.children[i] = Q(*[
                                child, 
                                ('_'.join([clean_name, 'currency']), F(get_currency_field_name(value.name)))
                            ])
    return args
Esempio n. 3
0
    def get_value(self, data):
        """
        Test that the returned amount is a valid Decimal
        """

        amount = super(DecimalField, self).get_value(data)

        # Convert an empty string to None
        if len(str(amount).strip()) == 0:
            amount = None

        try:
            if amount is not None and amount is not empty:
                amount = Decimal(amount)
        except:
            raise ValidationError({
                self.field_name: [_("Must be a valid number")],
            })

        currency = data.get(get_currency_field_name(self.field_name),
                            self.default_currency)

        if currency and amount is not None and not isinstance(
                amount, MONEY_CLASSES) and amount is not empty:
            return Money(amount, currency)

        return amount
Esempio n. 4
0
def _expand_money_params(kwargs):
    def get_clean_name(name):
        # Get rid of __lt, __gt etc for the currency lookup
        path = name.split(LOOKUP_SEP)
        if path[-1] in QUERY_TERMS:
            return LOOKUP_SEP.join(path[:-1])
        else:
            return name

    from moneyed import Money
    try:
        from django.db.models.constants import LOOKUP_SEP
    except ImportError:
        # Django < 1.5
        LOOKUP_SEP = '__'
    from django.db.models.sql.constants import QUERY_TERMS

    to_append = {}
    for name, value in kwargs.items():
        if isinstance(value, Money):
            clean_name = get_clean_name(name)
            to_append[name] = value.amount
            to_append[get_currency_field_name(clean_name)] = smart_unicode(
                value.currency)
        if isinstance(value, BaseExpression):
            clean_name = get_clean_name(name)
            to_append['_'.join([clean_name, 'currency'
                                ])] = F('_'.join([value.name, 'currency']))

    kwargs.update(to_append)
    return kwargs
Esempio n. 5
0
    def contribute_to_class(self, cls, name):

        cls._meta.has_money_field = True

        # Don't run on abstract classes
        # Removed, see https://github.com/jakewins/django-money/issues/42
        # if cls._meta.abstract:
        #    return

        if not self.frozen_by_south:
            c_field_name = get_currency_field_name(name)
            # Do not change default=self.default_currency.code, needed
            # for south compat.
            c_field = CurrencyField(
                max_length=3,
                price_field=self,
                default=self.default_currency,
                editable=False,
                choices=self.currency_choices,
            )
            c_field.creation_counter = self.creation_counter
            cls.add_to_class(c_field_name, c_field)

        super(MoneyField, self).contribute_to_class(cls, name)

        setattr(cls, self.name, MoneyFieldProxy(self))
Esempio n. 6
0
def Deserializer(stream_or_string, **options):
    """
    Deserialize a stream or string of JSON data.
    """
    if not isinstance(stream_or_string, (bytes, six.string_types)):
        stream_or_string = stream_or_string.read()
    if isinstance(stream_or_string, bytes):
        stream_or_string = stream_or_string.decode('utf-8')
    try:
        for obj in json.loads(stream_or_string):
            money_fields = {}
            fields = {}
            Model = _get_model(obj["model"])
            for (field_name, field_value) in six.iteritems(obj['fields']):
                field = Model._meta.get_field(field_name)
                if isinstance(field, MoneyField) and field_value is not None:
                    money_fields[field_name] = Money(field_value, obj['fields'][get_currency_field_name(field_name)])
                else:
                    fields[field_name] = field_value
            obj['fields'] = fields

            for obj in PythonDeserializer([obj], **options):
                for field, value in money_fields.items():
                    setattr(obj.object, field, value)
                yield obj
    except GeneratorExit:
        raise
Esempio n. 7
0
 def value_from_datadict(self, data, files, name):
     if name not in data:
         return None
     amount, currency = data.get(name), data.get(get_currency_field_name(name))
     if isinstance(amount, Money):
         return amount
     return Money(amount=amount, currency=currency)
Esempio n. 8
0
def Deserializer(stream_or_string, **options):
    """
    Deserialize a stream or string of JSON data.
    """
    if not isinstance(stream_or_string, (bytes, six.string_types)):
        stream_or_string = stream_or_string.read()
    if isinstance(stream_or_string, bytes):
        stream_or_string = stream_or_string.decode('utf-8')
    try:
        for obj in json.loads(stream_or_string):
            money_fields = {}
            fields = {}
            Model = _get_model(obj["model"])
            for (field_name, field_value) in six.iteritems(obj['fields']):
                field = Model._meta.get_field(field_name)
                if isinstance(field, MoneyField) and field_value is not None:
                    money_fields[field_name] = Money(
                        field_value,
                        obj['fields'][get_currency_field_name(field_name)])
                else:
                    fields[field_name] = field_value
            obj['fields'] = fields

            for obj in PythonDeserializer([obj], **options):
                for field, value in money_fields.items():
                    setattr(obj.object, field, value)
                yield obj
    except GeneratorExit:
        raise
Esempio n. 9
0
def _expand_money_params(kwargs):
    def get_clean_name(name):
        # Get rid of __lt, __gt etc for the currency lookup
        path = name.split(LOOKUP_SEP)
        if path[-1] in QUERY_TERMS:
            return LOOKUP_SEP.join(path[:-1])
        else:
            return name

    from moneyed import Money
    try:
        from django.db.models.constants import LOOKUP_SEP
    except ImportError:
        # Django < 1.5
        LOOKUP_SEP = '__'
    from django.db.models.sql.constants import QUERY_TERMS

    to_append = {}
    for name, value in kwargs.items():
        if isinstance(value, Money):
            clean_name = get_clean_name(name)
            to_append[name] = value.amount
            to_append[get_currency_field_name(clean_name)] = smart_unicode(
                value.currency)
        if isinstance(value, ExpressionNode):
            clean_name = get_clean_name(name)
            to_append['_'.join([clean_name, 'currency'])] = F('_'.join([value.name, 'currency']))

    kwargs.update(to_append)
    return kwargs
Esempio n. 10
0
 def value_from_datadict(self, data, files, name):
     if name not in data:
         return None
     amount, currency = data.get(name), data.get(
         get_currency_field_name(name))
     if isinstance(amount, Money):
         return amount
     return Money(amount=amount, currency=currency)
Esempio n. 11
0
 def get_value(self, data):
     amount = super().get_value(data)
     currency = data.get(get_currency_field_name(self.field_name),
                         self.default_currency)
     if currency and amount is not None and not isinstance(
             amount, MONEY_CLASSES) and amount is not empty:
         return Money(amount, currency)
     return amount
Esempio n. 12
0
def _expand_money_kwargs(model, kwargs):
    """
    Augments kwargs so that they contain _currency lookups.
    """
    to_append = {}
    for name, value in kwargs.items():
        if isinstance(value, Money):
            clean_name = _get_clean_name(name)
            to_append[name] = value.amount
            to_append[get_currency_field_name(clean_name)] = smart_unicode(
                value.currency)
        if isinstance(value, BaseExpression):
            field = _get_field(model, name)
            if isinstance(field, MoneyField):
                clean_name = _get_clean_name(name)
                to_append['_'.join([clean_name, 'currency'])] = F(get_currency_field_name(value.name))

    kwargs.update(to_append)
    return kwargs
Esempio n. 13
0
    def get_value(self, data):
        amount = super(MoneyField, self).get_value(data)
        currency = data.get(get_currency_field_name(self.field_name), None)

        # prevent circular dependency
        from rest_framework.fields import empty

        if currency and amount is not None:
            if amount == '' or type(amount) == empty:
                return None
            return Money(amount, currency)
        return amount
Esempio n. 14
0
    def render(self, name, value, attrs=None):
        amount, currency = '', ''
        if isinstance(value, Money):
            amount = value.amount
            currency = value.currency.code
        if isinstance(value, tuple):
            amount, currency = value[:2]
        if isinstance(value, (int, Decimal)):
            amount = value
            currency = self.default_currency

        result = super(InputMoneyWidget, self).render(name, amount, attrs)
        name = get_currency_field_name(name)
        attrs['id'] = 'id_' + name
        result += self.currency_widget.render(name, currency, attrs)

        return result
Esempio n. 15
0
    def render(self, name, value, attrs=None):
        amount, currency = '', ''
        if isinstance(value, Money):
            amount = value.amount
            currency = value.currency.code
        if isinstance(value, tuple):
            amount, currency = value[:2]
        if isinstance(value, (int, Decimal)):
            amount = value
            currency = self.default_currency

        result = super(InputMoneyWidget, self).render(name, amount, attrs)
        name = get_currency_field_name(name)
        attrs['id'] = 'id_' + name
        result += self.currency_widget.render(name, currency, attrs)

        return result
Esempio n. 16
0
def Deserializer(stream_or_string, **options):
    """
    Deserialize a stream or string of JSON data.
    """
    ignore = options.pop('ignorenonexistent', False)

    if not isinstance(stream_or_string, (bytes, six.string_types)):
        stream_or_string = stream_or_string.read()
    if isinstance(stream_or_string, bytes):
        stream_or_string = stream_or_string.decode('utf-8')
    try:
        for obj in json.loads(stream_or_string):
            money_fields = {}
            fields = {}
            try:
                Model = _get_model(obj["model"])
            except DeserializationError:
                if ignore:
                    continue
                else:
                    raise
            try:
                field_names = set(f.name for f in Model._meta.get_fields())
            except AttributeError:
                field_names = set(f.name for f in Model._meta.fields)
            for (field_name, field_value) in six.iteritems(obj['fields']):
                if ignore and field_name not in field_names:
                    # skip fields no longer on model
                    continue
                field = Model._meta.get_field(field_name)
                if isinstance(field, MoneyField) and field_value is not None:
                    money_fields[field_name] = Money(
                        field_value,
                        obj['fields'][get_currency_field_name(field_name)])
                else:
                    fields[field_name] = field_value
            obj['fields'] = fields

            for obj in PythonDeserializer([obj], **options):
                for field, value in money_fields.items():
                    setattr(obj.object, field, value)
                yield obj
    except GeneratorExit:
        raise
Esempio n. 17
0
def Deserializer(stream_or_string, **options):
    """
    Deserialize a stream or string of JSON data.
    """
    ignore = options.pop('ignorenonexistent', False)
    
    if not isinstance(stream_or_string, (bytes, six.string_types)):
        stream_or_string = stream_or_string.read()
    if isinstance(stream_or_string, bytes):
        stream_or_string = stream_or_string.decode('utf-8')
    try:
        for obj in json.loads(stream_or_string):
            money_fields = {}
            fields = {}
            try:
                Model = _get_model(obj['model'])
            except DeserializationError:
                if ignore:
                    continue
                else:
                    raise
            try:
                field_names = set(f.name for f in Model._meta.get_fields())
            except AttributeError:
                field_names = set(f.name for f in Model._meta.fields)
            for (field_name, field_value) in six.iteritems(obj['fields']):
                if ignore and field_name not in field_names:
                    # skip fields no longer on model
                    continue
                field = Model._meta.get_field(field_name)
                if isinstance(field, MoneyField) and field_value is not None:
                    money_fields[field_name] = Money(field_value, obj['fields'][get_currency_field_name(field_name)])
                else:
                    fields[field_name] = field_value
            obj['fields'] = fields

            for inner_obj in PythonDeserializer([obj], **options):
                for field, value in money_fields.items():
                    setattr(inner_obj.object, field, value)
                yield inner_obj
    except GeneratorExit:
        raise
Esempio n. 18
0
    def contribute_to_class(self, cls, name):

        # Don't run on abstract classes
        if cls._meta.abstract:
            return

        if not self.frozen_by_south:
            c_field_name = get_currency_field_name(name)
            # Do not change default=self.default_currency.code, needed
            # for south compat.
            c_field = CurrencyField(
                max_length=3, price_field=self,
                default=self.default_currency, editable=False,
                choices=self.currency_choices
            )
            c_field.creation_counter = self.creation_counter
            cls.add_to_class(c_field_name, c_field)

        super(MoneyField, self).contribute_to_class(cls, name)

        setattr(cls, self.name, MoneyFieldProxy(self))
Esempio n. 19
0
    def contribute_to_class(self, cls, name):

        cls._meta.has_money_field = True

        # Don't run on abstract classes
        # Removed, see https://github.com/jakewins/django-money/issues/42
        # if cls._meta.abstract:
        #    return

        if not self.frozen_by_south:
            c_field_name = get_currency_field_name(name)
            # Do not change default=self.default_currency.code, needed
            # for south compat.
            c_field = CurrencyField(max_length=3,
                                    price_field=self,
                                    default=self.default_currency,
                                    editable=False,
                                    choices=self.currency_choices)
            c_field.creation_counter = self.creation_counter
            cls.add_to_class(c_field_name, c_field)

        super(MoneyField, self).contribute_to_class(cls, name)

        setattr(cls, self.name, MoneyFieldProxy(self))
Esempio n. 20
0
 def __init__(self, field):
     self.field = field
     self.currency_field_name = get_currency_field_name(self.field.name)
Esempio n. 21
0
 def _check_currency(obj, field, amt):
     currency_field_name = get_currency_field_name(field.name)
     if obj.__dict__[currency_field_name] != str(amt.currency):
         raise ValueError(
             'You cannot use F() with different currencies.')
Esempio n. 22
0
def Deserializer(stream_or_string, **options):  # noqa
    """
    Deserialize a stream or string of JSON data.
    """
    # Copied almost without changes from djmoney.serializers (django-money).
    # Adding support for situation where old models to be deserialized have
    # price field, but not price_currency field.
    # In Ralph, price field existed before in various models as
    # a Decimal field. All price fields were migrated to MoneyField
    # without changing the original field name. This can cause problems
    # in original django-money's implementation of Deserializer.
    # This updated Deserializer is needed to get reversion (django-reversion)
    # to work in circumstances described above.

    from django.core.serializers.python import \
        Deserializer as PythonDeserializer, _get_model

    ignore = options.pop("ignorenonexistent", False)

    if not isinstance(stream_or_string, (bytes, six.string_types)):
        stream_or_string = stream_or_string.read()
    if isinstance(stream_or_string, bytes):
        stream_or_string = stream_or_string.decode("utf-8")
    try:
        for obj in json.loads(stream_or_string):
            try:
                Model = _get_model(obj["model"])
            except DeserializationError:
                if ignore:
                    continue
                else:
                    raise
            money_fields = {}
            fields = {}
            field_names = {field.name for field in Model._meta.get_fields()}
            for (field_name, field_value) in six.iteritems(obj["fields"]):
                if ignore and field_name not in field_names:
                    # skip fields no longer on model
                    continue
                field = Model._meta.get_field(field_name)
                if isinstance(field, MoneyField) and field_value is not None:
                    try:
                        currency = \
                            obj["fields"][get_currency_field_name(field_name)]
                    except KeyError:
                        currency = DEFAULT_CURRENCY_CODE
                    money_fields[field_name] = Money(field_value, currency)
                else:
                    fields[field_name] = field_value
            obj["fields"] = fields

            for inner_obj in PythonDeserializer([obj], **options):
                for field, value in money_fields.items():
                    setattr(inner_obj.object, field, value)
                yield inner_obj
    except (GeneratorExit, DeserializationError):
        raise
    except Exception as exc:
        six.reraise(
            DeserializationError, DeserializationError(exc), sys.exc_info()[2]
        )
Esempio n. 23
0
 def __init__(self, field):
     self.field = field
     self.currency_field_name = get_currency_field_name(self.field.name)
Esempio n. 24
0
 def get_value(self, data):
     amount = super(MoneyField, self).get_value(data)
     currency = data.get(get_currency_field_name(self.field_name), None)
     if currency:
         return Money(amount, currency)
     return amount
Esempio n. 25
0
 def _check_currency(obj, field, amt):
     currency_field_name = get_currency_field_name(field.name)
     if obj.__dict__[currency_field_name] != str(amt.currency):
         raise ValueError(
             'You cannot use F() with different currencies.')
Esempio n. 26
0
 def field_from_native(self, data, files, field_name, into):
     super(MoneyField, self).field_from_native(data, files, field_name,
                                               into)
     currency = data.get(get_currency_field_name(field_name), None)
     if currency:
         into[field_name] = Money(into[field_name], currency)
Esempio n. 27
0
 def get_value(self, data):
     amount = super(MoneyField, self).get_value(data)
     currency = data.get(get_currency_field_name(self.field_name), None)
     if currency:
         return Money(amount, currency)
     return amount
Esempio n. 28
0
 def get_value(self, data):
     amount = super(MoneyField, self).get_value(data)
     currency = data.get(get_currency_field_name(self.field_name), self.default_currency)
     if currency and amount is not None and not isinstance(amount, MONEY_CLASSES) and amount is not empty:
         return Money(amount, currency)
     return amount