У меня есть много образцовых классов с отношениями между ними с интерфейсом CRUD для редактирования. Проблема состоит в том, что некоторые объекты не могут быть удалены, так как существуют другие объекты, относящиеся к ним. Иногда я могу установить НА, УДАЛЯЮТ правило обработать этот случай, но в большинстве случаев я не хочу автоматическое удаление связанных объектов, пока они не развязаны вручную. Так или иначе я хотел бы представить редактора список объектов, относящихся к в настоящее время просматриваемому и выделить тех, которые предотвращают его удаление из-за ограничения FOREIGN KEY. Существует ли готовое решение автоматически обнаружить ссылающиеся домены?
Обновление
Задача, кажется, довольно распространена (например, django ORM показывает все зависимости), поэтому интересно, что еще нет никакого решения его.
Существует два предложенные направления:
backref
. Но нет никакой гарантии, что все отношения имеют backref
определенный. Кроме того, существуют некоторые случаи когда backref
бессмысленно. Хотя я могу определить его везде, мне не нравится делать этот путь, и это не надежно.MetaData
возразите и соберите зависимости из их foreign_keys
свойство (код sqlalchemy_schemadisplay может использоваться как пример благодаря комментариям stephan). Это позволит ловить все зависимости между таблицами, но в чем я нуждаюсь, зависимости между образцовыми классами. Некоторые внешние ключи определяются в промежуточных таблицах и не имеют никаких моделей, соответствующих им (используемый как secondary
в отношениях). Несомненно, я могу пойти дальше и найти связанную модель (должны найти способ сделать это все же), но это выглядит слишком сложным.Решение
Ниже метод класса базовой модели (разработанный для декларативного расширения), что я использую в качестве решения. Это не прекрасно и не отвечает всем моим требованиям, но это работает на текущее состояние моего проекта. Результат собран как словарь словарей, таким образом, я могу показать им сгруппированный объектами и их свойствами. Я havn't, решенный все же, является ли это хорошей идеей, начиная со списка ссылающихся доменов иногда, огромен и я вынужден ограничить его некоторым разумным числом.
def _get_referers(self):
db = object_session(self)
cls, ident = identity_key(instance=self)
medatada = cls.__table__.metadata
result = {}
# _mapped_models is my extension. It is collected by metaclass, so I didn't
# look for other ways to find all model classes.
for other_class in medatada._mapped_models:
queries = {}
for prop in class_mapper(other_class).iterate_properties:
if not (isinstance(prop, PropertyLoader) and \
issubclass(cls, prop.mapper.class_)):
continue
query = db.query(prop.parent)
comp = prop.comparator
if prop.uselist:
query = query.filter(comp.contains(self))
else:
query = query.filter(comp==self)
count = query.count()
if count:
queries[prop] = (count, query)
if queries:
result[other_class] = queries
return result
Благодаря всем, кто помог мне, особенно stephan и фургону.
SQL: я должен абсолютно не согласиться с S.Lott' ответ .
Я не знаю о out-of-the-box решении, но это определенно возможно для обнаружения всех таблиц, которые имеют ограничения ForeignKey к данной таблице. Нужно использовать должным образом представления INFORMATION_SCHEMA
такой как REFERENTIAL_CONSTRAINTS
, KEY_COLUMN_USAGE
, TABLE_CONSTRAINTS
, и т.д. См. пример SQL Server . С некоторыми ограничениями и расширениями, большинством версий новой поддержки реляционных баз данных стандарт INFORMATION_SCHEMA
. Когда у вас есть вся информация о FK и объект (строка) в таблице, это - вопрос выполнения немногих операторы SELECT
для получения всех других строк в других таблицах, которые относятся к данной строке и препятствуют тому, чтобы она была удалена.
SqlAlchemy: , Как отмечено stephan в его комментарии, если вы используете orm
с backref
для отношений, затем для вас должно быть довольно легко получить список родитель объекты, которые сохраняют ссылку на объект, который вы пытаетесь удалить, потому что те объекты являются в основном отображенными свойствами вашего объекта ( child1. Родитель
).
, Если вы работаете с объекты Таблицы
sql алхимии (или не всегда используете backref
для отношений), затем необходимо было бы получить значения foreign_keys
для всех таблиц, и затем для весь тех ForeignKey
вызов с ссылки (...)
метод, обеспечив таблицу в качестве параметра. Таким образом вы найдете весь FKs (и таблицы), которые имеют ссылку на таблицу, на которую отображается ваш объект. Затем можно запросить все объекты, которые сохраняют ссылку на объект путем построения запроса для каждого из тех FKs.
Для каждого класса модели вы можете легко увидеть, все ли его отношения «один ко многим» пусты, просто запросив список в каждом случае и посмотрев, сколько записей он содержит. (Вероятно, существует более эффективный способ, реализованный с точки зрения COUNT.) Если есть какие-либо внешние ключи, относящиеся к объекту, и у вас правильно настроены отношения между объектами, то по крайней мере один из этих списков будет отличным от нуля. в длину.
Как правило, невозможно «обнаружить» все ссылки в реляционной базе данных.
В некоторых базах данных они могут использовать декларативную ссылочную целостность в форме явных ограничений внешнего ключа или проверки.
Но этого не требуется. Он может быть неполным или непоследовательным.
Любой запрос может включать в себя не объявленную взаимосвязь FK. Без совокупности всех запросов вы не сможете узнать отношения, которые используются, но не объявлены.
Чтобы найти «референтов» в целом, вы должны действительно знать структуру базы данных и иметь все запросы.