Django Rest框架模型对象返回带有选项的字段的存储值

2024-10-06 12:39:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个带有Django Rest框架的项目,我有一个复杂的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'。你知道吗

我不知道我错过了什么。你知道吗


Tags: name模型idtrueverbosemodelscodehotel
1条回答
网友
1楼 · 发布于 2024-10-06 12:39:46

这是正确的行为,但很容易修复。你知道吗

一个解决办法就是

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

相关问题 更多 >