2016-06-16 6 views
1

Ich war Whoosh mit Haystack und alles funktioniert gut, ich möchte zu ElasticSearch wechseln, aber wenn ich rebuild_index ausführen, bekomme ich den folgenden Fehler. Ich bin nicht sicher, warum der Fehler passiert, es scheint sich über meine Modelle und die Daten zu beschweren, aber wenn ich zurück zu Whoosh Suche/Indizierung alle arbeiten gut gehen.SerializationError Wiederaufbau elastische Suche Django App

Django==1.8.4 
elasticsearch==2.3.0 
django-haystack==2.4.1 

File "C:\Users\user.virtualenvs\pguider\lib\site-packages\elasticsearch\serializer.py", line 50, in dumps raise SerializationError(data, e) elasticsearch.exceptions.SerializationError: ({u'django_id': u'1', 'created': '2016-02-13T22:19:28.037000+00:00', 'suppl ier_code': u'BL32291', 'related_supplier_parts': [], u'django_ct': u'products.supplierpart', 'supplier': u'Parts Town', 'text': u'BL32291\n32291\nBlodgett\n\nParts Town\n\n\n', 'part_code': u'32291', u'id': u'products.supplierpart.1'}, Type Error("Unable to serialize [] (type:)",))

Hier sind meine Modelle:

from django.db import models 


class Supplier(models.Model): 
    name = models.CharField(max_length=50) 

    def __unicode__(self): 
     return u'%s' % self.name 


class Part(models.Model): 
    name = models.CharField(max_length=200, null=True) 
    code = models.CharField(max_length=30, null=True) 

    def __unicode__(self): 
     return u'%s %s' % (self.code, self.name) 


class SupplierPart(models.Model): 
    part = models.ForeignKey(Part) 

    supplier = models.ForeignKey(Supplier) 
    supplier_code = models.CharField(max_length=30) 

    description = models.CharField(max_length=200) 
    price = models.CharField(max_length=6, null=True) 
    sale_price = models.CharField(max_length=6, null=True) 

    quantity = models.IntegerField(null=True) 
    photo = models.ImageField(upload_to='products', null=True) 
    url = models.URLField() 

    created = models.DateTimeField(auto_now_add=True) 

    def __unicode__(self): 
     return self.supplier_code 

    @property 
    def related_supplier_parts(self): 
     return self.part.supplierpart_set.all().exclude(pk=self.pk) 
+0

Sieht aus wie elasticsearch das Listenfeld, das 'related_supplier_parts' ist, nicht serialisieren kann. Kannst du sagen, was ist das? –

+0

@BartoszDabrowski sieht aus wie es über mein Fremdschlüsselfeld klagt, richtig? Ich habe meine Frage aktualisiert, um die Modelle zu enthalten –

Antwort

1

Das Problem in Ihrer Eigenschaft legt related_supplier_parts. Elastische Suche kann es nicht serialisieren. Diese Eigenschaft gibt Abfragegruppe zurück.

>>> parts = Part.objects.all() 
>>> import json 
>>> json.dumps({'related_supplier_parts': parts}) 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/usr/lib/python2.7/json/__init__.py", line 243, in dumps 
    return _default_encoder.encode(obj) 
    File "/usr/lib/python2.7/json/encoder.py", line 207, in encode 
    chunks = self.iterencode(o, _one_shot=True) 
    File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode 
    return _iterencode(o, 0) 
    File "/usr/lib/python2.7/json/encoder.py", line 184, in default 
    raise TypeError(repr(o) + " is not JSON serializable") 
TypeError: [] is not JSON serializable 

Wie löst man es?

Das beste für jedes Projekt ist es, Ihre Modelle nicht mit Eigenschaften zu verkomplizieren. Obwohl wir wissen, dass sie weit verbreitet und einfach zu schreiben sind. Ich habe nie eine Eigenschaft in meiner Django-Karriere benutzt. In meinem aktuellen Projekt habe ich 153 Modelle und keine einzige Eigenschaft. In 99% Fällen brauchen Sie sie nicht, weil die einfache Methode get_related_supplier_parts die gleiche Arbeit machen sollte.

class SupplierPart(models.Model): 
    [...] 

    created = models.DateTimeField(auto_now_add=True) 

    def __unicode__(self): 
     return self.supplier_code 

    def get_related_supplier_parts(self): 
     return self.part.supplierpart_set.all().exclude(pk=self.pk) 

Ein weiterer Nachteil von @property ist, wenn Sie versuchen, Objekt zusätzliche Abfragen serialisiert werden über die Serialisierung Millionen von ihnen ausgeführt und denken werden. Sie müssen sich nicht mit der Methode darum kümmern.

Wenn Sie dies aus irgendeinem Grund ablehnen, müssen Sie eine Möglichkeit finden, diese Abfrage in eine Liste zu konvertieren. Wahrscheinlich in Ihrer Indexklasse, die ein neues Feld definiert:

class MyIndex(indexes.SearchIndex, indexes.Indexable): 
    [...] 
    related_supplier_parts = indexes.MultiValueField() 

    def prepare_related_supplier_parts(self, obj): 
     return [part.id for part in obj.related_supplier_parts] 
+0

Hallo @Bartosz Vielen Dank für die vollständige Erklärung. Ich war tatsächlich in der Lage, dies zu handhaben, indem ich meine search_index.py Datei von return obj.related_supplier_parts zu den folgenden: Rückkehrliste (str (Teil) für Teil in obj.related_supplier_parts) Danke für die Hilfe! –

Verwandte Themen