django-simple-history 跟踪来自 python shell 的用户

django-simple-history track User from python shell

我们正在使用 django-simple-history 来跟踪模型的变化。所有模型都有一个 history = HistoricalRecords() 字段。当从 python shell 对模型进行更改时,将跟踪更改,但 changed_by 字段将保存为 None。当在 admin 中进行更改时,simple_history 中间件会从登录的任何人那里获取 User 实例。显然在 shell 中我们没有那个。有什么方法可以根据现有的 Account 对象手动注入 User 实例吗?

不幸的是,我无法更改这些模型中的任何一个,所以我无法将任何历史用户 getter 和 setter 添加到我们的模型中(项目经理对重构非常严格,我们也有很多模型)

docs 所示,对于一个名为 ObjectWithHistory 的具有历史记录的特定对象,您可以在保存之前在该对象上设置历史记录用户,如下所示:

o = ObjectWithHistory(*kwargs)
o._history_user = this_user
o.save()

使用中间件

如果您通过 Django 视图编辑数据库,HistoryRequestMiddleware middleware 会自动处理此问题

self.client.post(reverse("frontend:application_create"), data=data)

而不是直接在命令行中

myapp.models.Application.objects.create(name='My application')

示例(单元测试)

这是一个单元测试,用于找出哪个用户更改了记录(受 django-simple-history unit tests 启发)。

# tests.py
class HistoryTestCase(TestCase):
    def test_changed_by(self):
        """Find out which user changed a record"""

        # First, let's create and log a user in
        user = get_user_model().objects.create_user("jimihendrix", password="pwtest")
        self.client.login(username="jimihendrix", password="pwtest")

        # Let's create a new entry
        data = {"name": "A new application", }
        response = self.client.post(reverse("frontend:application_create"), data=data)

        # This how you know who changed the record
        self.assertEqual(app1.history.earliest().history_user, user)
        self.assertEqual(app1.history.last().history_user, user)
        self.assertEqual(app1.history.first().history_user, user)

# urls.py
    # ...
    path('application/create/', old_views.ApplicationCreate.as_view(), name='application_create'),
    # ...

# models.py
class Application(models.Model):
    name = models.CharField(max_length=200)