Django REST 框架:使用 URL 中的 ID 发布到 URL

Posted

技术标签:

【中文标题】Django REST 框架:使用 URL 中的 ID 发布到 URL【英文标题】:Django REST Framework: Posting to URL with ID in URL 【发布时间】:2021-01-17 03:39:15 【问题描述】:

鉴于以下人为的示例,我如何POST 到路径中具有 ID 的 URL 并让它解析模型实例,而不是将模型实例包含在 POST 主体本身中?

urls.py

path("api/schools/<int:pk>/student/", views.CreateStudentView.as_view(), name="createStudent")

models.py

class School(models.Model):
    name = models.CharField(default="", max_length=128)
    address = models.CharField(default="", max_length=128)
    mascot = models.CharField(default="", max_length=128)


class StudentModel(models.Model):
    first_name = models.CharField(default="", max_length=128)
    last_name = models.CharField(default="", max_length=128)
    notes = models.CharField(default="", max_length=512)
    school = models.ForeignKey(School, on_delete=models.CASCADE)

序列化器.py

class CreateStudentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = ("first_name", "last_name")

views.py

class CreateStudentView(generics.CreateAPIView):
    serializer_class = CreateStudentSerializer
    queryset = Student.objects.all()

我希望能够POST 只是将新学生的名字和姓氏添加到 URL 中,以便在我的数据库中创建一个新学生。但是,因为我没有在 POST 的正文中提供 School 对象,所以我收到错误消息。我希望我的代码能够解析我要将学生添加到哪个学校,因为 URL 包含 ID。

当我将POST 的以下正文发送到/api/schools/1/student/ 时出现错误。 ID 为 1 的学校确实存在于数据库中。


    "first_name": "John",
    "last_name": "Smith"

IntegrityError at /api/schools/1/student/

NOT NULL constraint failed: students_school.school_id

【问题讨论】:

【参考方案1】:

最简单的方法是覆盖 CreateStudentView 的 create 方法。 URL 参数存储在self.kwargs 中,因此您可以从那里检索它,并将其注入到您的序列化程序中:

class CreateStudentView(generics.CreateAPIView):
    serializer_class = CreateStudentSerializer
    queryset = Student.objects.all()

    def get_serializer(self, *args, **kwargs):
        serializer_class = self.get_serializer_class()
        kwargs["context"] = self.get_serializer_context()
        
        # Check if a pk was passed through the url.
        if 'pk' in self.kwargs:        
            modified_data = self.request.data.copy()
            modified_data['school'] = self.kwargs.get('pk')
            kwargs["data"] = modified_data
            return serializer_class(*args, **kwargs)

        # If not mind, move on.
        return serializer_class(*args, **kwargs)

感谢this article,您可以在其中详细了解其工作原理。

【讨论】:

我在kwards["data"] 行收到以下错误:When a serializer is passed a data` 关键字参数,您必须在尝试访问序列化的.data 表示之前调用.is_valid()。您应该先致电.is_valid(),或者改为访问.initial_data。` 我通过以下方式解决了上一个问题:serializer = serializer_class(*args, **kwargs) serializer.is_valid() return serializer。但是,现在当我 POST 时,我仍然收到我在问题中描述的原始错误。我认为这是因为 question 应该是一个模型实例,而不是模型实例的整数 ID。 嗯,我不这么认为,因为如果是这样的话,你会得到一个不同的错误,即变量的类型不正确。你能在调用 serializer.is_valid() 之后检查 serializer.validated_data 的样子吗?

以上是关于Django REST 框架:使用 URL 中的 ID 发布到 URL的主要内容,如果未能解决你的问题,请参考以下文章

Django + AngularJS:没有使用普通 URL 和视图的 Django REST 框架的类 REST 端点?

如何在 django rest 框架的分页 URL 中更改下一个键中的主机?

在 Django Rest 框架 URL 中通过唯一 ID 但不是 PK 获取详细信息

Django Rest 框架中的发布请求处理

带有 Django 2.0 的 Django REST 框架 URL

django rest框架:在视图中获取url路径变量