S
S
Sazoks2022-01-25 10:33:10
Django
Sazoks, 2022-01-25 10:33:10

How to do the correct serialization of models?

Task
There is a class controller that provides pagination of the gallery via ajax.
When I receive the desired selection of records from the model, I convert it to json format using django.core.serializers.serialize, thereby obtaining json representations of the list with objects.
Next, I send this case to the client using JsonResponse.

Problem
But here's the problem, due to the fact that it django.core.serializers.serializeworks with a collection of objects, I get a STRING, and not a list with serialized objects. Because it is a string, JsonResponse once again converts the STRING passed to it into json format. Because of this, you have to parse json 2 times on the client, which is somehow crooked.
To be more clear, here's an example:

...
# Получаем список объектов.
image_list = paginator.get_page(num_page).object_list
# image_list - это List[GalleryImage], а json_image_list - это str.
# Это строка вида '[{...}, {...}, ...]', но это строка! Если я захочу получить первый
# элемент, я получу не его, а '['.
json_image_list = serializers.serialize(image_list)
# Отправляем ответ в json-формате. Из-за этого и без того строка json_image_list
# еще раз конвертирует в json-формат...
return JsonResponse(data=json_image_list, safe=False)

$.ajax({
    ...
    success: function(json_image_list) {
        // Я думал, что тут я получу список с конвертированными в json экземплярами модели.
        image_list = JSON.parse(json_image_list);
        // Но вместо этого я получаю СТРОКУ вида "[{...}, {...}, ...]", и мне, выходит, нужно еще раз писать JSON.parse().
    }
});

This is where the problem lies. It's crooked. To avoid this, you need to pass to JsonResponse not a string, but a list() with model instances converted to json.

What did I try to solve the problem
  1. Using the json module
    The first thing I tried, after serializing the collection with objects, is to deserialize the list object itself with objects back into a python object using the json.loads. Again, it looks very crutch.

  2. Writing the to_json method on the model
    Then I decided to just write a method to manually serialize the model instance into json format by writing the corresponding method. There was some code like this:
    image_list = []
    for image in paginator.get_page(num_page).object_list:
        image_list.append(image.to_json())

    But this option also seems to me not flexible and somehow cycling: why write in such a simple task a functional that already exists, but which I simply did not figure out how to use correctly.

  3. Using the Finest DRF Serializers
    Finally, the nicest way to use, but not the nicest in realizing that for the sake of normal serialization, I installed a whole separate framework. Writing your own layer of serializers based on rest_framework.serializers.ModelSerializer. Now I have a whole separate custom serialization layer without changing the model itself and unnecessary gestures.
    # serializers.py
    from rest_framework import serializers
    from .models import GalleryImage
    
    class GalleryImageSerializer(serializers.ModelSerializer):
        """Сериализатор модели изобрежения в JSON"""
    
        image = serializers.SerializerMethodField()
    
        class Meta:
            model = GalleryImage
            fields = '__all__'
    
        @staticmethod
        def get_image(obj):
            return obj.image.url

    # views.py
    ...
    # Отправляем запрашиваемые по номеру страницы изображения из пагинатора.
    image_set = paginator.get_page(num_page).object_list
    json_image_set = [GalleryImageSerializer(image).data for image in image_set]
    ...

    But then again, installing a whole separate framework, writing your own layer for serialization in a regular Django template project... Somehow this is all wrong...



Question
In general, I hope I have clearly described the problem. It is important for me to understand how to competently solve such a triviality. The question itself is: what are the correct ways to solve such a trivial task, other than those described by me above?

Thank you!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dr. Bacon, 2022-01-25
@Sazoks

But here's the problem, due to the fact that django.core.serializers.serialize works with a collection of objects, I get a STRING, not a list with serialized objects.
What about "collection of objects"? serialize for you and for one object will return a string, hence the conclusion that JsonResponse is not needed in this bundle, use HttpResponse

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question