1
Vegetable 2019-09-24 17:25:07 +08:00
threadlocal 可破
|
2
a719114136 2019-09-24 17:50:28 +08:00 via Android
继承 Manager 重写他的 filter 等方法,然后你的 model 使用你重写的 Manager。具体细节记不清了,好久不写 Django 了。
不过最好还是在你要记录的地方手动写代码。 |
3
huazhaozhe OP @Vegetable 全局对象,可以,有点像 flask 的 LocalStuck
|
4
n329291362 2019-09-24 19:35:30 +08:00
|
5
huazhaozhe OP @n329291362 恩,已经了解到了全局对象
|
6
huazhaozhe OP @n329291362 emmm Manager 有 filter,我不知道...每个地方都手动写代码也太不好了, 设计的目地就是一个全局的用户操作记录, 而不是某几个应用
|
7
omri 2019-09-24 22:02:52 +08:00
没太明白,到底是记录数据库记录的增删改查记录,还是记录用户的操作记录呢?还有我还挺好奇什么样的地方拿不到 request。
我这边设计了一套记录用户操作记录的方法,前提是采用前后端分离的架构,前端请求“改”的时候要把当前数据(即改前数据)也传过来,django 这边用自定义的 middleware 来解析 request 并把相应的操作存到数据库,然后在展示时设计一个全局的 dict 来将原始数据转换成可读的中文内容 |
8
huazhaozhe OP @omri 应该都包括吧, 用户的一个操作一般对应了一个请求嘛, 但是不同情况下同一个 URL 请求到后台具体会引起那些表的那些记录的增删改查的那个一个操作都是不确定的, 所以记录了 request 的 url, 还记录增删改查个中的哪一个, 如果是改的话得记录改前改后的值分别是啥, 并且这些记录都和这个用户关联起来
这个操作记录是要全局有效的, 每个应用都会用到, 并且新增应用(也就是新的 model 的增删改查)的时候, 不再关心也不需要再写操作记录方面的任何逻辑, 就像这个操作记录不存在一样 request 大部分时候是能够拿到的, 但是为了上面的要求, 在操作记录的实现逻辑代码里面不能同时得到 request 和这个 request 到底引起那些模型的那些实例的那些字段的改变 全局的 dict 是啥, python 的全局可用嘛, 还是借助外部比如 redis 啥的 |
9
huazhaozhe OP @omri 让前端传改之前的数据也不太好, 本来改之前的数据数据库中都有, 而且前端传回来的数据也不完全可信, 如果有逻辑要依赖这个之前的数据的话更不好了
|
10
huazhaozhe OP 其实就是感觉 django 缺个像 flask 的 4 个全局对象, flask 的全局 request 在很多地方都可以用
|
11
omri 2019-09-24 23:01:18 +08:00
@huazhaozhe 我大概理解你的意思了。我说的方法是记录 request 的方法,而你想要的是记录 request 的同时,记录这个 request 增删改查了哪些数据?
如果是这样的话: 1.django.db.connections 存放了 django 运行过程中的所有 raw sql 语句。 https://docs.djangoproject.com/en/2.2/faq/models/#how-can-i-see-the-raw-sql-queries-django-is-running 2.django 的 middleware 可以在每个请求前和请求后记录上面的 raw sql,比较差异就知道该 request 进行了哪些 sql 操作( process_request 和 process_response ) https://docs.djangoproject.com/en/2.2/topics/http/middleware/ 3.如何标识唯一的 request ?我想到的为每个 request 生成唯一的 uuid,上面大佬们提到的 threadlocals 或许更好,这个我没试过 不知道能否给你提供一些思路 |
12
omri 2019-09-24 23:10:26 +08:00
好吧。。还要记录改之前的数据。。那我想到的除了前端回传就是上面大佬提到的覆写 filter 方法,在每个 filter 执行之前先记录当前的数据
|
13
huazhaozhe OP @omri
单独记录 request 或者单独记录一条数据的操作记录不难的,就是 2 个关联起来。。。 然后单独记录一条数据的操作记录其实已经有第三方现成的插件了,我自己的话是用的信号机制实现的,没有深入到涉及 SQL 真的有重写 manager filter 方法嘛,是啥意思我完全没懂,没有搜到文档哎😄 |
14
omri 2019-09-25 00:07:39 +08:00
|
15
sivacohan 2019-09-25 00:58:11 +08:00 via iPhone
你提出的需求实际上包含两个问题。
1. 数据变更日志 2. 用户操作日志 问题 1 有框架级解决方案,一般叫做 ActiveLog。Django 有三个以上的库来解决这个问题。 问题 2 本质上是基于操作审计产生的需求,搜索关键词用 AuditLog 或者 OperationLog。但是因为这种日志往往与实际接口有关,所以还是需要逐个接口配置。尤其像你说的查询操作,这里查询往往会有多表连表的情况,直接记录表名不太合适。 综上所述,数据变更是对应数据库表的,一般框架都能处理。操作日志是对应接口的,因为框架很难确定你使用的接口规范,所以这里需要你单独处理。 操作日志的一个简易形式是字段形式式为 id operator api api_version request response。这个部分直接输出到日志文件里。而后配置日志文件的监听器,把需要展示给用户的部分再抓出来,这样就可以完整满足用户需求了。 |
16
freakxx 2019-09-25 01:59:08 +08:00
拆成 2 个部分
记录的话用信号机制,用 init 事先 copy (性能的话会有损耗) 搜索关键词 django signal field change 参考 https://stackoverflow.com/questions/36719566/identify-the-changed-fields-in-django-post-save-signal https://stackoverflow.com/questions/1197674/actions-triggered-by-field-change-in-django 记录访问操作,考虑做一个中间件 流过 process request 或者 view request 做一下记录 搜索关键词 django middleware log 参考 https://djangosnippets.org/snippets/428/ https://stackoverflow.com/questions/862522/django-populate-user-id-when-saving-a-model/12977709#12977709 |
17
ohhe 2019-09-25 07:11:07 +08:00
|
18
huazhaozhe OP @ohhe 这个做的比较好了
这个必须在每个模型中定义一个 history, 不能抽象类继承, 并且一个每个模型都会创建一张记录表 与用户关联的话, 依赖 django 的中间件, 如果使用 rest_framework 自定义用户验证的话, 得不到用户的, 所以必须每次更改的时候传入 user |
19
huazhaozhe OP @freakxx
恩,是拆成 2 个部分, 不过现在要把 2 个部分关联起来, 也就是一个 request 引起的多个记录关联起来, 这些都要和用户关联 跟踪一个实例的 field change 的话我是直接改__init__和__setattr__方法添加一个属性就可以实现, 并且只记录了更改的 field. 没有变的 field 不会记录, 在实例更改保存的时候使用了信号来保存更改之前之后的值, 直接 copy 整个实例 emmm 貌似太伤了 |
20
huazhaozhe OP @sivacohan
我这里其实是需要把 2 个部分关联起来的, 一边是 ORM 操作, 另一边是视图, 大部分情况下其实可以关联起来, 不过这里要做一个全局的, 也不要每个接口单独配置, 每个视图都要写逻辑的这种 目前看来使用 threadlocals 应该可以 |
21
huazhaozhe OP @n329291362
@omri 还真有这个写法, 不过官方文档只介绍了 QuerySet filter, 没想到 manager, 不过跟踪实例字段变化已经有更好的实现思路了 manager 这部分也只是在 ORM 这边, 要和 request 有关系还是要在每个视图里面写逻辑 |
22
lowman 2019-09-25 11:43:23 +08:00
如果我没理解错楼主的需求的话, 我觉得 django signal 机制 可以实现这个需求
|
23
huazhaozhe OP @lowman
对的, 会用到, 只是全局跟踪变更记录的话, 用信号机制就可以 |
24
omri 2019-09-25 15:23:20 +08:00 via iPhone
@huazhaozhe 有最终方案了吗?能分享一下那?共同学习哈
|
25
huazhaozhe OP @omri
我自己想法大概是这样子: 全局 request 用 threadlocal, 这个比较简单, 上面有人说了有现成的 数据的增删改记录第三方也有, 比如 django-simple-history, 在每个模型里面加个字段就可以, 与用户关联的话参考 django-simple-history 文档有相关描述, 是可以满足这个需求的, 不过我打算自己用 django 的信号机制写这部分逻辑, 可以全局记录, 没全局需求的话用 django-simple-history 应该完全够了 |
26
kerwinlv12 2021-01-29 09:03:50 +08:00
@huazhaozhe 我这边有好几个应用,我需要全局使用信号,我发现只能应用到一个 app 模块,期待回复,感谢
|