Search code examples
dictionaryserializationdjango-rest-frameworkrestframeworkmongoengine

Mongoengine serialize dictionary (with nested dicts)?


I've created a dictionary from an Uploaded file in Django.

This dictionary has a nested list of dictionaries:

file = {"name": "filename", "sections": [{"section_name": "string", "lines": [{line_number: 0, "line"; "data"}]}], "etc": "etc"}

The model represents the dictionaries depth too.

class Line(EmbeddedDocument):
    line_number = IntField()
    line = StringField()
    definition = ReferenceField(Definition)


class Section(EmbeddedDocument):
    section_name = StringField()
    lines = EmbeddedDocumentListField(Line))


class File(Document):
    name = StringField()
    sections = EmbeddedDocumentListField(Section))
    created_on = DateTimeField()
    created_by = StringField()
    modified_on = DateTimeField()
    modified_by = StringField()

In the POST I have the following to chop the file up into the above Dict (the file is a simple text file):

file= {}
with open(os.path.join(path, filename + ".txt"), 'r') as temp_file:
    filelines = temp_file.readlines()
    sections = []
    section = {}
    lines = []
    for i, l in enumerate(filelines):
        if i == 0:
            section["section_name"] = "Top"
        elif '*' in l:
            if l.index('*') == 0 and '*' not in lines[len(lines) - 2"line"]:
                section["lines"] = lines
                lines = []
                sections.append(section)
                section = dict()
                section["section_name"] = filelines[i + 1][1:-2]
   line = {"line_number": i + 1, "line": l}
   lines.append(line)
   section['lines'] = lines
   sections.append(section)
   file["name"] = filename
   file["sections"] = sections

I will tidy this up eventually. Once the dict has been made how do I serialise it using the serializer?

Is it possible to insert this into a serializer?

If not how can I get it all into the database with validation?

I've tried json.dumps() and JsonRequst() then putting them in data= for the serializer but get Unable to get repr for <class '....'>

I'm pretty new to Django and MongoDB so if you need more info I can provide :)

Thanks!

Update

Change the model's List Fields to EmbeddedDocumentListField as suggest in the answer.

Answered

Thanks to Boris' suggestion below it pointed me to an error I wasn't getting initially. I had a typo and passing the dict directly into FileSerializer(data=file) works like a charm! :)


Solution

  • James!

    The easiest way to validate that your incoming JSONs adhere to the Mongoengine Documents schema that you've specified is to use DRF-Mongoengine's DocumentSerializer.

    Basically, what you need to do is create a serializer

    serializers.py

    import rest_framework_mongoengine
    
    class FileSerializer(rest_framework_mongoengine.DocumentSerializer):
        class Meta:
            fields = '__all__'
            model = File
    

    Then you need a view or viewset that makes use of this Serializer to respond to GET/POST/PUT/DELETE requests.

    views.py

    from rest_framework_mongoengine import viewsets
    
    class FileViewSet(viewsets.ModelViewSet):
        lookup_field = 'id'
        serializer_class = FileSerializer
    
        def get_queryset(self):
            return File.objects.all()
    

    and register this viewset with a router

    urls.py

    from rest_framework import routers
    
    # this is DRF router for REST API viewsets
    router = routers.DefaultRouter()
    
    # register REST API endpoints with DRF router
    router.register(r'file', FileViewSet, r"file")
    

    I'd also recommend using EmbeddedDocumentListField instead of ListField(EmbeddedDocumentField(Section)) - it has additional methods.