Django投掷“不正确的类型。 API调用上的预期URL字符串

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django投掷“不正确的类型。 API调用上的预期URL字符串相关的知识,希望对你有一定的参考价值。

我无法弄清楚为什么Django REST框架抱怨它期待一个字符串,它应该期待一个int!我得到的错误是:

"_body":"\"who_saw\":[\"Incorrect type. Expected URL string, received int.\"],\"item_seen\":[\"Incorrect type. Expected URL string, received int.\"]","status":400,"statusText":"Ok","headers":"Content-Type":["application/json;q=0.8"],"type":2,"url":"http://127.0.0.1:8000/api/seen/"

我使用以下Angular 2 http代码从应用程序向Django REST Framework服务器发出POST请求:

    let body = JSON.stringify( item_seen: 1, who_saw: 2, liked: 0 );

    let headers = new Headers();
    headers.append('Content-Type', 'application/json');

    this.http.post('http://127.0.0.1:8000/api/seen/',
        body, 
          headers: headers
        )
        .map(res => res.json())
        .subscribe(
            data => 
              alert('DATA: '+JSON.stringify(data));
            ,
            err => 
              alert('ERROR: '+JSON.stringify(err));
            ,
            () => 
              alert('Complete');
            
        );

我的模型是:

class Seen(models.Model):
    item_seen           = models.ForeignKey(Item, on_delete=models.CASCADE)     # id of the item that has been seen
    who_saw             = models.ForeignKey(User, on_delete=models.CASCADE)     # id of user who viewed it
    date_seen           = models.DateTimeField(auto_now_add=True)               # When item was viewed
    liked               = models.BooleanField(help_text='If the item was liked this is set to true')

我的观点是:

class SeenViewSet(viewsets.ModelViewSet):
    queryset = Seen.objects.all().order_by('-date_seen')
    serializer_class = SeenSerializer

    def perform_create(self, serializer):
        the_user = User.objects.get(pk=self.request.data['who_saw'])
        serializer.save(who_saw=the_user)

        the_item = Item.objects.get(pk=self.request.data['item_seen'])
        serializer.save(item_seen=the_item)

我的序列化器是:

class SeenSerializer(serializers.HyperlinkedModelSerializer):
    username = serializers.SerializerMethodField()

    def get_username(self, obj):
        value = str(obj.who_saw)
        return value

    def get_keywords(self, obj):
        value = str(obj.keywords)
        return value

    class Meta:
        model = Seen
        fields = ('who_saw', 'item_seen', 'liked', 'date_seen', 'username')
答案

问题是您正在使用serializers.HyperlinkedModelSerializer,您应该使用serializers.ModelSerializer或发送您作为int发送的ID的链接。

另一答案

除了wm3ndez的答案之外,另一个解决方案是在序列化程序中将此字段定义为与用户模型上的“id”字段相关的SlugRelatedField:

class SeenSerializer(serializers.HyperlinkedModelSerializer):
    username = serializers.SerializerMethodField()

    who_saw = serializers.SlugRelatedField(
         queryset= User.objects.all(),
         slug_field='id'
     )

    def get_username(self, obj):
        value = str(obj.who_saw)
        return value

    def get_keywords(self, obj):
        value = str(obj.keywords)
        return value

    class Meta:
        model = Seen
        fields = ('who_saw', 'item_seen', 'liked', 'date_seen', 'username')

此字段将覆盖HyperlinkedModelSerializer的默认行为,您将能够传递用户ID(作为int),而不是向用户发送链接。

以上是关于Django投掷“不正确的类型。 API调用上的预期URL字符串的主要内容,如果未能解决你的问题,请参考以下文章

Android - ListView 投掷手势触发上下文菜单

模拟投掷硬币100次

hihocoder [Offer收割]编程练习赛14 投掷硬币

如何向滑动 SpriteKit 的方向投掷精灵

CollapsingToolbarLayout 无法识别滚动投掷

如何向 CustomPainter 添加投掷动画?