Как получить данные из различных моделей в Django Rest-API

У меня есть три модели, студент, курс и домашнее задание:

Что происходит: у меня есть front end, в котором пользователь вводит эти поля, т.е. все поля из Student, Course и Homework, и после заполнения этих полей он должен нажать submit для выполнения операции CREATE. И это запускает функцию CreatedData в views.py.

Я нашел несколько подходящих примеров, но все же мой сериализатор возвращает только поля из модели Student для CRUD операций. Я не могу получить поля из Course & Homework модели.

Возврат другого сериализатора после create() в CreateAPIView в Django REST Framework

Django Rest API. Получите все данные из различных моделей за один вызов API

Как получить и создать данные из модели через DJANGO REST API?

как разместить несколько данных модели через один сериализатор в 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)

Для этих трех моделей у меня есть три класса сериализаторов, и я объединил один, чтобы получить все данные для одного вызова API: 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)

Я не могу увидеть поля моделей Course & Homework при печати serializer.data, только поля из моделей Student я могу получить поля.

Я хочу разработать представление, которое может получить доступ ко всем полям из всех таблиц. Я хочу получать их после того, как пользователь нажмет кнопку submit.

Как разработать представление для получения другой информации в Django rest API?

Заранее спасибо за помощь!

Combined_Serializer возвращает только поля студента, потому что:

  • установка модели: в Meta, model = Student
  • взаимосвязь: students = obj.student_set.all() <- можете ли вы объяснить, как работает это отношение?

Если вам нужноуказывать модель в сериализаторе, вы можете создать абстрактную модель, которая имеет отношение внешнего ключа ко всем трем моделям - Student, Course, Homework и соответствующим образом модифицировать ваш сериализатор. Но это рекомендуется только в том случае, если класс будет иметь сплошное использование и единую ответственность.

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

Альтернативы

Вы можете создать сериализатор без модели, используя serializers.Serializer.

class CombinedSerializer(serializers.Serializer):
    class Meta:
        fields = StudentSerializer.Meta.fields
        + CoursetSerializer.Meta.fields
        + HomeworkSerializer.Meta.fields

Другие вещи

  • удаление подчеркивания в имени класса будет более чистым.
  • если вы действительно собираетесь сделать сериализатор, который имеет поля всех трех моделей, то лучше использовать более конкретное имя.
  • Или вы можете использовать имя класса представления, как CreateDataSerializer
  • .
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

По просмотрам

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

В прошлом я добивался подобных результатов; удачи

Вернуться на верх