def __new__(cls, name, bases, attrs): # add Database.Base as parent class bases = list(bases) if object in bases: bases.remove(object) bases.append(Database.Base) seen = set() bases = tuple(base for base in bases if not base in seen and not seen.add(base)) attrs['__id__'] = __id__ = attrs.get('__id__', 'id') attrs['__tablename__'] = StringUtil.camelcase_to_underscore(name) attrs[__id__] = Column(Integer, primary_key = True) attrs['created_at'] = Column(DateTime) attrs['updated_at'] = Column(DateTime) attrs['_readable_name'] = attrs['__tablename__'] attrs['_readable_names'] = attrs['_readable_name'] + 's' attrs['_one_to_models'] = attrs['_many_to_models'] = [] if not '__mapper_args__' in attrs: attrs['__mapper_args__'] = {} # the for loop bellow handles table inheritance for base in [base for base in bases if base in models]: if not hasattr(base, 'real_type'): base.real_type = Column('real_type', String(24), nullable = False, index = True) base.__mapper_args__['polymorphic_on'] = base.real_type base.__mapper_args__['polymorphic_identity'] = base._readable_name attrs[__id__] = Column(Integer, ForeignKey('{0}.{1}'.format(base._readable_name, base.__id__), ondelete = "CASCADE"), primary_key = True) attrs['__mapper_args__']['polymorphic_identity'] = attrs['_readable_name'] attrs['__mapper_args__']['inherit_condition'] = attrs[__id__] == getattr(base, base.__id__) return MyDeclarativeMeta.__new__(cls, name, bases, attrs)
def __new__(cls, name, bases, attrs): # add Database.Base as parent class bases = list(bases) if object in bases: bases.remove(object) bases.append(Database.Base) seen = set() bases = tuple(base for base in bases if not base in seen and not seen.add(base)) attrs["__tablename__"] = StringUtil.camelcase_to_underscore(name) attrs["id"] = Column(Integer, primary_key=True) attrs["created_at"] = Column(DateTime) attrs["updated_at"] = Column(DateTime) attrs["_readable_name"] = attrs["__tablename__"] attrs["_readable_names"] = attrs["_readable_name"] + "s" attrs["_one_to_models"] = attrs["_many_to_models"] = [] if not "__mapper_args__" in attrs: attrs["__mapper_args__"] = {} # the for loop bellow handles table inheritance for base in [base for base in bases if base in models]: if not hasattr(base, "real_type"): base.real_type = Column("real_type", String(24), nullable=False, index=True) base.__mapper_args__["polymorphic_on"] = base.real_type base.__mapper_args__["polymorphic_identity"] = base._readable_name attrs["id"] = Column( Integer, ForeignKey("{0}.id".format(base._readable_name), ondelete="CASCADE"), primary_key=True ) attrs["__mapper_args__"]["polymorphic_identity"] = attrs["_readable_name"] attrs["__mapper_args__"]["inherit_condition"] = attrs["id"] == base.id return MyDeclarativeMeta.__new__(cls, name, bases, attrs)
def foreign_key(ref_model, ref_name=None, backref_name=None, one_to_one=False): """"Class decorator, add a foreign key to a SQLAlchemy model. Parameters: ref_model is the destination model, in a one-to-many relationship, it is the "one" side. ref_name is the user-friendly name of destination model(if omitted, destintion table name will be used instead). backref_name is the name used to back ref the "many" side. one_to_one is this foreign_key for a one-to-one relationship? """ if isinstance(ref_model, str): ref_model_name = ref_model else: ref_model_name = ref_model.__name__ ref_table_name = StringUtil.camelcase_to_underscore(ref_model_name) ref_name = ref_name or ref_table_name foreign_key = '{0}_id'.format(ref_name) def ref_table(cls): if one_to_one: if backref_name: cls._readable_name = backref_name if not isinstance(ref_model, str): if ref_name: ref_model._readable_name = ref_name cls._one_to_models.append(ref_model) ref_model._one_to_models.append(cls) else: if backref_name: cls._readable_names = backref_name if not isinstance(ref_model, str): if ref_name: ref_model._readable_name = ref_name cls._many_to_models.append(ref_model) ref_model._one_to_models.append(cls) model_name = cls.__name__ table_name = cls._readable_name setattr( cls, foreign_key, Column( Integer, ForeignKey('{0}.id'.format(ref_table_name), ondelete="CASCADE"))) my_backref_name = backref_name or (table_name if one_to_one else '{0}s'.format(table_name)) backref_options = dict(uselist=False) if one_to_one else dict( lazy='dynamic') backref_options['cascade'] = 'all' setattr( cls, ref_name, relationship(ref_model_name, primaryjoin='{0}.{1} == {2}.id'.format( model_name, foreign_key, ref_model_name), backref=backref(my_backref_name, **backref_options), remote_side='{0}.id'.format(ref_model_name))) return cls return ref_table
def many_to_many(ref_model, ref_name=None, backref_name=None, middle_table_name=None): """Class Decorator, add a many-to-many relationship between two SQLAlchemy models. Parameters: ref_table_name is the name of the destination table, it is NOT the one decorated by this method. ref_name is how this model reference the destination models. backref_name is how the destination model reference this model. middle_table_name is the middle table name of this many-to-many relationship. """ if isinstance(ref_model, str): ref_model_name = ref_model else: ref_model_name = ref_model.__name__ ref_table_name = StringUtil.camelcase_to_underscore(ref_model_name) ref_name = ref_name or "{0}s".format(ref_table_name) def ref_table(cls): if backref_name: cls._readable_names = backref_name if not isinstance(ref_model, str): ref_model._readable_names = ref_name cls._many_to_models.append(ref_model) ref_model._many_to_models.append(cls) table_name = cls._readable_name my_middle_table_name = middle_table_name or "{0}_{1}".format(table_name, ref_table_name) if table_name == ref_table_name: left_column_name = "left_id" right_column_name = "right_id" else: left_column_name = "{0}_id".format(table_name) right_column_name = "{0}_id".format(ref_table_name) middle_table = Table( my_middle_table_name, Database.Base.metadata, Column( left_column_name, Integer, ForeignKey("{0}.id".format(table_name), ondelete="CASCADE"), primary_key=True, ), Column( right_column_name, Integer, ForeignKey("{0}.id".format(ref_table_name), ondelete="CASCADE"), primary_key=True, ), ) my_backref_name = backref_name or "{0}s".format(table_name) parameters = dict(secondary=middle_table, lazy="dynamic", backref=backref(my_backref_name, lazy="dynamic")) if table_name == ref_table_name: parameters["primaryjoin"] = cls.id == middle_table.c.left_id parameters["secondaryjoin"] = cls.id == middle_table.c.right_id setattr(cls, ref_name, relationship(ref_model_name, **parameters)) return cls return ref_table
def foreign_key(ref_model, ref_name=None, backref_name=None, one_to_one=False): """"Class decorator, add a foreign key to a SQLAlchemy model. Parameters: ref_model is the destination model, in a one-to-many relationship, it is the "one" side. ref_name is the user-friendly name of destination model(if omitted, destintion table name will be used instead). backref_name is the name used to back ref the "many" side. one_to_one is this foreign_key for a one-to-one relationship? """ if isinstance(ref_model, str): ref_model_name = ref_model else: ref_model_name = ref_model.__name__ ref_table_name = StringUtil.camelcase_to_underscore(ref_model_name) ref_name = ref_name or ref_table_name foreign_key = "{0}_id".format(ref_name) def ref_table(cls): if one_to_one: if backref_name: cls._readable_name = backref_name if not isinstance(ref_model, str): if ref_name: ref_model._readable_name = ref_name cls._one_to_models.append(ref_model) ref_model._one_to_models.append(cls) else: if backref_name: cls._readable_names = backref_name if not isinstance(ref_model, str): if ref_name: ref_model._readable_name = ref_name cls._many_to_models.append(ref_model) ref_model._one_to_models.append(cls) model_name = cls.__name__ table_name = cls._readable_name setattr(cls, foreign_key, Column(Integer, ForeignKey("{0}.id".format(ref_table_name), ondelete="CASCADE"))) my_backref_name = backref_name or (table_name if one_to_one else "{0}s".format(table_name)) backref_options = dict(uselist=False) if one_to_one else dict(lazy="dynamic") backref_options["cascade"] = "all" setattr( cls, ref_name, relationship( ref_model_name, primaryjoin="{0}.{1} == {2}.id".format(model_name, foreign_key, ref_model_name), backref=backref(my_backref_name, **backref_options), remote_side="{0}.id".format(ref_model_name), ), ) return cls return ref_table
def __new__(cls, name, bases, attrs): # add Database.Base as parent class bases = list(bases) if object in bases: bases.remove(object) bases.append(Database.Base) seen = set() bases = tuple(base for base in bases if not base in seen and not seen.add(base)) attrs['__tablename__'] = StringUtil.camelcase_to_underscore(name) attrs['id'] = Column(Integer, primary_key=True) attrs['created_at'] = Column(DateTime) attrs['updated_at'] = Column(DateTime) attrs['_readable_name'] = attrs['__tablename__'] attrs['_readable_names'] = attrs['_readable_name'] + 's' attrs['_one_to_models'] = attrs['_many_to_models'] = [] if not '__mapper_args__' in attrs: attrs['__mapper_args__'] = {} # the for loop bellow handles table inheritance for base in [base for base in bases if base in models]: if not hasattr(base, 'real_type'): base.real_type = Column('real_type', String(24), nullable=False, index=True) base.__mapper_args__['polymorphic_on'] = base.real_type base.__mapper_args__[ 'polymorphic_identity'] = base._readable_name attrs['id'] = Column(Integer, ForeignKey('{0}.id'.format( base._readable_name), ondelete="CASCADE"), primary_key=True) attrs['__mapper_args__']['polymorphic_identity'] = attrs[ '_readable_name'] attrs['__mapper_args__']['inherit_condition'] = attrs[ 'id'] == base.id return MyDeclarativeMeta.__new__(cls, name, bases, attrs)
def test_camelcase_to_underscore(self): """convert camel case to underscore""" assert StringUtil.camelcase_to_underscore("StringUtilTestCase") == "string_util_test_case" assert StringUtil.camelcase_to_underscore("ModelQuestion") == "model_question"
def many_to_many(ref_model, ref_name=None, backref_name=None, middle_table_name=None): """Class Decorator, add a many-to-many relationship between two SQLAlchemy models. Parameters: ref_table_name is the name of the destination table, it is NOT the one decorated by this method. ref_name is how this model reference the destination models. backref_name is how the destination model reference this model. middle_table_name is the middle table name of this many-to-many relationship. """ if isinstance(ref_model, str): ref_model_name = ref_model else: ref_model_name = ref_model.__name__ ref_table_name = StringUtil.camelcase_to_underscore(ref_model_name) ref_name = ref_name or '{0}s'.format(ref_table_name) def ref_table(cls): if backref_name: cls._readable_names = backref_name if not isinstance(ref_model, str): ref_model._readable_names = ref_name cls._many_to_models.append(ref_model) ref_model._many_to_models.append(cls) table_name = cls._readable_name my_middle_table_name = middle_table_name or '{0}_{1}'.format( table_name, ref_table_name) if table_name == ref_table_name: left_column_name = 'left_id' right_column_name = 'right_id' else: left_column_name = '{0}_id'.format(table_name) right_column_name = '{0}_id'.format(ref_table_name) middle_table = Table( my_middle_table_name, Database.Base.metadata, Column(left_column_name, Integer, ForeignKey('{0}.id'.format(table_name), ondelete="CASCADE"), primary_key=True), Column(right_column_name, Integer, ForeignKey('{0}.id'.format(ref_table_name), ondelete="CASCADE"), primary_key=True)) my_backref_name = backref_name or '{0}s'.format(table_name) parameters = dict(secondary=middle_table, lazy='dynamic', backref=backref(my_backref_name, lazy='dynamic')) if table_name == ref_table_name: parameters['primaryjoin'] = cls.id == middle_table.c.left_id parameters['secondaryjoin'] = cls.id == middle_table.c.right_id setattr(cls, ref_name, relationship(ref_model_name, **parameters)) return cls return ref_table