Reputation: 4635
I have three models, Student, Course and Homework:
What is happening is that I have a front end that the user inputs those fields in ie. all fields from Student
, Course
and Homework
and once those fields are filled out they suppose to click submit
to perform CREATE
operation. And that's triggers the CreatedData
function in views.py
.
I have found some relevant examples but still, my serializer is only returning the fields from the Student
model for CRUD
operation. I'm not able to get the Course
& Homework
models fields.
Return different serializer after create() in CreateAPIView in Django REST Framework
Django Rest API. Get all data from different models in a single API call
How to retrieve and create data from model via DJANGO REST API?
how to post multiple model data through one serializer in django rest api
models.py
class Student(models.Model):
student_id = models.UUIDField(default=uuid.uuid4, unique=True,
primary_key=True, editable=False)
firstName = models.CharField(max_length=20)
age = models.IntegerField(default=18)
class Course(models.Model):
student_id = models.ForeignKey(Student, on_delete=models.CASCADE)
courseName = models.CharField(max_length=20)
courseYear = models.IntegerField(default=2021)
student = models.ManyToManyField(Student, related_name='courses')
class Homework(models.Model):
student_id = models.ForeignKey(Student, on_delete=models.CASCADE)
hwName = models.CharField(max_length=20)
hwPossScore = models.IntegerField(default=100)
course = models.ForeignKey(Course, related_name='homeworks', on_delete=models.CASCADE, null=True, blank=True)
students = models.ManyToManyField(Student)
For these three models I have three serializer classes and combined one to get all data for one API call: Serializers.py
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = "__all__"
class HomeworkSerializer(serializers.ModelSerializer):
class Meta:
model = Homework
fields = __all__
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = "__all__"
###I combine both Student and Course into one
class Combined_Serializer(serializers.ModelSerializer):
students = serializers.SerializerMethodField()
homeworks = serializers.SerializerMethodField()
courses = serializers.SerializerMethodField()
def get_students(self, obj):
students = obj.student_set.all()
serializer = StudentSerializer(students, many=True)
return serializer.data
def get_homeworks(self, obj):
homeworks = obj.homework_set.all()
serializer = HomeworkSerializer(homeworks, many=True, read_only=True)
return serializer.data
def get_courses(self, obj):
courses = obj.courses_set.all()
serializer = CourseSerializer(courses, many=True, read_only=True)
return serializer.data
class Meta:
model = Student
fields = ('student_id','firstName','age','homeworks','courses')
views.py
class CreatedData(viewsets.ModelViewSet):
queryset = Student.objects.all()
serializer_class = Combined_Serializer
def create(self, request, pk=None):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
student_id = serializer.data['student_id']
name = serializer.data['Name']
student_age = serializer.data['age']
print("SERIALIZER.DATA >" , serializer.data)
print("HEADERS", headers)
I'm not able to see the Course
& Homework
models fields when I print serializer.data
, only fields from Student
models I can get the fields.
I want to design a view which I can access the all fields from all tables. I want to get them after user click submit
button.
How to design the view to get that other information in Django rest API?
thanks for your help in advance!
Upvotes: 0
Views: 1848
Reputation: 629
class CombinedCreateSerializer(serializers.Serializer):
students = NewStudentSerializer()
homeworks = NewHomeworkSerializer() # with minimal fields required to create like student_id is not required as it will be obtained later
courses = NewCourseSerializer() # with minimal fields
def create(self, validated_data):
student = Student.objects.create(**validated_data['students'])
# add student id in courses data
courses = Course.objects.create(**validated_data['courses'])
# add student id and course id in homeworks data
homeworks = Homework.objects.create(**validated_data['homework'])
return student
In views
class CreatedData(viewsets.ModelViewSet):
queryset = Student.objects.all()
serializer_class = Combined_Serializer # your previously defined
def create(self, request):
# first verify combined create serializer
combined_create_serializer = CombinedCreateSerializer(data=request.data)
combined_create_serializer.is_valid(raise_exception=True)
student_instance = self.perform_create(combined_create_serializer)
combined_serializer_data = self.get_serializer(student_instance) # your final data here which is from previously defined
# ... rest of your codes
In the past I have achieved doing similar like this; good luck
Upvotes: 1
Reputation: 224
Combined_Serializer
returns only the student fields because:
Meta
, model = Student
students = obj.student_set.all()
<- can you explain how this relation works?If you have to specify model in the serializer, you can create an abstract model that has foreign key relation to all three models - Student, Course, Homework and modify your serializer accordingly. But it's recommended only if the class will have a solid use and a single responsibility.
class StudentCourseHomework:
```you can name it better with abstract term that explains
what you want to do with this model```
student = models.ForeignKey()
course = models.ForeignKey()
homework = models.ForeignKey()
class Meta:
abstract = True
You can create serializer without model using serializers.Serializer
.
class CombinedSerializer(serializers.Serializer):
class Meta:
fields = StudentSerializer.Meta.fields
+ CoursetSerializer.Meta.fields
+ HomeworkSerializer.Meta.fields
CreateDataSerializer
Upvotes: 1