0

I'm stumled upon a case I don't understand.

I have two related models:

class Course(models.Model):
  code = models.CharField(max_length=10, default='')
  semester = models.CharField(max_length=10, default='')

  class Meta:
        unique_together = [['code', 'semester']]

and:

class StudentWork(models.Model):
  code = models.CharField(max_length=10, default='')
  course = models.ForeignKey(Course,on_delete=models.CASCADE, related_name='student_works')
  deadline = models.DateTimeField(blank=True)

In the StudentWorkSerializer I'd like to expand a course field into [code, semester]:

class CourseNaturalSerializer(serializers.ModelSerializer):
    class Meta:
        model = Course
        fields = ['code', 'semester']

class StudentWorkWithCourseSerializer(serializers.ModelSerializer):
    course = CourseNaturalSerializer(read_only=True)
    
    class Meta:
       model = StudentWork
       fields = ['code', 'course', 'deadline']

This works nicely for GET, e.g. I receive this:

{'code': 'HW1', 'course': {'code': 'T101', 'semester': 'S20'}, 'deadline': '2020-09-04T23:59:00+03:00'}

but this does not work for POST:

POST /studentworks json=dict(code='HW2', course={"code": "T101", "semester": "S20"}, deadline="2020-09-04T23:59")

says in the stacktrace:

django.db.utils.IntegrityError: NOT NULL constraint failed: botdb_studentwork.course_id

So this looks to me that {"code": "T101", "semester": "S20"} does not de-serialize into Course object and it's id is not passed to StudentWork's create?

What should I do?

Thanks in advance!

UPDATE: I was asked if read_only=True on the related field serializer is intentional?

If I don't set it, I get:

'{"course":{"non_field_errors":["The fields code, semester must make a unique set."]}}'

which makes me thinking that it wants to create a new Course for me (Since code and semester are declared unique_together) at the time I want to create a StudentWork. Which I don't want.

If I than change, say, semester to S21 in the POST data, I get:

AssertionError: The `.create()` method does not support writable nested fields by default.
Write an explicit `.create()` method for serializer `botdb.serializers.StudentWorkWithCourseSerializer`, or set `read_only=True` on nested serializer fields.

So hence my confusion - I can't figure out how to prevent it from attempting to create a new Course, and just use an existing in a related field.

Artem Trunov
  • 1,340
  • 9
  • 16
  • read_only=True, is this intentional? – intelis Aug 30 '20 at 21:44
  • Because the DRF didn't consider the `course` data in the payload since you have set **`read_only=True`** in the `course` field. – JPG Aug 31 '20 at 04:04
  • Please see an Update section at the end with what I get w/o read_only=True – Artem Trunov Aug 31 '20 at 06:38
  • possible duplicate: https://stackoverflow.com/questions/41312558/django-rest-framework-post-nested-objects – 404pio Aug 31 '20 at 07:52
  • Does this answer your question? [Django REST Framework POST nested objects](https://stackoverflow.com/questions/41312558/django-rest-framework-post-nested-objects) – 404pio Aug 31 '20 at 07:53

1 Answers1

0

You can consider passing just course_id in POST.