Преобразование данных при сохранении и чтении из базы данных - PullRequest
1 голос
/ 30 декабря 2011

Предположим, у меня есть эта модель (не реальный код):

class Message(models.Model):
    content = models.CharField(...)
    mentions = models.ManyToManyField(User)

содержимое может быть, например:

Скажите привет @Adam и @ Bernard

Во время модели сообщения save () из текста извлекаются «Адам» и «Бернард», и к ним добавляются соответствующие экземпляры пользователей, так что

 >>> m = Message.objects.create(content="Say hi to @Adam and @Bernard")
 >>> m.mentions.all()
 >>> [User: Adam, User: Bernard]

Теперь, что касаетсямоя проблема:

Как мне справиться с тем, как Бернард сменил пол и переименовал себя в Бернарду?Мне бы очень хотелось, чтобы содержимое читалось Say hi to @Adam and @Bernarda.

По сути, я попробовал стратегию замены имен на идентификаторы при сохранении (Say hi to @Adam and @Bernard затем становится Say hi to @1 and @2, то есть их User.pk's).Это отлично работает при сохранении, и ОК при чтении.

Выполнение этой замены в методе save () модели работает нормально, но операции чтения и поиска являются серьезной проблемой.Я не могу найти простой способ убедиться, что то, что хранится в базе данных (т. Е. Say hi to @1 and @2), «волшебным образом» становится Say hi to @Adam and @Bernard всякий раз, когда к нему обращаются (например, через .filter () и связанные с ним операции) или когда его экземпляр являетсяоценил.

Я не уверен, что я на правильном пути здесь;любые указания или идеи сделать это по-другому, очень приветствуются!

1 Ответ

3 голосов
/ 30 декабря 2011
  1. Напишите класс поля пользовательской модели , который расширяет CharField, вы должны перечитать сначала документацию , чтобы иметь представление о том, что там,

  2. , что метакласс = models.SubfieldBase требуется для пользовательского поля для вызова пользовательского метода to_python

  3. Overrideto_python () , принимает значение базы данных и должно возвращать значение Python, там вы можете заменить @ 1 именем пользователя # 1 (скажем, @Adam или @Bernarda),

  4. Переопределить get_prep_value () , , он принимает значение Python и должен возвращать значение для SQL, там вы можете заменить @Adam на pk ofПользователь Admin (скажем @ 1),

  5. Запрос на упоминание , например Message.objects.filter(mention=someuser), или создание другого поля: одно, которое содержит замененную версию, и другое, котороесодержит возможно устаревшие имена пользователей - я не рекомендую последние

  6. Вы можететакже запросить содержание , например Message.objects.filter(content__contains='@1')

Вуду не приносит никакой пользы , я бы сделал метод модели get_content_display() который выполняет замену, и тег шаблона, отображающий html-версию содержимого - поскольку вы, вероятно, все равно захотите связать @Adam с его пользовательской страницей.Я бы придерживался этого, потому что это KISS .

КРЕДИТЫ в LaundroMat для отладки этого ответа и его исправления (было 2 ошибки и 1 неточность, которую он отладил ивернулся, чтобы сообщить !!!).Также СДЕЛАЙТЕ ЕГО КОММЕНТАРИЙ , если у вас нет лучшего способа наградить его.Rock'on.

...