Serializer ForeignKey导致“预期字典......”

时间:2016-11-07 21:51:53

标签: django django-rest-framework

我的模特:

class Font(ValidateVersionOnSaveMixin, models.Model):
    id = models.UUIDField(primary_key=True, editable=True)  
    name = models.CharField(max_length=100, blank=False, null=False)


class Glyph(ValidateVersionOnSaveMixin, models.Model):
    id = models.UUIDField(primary_key=True, editable=True)  
    unit = models.CharField(max_length=100, blank=False, null=False, unique=True)
    font = models.ForeignKey(Font, on_delete=models.CASCADE)

我想发布以下JSON,将Glyph添加到已存在的Font(ID为fontId)对象。

{
  fontId: "4a14a055-3c8a-43ba-aab3-221b4244ac73"
  id: "40da7a83-a204-4319-9a04-b0a544bf4440"
  unit: "aaa"
}

由于ForeignKey字段font与JSON属性fontId之间存在不匹配,我在我的序列化程序中添加了source='font'

class FontSerializer(serializers.ModelSerializer):
    class Meta:
        model = Font
        fields = ('id', 'name')


class GlyphSerializer(serializers.ModelSerializer):
    fontId = FontSerializer(source='font')
    class Meta:
        model = Glyph
        fields = ('id', 'unit', 'fontId' )

但结果是一个不良请求错误:

{"fontId":{"non_field_errors":["Invalid data. Expected a dictionary, but got str."]}}

更新

以下Serializer向我提供了我正在寻找的结果。

class GlyphSerializer(serializers.ModelSerializer):
    fontId = serializers.PrimaryKeyRelatedField(
        queryset=Font.objects.all(),
        required=True,
        source='font',
        write_only=False
    )
    class Meta:
        model = Glyph
        fields = ('id', 'unit', 'version', 'fontId')

3 个答案:

答案 0 :(得分:1)

您已将fontId定义为序列化对象(FontSerializer)。但是,该序列化器又被定义为具有id和名称。你的json字典只发布一个id。您必须将其更改为包含id和名称的字典

{
  fontId: {id: "4a14a055-3c8a-43ba-aab3-221b4244ac73",name: "some name" },
  id: "40da7a83-a204-4319-9a04-b0a544bf4440"
  unit: "aaa"
}

答案 1 :(得分:1)

您收到此错误的原因是,在反序列化过程中,DRF会在您调用.is_valid(raise_exception=True)之前调用serializer.save(validated_data)non_field_errors列出了此过程中的所有常规验证错误。在GlyphSerializer中,FontSerializer是一个嵌套的序列化程序,它与Python字典相关联。因此,它会引发您遇到的任何非字典数据类型的错误。

您可以创建名为GlyphSerializer

GlyphCreateSerializer的子类
class FontSerializer(serializers.ModelSerializer):
    class Meta:
        model = Font
        fields = ('id', 'name')


class GlyphSerializer(serializers.ModelSerializer):
    fontId = FontSerializer(source='font')
    class Meta:
        model = Glyph
        fields = ('id', 'unit', 'fontId' )

class GlyphCreateSerializer(GlyphSerializer):
    fontId = serializers.CharField()

您可以在Viewset上使用GlyphCreateSerializer作为POST请求。

答案 2 :(得分:0)

您可以按以下方式使用 model_to_dict 方法:

void uart_menu(void){
    char line1[] = "Test Menu:\n";
    for (uint8_t i=0; i < strlen(line1); i++){
        USART_0_write(line1[i]);
    }

    char line2[] = "1: Turn on 0xA2\n";
    for (uint8_t i=0; i < strlen(line2); i++){
        USART_0_write(line2[i]);
    }

    char line3[] = "2: Turn off 0xA2\n";
    for (uint8_t i=0; i < strlen(line3); i++){
        USART_0_write(line3[i]);
    }

    char line4[] = "3: Turn on All Addresses\n";
    for (uint8_t i=0; i < strlen(line4); i++){
        USART_0_write(line4[i]);
    }

    char line5[] = "4: Turn off All Addresses\n";
    for (uint8_t i=0; i < strlen(line5); i++){
        USART_0_write(line5[i]);
    }

}