在 Django REST Framework 中公开 MoneyFields?

Cer*_*rin 3 python django django-rest-framework

我有一些使用 Django 模型djmoney.models.fields.MoneyField。这存储了诸如“US$1,000.00”之类的数据。

我试图通过Django REST Framework的 API直接在 Django 的管理中使用自定义视图来公开它,例如:

from rest_framework import generics
from rest_framework import serializers

class MyModelAdmin(admin.ModelAdmin):

    def changelist_view_api(self, request, extra_context=None):

        cl = self.get_changelist_instance(request)
        base_queryset = cl.get_queryset(request)

        fieldsets = self.get_fieldsets(request)

        class ModelSerializer(serializers.ModelSerializer):

            class Meta:
                model = self.model
                fields = all_fields

        class ModelAdminListAPI(generics.ListCreateAPIView):
            queryset = base_queryset
            serializer_class = ModelSerializer

            name = '%s List API' % self.model._meta.verbose_name.title()

            def get(self, request, *args, **kwargs):
                return self.list(request, *args, **kwargs)

        view_handler = ModelAdminListAPI.as_view(queryset=base_queryset, serializer_class=ModelSerializer)
        return view_handler(request, extra_context, format=_format)
Run Code Online (Sandbox Code Playgroud)

这很有效,唯一的例外是它会因这些特殊的 MoneyField 实例而窒息。如果字段列表中包含其中之一,此视图将返回异常:

  File "~/.env/lib/python3.7/site-packages/rest_framework/mixins.py", line 43, in list
    return self.get_paginated_response(serializer.data)
  File "~/.env/lib/python3.7/site-packages/rest_framework/serializers.py", line 761, in data
    ret = super().data
  File "~/.env/lib/python3.7/site-packages/rest_framework/serializers.py", line 260, in data
    self._data = self.to_representation(self.instance)
  File "~/.env/lib/python3.7/site-packages/rest_framework/serializers.py", line 679, in to_representation
    self.child.to_representation(item) for item in iterable
  File "~/.env/lib/python3.7/site-packages/rest_framework/serializers.py", line 679, in <listcomp>
    self.child.to_representation(item) for item in iterable
  File "~/.env/lib/python3.7/site-packages/rest_framework/serializers.py", line 530, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "~/.env/lib/python3.7/site-packages/rest_framework/fields.py", line 1148, in to_representation
    value = decimal.Decimal(str(value).strip())
decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>]
Run Code Online (Sandbox Code Playgroud)

深入研究 DRF 的内部结构,它似乎将 MoneyField 视为 DecimalField,因为它是从它继承的。然而,djmoney 还创建了另一个名为 的 CharField*_currency来存储货币面额(例如“USD”)。然后,当您请求货币字段的逻辑值时,它会将小数和货币值组合成“”格式。

我认为 DRF 遇到了一个问题,它试图将此值解释为小数。

这是 DRF 中的错误还是我配置错误?如何让 DRF 正确解释 MoneyField 值?

小智 5

我遇到了同样的问题,通过添加解决'djmoney',INSTALLED_APPS。当您执行此操作时,MoneyField将为转换和所有工作注入正确的序列化器字段。哈:-)