Django Rest Framework模型对象返回带有选择的字段的存储值

时间:2018-06-27 22:16:44

标签: python django django-rest-framework

我有一个使用Django Rest Framework的项目,并且有一个复杂的ViewSet,它使用多个模型和序列化程序来组合大型复杂的json。一切正常,但我注意到HotelSerializer(即ModelSerializer)正在返回字段category的存储值,而不是其模型choices的可读值

这是模型:

class Hotel(models.Model):
    ONE_STAR = '*'
    TWO_STARS = '**'
    THREE_STARS = '***'
    FOUR_STARS = '****'
    FIVE_STARS = '*****'
    GRAND_TOURISM = 'GRAND_TOURISM'
    NA = 'NA'
    SPECIAL = 'SPECIAL'
    ECO = 'ECO'
    BOUTIQUE = 'BOUTIQUE'

    HOTEL_CATEGORY_CHOICES = (
        (ONE_STAR, _('*')),
        (TWO_STARS, _('**')),
        (THREE_STARS, _('***')),
        (FOUR_STARS, _('****')),
        (FIVE_STARS, _('*****')),
        (GRAND_TOURISM, _('Grand Tourism')),
        (NA, _('NA')),
        (SPECIAL, _('Special')),
        (ECO, _('Eco-Hotel')),
        (BOUTIQUE, _('Boutique-Hotel'))
    )

    company = models.OneToOneField(Company, on_delete=models.CASCADE, primary_key=True, verbose_name=_('Company'))
    code = models.CharField(max_length=10, verbose_name=_('Code'))
    zone = models.ForeignKey(Zone, on_delete=models.PROTECT, related_name='hotels', verbose_name=_('Zone'))
    category = models.CharField(max_length=20, choices=HOTEL_CATEGORY_CHOICES, verbose_name=_('Category'))
    capacity = models.IntegerField(verbose_name=_('Capacity'))
    position = models.DecimalField(max_digits=11, decimal_places=2, default=0.00, verbose_name=_('Position'))
    in_pickup = models.BooleanField(default=False, verbose_name=_('In pickup?'))
    is_active = models.BooleanField(default=True, verbose_name=_('Is active?'))
    latitude = models.FloatField(null=True, blank=True, verbose_name=_('Latitude'))
    longitude = models.FloatField(null=True, blank=True, verbose_name=_('Longitude'))

这是序列化器:

class HotelSerializer(serializers.ModelSerializer):
    category = serializers.ChoiceField(choices=models.Hotel.HOTEL_CATEGORY_CHOICES)
    class Meta:
        model = models.Hotel
        fields = ('company', 'code', 'zone', 'category', 'capacity', 'position', 'in_pickup', 'is_active', 'latitude', 'longitude')
        depth = 4

    def __init__(self, *args, **kwargs):
        exclude = kwargs.pop('exclude', None)

        super(HotelSerializer, self).__init__(*args, **kwargs)

        if exclude is not None:
            for field_name in exclude:
                self.fields.pop(field_name)

这是ViewSet函数,可在其中获取Hotel模型信息:

def get_hotel(self, company_id):
    hotel = Hotel.objects.get(company=company_id)

    import ReservationsManagerApp.serializers
    return ReservationsManagerApp.serializers.HotelSerializer(hotel, exclude=('company',)).data

这是我得到的结果:

"hotel": {
        "code": "xxxx...",
        "zone": {
            "id": 1,
            "name": "Zona hotelera",
            "city": {
                "id": 5,
                "name": "Cancun",
                "code": "998",
                "state": {
                    "id": 2,
                    "name": "Quintana Roo",
                    "code": "98",
                    "country": {
                        "id": 1,
                        "name": "Mexico",
                        "code": "MX",
                        "calling_code": "52"
                    }
                }
            }
        },
        "category": "GRAND_TOURISM",
        "capacity": 300,
        "position": "1.00",
        "in_pickup": true,
        "is_active": true,
        "latitude": null,
        "longitude": null
    },

您会看到Category字段返回值'GRAND_TOURISM',而不是其choices的可读版本:'Grand Tourism'。它甚至会错过翻译,因此它必须返回'Gran Turismo'

我不知道自己在想什么。

1 个答案:

答案 0 :(得分:0)

这是正确的行为AFAIK,但易于修复。

一种解决方案是只做

class HotelSerializer(serializers.ModelSerializer):
  category = serializers.ChoiceField(choices=Hotel.HOTEL_CATEGORY_CHOICES)
  company = CompanySerializer()
  ...