在ChoiceField中返回display_name

时间:2015-12-30 17:30:05

标签: json django django-rest-framework choicefield django-serializer

我在<?xml version="1.0" encoding="UTF-8"?> <fontFamilies> <fontFamily name="DejaVu Sans"> <normal>net/sf/jasperreports/fonts/dejavu/DejaVuSans.ttf</normal> <bold>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Bold.ttf</bold> <italic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Oblique.ttf</italic> <boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-BoldOblique.ttf</boldItalic> <pdfEncoding>Identity-H</pdfEncoding> <pdfEmbedded>true</pdfEmbedded> <exportFonts> <export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export> <export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export> </exportFonts> <!-- <locales> <locale>en_US</locale> <locale>de_DE</locale> </locales> --> </fontFamily> <fontFamily name="DejaVu Serif"> <normal>net/sf/jasperreports/fonts/dejavu/DejaVuSerif.ttf</normal> <bold>net/sf/jasperreports/fonts/dejavu/DejaVuSerif-Bold.ttf</bold> <italic>net/sf/jasperreports/fonts/dejavu/DejaVuSerif-Italic.ttf</italic> <boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSerif-BoldItalic.ttf</boldItalic> <pdfEncoding>Identity-H</pdfEncoding> <pdfEmbedded>true</pdfEmbedded> <exportFonts> <export key="net.sf.jasperreports.html">'DejaVu Serif', 'Times New Roman', Times, serif</export> <export key="net.sf.jasperreports.xhtml">'DejaVu Serif', 'Times New Roman', Times, serif</export> </exportFonts> </fontFamily> <fontFamily name="DejaVu Sans Mono"> <normal>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono.ttf</normal> <bold>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono-Bold.ttf</bold> <italic>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono-Oblique.ttf</italic> <boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono-BoldOblique.ttf</boldItalic> <pdfEncoding>Identity-H</pdfEncoding> <pdfEmbedded>true</pdfEmbedded> <exportFonts> <export key="net.sf.jasperreports.html">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export> <export key="net.sf.jasperreports.xhtml">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export> </exportFonts> </fontFamily> <fontFamily name="Arial"> <normal>net/sf/jasperreports/fonts/arial/arial.ttf</normal> <bold>net/sf/jasperreports/fonts/arial/arialbd.ttf</bold> <italic>net/sf/jasperreports/fonts/arial/ariali.ttf</italic> <boldItalic>net/sf/jasperreports/fonts/arial/arialbi.ttf</boldItalic> <pdfEncoding>Identity-H</pdfEncoding> <pdfEmbedded>true</pdfEmbedded> <exportFonts> <export key="net.sf.jasperreports.html">Arial</export> <export key="net.sf.jasperreports.xhtml">Arial</export> </exportFonts> </fontFamily> <fontFamily name="Arial Black"> <normal>net/sf/jasperreports/fonts/arial/ariblk.ttf</normal> <pdfEncoding>Identity-H</pdfEncoding> <pdfEmbedded>true</pdfEmbedded> <exportFonts> <export key="net.sf.jasperreports.html">Arial Black</export> <export key="net.sf.jasperreports.xhtml">Arial Black</export> </exportFonts> </fontFamily> <!-- Mapping Java logical fonts, for the sake of HTML export only. --> <fontFamily name="SansSerif"> <exportFonts> <export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export> <export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export> </exportFonts> </fontFamily> <fontFamily name="Serif"> <exportFonts> <export key="net.sf.jasperreports.html">'DejaVu Serif', 'Times New Roman', Times, serif</export> <export key="net.sf.jasperreports.xhtml">'DejaVu Serif', 'Times New Roman', Times, serif</export> </exportFonts> </fontFamily> <fontFamily name="Monospaced"> <exportFonts> <export key="net.sf.jasperreports.html">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export> <export key="net.sf.jasperreports.xhtml">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export> </exportFonts> </fontFamily> </fontFamilies> ModelViewSet的DRF中实施了一些REST API。我的所有API都使用JSON格式,我的一些模型使用ChoiceField字段,如:

ModelSerializer

我的问题是默认情况下DRF总是返回(并接受)JSON消息的这些选择的密钥(参见here),但我想改用标签,因为我认为它是&#39;对于谁将使用这些API更加一致和清晰。有什么建议吗?

3 个答案:

答案 0 :(得分:3)

我找到了一个可能的解决方案,即定义我自己的字段如下:

class MyChoiceField(serializers.ChoiceField):

    def to_representation(self, data):
        if data not in self.choices.keys():
            self.fail('invalid_choice', input=data)
        else:
            return self.choices[data]

    def to_internal_value(self, data):
        for key, value in self.choices.items():
            if value == data:
                 return key
        self.fail('invalid_choice', input=data)

它的工作方式与ChoiceField相同,但返回并接受标签而不是键。

答案 1 :(得分:1)

除了覆盖序列化程序之外别无他法。请查看here,了解如何完成。

答案 2 :(得分:1)

以前的答案对我有很大帮助,但由于我使用的是Django版本3和DRF版本3.11,因此对我没有用,所以我想到了:

# models.py
class Ball(models.Model):
    
    class Types(models.TextChoice):
        VOLLYBALL = 'VB', gettext_lazy('VollyBall')
        FOOTBALL = 'FB', gettext_lazy('FootBall')

    type = models.CharField(max_length=2, choices=Types.choices)
# serializers.py

class CustomChoiceField(serializers.ChoiceField):

    def to_representation(self, value):
        if value in ('', None):
            return value

        choice_dict = {str(key): key.label for key in self.choices}
        return choice_dict.get(str(value), value)

    def to_internal_value(self, data):
        if data == '' and self.allow_blank:
            return ''

        try:
            choice_dict = {key.label: str(key) for key in self.choices}
            return choice_dict[str(data)]
        except KeyError:
            self.fail('invalid_choice', input=data)

class BallSerializer(serializers.ModelSerializer):
    type = CustomChoiceField(choices=Book.Types)
    
    class Meta:
        model = Book
        fields = ['type']