【问题标题】:django-simple-history track User from python shelldjango-simple-history 从 python shell 跟踪用户
【发布时间】:2023-03-28 14:34:01
【问题描述】:

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

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

【问题讨论】:

  • “根据现有的 Account 对象手动注入 User 实例”是什么意思?
  • 我可能没有使用正确的术语。您应该能够从HistoricalRecords.thread.request.user 获取用户,但在 shell 中,本地线程没有请求属性。我想知道是否有某种方法可以附加它
  • 但是你会附加什么用户呢?没有办法知道。
  • 我们正在通过 shell 从外部服务 (jenkins) 运行脚本,该服务将拥有用户电子邮件,该电子邮件对应于数据库中的一个帐户

标签: python django django-simple-history


【解决方案1】:

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

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

【讨论】:

  • 哦,天哪,我想我之前阅读时一定误解了文档所说的内容。谢谢!
【解决方案2】:

使用中间件

如果您通过 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)

【讨论】:

    猜你喜欢
    • 2020-10-10
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多