Django Admin的版本管理和回滚

2023-04-11 00:00:00 django 版本 管理

Django Admin默认提供了版本管理功能,可以方便地在后台管理界面进行记录和比较不同版本的修改。

首先,需要在model定义中添加版本管理器:

from django.contrib.admin.models import LogEntry
from django.contrib.contenttypes.models import ContentType
from django.db import models

class MyModel(models.Model):
    # fields and methods here

    class Meta:
        verbose_name_plural = "MyModels"

class MyModelVersionManager(models.Manager):
    def get_queryset(self):
        content_type = ContentType.objects.get_for_model(MyModel)
        return super(MyModelVersionManager, self).get_queryset().filter(content_type=content_type)

class MyModelVersion(LogEntry):
    objects = MyModelVersionManager()

    class Meta:
        proxy = True
        verbose_name = "MyModel Version"
        verbose_name_plural = "MyModel Versions"

这里使用了Django内置的LogEntry模型作为版本记录的基础,可以通过继承LogEntry来扩展版本记录的字段和方法。

MyModelVersionManager中,使用ContentType来获取MyModel的内容类型,然后使用super()来获取所有版本,并只筛选出MyModel的版本。

最后,定义了一个MyModelVersion模型,将其设置为代理模型,可以方便地对版本进行查询和比较,并添加了verbose_nameverbose_name_plural以便在管理界面中显示友好的名称。

接下来,在admin.py中添加版本管理的视图:

from django.contrib import admin
from django.contrib.admin.models import LogEntry

from .models import MyModel, MyModelVersion


class MyModelVersionInline(admin.TabularInline):
    model = MyModelVersion
    verbose_name = "Version"
    verbose_name_plural = "Versions"
    can_delete = False
    fields = ("action_time", "user", "action_flag", "change_message")

class MyModelAdmin(admin.ModelAdmin):
    list_display = (...)
    inlines = [MyModelVersionInline]

admin.site.register(MyModel, MyModelAdmin)
admin.site.register(LogEntry)

这里使用了MyModelVersionInline作为MyModelAdmin的内联管理器,将版本记录添加到MyModelAdmin的编辑界面中。

最后,可以在管理界面中查看和比较不同版本的修改。

对于回滚操作,可以使用Django的ORM和版本管理器来恢复到任意历史版本:

def rollback_to_version(model_instance, version_id):
    try:
        version = model_instance.versions.get(pk=version_id)
        for field, value in version.changed_data.items():
            setattr(model_instance, field, value)
        model_instance.save()
    except MyModelVersion.DoesNotExist:
        pass

这个函数接受两个参数:model_instance是要回滚的模型实例,version_id是要恢复的版本ID。使用get()方法从版本管理器中获取版本记录,然后使用版本记录的changed_data属性恢复模型实例的属性,并保存模型实例。如果指定的版本记录不存在,则跳过恢复操作。

相关文章