|
35 | 35 | """
|
36 | 36 |
|
37 | 37 | import inspect
|
| 38 | +import json |
38 | 39 | import logging
|
39 | 40 | import sys
|
40 | 41 | from collections import OrderedDict
|
@@ -132,6 +133,36 @@ def formfield(self, **kwargs): # pylint:disable=arguments-differ
|
132 | 133 |
|
133 | 134 | return super().formfield(**defaults)
|
134 | 135 |
|
| 136 | + def to_python(self, value): |
| 137 | + """ |
| 138 | + Convert a value to the correct type for this field. Values from the |
| 139 | + database will already be of the correct type, due to the the caster |
| 140 | + registered with psycopg2. The field can also be serialized as a string |
| 141 | + via value_to_string, where it is encoded as a JSON object. |
| 142 | + """ |
| 143 | + # Composite types are serialized as JSON blobs. If BaseField.to_python |
| 144 | + # is called with a string, assume it was produced by value_to_string |
| 145 | + # and decode it |
| 146 | + if isinstance(value, str): |
| 147 | + value = json.loads(value) |
| 148 | + return self.Meta.model(**{ |
| 149 | + name: field.to_python(value.get(name)) |
| 150 | + for name, field in self.Meta.fields |
| 151 | + }) |
| 152 | + |
| 153 | + return super().to_python(value) |
| 154 | + |
| 155 | + def value_to_string(self, obj): |
| 156 | + """ |
| 157 | + Serialize this as a JSON object {name: field.value_to_string(...)} for |
| 158 | + each child field. |
| 159 | + """ |
| 160 | + value = self.value_from_object(obj) |
| 161 | + return json.dumps({ |
| 162 | + name: field.value_to_string(value) |
| 163 | + for name, field in self.Meta.fields |
| 164 | + }) |
| 165 | + |
135 | 166 |
|
136 | 167 | class BaseOperation(migrations.operations.base.Operation):
|
137 | 168 | """Base class for the DB operation that relates to this type."""
|
|
0 commit comments