Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Magic Orm that can create orm models straight from the db #95

Open
Jaymon opened this issue Feb 11, 2020 · 0 comments
Open

Magic Orm that can create orm models straight from the db #95

Jaymon opened this issue Feb 11, 2020 · 0 comments

Comments

@Jaymon
Copy link
Owner

Jaymon commented Feb 11, 2020

We did something similar to this in another project:

class DBOrm(Orm):

    table_name = ""
    """This will get set when you use .get_orm_class() so you can query and stuff"""

    _id = _created = _updated = pk = None

    _cache = {"orm": {}, "schema": {}}
    """Caches the schemas generated from the database (see .schema) and orms created
    for individual tables (see .get_orm_class()). These values are cached because
    otherwise they have to be recreated every time you created a child instance
    which would kick off a query to get the fields and to convert those fields to
    Field instances, no sense in doing that since this stuff should change and 
    caching speeds it up considerably"""

    @classproperty
    def schema(cls):
        """overrides schema to generate it from the table information from the db"""
        table_name = cls.table_name
        if table_name in cls._cache["schema"]:
            schema = cls._cache["schema"][table_name]

        else:
            orm_fields = {}
            fields = cls.interface.get_fields(cls.table_name)
            for fn, fopts in fields.items():
                orm_fields[fn] = Field(
                    fopts["field_type"],
                    fopts["field_required"],
                )

            schema = Schema(cls.table_name, **orm_fields)
            cls._cache["schema"][table_name] = schema

        return schema

    @classmethod
    def get_orm_class(cls, table_name):
        """Generate a child class that inherits from this class with the given 
        table_name

        :param table_name: string, the medispan table name
        :returns: a child of this class that can read table_name
        """
        if table_name in cls._cache["orm"]:
            orm_class = cls._cache["orm"][table_name]

        else:
            # https://stackoverflow.com/a/15247892/5006
            orm_class = type(ByteString(table_name), (cls,), {"table_name": table_name})
            cls._cache["orm"][table_name] = orm_class
        return orm_class

It allowed us to have a similar interface for a readonly database we are given, it actually worked surprisingly well, we even had this in the module:

    # Go through the db and export prom.Orm classes for all the tables in the db
    # so they can be imported in other python modules
    for table_name in DBOrm.interface.get_tables():
        logger.debug("Generating Orm class {}.{}".format(__name__, table_name))
        locals()[table_name] = DBOrm.get_orm_class(table_name)

so we could import the table names into other modules like:

from some.module import tablename1, tablename2

Links

Search

  • python create a new class programmatically
@Jaymon Jaymon mentioned this issue Mar 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant