diff --git a/pydal/helpers/classes.py b/pydal/helpers/classes.py index e7892cedf..58425e0a7 100644 --- a/pydal/helpers/classes.py +++ b/pydal/helpers/classes.py @@ -217,6 +217,47 @@ def __setitem__(self, key, value): self.__allocate() self._record[key] = value +class ReferenceUUID(str): + def __allocate(self): + if not self._record: + self._record = self._table[str(self)] + if not self._record: + raise RuntimeError( + "Using a recursive select but encountered a broken " + + "reference: %s %d" % (self._table, str(self)) + ) + + def __getattr__(self, key): + if key == 'id': + return str(self) + if key in self._table: + self.__allocate() + if self._record: + # to deal with case self.update_record() + return self._record.get(key, None) + else: + return None + + def get(self, key, default=None): + return self.__getattr__(key, default) + + def __setattr__(self, key, value): + if key.startswith('_'): + str.__setattr__(self, key, value) + return + self.__allocate() + self._record[key] = value + + def __getitem__(self, key): + if key == 'id': + return str(self) + self.__allocate() + return self._record.get(key, None) + + def __setitem__(self, key, value): + self.__allocate() + self._record[key] = value + def Reference_unpickler(data): return marshal.loads(data) diff --git a/pydal/parsers/base.py b/pydal/parsers/base.py index 2783fda50..87d979045 100644 --- a/pydal/parsers/base.py +++ b/pydal/parsers/base.py @@ -4,7 +4,7 @@ from decimal import Decimal from .._compat import PY2, integer_types, basestring, to_bytes, to_native from ..adapters.base import SQLAdapter -from ..helpers.classes import Reference +from ..helpers.classes import Reference, ReferenceUUID from ..helpers.methods import bar_decode_string, bar_decode_integer from . import Parser, parsers, for_type, before_parse @@ -43,7 +43,10 @@ def reference_extras(self, field_type): @for_type('reference') def _reference(self, value, referee): if '.' not in referee: - value = Reference(value) + try: + value = Reference(value) + except ValueError: + value = ReferenceUUID(value) value._table, value._record = self.adapter.db[referee], None return value