Джанго: Как я могу позволить пользователю определять семантические отношения между объектами?

В медиавики пользователь может сделать ссылку на страницу, просто введя [[Имя страницы]]. В семантической медиавики пользователь может создать семантическую связь со страницей, указав [[example::Some Page]] в качестве примера страницы.

Я хочу иметь возможность делать это с моделями django.

Например, я хочу, чтобы пользователь мог написать описание объекта «Задача» в приложении рабочего процесса и добавить что-то вроде «Продолжить с [[User.id:43]]».

Я также хотел бы иметь возможность делать семантические вещи.

Наконец, я хотел бы иметь возможность посмотреть на пользователя 43 и посмотреть, какие модели ссылаются на него.

Есть ли пакет django, который сделает это частично или полностью? Если нет, то как вообще называется эта методология?


person jMyles    schedule 08.07.2011    source источник


Ответы (1)


Прежде всего, я бы настроил следующее для обнаружения и создания ссылок:

  1. Создайте ModelForm для получения отправленных пользователем Task. Создайте пользовательский валидатор для работы с полем description. этой формы. Этот валидатор проверит, что любые ссылки, введенные пользователем, соответствуют указанному вами формату [[:]].
  2. Override the save method on the Task model. This is a good time to inspect the contents of the description and create links as appropriate.

Теперь в методе сохранения происходит настоящее действие. Я бы использовал регулярное выражение, чтобы вытащить все ссылки, а затем работать с ними одну за другой.

  1. Для каждой ссылки необходимо определить модель, с которой связана ссылка. Это было бы легко сделать, если бы словарь моделей включал их имена.
  2. Вам необходимо определить, действительно ли ссылка идентифицировала действительный экземпляр модели. Если нет, либо пропустите эту ссылку, либо создайте исключение и выбросьте из всего процесса (см. выше о транзакциях).
  3. Вам нужно создать ссылки. Смотри ниже.

В Django есть стандартный механизм для универсальных внешних ключей, который вам следует определенно рассмотрите возможность использования здесь. Вы можете создать класс ссылок примерно так:

class Link(models.Model):
    # link to particular task:
    task = models.ForeignKey(Task)

    # these three fields together set up a generic foreign key which 
    # represents the object you're linking to:
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

Затем ваши объекты модели Task автоматически получат атрибут с именем link_set, который будет списком экземпляров Link.

Создание ссылки будет выглядеть примерно так:

# encountered a description with [[User:43]]
instance = User.objects.get(pk=43)
link = Link.objects.create(task=my_task_object, content_object=instance)

При предоставлении атрибуту content_object ссылки экземпляра другой модели ее поля content_type и object_id автоматически заполняются для вас, и ваша ссылка будет разрешаться обратно в указанный экземпляр.

Надеюсь, это полезно. Запросите более подробную информацию, если вам это нужно.

person Gareth    schedule 09.07.2011
comment
Интересно и, возможно, неотразимо, но не слишком универсально, не так ли? Я имею в виду, что мне придется вернуться и сделать это для каждой модели отдельно. Я предполагаю, что альтернативой является создание вторичного менеджера для использования рассматриваемых моделей? - person jMyles; 09.07.2011
comment
И еще - это еще никто не проходил? Неужели я буду первой, кто этого захочет?! - person jMyles; 09.07.2011
comment
Здесь есть полезная информация о работе с моделями в целом: b- list.org/weblog/2007/nov/03/working-models . См., например, метод get_model() для получения класса модели на основе его имени. Не нужно делать это для каждой модели отдельно. Я гуглил, прежде чем ответить, и не смог найти существующее решение для вас. Извиняюсь! - person Gareth; 10.07.2011
comment
Интересно, правда? Я удивлен, что это не тема для дальнейшего разговора. Или мы просто не знаем, что искать? - person jMyles; 10.07.2011
comment
Что ж, если вы решите продолжить это (и я думаю, что вы должны), обязательно расскажите об этом всем, чтобы сообщество могло получить пользу :) - person Gareth; 10.07.2011