1

I am trying to use Django with mongoengine to make an API.

So far I can get the objects and delete them. but when I want to post some data. Lets say student + course it is giving an error:

type object 'Course' has no attribute 'objects'

Models en ..

#Model.py


class Course(EmbeddedDocument): 
    course_name = StringField(max_length=200)
    course_fee = StringField(max_length=200)

class Student(Document):
    student_name = StringField(max_length=200)
    student_contactperson = StringField(max_length=200)
    student_adress = StringField(max_length=200)
    courses = ListField(EmbeddedDocumentField(Course))


#Serializers.py
class CourseSerializer(EmbeddedDocumentSerializer):
    class Meta:
        model = Course
        fields = ('course_name','course_fee')


class StudentSerializer(DocumentSerializer):
    courses = CourseSerializer(many=True)
    class Meta:
        model = Student
        fields = ('student_name','student_contactperson','student_adress','courses')
        depth = 2

    def create(self, validated_data):
        course_data = validated_data.pop('courses')
        student = Student.objects.create(**validated_data)
        Course.objects.create(student=student, **course_data)
        return student

#Views.py

class StudentViewSet(meviewsets.ModelViewSet):
    lookup_field = 'name'
    queryset = Student.objects.all().order_by('-date_joined')
    serializer_class = StudentSerializer

1 Answers1

0

A Document represents a MongoDB document (i.e a record in a collection), a Document class is bound to a particular collection. An EmbeddedDocument represents a structure that gets nested in a Document.

So by design an EmbeddedDocument isn't attached to any collection unless you embed it inside a Document.

This means that you can't query or save an EmbeddedDocument class, you need to query/save the parent Document.

Document.objects is an entry point for querying a collection, it only exists on Document classes. You are calling Course.objects.create but Course is an EmbeddedDocument.

I believe you need to change your code to the following class StudentSerializer(DocumentSerializer): ...

def create(self, validated_data):
    course_data = validated_data.pop('courses')
    course = Course(**course_data)    # assuming course_data is {course_name: ..., course_fee: ...}
    return Student.objects.create(courses=[course], **validated_data)
bagerard
  • 5,681
  • 3
  • 24
  • 48
  • thanks for your answer. I am confused about courses = CourseSerializer(many=True). When i set to False it works with your code and the new document will be created but the response has no course information in it("courses": {}). when I choose many=True is the code is not working en got error: Expected a list of items but got type \"dict\".". – shabir Sole May 16 '19 at 20:44
  • Could you clarify what you mean by `and use [] to add nested` ? – bagerard May 16 '19 at 21:41
  • According to your model, student.courses should be a list of dict, but you are posting a simple dict instead. Something isn’t right – bagerard May 16 '19 at 22:32