Django Rest Framework и MongoDB - listField не работает. Возвращает None, когда объект внедрен. - PullRequest
0 голосов
/ 22 марта 2019

Я использую MongoDB, соединение обеспечивается Djongo, поверх используется DRF для управления всеми запросами к mi API.

Мои данные (профиль) структурированы следующим образом

{
    "name" : "profile name",
    "description" : "this is a description",
    "params" : "X1, X2,X3, etc",
    "config" : "CONFIG OF DEVICE",
    "user" : {
        "name" : "user name",
        "middle_name" : "test middle name",
        "last_name" : "test last name",
        "email" : "test@test.com",
        "institute" : {
            "name" : "MIT",
            "place" : {
                "coordinates" : [ 30.0, 101.0,  0.0 ],
                "type" : "Point"
            },
            "country" : "US"
        }
    },
    "place" : {
        "coordinates" : [  90.0, 901.0, 10.0 ],
        "type" : "Point"
    },
    "devices" : [ 
        {
            "name" : "DEVICE 1",
            "verification_code" : "",
            "verificated" : 0,
            "configuration" : "kjk",
            "places" : [ 
                {
                    "coordinates" : [ 30.0,  101.0,  0.0 ],
                    "type" : "Point"
                }, 
                {
                    "coordinates" : [  31.0, 102.0, 1.0 ],
                    "type" : "Point"
                }
            ]
        }
    ]
}

Я знаю, что координаты неверны, но это просто для проверки.

Хорошо, я отправляю этот объект на мой взгляд, а затем в ProfileSerializer, это отвечает за проверку встроенных объектов (у каждого есть свойсобственный сериализатор).После проверки данных информация сохраняется без проблем, как вы можете видеть на следующем рисунке:

Screenshot 2019-03-21 at 14 44 05

Но проблема в том, когда я пытаюсь.восстановить все профили.Просто координаты равны нулю. Другие встроенные объекты извлекаются надлежащим образом, только объект Place искажен.Далее я покажу вам ответ:

[
{
        "id": 22,
        "name": "profile name",
        "description": "this is a description",
        "params": "X1, X2,X3, etc",
        "config": "CONFIG OF DEVICE",
        "user": {
            "name": "user name",
            "middle_name": "test middle name",
            "last_name": "test last name",
            "email": "test@test.com",
            "institute": {
                "name": "MIT",
                "place": {
                    "coordinates": **null**,
                    "type": "Point"
                },
                "country": "US",
                "created_at": "2019-03-21T20:43:33.928000Z"
            },
            "created_at": "2019-03-21T20:43:33.959000Z"
        },
        "place": {
            "coordinates": **null**,
            "type": "Point"
        },
        "devices": [
            {
                "name": "DEVICE 1",
                "verificated": 0,
                "configuration": "kjk",
                "places": [
                    {
                        "coordinates": **null**,
                        "type": "Point"
                    },
                    {
                        "coordinates": **null**,
                        "type": "Point"
                    }
                ],
                "created_at": "2019-03-21T20:43:33.898000Z"
            }
        ],
        "created_at": "2019-03-21T20:43:33.976000Z"
    }
]

Только для этих вопросов я опишу / покажу сериализатор одного объекта, но если вам понадобится некоторая информация, я получу вас как можно скорее.

Модели

class Place(models.Model):
    coordinates = models.ListField(blank=True, null=True, default=[0.0, 0.0, 0.0])
    type = models.CharField(max_length=10, default="Point")
    objects = models.DjongoManager()

class Profile(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField(default="Without Description")
    params = models.TextField(default="No params")
    config = models.CharField(max_length=200)
    user = models.EmbeddedModelField(
        model_container=User
    )
    place = models.EmbeddedModelField(
        model_container=Place
    )
    devices = models.ArrayModelField(
        model_container=Device
    )
    created_at = models.DateTimeField(auto_now_add=True)
    objects = models.DjongoManager()

Сериализаторы

class PlaceSerializer(serializers.ModelSerializer):
    coordinates = serializers.ListSerializer(
        child=serializers.FloatField(),
    )
    class Meta:
        model = Place
        fields = ('id', 'coordinates', 'type')

class ProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer( )
    place = PlaceSerializer()
    devices = DeviceSerializer( many=True)

    class Meta:
        model = Profile
        fields = ('id', 'name', 'description', 'params', 'config',
                  'user', 'place', 'devices', 'created_at')
        depth=8

    def create(self, validated_data):
        # get principal fields
        user_data = validated_data.pop('user')
        **place_data = validated_data.pop('place')**
        devices_data = validated_data.pop('devices')

        # get nested fields

        # devices nested fields
        devices = []
        for device in devices_data:
            places = []
            places_data = device.pop('places')
            for place in places_data:
                places.append( **Place(coordinates=place['coordinates'], type=place['type'])** )

            device['places'] = places
            devices.append( Device.objects.create(**device) )
        validated_data['devices'] = devices
        # user nested fields
        institute_data = user_data.pop('institute')
        place = institute_data.pop('place')
        institute_data['place'] = Place(coordinates=place['coordinates'], type=place['type'])
        user_data['institute'] = Institute.objects.create(**institute_data)
        validated_data['user'] = User.objects.create(**user_data)
        profile = Profile.objects.create(**validated_data)
        return profile

Я определил PlaceSerializer по-разному, но все они получают один и тот же результат, Ниже опишите эти способы

CASE 1

class PlaceSerializer(serializers.ModelSerializer):
    coordinates = serializers.ListSerializer(
        child=serializers.FloatField(),
    )

CASE 2

class CoordinatesSerializer(serializers.ListSerializer):
        child=serializers.FloatField()

class PlaceSerializer(serializers.ModelSerializer):
    coordinates = CoordinatesSerializer()

CASE 3

class PlaceSerializer(serializers.ModelSerializer):
    coordinates = serializers.ListField(
        child=serializers.FloatField()
    )

CASE 4

class PlaceSerializer(serializers.ModelSerializer):
    coordinates = serializers.ListField()

CASE 5

class PlaceSerializer(serializers.ModelSerializer):
    coordinates = serializers.ListSerializer()
#gives error for child is not present

Я изменил типы, CharField, IntegerField, FloatField и т. Д. С теми же результатами.

Еще один тест, который я сделал, - добавление в сериализатор методов create, update, to_representation, to_internal_value, все это для лучшего управления информацией, которая будет сохранена, извлечена, но все работает.Еще одно любопытство, если я добавлю простое поле списка, например [10,90,1], в отличие от этого, если поле ListField находится внутри Place Objects,

будет сохранено и извлечено без проблем. Пожалуйста, если вы знаете, как решить эту проблему, ярад тебе.

...