简体   繁体   中英

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?

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 (eg, 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

You have a problem in the path:

__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
db = pw.SqliteDatabase(os.path.join(__location__, 'db/food.db'));

Try also to implement __init__ of classes and pass the db as an argument to it:

class BaseModel(pw.Model):
    def __init__(self, db = None)
        self.database = db

than in __init__.py :

from BaseModel import BaseModel
db = pw.SqliteDatabase('./db/food.db')
bm = BaseModel(db)

See this post for instructions on modularizing a flask app using peewee:

http://charlesleifer.com/blog/structuring-flask-apps-a-how-to-for-those-coming-from-django/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM