How to create all tables defined in models using peewee
Asked Answered
G

7

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?

Gemperle answered 7/2, 2014 at 15:16 Comment(0)
P
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)
Pompeii answered 7/2, 2014 at 16:13 Comment(3)
Seems create_model_tables is deprecated in newer peewee versions.Dasilva
docs.peewee-orm.com/en/latest/peewee/…Dasilva
Possibly, I no longer use peewee for a very long time now.Pompeii
T
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])
Trahurn answered 7/2, 2014 at 15:40 Comment(1)
Maybe this function's docstring could appear in the API docs?Pompeii
I
17

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.

Improbable answered 6/5, 2017 at 13:14 Comment(2)
Hands down best solution!Liguria
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.Neutron
P
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)
Pompeii answered 7/2, 2014 at 16:13 Comment(3)
Seems create_model_tables is deprecated in newer peewee versions.Dasilva
docs.peewee-orm.com/en/latest/peewee/…Dasilva
Possibly, I no longer use peewee for a very long time now.Pompeii
K
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
Klos answered 30/6, 2014 at 6:34 Comment(0)
C
2
for cls in globals().values():
    if type(cls) == peewee.BaseModel:
        try:
            cls.create_table()
        except peewee.OperationalError as e:
            print(e)
Chantey answered 27/3, 2016 at 12:9 Comment(0)
H
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().

Hessian answered 3/10, 2018 at 12:26 Comment(0)
A
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)
Archaic answered 21/10, 2021 at 16:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.