SQLModel, как найти информацию о внешнем ключе при анализе классов SQLModel?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 SQLModel, как найти информацию о внешнем ключе при анализе классов SQLModel?

Сообщение Anonymous »

Я просматриваю классы SQLModel, извлекаю информацию о поле и создаю файл формата .dbml на основе деталей. Это отлично работает, за исключением попыток найти информацию о внешнем ключе в полях. Вот пример классов SQLModel:

class Account(PostgresBase, table=True):
__tablename__ = 'accounts'

id: str = Field(default_factory=lambda: genb58_id(22, "account"),
primary_key=True, index=True, nullable=False)
first_name: str = Field(index=True)
last_name: str = Field(index=True)
username: str = Field(index=True, unique=True)

# ----- Relationships -----
some_activity_records: list["SomeActivity"] = Relationship(
back_populates="account")

class SomeActivity(PostgresBase, table=True):
__tablename__ = 'some_activity_recs'

id: str = Field(default_factory=lambda: genb58_id(22, "activity"),
primary_key=True, index=True, nullable=False)

name: str
type: Union[dict, None] = Field(sa_type=JSON)
fk_account_id: Union[str, None] = Field(
default=None, foreign_key="accounts.id")
things: list[str] = Field(sa_type=ARRAY(String), default=[])

# ----- Relationships -----
account: Union["Account", None] = Relationship(
back_populates="some_activity_records")

Как я могу получить информацию Foreign_key о том, что поле SomeActivity fk_account_id связано с таблицей + полем account.id?
Вот сценарий, который я запускаю, чтобы получить поля и связи:
import inspect
from sqlmodel import SQLModel
import sys
import types
import typing
from typing import get_args

from models import *

# Get all classes from models.py that are subclasses of SQLModel.
models = [obj for name, obj in inspect.getmembers(sys.modules[__name__])
if inspect.isclass(obj) and issubclass(obj, SQLModel) and obj != SQLModel]

# Generate dbml for each model.
dbml_content = ""
for model in models:
# Extract class docstring.
doc = inspect.getdoc(model).replace('\n', ' ')
if doc.startswith("Usage docs"):
doc = None

# Build the table definition.
dbml_content = f"Table {model.__tablename__} {{\n"
dbml_content += f" // {doc}\n" if doc else ""

# Build the field lines.
for key in model.model_fields.keys():
fieldstr = f" {key}"

field_info = model.model_fields[key]
annotation = field_info.annotation

match type(annotation):
case t if t == type:
type_name = annotation.__name__
if type_name == "str":
type_name = "varchar"
opts = ""
if key == "id":
opts = "[pk, unique, not null]"
fieldstr += f" {type_name} {opts}"

case t if t == typing._UnionGenericAlias:
args = get_args(annotation)
arg_name = args[0].__name__
match arg_name:
case "dict":
arg_name = "json"
case "str":
arg_name = "varchar"
fieldstr += f" {arg_name}"

case t if t == types.GenericAlias:
fieldstr += f" varchar[]"

case t if t == typing._LiteralGenericAlias:
args = get_args(annotation)
fieldstr += f" varchar //{args}"

dbml_content += fieldstr + "\n"

dbml_content += "}\n\n"

# Add relationships.
relationships = []
for model in models:
for field in model.model_fields.values():
if 'foreign_key' in field.metadata:
fk = field.metadata['foreign_key']
if fk:
ref_table, ref_field = fk.split('.')
relationships.append(
f'Ref: "{model.__tablename__}"."{field.name}" < "{ref_table}"."{ref_field}"\n')

dbml_content += ''.join(relationships)

print(dbml_content)

Настройка «Создать dbml для каждой модели». цикл отлично работает и создает соответствующий dbml, например:
Table accounts {
id varchar [pk, unique, not null]
first_name varchar
last_name varchar
username varchar
}

Table some_activity_recs {
id varchar [pk, unique, not null]
name varchar
type json
fk_account_id varchar
things varchar[]
}

Однако, когда я запускаю раздел «Добавить отношения», поле field.metadata всегда представляет собой пустой список, даже при проверке поля fk_account_id.
Я пытался использовать элемент field.foreign_key, который должен существовать в классе SQLModel FieldInfo, но он дает мне следующую обратную трассировку:
***** model.__name__: Account
***** type(model):
***** field.foreign_key: PydanticUndefined
Traceback (most recent call last):
File "/soc-api/./soc/dao/scripts/create_dbml.py", line 86, in
print(f"***** field.foreign_key: {field.foreign_key}")
^^^^^^^^^^^^^^^^^
AttributeError: 'FieldInfo' object has no attribute 'foreign_key'


Подробнее здесь: https://stackoverflow.com/questions/790 ... del-classe
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»