Метод __post_init__
специфичен для библиотеки dataclasses
, поскольку метод __init__
в классах dataclass
генерируется, и его переопределение полностью исключает цель его генерации.
SQLAlchemy, с другой стороны, предоставляет реализацию __init__
для базового класса модели (сгенерированного для вас с помощью declarative_base()
). Вы можете безопасно использовать этот метод самостоятельно после установки значений по умолчанию, набрав super().__init__()
. Учтите, что SQLAlchemy
-обеспечиваемый метод __init__
принимает только ключевые аргументы:
def __init__(self, useragent, profile):
"""specify the main information"""
id = generate_new_id(self)
super().__init__(id=id, useragent=useragent, profile=profile)
Если вам нужно подождать, пока другие столбцы получат обновленные значения вначале (поскольку, возможно, они определяют функции Python как default
), то вы также можете запускать функции после вызова super().__init__()
и просто назначить self
:
def __init__(self, useragent, profile):
"""specify the main information"""
super().__init__(useragent=useragent, profile=profile)
self.id = generate_new_id(self)
Примечание: вы не хотите использовать встроенную функцию id()
для генерации идентификаторов для данных, вставленных в SQL, возвращаемые функцией значения не гарантируются как уникальные . Они уникальны только для набора всех активных объектов Python и только в текущем процессе. В следующий раз, когда вы запустите Python или когда объекты будут удалены из памяти, значения могут и будут использоваться повторно, и вы не можете контролировать, какие значения будут сгенерированы в следующий раз или в другом процессе.
Если вы когда-либо создавали строки с уникальными комбинациями столбцов useragent
и profile
, то вам нужно определить UniqueConstraint
в аргументах таблицы . Не пытайтесь обнаружить уникальность на уровне Python, поскольку вы не можете гарантировать, что другой процесс не выполнит такую же проверку одновременно. База данных находится в гораздо лучшем положении, чтобы определить, есть ли у вас повторяющиеся значения, не рискуя условиями гонки:
class Worker(Base):
__tablename__='worker'
id = Column(Integer, primary_key=True, autoincrement=True)
profile = Column(String(100), nullable=False)
useragent = Column(String(100), nullable=False)
__table_args__ = (
UniqueConstraint("profile", "useragent"),
)
или вы можете использовать составной первичный ключ на основе двух столбцов; первичные ключи (составные или иные) всегда должны быть уникальными:
class Worker(Base):
__tablename__='worker'
profile = Column(String(100), primary_key=True, nullable=False)
useragent = Column(String(100), primary_key=True, nullable=False)