LINUX.ORG.RU

Сконвертить данные класса Python3 в строку INSERT для Postgree

 


1

1

Привет, всем! Имеется множество классов Python с типизированными полями.

from datetime import date


class A:
    
    x: int = 1
    y: date = date(2020, 12, 12)
    
    def __init__(self, x:int, y:date):
        self.x = x
        self.y = y
        
    def getX(self) -> int:
        return self.x

    def getY(self) -> date:
       return self.y

    ...


class B:
    z: float = 2.2

...

Можно ли сделать универсальную процедуру (лучше метод базового класса), генерирующую запрос SQL INSERT в стиле psycopg2

query = ("INSERT INTO A (x, y, ...) VALUES (%s, %s, ...)", (a.x, a.y, ...))

Спасибо.

Ответ на: комментарий от scientistpython

Кроме этого можно заиспользовать dataclass у которого из коробки есть dict(), также можно явно перечислить поля в slots, заодно выиграв в скорости работы с классом.

slovazap ★★★★★
()

Нуууууу. Во первых используй какой-нибудь ORM. Sql alchemy или django, будет гораздо удобнее.

Если все же не хочешь по какой-то причине брать готовое решение в виде ORM, то отнаследуй свои классы от pydantic.BaseModel. Тогда у каждого класса будет метод .dict, который вернет тебе нужные свойства, а метод .schema даст тебе инфу о типах полей. Кроме того пидатик тебе провалидирует, что в int поле действительно int.

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

Нуууууу. Во первых используй какой-нибудь ORM. Sql alchemy или django, будет гораздо удобнее.

Ну если просто модельки данных юзать, то Sql Alchemy более точно.

Не подскажите что не так. Таблица не создается (((

from sqlalchemy import create_engine, MetaData, Table, Integer, Date, Column
engine = create_engine('postgresql://pyuser:123@localhost/py_db', echo = True)
meta = MetaData()

pyTest = Table(
   'pyTest', meta, 
   Column('id', Integer, primary_key = True), 
   Column('firstDate', Date), 
)
meta.create_all(engine, tables=[pyTest])
py_db=> SELECT * FROM pyTest;
ERROR:  relation "pytest" does not exist

2020-12-09 13:37:11,023 INFO sqlalchemy.engine.base.Engine select version()
2020-12-09 13:37:11,024 INFO sqlalchemy.engine.base.Engine {}
2020-12-09 13:37:11,025 INFO sqlalchemy.engine.base.Engine select current_schema()
2020-12-09 13:37:11,026 INFO sqlalchemy.engine.base.Engine {}
2020-12-09 13:37:11,029 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2020-12-09 13:37:11,030 INFO sqlalchemy.engine.base.Engine {}
2020-12-09 13:37:11,031 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2020-12-09 13:37:11,032 INFO sqlalchemy.engine.base.Engine {}
2020-12-09 13:37:11,033 INFO sqlalchemy.engine.base.Engine show standard_conforming_strings
2020-12-09 13:37:11,033 INFO sqlalchemy.engine.base.Engine {}
2020-12-09 13:37:11,035 INFO sqlalchemy.engine.base.Engine select relname from pg_class c join pg_namespace n on n.oid=c.relnamespace where pg_catalog.pg_table_is_visible(c.oid) and relname=%(name)s
2020-12-09 13:37:11,035 INFO sqlalchemy.engine.base.Engine {'name': 'pyTest'}
scientistpython
() автор топика
Ответ на: комментарий от Aswed

Блин, поэтому и боишся этих фреймворков. Когда мелкая задачка не понятно что быстрее: самому написать или работать фреймворк заставить?

scientistpython
() автор топика
Ответ на: комментарий от Aswed

Во первых используй какой-нибудь ORM. Sql alchemy или django, будет гораздо удобнее.

Не всегда, и не всегда гораздо удобнее.

Видел я людей которые использовали только ORM. Видел и плакал, минимального понимания того, как все внутри работает у многих не было вообще.

Kazun3500
()
VALUES (%s, %s, ...)

Только вместо форматирования строк, используй плейсхолдеры

VALUES ($1, $2, ...)
nikolnik ★★★
()
Ответ на: комментарий от scientistpython

Я не настоящий алхимик, я по джанге. Однако, я вообще никогда не видел, что бы алхимию инициализировали так. Обычно объявляют модели не через Table, а наследуясь от Model. Вот простейший пример из доков flask: https://flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart/ попробуй его

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

Да, спасибо! Я заюзал Академию, Флак мне в этой ситуации не нужен, нужны только модельки для БД. И отнаследовался не от db.Model, а от declarative_base().

https://flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart/ это сильно похоже на быстрый старт в Академии )

Base = declarative_base()
class AA(Base):
    
    __tablename__ = 'aa'
    id = Column(Integer, primary_key=True)
    firstDate = Column('firstDate', Date)
        
    def __init__(self, firstDate):
        self.firstDate = firstDate

    def __repr__(self):
        return "<aa('{}')>".format(self.firstDate)    

P.S. осталось как-то правильно с Пандосом сынтегрироваться ) ... у меня как бы представление - это Пандас ДатаФреймы

scientistpython
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.