无法使用外键保存Django模型

时间:2019-06-12 16:12:48

标签: python django python-3.x post

我正在尝试从前端发送POST请求以添加新的“成就”记录。成绩记录有一个外键字段,它引用一个集合,其中包含许多成就。但是,当我尝试保存时,出现错误:“ {” set“:[”错误的类型。预期的资源标识符对象,已接收Set。“]}”我不知道什么是“资源标识符类型”,并且无法通过在线搜索找到任何文档。这是我的POST请求数据:{“成就”:{“标题”:“ Rails是Omakase”,“描述”:“ Lorem ipsum”,“体验”:100,“设置”:“ 52”}}

在保存之前,我尝试将“ set”设置为集合的ID和“ Set”序列化程序实例。

Serializers.py

class SetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Set
        fields = ('id', 'title', 'description')

class AchievementSerializer(serializers.ModelSerializer):
    class Meta:
        model = Achievement
        fields = ('id', 'title', 'description', 'experience', 'set')

models.py

class Set(models.Model):
    title = models.CharField(max_length=100, blank=False)
    description = models.TextField()

    class JSONAPIMeta:
        resource_name = "sets"

class Achievement(models.Model):
    title = models.CharField(max_length=100, blank=False)
    description = models.TextField()
    experience = models.IntegerField()
    set = models.ForeignKey(Set, on_delete=models.CASCADE, related_name="achievements")

views.py

class AchievementList(APIView):
    def post(self, request):
        data = request.data["achievement"]
        setId = data["set"]
        set = Set.objects.get(pk=setId)
        data["set"] = set
        serializer = AchievementSerializer(data=data)

        if serializer.is_valid():
            serializer.save()
            return JsonResponse({"achievement":serializer.data}, safe=False)
        return JsonResponse(serializer.errors, status=400)

2 个答案:

答案 0 :(得分:1)

如果您仅将post保留为此:

def post(self, request):
    data = request.data["achievement"]

    serializer = AchievementSerializer(data=data)

    if serializer.is_valid():
        serializer.save()
        return JsonResponse({"achievement":serializer.data}, safe=False)
    return JsonResponse(serializer.errors, status=400)

然后我运行它没有问题。通常,期望对象具有主键。我使用了以下测试:

class TestAchievementList(TestCase):
    def test_add_achievement(self):
        title = 'title'
        description = 'desc'
        experience = 1
        set_object = Set.objects.create(title='new set')

        json = {
            'achievement': {
                'title': title,
                'description': description,
                'experience': experience,
                'set': set_object.id
            }
        }

        url = reverse('achievements')

        response = self.client.post(url, data=json, content_type='application/json')

        self.assertEqual(response.status_code, 200)
        self.assertIn('achievement', response.json())

        achievement_json = response.json()['achievement']

        self.assertEqual(achievement_json['title'], title)
        self.assertEqual(achievement_json['description'], description)
        self.assertEqual(achievement_json['experience'], experience)
        self.assertEqual(achievement_json['set'], set_object.id)

答案 1 :(得分:0)

我通过阅读一些JSON文档找到了解决方案:https://jsonapi.org/format/#document-resource-identifier-objects。该错误表明它希望为“ set”键传递一个资源标识符对象。资源标识符对象只是包含类型和id成员的对象。因此,我确保set具有type和id元素,并且可以解决问题。因此,我的新发布请求看起来像这样:{“成就”:{“标题”:“ Rails是Omakase”,“描述”:“ Lorem ipsum”,“体验”:100,“设置”:{“类型”: “ sets”,“ id”:“ 4”}}}