【问题标题】:django historical object valuesdjango 历史对象值
【发布时间】:2013-02-01 08:59:26
【问题描述】:

我知道那里有回归,我知道 django 中有 fullhistory 分支。但我非常想坚持 django 对象的原始历史。我只需要确保我还保存 OLD 和 NEW 值。

默认情况下,django 只保存发生的事情(例如更新),但不存储值。任何人都可以向我指出一些东西(sn-p 或应用程序),它略微增强了 django 的默认历史记录,并且还存储了编辑属性的值,而不仅仅是它被编辑的事实。

现在我的历史说

9-01-2012 12:55:02 更改:时间

我想说

9-01-2012 12:55:02 更改:时间从 6 点到 8 点

更新: ==> 对于任何对我的解决方案感兴趣的人(基于下面的答案)..

  1. 在我的 models.py 中添加了 HistoryModel(object) 类

       class HistoryModel(object):
             changed_fields = {}
    
  2. 在我的任何模型中继承

  3. 添加了一个 pre_save 接收器来保存旧值:

        @receiver(pre_save, sender=Customer) 
        def save_old_values(sender,**kwargs):
            #dont delete using in eval
            db_obj = sender.objects.get(pk=kwargs['instance'].pk)
            for field in kwargs['instance']._meta.fields:
                if not eval("db_obj." + str(field.get_attname_column()[0])) == eval("kwargs['instance']." +  str(field.get_attname_column()[0])):
                         kwargs['instance'].changed_fields[field.get_attname_column()[0]] = "from "+str(eval("db_obj." + str(field.get_attname_column()[0]))) + " to " + str(eval("kwargs['instance']." +  str(field.get_attname_column()[0])))
    
  4. 在我的 admin 中重写 log_change 方法并收集 object.changed_fields 字典并将其存储为消息

【问题讨论】:

    标签: django


    【解决方案1】:

    这不是“默认 django”。您正在使用贡献的 django 应用程序 (the admin),因此它与任何其他应用程序(即 django-reversion)一样,并且在某种程度上,它不支持您想到的开箱即用的功能。

    幸运的是,django 管理员是可配置的。您可以尝试ModelAdmin 类的overwriting the log_change 方法,并通过检测哪些字段已更改(通过将表单值与数据库值进行比较)使change_message 更详细。大概您希望在项目中的所有应用程序中都使用此功能,因此可以编写一个 mixin 来支持此功能,或者分叉整个管理员并对功能进行硬编码。

    【讨论】:

    • 太好了,谢谢,这帮助很大!我最终在我的自定义管理类中使用了覆盖 log_change 并且还为模型附加了一个 pre_save 函数以保留旧值(在调用 log_change 时这些值已经消失)。谢谢
    【解决方案2】:

    要扩展有关更改的信息,仅覆盖 ModelAdmin.construct_change_message 方法就足够了。无需在模型上添加属性(例如 changed_fields),因为您可以从表单和表单集的初始数据构建日志消息。

    这是一个记录每个更改字段的先前值的版本:

    def construct_change_message(self, request, form, formsets):
        change_message = []
        if form.changed_data:
            msg_list = u''
            for field in form.changed_data:
                if form.initial[field] is not None and hasattr(form.fields[field], 'queryset'):
                    old_value = form.fields[field].queryset.get(id=form.initial[field]).__unicode__()
                else:
                    old_value = form.initial[field]
                msg_list = _("{0}field '{1}' from \"{2}\", ").format(msg_list, field, old_value)
            change_message.append(capfirst(_(u'changed {0}.').format(msg_list[:-2])))
    
        if formsets:
            for formset in formsets:
                for added_object in formset.new_objects:
                    change_message.append(_('Added %(name)s "%(object)s".')
                                          % {'name': force_unicode(added_object._meta.verbose_name),
                                             'object': force_unicode(added_object)})
                for changed_object, changed_fields in formset.changed_objects :
                    for form in formset.initial_forms:
                        if form.instance != changed_object:
                            continue
                        msg_list = u''
                        for field in changed_fields:
                            if form.initial[field] is not None and hasattr(form.fields[field], 'queryset'):
                                old_value = form.fields[field].queryset.get(id=form.initial[field]).__unicode__()
                            else:
                                old_value = form.initial[field]
                            msg_list = _("{0}field '{1}' from \"{2}\", ").format(msg_list, field, old_value)
                        change_message.append(_('Changed %(list)s for %(name)s "%(object)s".')
                                              % {'list': msg_list[:-2],
                                                 'name': force_unicode(changed_object._meta.verbose_name),
                                                 'object': force_unicode(changed_object)})
                for deleted_object in formset.deleted_objects:
                    change_message.append(_('Deleted %(name)s "%(object)s".')
                                          % {'name': force_unicode(deleted_object._meta.verbose_name),
                                             'object': force_unicode(deleted_object)})
        change_message = ' '.join(change_message)
        return change_message or _('No fields changed.')
    

    【讨论】:

      猜你喜欢
      • 2013-10-07
      • 1970-01-01
      • 1970-01-01
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多