2016-04-05 12 views
3

Im mit stream-django mit Django REST-Framework und die angereicherten Aktivitäten werfen "nicht JSON serializable" auf die Objekte von Anreicherung zurückgegeben, die wie erwartet ist, da sie keine Serialisierung durchlaufen haben.Wie serialisiert ich Objekte während der Anreicherung mit stream-django und django rest framework?

Wie kann ich den Anreicherungsprozess so anpassen, dass er ein serialisiertes Objekt aus meinem DRF-Serializer und nicht das Objekt selbst zurückgibt?

Einige Beispieldaten, nicht angereichert:

"is_seen": false, 
"is_read": false, 
"group": "19931_2016-04-04", 
"created_at": "2016-04-04T08:53:42.601", 
"updated_at": "2016-04-04T11:33:26.140", 
"id": "0bc8c85a-fa59-11e5-8080-800005683205", 
"verb": "message", 
"activities": [ 
    { 
    "origin": null, 
    "verb": "message", 
    "time": "2016-04-04T11:33:26.140", 
    "id": "0bc8c85a-fa59-11e5-8080-800005683205", 
    "foreign_id": "chat.Message:6", 
    "target": null, 
    "to": [ 
    "notification:1" 
    ], 
"actor": "auth.User:1", 
"object": "chat.Message:6" 
} 

Aussicht:

def get(self, request, format=None): 
    user = request.user 
    enricher = Enrich() 
    feed = feed_manager.get_notification_feed(user.id) 
    notifications = feed.get(limit=5)['results'] 
    enriched_activities=enricher.enrich_aggregated_activities(notifications) 
    return Response(enriched_activities) 

Antwort

3

Ich löste es, indem Sie folgendermaßen vorgehen: auf dem Modell

Eigenschaft Tag, das den Serializer Klasse

@property 
def activity_object_serializer_class(self): 
    from .serializers import FooSerializer 
    return FooSerializer 

Dann ist dieses die angereicherten Aktivitäten zur Serialisierung verwendet zurückgibt. Unterstützt das Verschachteln.

@staticmethod 
def get_serialized_object_or_str(obj): 
    if hasattr(obj, 'activity_object_serializer_class'): 
     obj = obj.activity_object_serializer_class(obj).data 
    else: 
     obj = str(obj) # Could also raise exception here 
    return obj 

def serialize_activities(self, activities): 
    for activity in activities: 
     for a in activity['activities']: 
      a['object'] = self.get_serialized_object_or_str(a['object']) 
      # The actor is always a auth.User in our case 
      a['actor'] = UserSerializer(a['actor']).data 
    return activities 

und die Aussicht:

def get(self, request, format=None): 
    user = request.user 
    enricher = Enrich() 
    feed = feed_manager.get_notification_feed(user.id) 
    notifications = feed.get(limit=5)['results'] 
    enriched_activities = enricher.enrich_aggregated_activities(notifications) 
    serialized_activities = self.serialize_activities(enriched_activities) 
    return Response(serialized_activities) 
0

Der Enrich Schritt String Verweise in der vollen Django Modellinstanzen ersetzt.

Zum Beispiel: Die Zeichenfolge "chat.Message: 6" wird durch eine Instanz chat.models.Message (wie Message.objects.get(pk=6)) ersetzt.

Standardmäßig weiß DRF nicht, wie man Django-Modelle serialisiert und schlägt mit einem Serialisierungsfehler fehl. Glücklicherweise ist das Serialisieren von Modellen eine sehr einfache Aufgabe bei der Verwendung von DRF. Es gibt eine integrierte Serialisierungsklasse, die spezifisch für Django-Modelle ist (serializers.ModelSerializer).

Die Dokumentation von DRF erklärt diesen Prozess im Detail hier: http://www.django-rest-framework.org/api-guide/serializers/#modelserializer.

In Ihrem Fall müssen Sie wahrscheinlich eine verschachtelte Serialisierung verwenden und die Serialisierung des Feldes object intelligent machen (dieses Feld kann Verweise auf verschiedene Arten von Objekten enthalten).

Es gibt ein offenes Problem darüber auf Github: https://github.com/GetStream/stream-django/issues/38. Idealerweise ist dies etwas, das die Bibliothek als Helfer/Beispiel bereitstellen wird, so dass jeder Codebeitrag/Eingabe dazu beitragen wird, dies zu ermöglichen.

Verwandte Themen