52 lines
2 KiB
Python
52 lines
2 KiB
Python
|
import json
|
||
|
|
||
|
from rest_framework import serializers, exceptions
|
||
|
|
||
|
|
||
|
class OptionField(serializers.WritableField):
|
||
|
"""
|
||
|
Dict-like representation of a OptionField
|
||
|
A bit hacky, objects get deleted on from_native method and Serializer will
|
||
|
need a custom override of restore_object method.
|
||
|
"""
|
||
|
def to_native(self, value):
|
||
|
""" dict-like representation of a Property Model"""
|
||
|
return dict((prop.name, prop.value) for prop in value.all())
|
||
|
|
||
|
def from_native(self, value):
|
||
|
""" Convert a dict-like representation back to a WebOptionField """
|
||
|
parent = self.parent
|
||
|
related_manager = getattr(parent.object, self.source or 'options', False)
|
||
|
properties = serializers.RelationsList()
|
||
|
if value:
|
||
|
model = getattr(parent.opts.model, self.source or 'options').related.model
|
||
|
if isinstance(value, basestring):
|
||
|
try:
|
||
|
value = json.loads(value)
|
||
|
except:
|
||
|
raise exceptions.ParseError("Malformed property: %s" % str(value))
|
||
|
if not related_manager:
|
||
|
# POST (new parent object)
|
||
|
return [ model(name=n, value=v) for n,v in value.iteritems() ]
|
||
|
# PUT
|
||
|
to_save = []
|
||
|
for (name, value) in value.iteritems():
|
||
|
try:
|
||
|
# Update existing property
|
||
|
prop = related_manager.get(name=name)
|
||
|
except model.DoesNotExist:
|
||
|
# Create a new one
|
||
|
prop = model(name=name, value=value)
|
||
|
else:
|
||
|
prop.value = value
|
||
|
to_save.append(prop.pk)
|
||
|
properties.append(prop)
|
||
|
|
||
|
# Discart old values
|
||
|
if related_manager:
|
||
|
properties._deleted = [] # Redefine class attribute
|
||
|
for obj in related_manager.all():
|
||
|
if not value or obj.pk not in to_save:
|
||
|
properties._deleted.append(obj)
|
||
|
return properties
|