给出以下人为设计的示例,我如何POST
到路径中带有 ID 的 URL 并让它解析模型实例,而不是在 POST
中包含模型实例> body 本身?
网址.py
path("api/schools/<int:pk>/student/", views.CreateStudentView.as_view(), name="createStudent")
模型.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")
View .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
最佳答案
最简单的方法是覆盖 CreateStudentView
的创建方法。 URL 参数存储在 self.kwargs
中,因此您可以从那里检索它,并将其注入(inject)序列化程序:
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 ,您可以在其中详细了解其工作原理。
关于Django REST 框架 : Posting to URL with ID in URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64154970/