django-elasticsearch-dsl type' attrlist的对象'不是JSON可序列化

发布于 2025-01-20 11:02:18 字数 7180 浏览 1 评论 0原文

我有一个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模型:

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

我的serializer:

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

我的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-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

我该怎么办才能将该字段的数据返回包含词典的列表?

感谢任何帮助。

I have a Django application where I need to implement a search system, for this application, elasticsearch seems to be the most suitable, but I came across a problem that I can't solve.

I have in postgres a table with a column of type jsonb similar to this:

[
  {
    "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

My serializer:

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',
        ]

My view:

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)

The command 'python manage.py search_index --rebuild' works normally, but when recovering the data I get the following error:

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

What can I do to be able to return the data of this field as a list containing dictionaries?

I appreciate any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文