Given the following contrived example, how can I POST
to a URL with an ID in path and have it resolve the model instance instead of including the model instance in the POST
body itself?
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)
serializers.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()
I want to be able to POST
just the new student's first name and last name to the URL to create a new student in my database. However, because I don't provide a School
object in the body of my POST
I get an error. I was hoping it would be possible for my code to resolve which school I want to add the student to because the URL contains the ID.
I get an error when I POST
the following body to /api/schools/1/student/
. The school with an ID of 1 does exist in the database.
{
"first_name": "John",
"last_name": "Smith"
}
IntegrityError at /api/schools/1/student/
NOT NULL constraint failed: students_school.school_id
The easiest way to do this is by overriding the create method of your
CreateStudentView
. URL parameters are stored inself.kwargs
, so you can retrieve it from there, and inject it into your serializer:Credits to this article, where you can read more about why this works.