def __init__(self, dbobj, relationship): """ @param dbobj: The dbobj our parent is a property of. @param relationship: The parent one2many relationship. """ _2many.result.__init__(self, dbobj, relationship) if relationship.child_key is None: # guess the child key name try: pkey_column = dbobj.__primary_key__.column() except SimplePrimaryKeyNeeded: msg = "Can't guess foreign key column "+\ "name for multiple column keys %s" info = repr(tuple(dbobj.__primary_key__.attribute_names())) SimplePrimaryKeyNeeded(msg % info) child_key = "%s_%s" % ( dbobj.__view__.name(True), pkey_column.name(True), ) else: child_key = relationship.child_key if relationship.foreign_key is None: foreign_key = tuple(dbobj.__primary_key__.attribute_names()) else: foreign_key = relationship.foreign_key self.foreign_key = keys.foreign_key(dbobj, relationship.child_class, foreign_key, child_key)
def isset(self, dbobj): if self.column is not None: return datatype.isset(self, dbobj) else: foreign_key = keys.foreign_key(dbobj, self.child_class, self.foreign_key, self.child_key) return foreign_key.isset()
def __set__(self, dbobj, value): """ Set the child object to `value'. If the child object has not been inserted, yet it will be by this function. """ if value is None: if self.column is not None: datatype.__set__(self, dbobj, None) else: foreign_key = keys.foreign_key(dbobj, self.child_class, self.foreign_key, self.child_key) for prop in foreign_key.my_attributes(): prop.__set__(dbobj, None) if hasattr(dbobj, self.data_attribute_name() + "_cache"): delattr(dbobj, self.data_attribute_name() + "_cache") else: if not isinstance(value, self.child_class): raise TypeError("A many2one attribute can only be set to " + \ self.child_class.__name__, " + instances") if not value.__is_stored__(): self.__ds__().insert(value) if self.column is not None: key = value.__primary_key__.attribute().__get__(value) assert key is not None, ValueError datatype.__set__(self, dbobj, key) else: foreign_key = keys.foreign_key(dbobj, self.child_class, self.foreign_key, self.child_key) for my, other in zip(foreign_key.my_attributes(), foreign_key.other_attributes()): my.__set__(dbobj, other.__get__(value)) if self.cache: setattr(dbobj, self.data_attribute_name() + "_cache", value)
def __get__(self, dbobj, owner=None): if self.cache and \ hasattr(dbobj, self.data_attribute_name() + "_cache"): return getattr(dbobj, self.data_attribute_name() + "_cache") ds = dbobj.__ds__() if self.column is not None: value = datatype.__get__(self, dbobj) if value is None: return None ret = ds.select_by_primary_key(self.child_class, value) else: foreign_key = keys.foreign_key(dbobj, self.child_class, self.foreign_key, self.child_key) # Ok, let's check some exception condition... set_count = 0 none_count = 0 for attr in foreign_key.my_attributes(): if attr.__get__(dbobj) is None: none_count += 1 else: set_count += 1 if set_count == 0: return None # a many2one attribute with a multi column key # is considered None, if all key attributes are # None if none_count != 0: # If some of the key attributes are None, and some are set, # it is considered an error raise IllegalForeignKey("For a many2one relationship with a "+\ "multi column key, either all attrs "+\ "must be set or all must be None.") result = ds.select(self.child_class, foreign_key.other_where()) try: ret = result.next() except StopIteration: raise IllegalForeignKey("The foreign key you set for " + \ repr(dbobj) + " does not refer to " + \ "exaxtly one child object") if self.cache: setattr(dbobj, self.data_attribute_name() + "_cache", ret) return ret