Обнаружение ссылающихся доменов к объекту SQLAlchemy

У меня есть много образцовых классов с отношениями между ними с интерфейсом CRUD для редактирования. Проблема состоит в том, что некоторые объекты не могут быть удалены, так как существуют другие объекты, относящиеся к ним. Иногда я могу установить НА, УДАЛЯЮТ правило обработать этот случай, но в большинстве случаев я не хочу автоматическое удаление связанных объектов, пока они не развязаны вручную. Так или иначе я хотел бы представить редактора список объектов, относящихся к в настоящее время просматриваемому и выделить тех, которые предотвращают его удаление из-за ограничения FOREIGN KEY. Существует ли готовое решение автоматически обнаружить ссылающиеся домены?

Обновление

Задача, кажется, довольно распространена (например, django ORM показывает все зависимости), поэтому интересно, что еще нет никакого решения его.

Существует два предложенные направления:

  1. Перечислите все отношения текущего объекта и пройдите их backref. Но нет никакой гарантии, что все отношения имеют backref определенный. Кроме того, существуют некоторые случаи когда backref бессмысленно. Хотя я могу определить его везде, мне не нравится делать этот путь, и это не надежно.
  2. (Предложенный фургоном и stephan) Проверка все таблицы 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 и фургону.

8
задан Denis Otkidach 19 February 2010 в 17:25
поделиться

3 ответа

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.

6
ответ дан 5 December 2019 в 21:18
поделиться

Для каждого класса модели вы можете легко увидеть, все ли его отношения «один ко многим» пусты, просто запросив список в каждом случае и посмотрев, сколько записей он содержит. (Вероятно, существует более эффективный способ, реализованный с точки зрения COUNT.) Если есть какие-либо внешние ключи, относящиеся к объекту, и у вас правильно настроены отношения между объектами, то по крайней мере один из этих списков будет отличным от нуля. в длину.

0
ответ дан 5 December 2019 в 21:18
поделиться

Как правило, невозможно «обнаружить» все ссылки в реляционной базе данных.

В некоторых базах данных они могут использовать декларативную ссылочную целостность в форме явных ограничений внешнего ключа или проверки.

Но этого не требуется. Он может быть неполным или непоследовательным.

Любой запрос может включать в себя не объявленную взаимосвязь FK. Без совокупности всех запросов вы не сможете узнать отношения, которые используются, но не объявлены.

Чтобы найти «референтов» в целом, вы должны действительно знать структуру базы данных и иметь все запросы.

1
ответ дан 5 December 2019 в 21:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: