Pergunta

I define a lot of model classes using peewee. ClassName.create_table() can generate the table,but only one table. How could I create all tables using a single statement?

Foi útil?

Solução 3

Extending coleifer's answer with the assumption that all tables are grouped in one module:

import inspect
import peewee
import tables
models = [
    obj for name, obj in inspect.getmembers(
        tables, lambda obj: type(obj) == type and issubclass(obj, peewee.Model)
    )
]
peewee.create_model_tables(models)

Outras dicas

Peewee has a helper that will create the tables in the correct order, but you still need to explicitly pass in all the models:

from peewee import *
db = SqliteDatabase(':memory:')
db.create_tables([ModelA, ModelB, ModelC])

An update for Python 3 (and everyone who comes across this question via Google like I did). If you have all models based on the main peewee Model class you can simply use:

import peewee    
models = peewee.Model.__subclasses__()

Credit to this question for the idea. They also go into more detail on how to get it to work recursively if your model is more complex.

This snipnet will create all tables which objects are defined in the current module:

import sys

for cls in sys.modules[__name__].__dict__.values():
    try:
        if BaseModel in cls.__bases__:
            cls.create_table()
    except:
        pass
for cls in globals().values():
    if type(cls) == peewee.BaseModel:
        try:
            cls.create_table()
        except peewee.OperationalError as e:
            print(e)
def create_all_tables():
    for cls in sys.modules[__name__].__dict__.values():
        if hasattr(cls, '__bases__') and issubclass(cls, peewee.Model):
            if cls is not BaseModel:
                cls.create_table()

This also works for ManyToManyField's get_through_model().

I found the existing answers did not support the BaseModel pattern recommended in the docs. I created a helper function to recursively find Models

def all_subclasses(base: type) -> list[type]:
    return [
        cls
        for sub in base.__subclasses__()
        for cls in [sub] + all_subclasses(sub)
    ]

I then filtered out base models, by prefixing them with an underscore.

class _BaseModel(Model):
    class Meta:
        database = db

models = [
    sub for sub in all_subclasses(Model)
    if not sub.__name__.startswith('_')
]

db.create_tables(models)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top