将django模型的编辑历史存储在另一个自定义模型中 [英] Storing the edit history of a django model in another custom model
问题描述
我有两个模型可以说:
class superfields(Model):
/ pre>
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中的所有值的新行,此外还有'reason'字段,而'my_model'数据保持不变
根据自定义模板,自定义视图,模型管理员等来处理这种情况的最佳方法是什么?我正在做正确的?
为了让我的问题更有意义,在我的项目中,my_model下的数据的性质是市场价格,我需要保持所有市场价格历史,
解决方案我的解决方案:
是的。我所追踪的一个简单而快速的解决方案如下:
我创建了类似于以下的三个模型:class my_super_abstract_model (模型):
/ pre>
#所有字段我需要保留以下历史:
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。连接(create_history,
sender = my_model_history)
和创建历史记录保存在my_model_history中的pre_save()信号:
def create_history(sender,** kwargs):
#get通过预先保存信号传递的变量:
history_model = kwargs ['instance']
#获取主模型对象
main_model = history_model.history_entry_for
#交换历史记录之间的所有常用字段编辑和主模型(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 history in history_mo del_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)
#交换后,在这里保存主模型对象
main_model.save()
每当用户单击my_model行进行编辑时,我使用'my_model_history'生成我的编辑表单,并使用用户选择的行中的值填充它。 (已经写了一个视图和模板)
所以编辑表单现在将有:
- 字段A包含来自
my_model数据行的值
- 字段使用
中的值填充b $ b
my_model数据行- 原因 - 空文本框
- history_entry_for -hidden from view
用户现在可以编辑fieldA / fieldB。输入原因按保存触发上述信号。
在保存之前,
- 信号将交换主模型(旧值)和$ b $之间的
之间的值b历史模型(新值)
- 替换并保存主模型行
(使用新值)。
- 插入并保存
历史模型中的新行(具有旧值)
有原因。
希望它帮助。如果还有其他问题,请通知我。
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.
解决方案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:
- field A -populated with values from my_model data row
- field B -populated with values from my_model data row
- Reason -empty text box
- history_entry_for -hidden from view
User can now edit fieldA/fieldB. Enter a reason. Press save to trigger the signal above. Before saving,
- Signal will swap the values between the main model(old values) and history model(New values)
- Replace and save the main model row (with the new values).
- 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.
这篇关于将django模型的编辑历史存储在另一个自定义模型中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!