djongo
djongo copied to clipboard
nested document is not serialized in json format
i try store nested json document in mongodb. insert is ok but when i get document nested object not json format but string
i want to store json files in mogodb and create and get with django rest framework.
i share my code below. this code insert posted data into mongo. but when i 'get' data, nested object represent as string. i want to get object as json.
i reseached a lot but i haven't found anything about this.
postman get result :
{ "id": 1, "country": "United Kingdom", "country_code": "UK", "nested": "{"name": "London", "icon": "icon_url"}" #problem here. this field must be json object. in mogodb json object here }
Python script
###########################models.py########################
from djongo import models
class Nest(models.Model):
name = models.CharField(max_length=150, blank=True, null=True)
icon = models.CharField(max_length=150, blank=True, null=True)
class Meta:
abstract = True
class Root(models.Model):
#_id = models.ObjectIdField()
country = models.CharField(max_length=200, blank=True, null=True)
country_code = models.CharField(max_length=5, blank=True, null=True)
nested = models.EmbeddedField(
model_container=Nest, null=True)
###########################serializers.py#####################
from rest_framework import serializers
from .models import Root
class RootSerializer(serializers.ModelSerializer):
class Meta:
model = Root
fields = '__all__'
###########################views.py###########################
from django.shortcuts import render
from django.http.response import JsonResponse
from rest_framework.parsers import JSONParser
from rest_framework import status
from .models Root
from .serializers import RootSerializer
from rest_framework.decorators import api_view
@api_view(['GET', 'POST', 'DELETE'])
def root(request):
if request.method == 'GET':
first_root = Root.objects.first()
root_serializer = RootSerializer(first_root, many=False)
return JsonResponse(root_serializer.data, safe=False)
elif request.method == 'POST':
root_data = JSONParser().parse(request)
root_serializer = RootSerializer(data=root_data)
if root_serializer.is_valid():
root_serializer.save()
return JsonResponse(root_serializer.data, status=status.HTTP_201_CREATED)
return JsonResponse(root_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
###########################urls.py###########################
from django.conf.urls import url
from rootApp import views
urlpatterns = [
url(r'^api/root$', views.root),
]
###########################settings.py#######################
DATABASES = {
'default': {
'ENGINE': 'djongo',
'NAME': 'root_db',
'HOST': '127.0.0.1',
'PORT': 27017,
}
}
i have the same issue, someone help plz....
Following the question. I have the exact same issue.
Did you try to implement a serializer for the embedded field Nest
? Then, you need to apply it on the root serializer - otherwise rest_framework
just serializes the fields that contain objects as string (its the default behaviour, not a djongo
issue).
https://www.django-rest-framework.org/api-guide/relations/#nested-relationships
class RootSerializer(serializers.ModelSerializer):
nested = NestSerializer(Nest)
class Meta:
model = Root
fields = '__all__'
@SebastianRemander Thank for the suggestion. Your solution probably works when both Root and Nest are non-abstract classes. It does not work in our case because here the class Nest is abstract. When we try it, we get the following error:
ValueError: Cannot use ModelSerializer with Abstract Models.
In my particular case, I am setting Nest as and abstract class just because Nest defines a structured dictionary attribute of Root, thus it should not have an id.
May it be just a poor design choice?
I see, that is unfortunate and definitely djongo
issue after all. I don't know if it's a design choice or can they actually fix that, since the django-rest-framework does not seem to support these kind of embedded models...
I'm no djongo expert, but you could try switching to mongoengine
and define all your "data" models with it, and only use djongo
for the internal django stuff. At least that's how I've done it, and it works to some extent quite neatly.
I totaly forgot this post. i had handled this issue by myself. my solution is in the following link see: https://stackoverflow.com/questions/63446810/django-nested-document-serializer-problem/63592038#63592038
i created simply global variable and if i have to makemigrate this variable set to True and create migration files then i return this variable to False for runtime serialization. this is not neat solution but it works for me.
this variable determine if nested classes is meta class or not.
from djongo import models
isMigrate = False //added this line
class Nest(models.Model):
name = models.CharField(max_length=150, blank=True, null=True)
icon = models.CharField(max_length=150, blank=True, null=True)
class Meta:
abstract = isMigrate //changed this line.
class Root(models.Model):
#_id = models.ObjectIdField()
country = models.CharField(max_length=200, blank=True, null=True)
country_code = models.CharField(max_length=5, blank=True, null=True)
nested = models.EmbeddedField(
model_container=Nest, null=True)
###########################serializers.py##################### from rest_framework import serializers from .models import Root
class NestSerializer(serializers.ModelSerializer): # added
class Meta: # this
model = Nest #
fields = '__all__' # lines
class RootSerializer(serializers.ModelSerializer):
class Meta:
model = Root
fields = '__all__'