zoukankan      html  css  js  c++  java
  • django revision

    由于多次涉及到了这个东东,又不是很理解机制,决定深入研究下。

    what

      django-revision到底啥玩意?readthedocs上只有一句话概括:django-reversion can be used to add a powerful rollback and recovery facility to your admin site

    而且只是说明了能干嘛:给admin后台管理提供强大的回滚和恢复功能。

      下面我们来看看,啥叫作强大的回滚和恢复。

          首先,新建一个项目: test_revision,过程略。

          新增模型: articles,包含以下字段:

     
    序号 栏位 说明
    1 title 标题
    2 content 内容
    3 author 作者
    4 status 状态
    5 create_date 创建日期
    6 publish_date 发布日期

         并注册到管理后台。因为只需要看后台,所以views/template/forms全部略。只需要写models 和 admin.py 如下:

    models.py

    from django.db import models
    
    # Create your models here.
    class article(models.Model):
        title = models.CharField(max_length=128)
        content = models.TextField()
        author = models.CharField(max_length=32)
        status_list=(('draft','draft'),('pending','pending'),('published','published'))
        status = models.CharField(max_length=16, choices=status_list)
        create_date = models.DateTimeField(auto_now_add=True)
        publish_date = models.DateTimeField()
    

    admin.py

    from django.contrib import admin
    import reversion
    from .models import article
    # Register your models here.
    class articleAdmin(reversion.VersionAdmin):
        list_display = ("id", "title", "author", "status","create_date")
    
    admin.site.register(article,articleAdmin)
    

    project文件夹结构:

    settings.py的installed_app中添加了“reversion",它涉及到的表是reversion_revision/ reversion_version,如下:

    再把test_app加入到installed_app中并syncdb一下,过程略,直接runserver,查看效果,如下:

    ok,测试下,

    1). 回滚操作:

    2). 数据恢复操作:

    点击"recover deleted articles"(右侧),选择某个时间对应的对象进入详细,要恢复点击保存即可,如下:

    awesome and impressive!

    How?

    原理:

    权威解释看这里:http://django-reversion.readthedocs.org/en/latest/how-it-works.html

    这里简单总结下:

          被注册,标记,子类化的模型,在其被create/update时会在version表里面做相应的记录,记录的内容就是模型的数据序列化后的json表达式。当需要恢复时,将json表达式反序列化出来,填充到表单里面去,让用户自己选择回滚到哪。至于恢复,则是恢复到最后一次操作后的状态。

    如何使用:

    以下方式都是在Admin.py中进行。

      1. 继承方式,需要继承reversion.VersionAdmin,适用于新开发的app,如下:

    import reversion
    
    class YourModelAdmin(reversion.VersionAdmin):
    
        pass
    
    admin.site.register(YourModel, YourModelAdmin)
    

      2. patch_admin注册方式,适用于已存在的尚未使用reversion的app,如下:

    from reversion.helpers import patch_admin
    
    patch_admin(User)
    

      对于尚未在admin.py中注册或者继承versionAdmin的模型,如果要实现版本控制有两个选择:

    1). 在admin.py中注册或者继承VersionAdmin

    2). 使用reversion的api进行控制,

    使用reversion.register()进行注册/修饰对应的模型类.

    具体参考这里

    后记

    发现一个有意思的问题,对于一个已经使用了reversion支持的模型:如果非admin后台修改了记录(update/delete),则delete的数据可以还原,update则无记录。实现如下:

    views.py

    from django.shortcuts import render
    from django.views.generic.edit import UpdateView,DeleteView
    from .models import article
    from django.shortcuts import render_to_response
    # Create your views here.
    
    class articleDV(DeleteView):
        model = article
        success_url = "/admin/test_app/article/"
        template_name = "article_delete.html"
    
    class articleUV(UpdateView):
        model = article
        success_url = "/admin/test_app/article/"
        template_name = "article_update.html"
    

    解决方案:

           适用于django-reversion 1.8.4 

          采用中间件(可以不用在admin里面继承VersionAdmin),在installed_app中加入中间件"reversion.middleware.RevisionMiddleware",同时修改django-reversion的reversion.py文件(windows则在C:Python27Libsite-packagesdjango_reversion-1.8.4-py2.7.egg eversion evisions.py)的171~182行(原码如下):

                           manager.save_revision(
                                dict(
                                    (obj, callable(data) and data() or data)
                                    for obj, data
                                    in manager_context.items()
                                ),
                                user = self._user,
                                comment = self._comment,
                                meta = self._meta,
                                ignore_duplicates = self._ignore_duplicates,
                                db = self._db,
                            )
    

      其中, self._user丢失,原因貌似由于多线程(至少有两个线程执行中间件的process_response方法),导致在实际写入数据的时候,self._user还没赋值,虽然逻辑上是先赋值给revision_context_manager._user(middleware.py 33~36行),后执行此段代码。鉴于这点,还需要修改middleware.py(C:Python27Libsite-packagesdjango_reversion-1.8.4-py2.7.egg eversionmiddleware.py)的类RevisionMiddleware的_close_revision方法,其原码如下:

        def _close_revision(self, request):
            """Closes the revision."""
            if request.META.get(REVISION_MIDDLEWARE_FLAG, False):
                del request.META[REVISION_MIDDLEWARE_FLAG]
                revision_context_manager.end()
    

      新代码:

    middleware.py(24~28)

        def _close_revision(self, request):
            """Closes the revision."""
            if request.META.get(REVISION_MIDDLEWARE_FLAG, False):
                del request.META[REVISION_MIDDLEWARE_FLAG]
                revision_context_manager.end(request=request)
    

    即:将request传入到reversion.py的RevisionContextManager类的end方法。

    reversion.py(171~182)

                            manager.save_revision(
                                dict(
                                    (obj, callable(data) and data() or data)
                                    for obj, data
                                    in manager_context.items()
                                ),
                                user = self._user or (hasattr(request, "user") and request.user),
                                comment = self._comment,
                                meta = self._meta,
                                ignore_duplicates = self._ignore_duplicates,
                                db = self._db,
                            )

    即:重写user的赋值逻辑。

    reversion.py(162行),函数定义改为:

    def end(self,request=None):
    

    即增加一个参数: request

  • 相关阅读:
    java Object类是可以接收集合类型的
    java.lang.String中[ "张飞"+1+1 ] 和 [ "张飞"+(1+1) ]
    AFL Fuzz入门
    [转载]linux与grep
    linux下安装clamav
    [转载]Linux连续执行多条命令
    [转载]linux下各文件夹的结构说明及用途介绍
    [转载]linux常用命令
    [转载]Ubuntu 16.04 蓝屏解决方案
    pycharm修改python版本
  • 原文地址:https://www.cnblogs.com/Tommy-Yu/p/3964391.html
Copyright © 2011-2022 走看看