Python 添加创建人/修改人和时间的干燥方式

Python 添加创建人/修改人和时间的干燥方式,python,django,Python,Django,有点像 创建于 创建日期 修改 修改日期 对于许多表来说,这是一种非常常见的模式 1) 您可以使用在model.py中自动设置创建日期(但不能设置其他日期) created_date = models.DateTimeField(auto_now_add=True, editable=False) def save(self): if self.id: self.modified_date = datetime.now() else: sel

有点像

  • 创建于
  • 创建日期
  • 修改
  • 修改日期
对于许多表来说,这是一种非常常见的模式

1) 您可以使用在model.py中自动设置创建日期(但不能设置其他日期)

created_date = models.DateTimeField(auto_now_add=True, editable=False)
def save(self):
    if self.id:
        self.modified_date = datetime.now()
    else:
        self.created_date = datetime.now()
    super(MyModel,self).save()
2) 您可以在model.py中使用

created_date = models.DateTimeField(auto_now_add=True, editable=False)
def save(self):
    if self.id:
        self.modified_date = datetime.now()
    else:
        self.created_date = datetime.now()
    super(MyModel,self).save()
3) 您可以在admin.py中设置创建/修改的日期和时间,但这不处理非管理员更新

def save_model(self, request, obj, form, change):
    if change:
        obj.modified_by = request.user
        obj.modified_date = datetime.now()
    else:
        obj.created_by = request.user
        obj.created_date = datetime.now()
    obj.save()
4) 最后一个位置是view.py,它可以完成所有4项,但不包括管理员更新

因此,现实地说,必须将逻辑展开,至少在3和4中重复(或者从这两种方法调用模型上的方法,这将被忽略)

有什么更好的办法?(我已经与python/django合作了几天,因此很容易遗漏一些显而易见的东西)

  • 您是否可以执行诸如@login\u required之类的操作,例如@audit\u更改
  • 您能否访问模型中的请求和当前用户,并在那里集中逻辑

能否导入用户模型对象并调用get_current()


另外,我认为您可以调用admin.py中的视图。

来查看可能需要查看或修改的时间戳模型。它们每个都包含抽象基类,这些抽象基类自动处理创建的和最后修改的时间戳。您可以直接使用这些工具,也可以查看它们是如何解决问题的,并提出自己的解决方案

至于你的其他问题:

您是否可以执行诸如@login\u required之类的操作,例如@audit\u更改

可能是的,但你必须非常小心,以保持线程安全。您可能要做的是在@audit\u changes装饰程序中,设置一个标志以在threadlocal中启用审核。然后,无论是在模型的save方法中还是在信号处理程序中,您都可以检查您的审计标志,并记录您的审计信息(如果该标志已设置)

您能否访问模型中的请求和当前用户,并在那里集中逻辑


是的,但你要做一个权衡。正如您所提到的,Django的ORM和它的请求/身份验证处理位之间有一个非常明确和有意的分离。有两种方法可以从请求(当前用户)到ORM(您的模型)获取信息。您可以手动管理对象上的创建者/修改器信息的更新,也可以设置一种机制来自动处理该维护工作。如果您采用手动方法(通过方法调用将信息从视图中的请求传递到ORM),则需要维护/测试更多的代码,但您需要保持关注点的分离。使用手动方法,如果您必须在请求/响应周期之外使用对象(例如cron脚本、延迟任务、交互式shell),您的状态会更好。如果您同意打破这种关注点分离,那么您可以设置一些东西,在中间件中为当前用户设置一个本地线程,然后在模型的save方法中查看该本地线程。与手动方法相反,您需要处理的代码会更少,但如果您想要在请求/响应周期之外处理对象,则会遇到更大的困难。此外,您必须非常小心,以更自动化的方式确保所有内容的线程安全。

创建/修改日期现在可以由Django处理,因此它们可以像以下那样实现:

class BaseModel(models.Model):
    created_date = models.DateTimeField(auto_now_add=True)
    modified_date = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True
通过将其添加到抽象模型基类中,可以轻松地将其添加到应用程序的所有模型中

存储用户比较困难,因为
请求.user
不可用。正如SeanOC提到的,这是web请求和模型层之间的关注点分离。要么一直传递此字段,要么将
request.user
存储在threadlocal中。Django CMS为其权限系统执行此操作

class CurrentUserMiddleware(object):
    def process_request(self, request):
        set_current_user(getattr(request, 'user', None))
用户跟踪发生在其他地方:

from threading import local
_thread_locals = local()

def set_current_user(user):
    _thread_locals.user=user

def get_current_user():
    return getattr(_thread_locals, 'user', None)

对于非web环境(例如管理命令),您必须在脚本开始时调用
set\u current\u user

get\u current用于Django的站点框架,而不是身份验证。如果不将请求对象传递到作用域中,它将无法帮助您获取当前用户。找到它-尚未正确读取它+1。我希望看到Djangoseque解决方案集中基于请求的模型代码。。最干净的方法是什么!?这个答案解决了这个问题,但如果它还讨论了线程局部变量的潜在问题,那就太好了。我已经简单地谈到了这一点,但我主要可以说它可能会打破关注点的分离,并在整个应用程序中公开敏感数据(不确定第二部分是否是真正的风险)。所有关于全局变量的关注点也适用。在Django==1.10.2中使用,这会破坏中间件。您必须使用
类CurrentUserMiddlexin(MiddlewareMixin):
意味着您从django.utils.Deprection导入
MiddlewareMixin
注意:
自动\u now
处于启用状态。更新。