Ejemplo n.º 1
0
        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)
Ejemplo n.º 2
0
        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)
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
        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)
Ejemplo n.º 7
0
 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"
Ejemplo n.º 8
0
    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