Django-elasticsearch-dsl Объект типа 'AttrList' не является JSON сериализуемым

У меня есть приложение Django, где мне нужно реализовать систему поиска, для этого приложения elasticsearch кажется наиболее подходящим, но я столкнулся с проблемой, которую не могу решить.

У меня есть в postgres таблица со столбцом типа jsonb, похожим на этот:

[
  {
    "act": 1900,
    "max": 2850,
    "min": 2850,
    "tgt": 2850,
    "desc": "L - Durchsatz (kg/h)",
    "name": "L - Durchsatz (kg/h)",
    "unit": "kg/h",
    "color": "red",
    "ordering": 1,
    "monitoring": true
  },
  {
    "act": 283,
    "max": 425,
    "min": 425,
    "tgt": 425,
    "desc": "L - Siebbandgeschwindigkeit (m/min)",
    "name": "L - Siebbandgeschwindigkeit (m/min)",
    "unit": "m/min",
    "color": "red",
    "ordering": 2,
    "monitoring": true
  },
  ...
]

Django Model:

class Collect(models.Model):
    recipe = models.ForeignKey(RecipeSentHistory, on_delete=models.CASCADE, null=True, default='1')
    general_info = models.JSONField(default=dict)
    record = models.JSONField(default=dict)
    justify = models.CharField(max_length=255, default='*')
    automatic = models.BooleanField(default=False)
    user = models.CharField(max_length=255, default='*')
    user_job_position = models.CharField(max_length=255, default='*')
    timestamp = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.recipe.machine.name

Мой сериализатор:

class MyCollectSerializer(serializers.ModelSerializer):
    class Meta:
        model = Collect
        fields = [
            'justify',
            'record',
            'user',
            'user_job_position',
            'timestamp',
            'automatic',
            'recipe_id',
            'general_info',
        ]
        read_only = True

My documents.py:

from django_elasticsearch_dsl import Document, fields
from django_elasticsearch_dsl.registries import registry
from mpa.models import Collect


@registry.register_document
class CollectDocument(Document):
    general_info = fields.ObjectField(
        properties={
            'batch': fields.TextField(),
            'machine': fields.TextField(),
            'recipe_cep': fields.TextField(),
            'recipe_mpa': fields.TextField(),
            'fabrication_order': fields.TextField(),
        }
    )

    record = fields.NestedField()

    def prepare_general_info(self, instance):
        return instance.general_info

    def prepare_record(self, instance):
        return instance.record

    class Index:
        name = 'collect'

    class Django:
        model = Collect
        fields = [
            'justify',
            'user',
            'user_job_position',
            'timestamp',
            'automatic',
        ]

Мое мнение:

from dataclasses import fields
from django.http import HttpResponse
from elasticsearch_dsl import Q
from rest_framework.views import APIView
from rest_framework.pagination import LimitOffsetPagination
from mpa.serializers import MyCollectSerializer
from .documents import CollectDocument
from json import JSONEncoder
from rest_framework.renderers import JSONRenderer
from rest_framework.views import APIView


class JSONSearchEncoder(JSONEncoder):
    def default(self, obj):
        from elasticsearch_dsl import InnerDoc
        if isinstance(obj, InnerDoc):
            return obj.to_dict()
        return super().default(obj)


class JSONSearchRenderer(JSONRenderer):
    encoder_class = JSONSearchEncoder


class GeneralSearchAPIView(APIView):
    renderer_classes = (JSONSearchRenderer,)


class SearchCollect(GeneralSearchAPIView, LimitOffsetPagination):
    collect_serializer = MyCollectSerializer
    search_document = CollectDocument

    def get(self, request, query):
        try:
            q = Q(
                'multi_match',
                query=query,
                fields=[
                    'user',
                ]
            )

            search = self.search_document.search().query(q)
            response = search.execute()

            results = self.paginate_queryset(
                response, request, view=self)
            serializer = self.collect_serializer(results, many=True)
            return self.get_paginated_response(serializer.data)

        except Exception as e:
            return HttpResponse(e, status=500)

Команда 'python manage.py search_index --rebuild' работает нормально, но при восстановлении данных я получаю следующую ошибку:

Environment:


Request Method: GET
Request URL: http://localhost:8000/search/GER02

Django Version: 3.2.12
Python Version: 3.9.12
Installed Applications:
['corsheaders',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django_apscheduler',
 'mes.apps.MesConfig',
 'collector.apps.CollectorConfig',
 'vla.apps.VlaConfig',
 'mpa.apps.MpaConfig',
 'search.apps.SearchConfig',
 'authentication',
 'crispy_forms',
 'rest_framework',
 'simple_history',
 'tz_detect',
 'django_elasticsearch_dsl']
Installed Middleware:
['corsheaders.middleware.CorsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'simple_history.middleware.HistoryRequestMiddleware',
 'tz_detect.middleware.TimezoneMiddleware',
 'mpa.middlewares.middleware.userLanguageMiddleware',
 'mpa.middlewares.middleware.userTimeZoneMiddleware']



Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 204, in _get_response
    response = response.render()
  File "/usr/local/lib/python3.9/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/usr/local/lib/python3.9/site-packages/rest_framework/response.py", line 70, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/renderers.py", line 100, in render
    ret = json.dumps(
  File "/usr/local/lib/python3.9/site-packages/rest_framework/utils/json.py", line 25, in dumps
    return json.dumps(*args, **kwargs)
  File "/usr/local/lib/python3.9/json/__init__.py", line 234, in dumps
    return cls(
  File "/usr/local/lib/python3.9/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/lib/python3.9/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/app/search/views.py", line 18, in default
    return super().default(obj)
  File "/usr/local/lib/python3.9/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '

Exception Type: TypeError at /search/GER02
Exception Value: Object of type AttrList is not JSON serializable

Что я могу сделать, чтобы иметь возможность возвращать данные этого поля в виде списка, содержащего словари?

Я благодарен за любую помощь.

Вернуться на верх