Django 后台在记录保存时先保存旧记录内容
场景:在一些重要的数据表,如设备台账表里,我们希望在记录保存时能够先保存一下旧记录内容,以便出现错误修改时能反查,恢复,这就是我们的需求。
首先我们考虑一下,各数据表数据结构各不相同,如果针对每一个数据表做一个备份表太过繁琐,所以我们考虑只用一个 TextField
来保存旧记录内容,而把记录的各字段内容生成 Json
的形式保存到 TextField
中,就可以不用管各数据表的字段有多少,再附上方便检索和引用的表名、记录号、修改时间、操作人员等字段信息,那一个备份表就基本上够了。
我们在 recordbackup
这个应用里
# recordbackup.models.py
from django.db import models
# Create your models here.
class RecordBack(models.Model):
app = models.CharField(max_length=20, verbose_name='应用', blank=True)
model = models.CharField(max_length=20, verbose_name='数据表')
rid = models.IntegerField(verbose_name='记录号')
content = models.TextField(verbose_name='原记录内容')
modified_time = models.DateTimeField(verbose_name='修改时间')
user = models.CharField(max_length=20, verbose_name='操作人')
class Meta:
verbose_name_plural = verbose_name = '记录备份'
创建 admin.py
用于后台查看备份数据,只读
# recordbackup/admin.py
from django.contrib import admin
from .models import *
# Register your models here.
@admin.register(RecordBack)
class RecordBackAdmin(admin.ModelAdmin):
list_display = ('app', 'model', 'rid', 'modified_time', 'user', 'list_operate')
readonly_fields = ('app', 'model', 'rid', 'content', 'modified_time', 'user')
list_filter = ('app', 'model',)
def list_operate(self, obj):
return '<a href="/admin/%s/%s/%s/"><i class="icon-th-list" title="查看原记录"></i></a>' % (obj.app, obj.model, obj.rid)
list_operate.short_description = '操作'
list_operate.allow_tags = True
生成相关数据表
./manage.py makemigrations
./manage.py migrate
再创建一个 utils.py
用于转换记录为 Json
和保存旧记录功能的函数。
# recordbackup/utils.py
import json
import datetime
def toJSON(obj):
"""
对对象进行 json 序列化,以 json 序列方式保存记录内容
:param obj: 记录对象
:return: 返回 json 串
"""
fields = []
for field in obj._meta.fields:
fields.append(field.name)
d = {}
for attr in fields:
if isinstance(getattr(obj, attr),datetime.datetime):
d[attr] = getattr(obj, attr).strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(getattr(obj, attr),datetime.date):
d[attr] = getattr(obj, attr).strftime('%Y-%m-%d')
else:
d[attr] = getattr(obj, attr)
return json.dumps(d)
def OldRecordSave(self, request, obj, form, change):
"""
保存旧记录的数据
:param self: 修改前的记录对象
:param request:
:param obj: 修改后的记录对象
:param form: 表单数据
:param change: 表单数据是否被修改
:return: None
"""
from .models import RecordBack
if change:# 更改的时候
rb = RecordBack()
rb.app = self.model._meta.app_label
rb.model = self.model.__name__.lower()
rb.rid = obj.pk
rb.modified_time = datetime.datetime.now()
obj_original = self.model.objects.get(pk=obj.pk)
if obj_original:
rb.content = toJSON(obj_original)
rb.user = request.user
rb.save()
else:# 新增的时候
pass
现在记录备份的功能可以用了,我们在台账数据表 PcAdmin
的 save_model()
里加了保存旧记录的操作 OldRecordSave()
# pc/admin.py
from .models import *
from recordbackup.utils import OldRecordSave
class PcAdmin(admin.ModelAdmin):
......
def save_model(self, request, obj, form, change):
OldRecordSave(self, request, obj, form, change) # 保存旧记录的数据到备份表
obj.save()
现在我们可以做一个测试,进入 PC 的编辑页面,修改一个字段信息,然后保存,我们看看 记录备份
表是不是多出一条记录,内容正是 PC 保存前的内容。
类似的,我们只要在需要保存旧数据的 admin 中引入 from recordbackup.utils import OldRecordSave
,再在 save_model()
的 obj.save()
前加入 OldRecordSave(self, request, obj, form, change)
就可以实现旧记录数据的保存了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Vue 入门
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论