Использование нескольких отношений M2M в нескольких базах данных в peewee - PullRequest
0 голосов
/ 27 января 2020

У меня есть два python проекта, которые поддерживают разные соединения с базой данных и файлы sqlite. model1.py в проекте низкого уровня, model2.py в проекте высокого уровня, который использует класс модели model1.py. Ниже приведен пример кода:

model1.py

from os.path import join, dirname

from peewee import *
from playhouse.sqlite_ext import *

_db = SqliteDatabase(join(dirname(__file__), 'db1.sqlite'))

class Student(Model):
    name = CharField()
    sex = CharField()

    class Meta:
        database = _db

    def __str__(self):
        return 'student name: %s, sex: %s' % (self.name, self.sex)

_db.connect()
_db.create_tables([
    Student,
])

model2.py

from os.path import join, dirname

from peewee import *
from playhouse.sqlite_ext import *

from model1 import *

_db = SqliteDatabase(join(dirname(__file__), 'db2.sqlite'))

class Teacher(Model):
    name = CharField()
    age = IntegerField()

    sample_student = ForeignKeyField(Student, null=True, backref='sample_teacher')
    students = ManyToManyField(Student, backref='teachers')

    class Meta:
        database = _db

    def __str__(self):
        return 'teacher name: %s, age: %d' % (self.name, self.age)

_db.connect()
_db.create_tables([
    Teacher,
    Teacher.students.get_through_model(),
])

main.py

from model1 import *
from model2 import *

if __name__ == '__main__':
    Teacher.students.through_model.delete().execute()
    Teacher.delete().execute()
    Student.delete().execute()

    s1 = Student.create(name='s1', sex='male')
    s2 = Student.create(name='s2', sex='female')

    t1 = Teacher.create(name='t1', age=20)
    t1.students.add(s1)
    t1.students.add(s2)

    t1.sample_student = s1
    t1.save()

    print(t1.sample_student)  # ForeignKeyField works!

    [print(s) for s in Student.select()]
    [print(t) for t in Teacher.select()]

    for s in t1.students:    # crash here: peewee.OperationalError: no such table: teacher_student_through
        print(s)

Для таблица teacher_student_through, фактически существует в базе данных db2.sqlite. Итак, это ошибка peewee или мое неправильное использование?

1 Ответ

0 голосов
/ 23 февраля 2020

Вместо использования объекта базы данных для Meta.database я изменил инициализацию метамодели с помощью прокси-сервера базы данных для моего python пакета.

_db_proxy = DatabaseProxy()

class PeeweeModel(Model):
    class Meta:
        database = _db_proxy

# skip the other subclass models implementation here...

def setup_database(dbpath):
    '''Initialize database.'''

    database = SqliteDatabase(dbpath)
    _db_proxy.initialize(database)

    database.connect(reuse_if_open=True)
    database.create_tables([
        Model1,
        Model2,
    ])

    return database

Теперь вызывающий пакет имеет ответственность за инициализацию объекта базы данных, , см. дополнительную документацию об этом .

. Publi c PeeweeModel также доступен для пакета высокого уровня python для расширения базы данных. таблицы, просто используйте его как общий класс супермодели.

...