12

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?

Vader
  • 6,335
  • 8
  • 31
  • 43
Alexander.Li
  • 133
  • 1
  • 1
  • 5

7 Answers7

22

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])
coleifer
  • 24,887
  • 6
  • 60
  • 75
16

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.

Community
  • 1
  • 1
ninetynine
  • 327
  • 2
  • 10
  • 2
    Hands down best solution! – SkyWalker Mar 23 '20 at 16:03
  • Fails in some instances, e.g. if using the `SqliteQueueDatabase` extension, you get an `ImproperlyConfigured` error for the `VirtualModel` model, which is used internally but not actually part of your database. – fdmillion Jan 26 '22 at 07:41
10

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)
Cilyan
  • 7,883
  • 1
  • 29
  • 37
2

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
Mathieu Rodic
  • 6,637
  • 2
  • 43
  • 49
2
for cls in globals().values():
    if type(cls) == peewee.BaseModel:
        try:
            cls.create_table()
        except peewee.OperationalError as e:
            print(e)
thinker3
  • 12,771
  • 5
  • 30
  • 36
1
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().

Polv
  • 1,918
  • 1
  • 20
  • 31
0

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)
bphi
  • 3,115
  • 3
  • 23
  • 36