将 django 模型的编辑历史存储在另一个自定义模型中

发布于 2024-10-01 10:55:12 字数 699 浏览 2 评论 0原文

我有两个模型可以说:

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”填充了数据(在 fieldA 和 fieldB 下)。每当有人编辑“my_model”的字段并保存时,我不想保存此模型中的更改,而是希望将其存储为新行,其中所有值都在“my_model_history”中,此外还有“原因”字段,而“my_model”数据保持不变。

在自定义模板、自定义视图、模型管理等方面处理这种情况的最佳方法是什么?我做得正确吗?

为了让我的上述问题有一定的意义,在我的项目中,“my_model”下的数据本质是市场价格,我需要维护所有曾经编辑过的市场价格的历史记录,并附上编辑的“原因”。

I have two models lets say:

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' is populated with data (under fieldA and fieldB). Whenever someone edits 'my_model's fields and saves, I don't want to save the change in this model but want to store it as a new row with all values in 'my_model_history', in addition to a 'reason' field while 'my_model' data stays the same.

What is the best way to approach this scenario in terms of custom templates, custom views, model admins etc etc. Am I doing it correctly?

To give my question above some sense, in my project, the nature of data under 'my_model' is market prices and I need to maintain a history of all the market prices ever edited with a 'reason' for the edit.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

转角预定愛 2024-10-08 10:55:12

我的解决方案:

是的。我遵循的一个简单快速的解决方案如下:
我创建了三个与此类似的模型:

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 )

并在保存到 my_model_history 之前由 pre_save() 信号调用“创建历史记录”:

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. 字段 A -填充来自
    my_model 数据行
  2. 字段 B - 填充来自的值
    my_model 数据行
  3. Reason - 空文本框
  4. History_entry_for - 从视图中隐藏

用户现在可以编辑 fieldA/fieldB。输入原因。按保存触发上面的信号。
在保存之前,

  1. Signal 会交换之间的值
    主模型(旧值)和
    历史模型(新值)
  2. 替换并保存主模型行
    (使用新值)。
  3. 在中插入并保存新行
    历史模型(使用旧值)
    有一个理由。

希望有帮助。如果还有任何其他问题,请告诉我。

My Solution:

yes. A simple and quick solution I am following is as follows:
I create three models similar to this:

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 )

I've setup a signal:

pre_save.connect( create_history, 
                  sender = my_model_history )

and 'create history' to be called by the pre_save() signal before saving in 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()

Whenever user clicks on a my_model row for editing, I use 'my_model_history' to generate my edit form and populate it with the values from the user selected row. (Have written a view and template to do that)

So the edit form will now have:

  1. field A -populated with values from
    my_model data row
  2. field B -populated with values from
    my_model data row
  3. Reason -empty text box
  4. history_entry_for -hidden from view

User can now edit fieldA/fieldB. Enter a reason. Press save to trigger the signal above.
Before saving,

  1. Signal will swap the values between
    the main model(old values) and
    history model(New values)
  2. Replace and save the main model row
    (with the new values).
  3. Insert and save a new row in the
    history model (with the old values)
    with a reason.

Hope it helps. Let me know if there are any further questions.

三生殊途 2024-10-08 10:55:12

为什么不使用该条目作为表单的初始数据来创建新实例,而不是编辑现有条目?新对象被保存,原始对象保持不变......

Instead of editing an existing entry, why not use that entry as initial data for a form to create a new instance? The new object gets saved, the original stays the same...

ぇ气 2024-10-08 10:55:12

我在“pro Django”一书中第 264 页找到了关于保留详细编辑历史记录的解释。通读完之后,我将尝试实现我需要的内容。完成后将在这里发布我的方法

I found an explanation on keeping detailed edit histories in the book 'pro Django' page 264. After a read through I'll try an implementation of what I need. Will post my approach here when I'm done

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文