Предположим, у меня есть пара простых моделей, находящихся в 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()

После этого у меня есть food.py и food.db. Но скажем, модели Taco и Spaghetti становятся большими и сложными, поэтому я хотел бы разбить их на разные файлы. В частности, я хотел бы создать папку food в моем PYTHONPATH с типичной иерархией:

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

Я хотел бы поместить модели в соответствующие файлы .py и получить файл __init__.py, который выглядит примерно так:

import peewee as pw

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

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

db.connect()

Однако это явно не работает, потому что BaseModel.py не может получить доступ к db. Если таким образом можно модульно модифицировать несколько моделей peewee, каков правильный способ сделать это?

1
Matt Hancock 18 Дек 2015 в 00:27

3 ответа

Лучший ответ

Очевидно, уловка заключается в подключении к базе данных в файле BaseModel.py. Я дам полный обзор содержания модуля. Предположим, что папка верхнего уровня называется food и находится в PYTHONPATH. Наконец, предположим, что food.db существует в food/db/food.db и заполнен (например, как внизу самого первого блока кода в вопросе).

Вот файлы модуля:

__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()

Теперь, например, вы можете написать скрипт (конечно, находящийся вне папки модуля), например:

main.py

import food

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

Производит:

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
2
Matt Hancock 18 Дек 2015 в 01:57

См. Этот пост для получения инструкций по модуляции приложения колбы с использованием peewee:

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

0
coleifer 18 Дек 2015 в 16:33

У вас есть проблема в пути:

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

Попробуйте также реализовать __init__ классов и передать db в качестве аргумента:

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

Чем в __init__.py:

from BaseModel import BaseModel
db = pw.SqliteDatabase('./db/food.db')
bm = BaseModel(db)
0
BigOther 17 Дек 2015 в 22:06