Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modularizing peewee

Suppose I have a couple of simple models residing in food.py:

import peewee as pw

db = pw.SqliteDatabase('food.db')

class BaseModel(pw.Model):
    class Meta:
        database = db

class Taco(BaseModel):
    has_cheese = pw.BooleanField()

class Spaghetti(BaseModel):
    has_meatballs = pw.BooleanField()

db.connect()

# populate with some data if table doesn't exist
from random import random
if not Taco.table_exists():
    db.create_table(Taco)
    for _ in range(10):
        Taco.create( has_cheese = (random() < 0.5) )
    db.commit()
if not Spaghetti.table_exists():
    db.create_table(Spaghetti)
    for _ in range(10):
        Spaghetti.create( has_meatballs = (random() < 0.5) )
    db.commit()

Afterwards, I have food.py and food.db. But let's say the Taco and Spaghetti models are becoming large and complicated, so I'd like to split them into different files. Specifically, I'd like to create a food folder in my PYTHONPATH with the typical hierarchy:

food/
    - __init__.py
    - BaseModel.py
    - Taco.py
    - Spaghetti.py
    - db/
        - food.db

I'd like to put the models into their respective .py files and have an __init__.py file that looks something like this:

import peewee as pw

db = pw.SqliteDatabase('./db/food.db')

from . import BaseModel
from . import Taco
from . import Spaghetti

db.connect()

However, this clearly doesn't work because BaseModel.py can't access db. If it is possible to modularize multiple peewee models in this manner, what is the correct way to do so?

like image 220
Matt Hancock Avatar asked Oct 16 '25 04:10

Matt Hancock


1 Answers

Apparently the trick is to connect to the database in the BaseModel.py file. I will give a full outline of the module contents. Assume that the top-level folder is named food and lives in the PYTHONPATH. Finally assume that food.db exists in food/db/food.db and has been populated (e.g., as in the bottom of the very first code block in the question).

Here are the module files:

__init__.py

from Taco import Taco
from Spaghetti import Spaghetti

BaseModel.py

import peewee as pw
db = pw.SqliteDatabase('/abs/path/to/food/db/food.db')

class BaseModel(pw.Model):
    class Meta:
        database = db

Taco.py

import peewee as pw
from BaseModel import BaseModel

class Taco(BaseModel):
    has_cheese = pw.BooleanField()

Spaghetti.py

import peewee as pw
from BaseModel import BaseModel

class Spaghetti(BaseModel):
    has_meatballs = pw.BooleanField()

Now, for example, you can write a script (residing outside the module folder, of course), like:

main.py

import food

for t in food.Taco.select():
    print "Taco", t.id, ("has" if t.has_cheese else "doesn't have"), "cheese"

produces:

Taco 1 has cheese
Taco 2 has cheese
Taco 3 has cheese
Taco 4 doesn't have cheese
Taco 5 doesn't have cheese
Taco 6 has cheese
Taco 7 has cheese
Taco 8 has cheese
Taco 9 doesn't have cheese
Taco 10 doesn't have cheese
like image 125
Matt Hancock Avatar answered Oct 17 '25 19:10

Matt Hancock