Хранение истории редактирования модели Django в другой пользовательской модели - PullRequest
4 голосов
/ 11 ноября 2010

У меня есть две модели, скажем:

class superfields(Model):
    fieldA = models.FloatField()
    fieldB = models.FloatField()
    class Meta:
        abstract = True

class my_model( superfields ):
    def has_history( self ):
        return self.my_model_history_set.count() > 0

class my_model_history( superfields ):
    reason = models.TextField()
    mymodel = models.ForeignKey( my_model )

'my_model' заполняется данными (в полях A и fieldB). Всякий раз, когда кто-то редактирует поля my_model и сохраняет их, я не хочу сохранять изменения в этой модели, но хочу сохранить их в виде новой строки со всеми значениями в my_model_history, в дополнение к полю причины, тогда как my_model данные остаются прежними.

Каков наилучший способ приблизиться к этому сценарию с точки зрения пользовательских шаблонов, пользовательских представлений, администраторов моделей и т. Д. И т. Д. Правильно ли я делаю это?

Чтобы придать моему вопросу некоторый смысл, в моем проекте характер данных в 'my_model' - это рыночные цены, и мне нужно вести историю всех рыночных цен, когда-либо редактировавшихся, с указанием причины для редактирования.

Ответы [ 3 ]

2 голосов
/ 01 марта 2011

Мое решение:

да. Вот простое и быстрое решение, которому я следую: Я создаю три модели, похожие на это:

class my_super_abstract_model(Model):
    #All fields I need to keep a history for:
    fieldA = models.FloatField()
    fieldB = models.FloatField()
    class Meta:
        abstract = True

class my_model( my_super_abstract_model ):
    def has_history( self ):
        return self.my_model_history_set.count() > 0

class my_model_history( my_super_abstract_model ):
    reason = models.TextField()
    history_entry_for = models.ForeignKey( my_model )

Я настроил сигнал:

pre_save.connect( create_history, 
                  sender = my_model_history )

и 'create history' для вызова по сигналу pre_save () перед сохранением в my_model_history:

def create_history(sender, **kwargs):
    #get variables passed by the pre-save signal:
    history_model = kwargs['instance']
    # Get main model object
    main_model = history_model.history_entry_for
    # swap all common fields between history edit and main model (except id)  
    main_model_fields = [f.name for f in main_model._meta.fields]
    history_model_fields = [f.name for f in history_model._meta.fields]
    field_index = list( [f for f in history_model_fields if f in main_model_fields and f != 'id' and f != 'created_date' ] )
    #loop thru to swap values:
    for field_name in field_index:
        temp = getattr(main_model, field_name)
        setattr( main_model, field_name, getattr( history_model, field_name ) )
        setattr( history_model, field_name, temp)
    # After the swap, save main model object here 
    main_model.save()

Всякий раз, когда пользователь нажимает на строку my_model для редактирования, я использую my_model_history, чтобы сгенерировать форму редактирования и заполнить ее значениями из выбранной пользователем строки. (Для этого написали вид и шаблон)

Таким образом, форма редактирования теперь будет иметь:

  1. поле А заполнено значениями от Строка данных my_model
  2. поле B заполнено значениями от Строка данных my_model
  3. Причина - пустое текстовое поле
  4. history_entry_for - скрыто от просмотра

Пользователь теперь может редактировать поле A / fieldB. Введите причину. Нажмите сохранить, чтобы активировать сигнал выше. Перед сохранением

  1. Сигнал поменяет местами значения между основная модель (старые значения) и Модель истории (Новые значения)
  2. Заменить и сохранить основной ряд моделей (с новыми значениями).
  3. Вставьте и сохраните новую строку в модель истории (со старыми ценностями) с причиной.

Надеюсь, это поможет. Дайте мне знать, если есть еще вопросы.

2 голосов
/ 11 ноября 2010

Вместо редактирования существующей записи, почему бы не использовать эту запись в качестве исходных данных для формы для создания нового экземпляра? Новый объект будет сохранен, оригинал останется прежним ...

0 голосов
/ 12 ноября 2010

Я нашел объяснение о сохранении подробных историй редактирования в книге «pro Django», стр. 264. После прочтения я попробую реализовать то, что мне нужно.Опубликую мой подход здесь, когда я закончу

...