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, str):
|
|
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.items()]
|
|
# PUT
|
|
to_save = []
|
|
for (name, value) in value.items():
|
|
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
|