Peewee: динамически устанавливается имя_таблицы при создании экземпляра модели - PullRequest
0 голосов
/ 05 января 2019

Я почти уверен, что это не дубликат. Я знаю, что мы можем «динамически» установить имя таблицы, используя это:

class DBmodel(Model)
    class Meta:
        database = db
        table_name = "foobar"

Но что, если я захочу изменить table_name каждый раз, когда создается экземпляр DBmodel?

Например, рассмотрим этот рабочий фрагмент:

#!/usr/bin/env python3
# coding: utf-8

from peewee import *

conf = {
    "foo": {
        "foo1": "CharField(null=True)",
        "foo2": "CharField(null=True)"
    },
    "bar": {
        "bar1": "CharField(null=True)",
        "bar2": "CharField(null=True)"
    }
}

db = SqliteDatabase("foobar.db")


class DBmodel(Model):
    class Meta:
        database = db
        table_name = "foobar"


class Data:
    def __init__(self, conf):
        self.conf = conf
        self.DBmodel = DBmodel()
        for entry in self.conf:
            # I have to use eval because my conf is actually coming from parsed json, where I can only have text field
            self.DBmodel._meta.add_field(entry, eval(self.conf[entry]))


if __name__ == "__main__":
    dataFoo = Data(conf["foo"])
    dataBar = Data(conf["bar"])
    dataFoo.DBmodel.create_table()
    dataBar.DBmodel.create_table()

Итак, я получаю:

$ sqlite3 foobar.db
SQLite version 3.22.0 2018-01-22 18:45:57
sqlite> .schema foobar
CREATE TABLE IF NOT EXISTS "foobar" ("id" INTEGER NOT NULL PRIMARY KEY, "foo1" VARCHAR(255), "foo2" VARCHAR(255), "bar1" VARCHAR(255), "bar2" VARCHAR(255));

Но я хочу иметь две такие таблицы:

$ sqlite3 foobar.db
SQLite version 3.22.0 2018-01-22 18:45:57
sqlite> .schema foo
CREATE TABLE IF NOT EXISTS "foo" ("id" INTEGER NOT NULL PRIMARY KEY, "foo1" VARCHAR(255), "foo2" VARCHAR(255));
sqlite> .schema bar
CREATE TABLE IF NOT EXISTS "bar" ("id" INTEGER NOT NULL PRIMARY KEY, "bar1" VARCHAR(255), "bar2" VARCHAR(255));

Конечно, я мог бы дублировать свой DBmodel и каждый раз менять table_name, но это выглядит ужасно. Есть ли лучшее решение?

1 Ответ

0 голосов
/ 09 января 2019

Вы всегда можете объявить классы динамически с помощью встроенного type:

attrs = {
    'foo': TextField(),
    'bar': TextField(),
}
MyModel = type('MyModel', (BaseModel,), attrs)

Почему ваши "Данные" должны быть классом? Предположительно все, что вам нужно, это функция, которая принимает ключ к config config, и вы должны вернуть новый объект класса. Вы можете подумать об этом.

Я также укажу, что это плохая идея.

...