python DRY方式添加创建/修改人和时间

bvhaajcl  于 2023-06-20  发布在  Python
关注(0)|答案(3)|浏览(124)

有一些像

  • 创建者
  • 创建日期
  • 修改者
  • 修改日期

对很多table来说都是很常见的模式。
1)您可以在www.example.com中使用以下命令自动设置创建日期(而不是其他日期)model.py

created_date = models.DateTimeField(auto_now_add=True, editable=False)

2)您可以在www.example.com中使用以下命令创建/修改日期(但不是由/user创建,因为没有请求上下文)model.py:

def save(self):
    if self.id:
        self.modified_date = datetime.now()
    else:
        self.created_date = datetime.now()
    super(MyModel,self).save()

3)您可以在www.example.com中设置创建/修改日期和截止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_required的事情吗?@audit_changes
  • 你能访问模型中的请求和当前用户,并在那里集中逻辑吗?
zvms9eto

zvms9eto1#

创建/修改日期现在可以由Django处理,所以它们可以像这样实现:

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

    class Meta:
        abstract = True

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

class Pizza(BaseModel):
    ....

class Topping(BaseModel):
    ...

由于request.user不可用,因此存储用户更加困难。正如SeanOC所提到的,这是Web请求和模型层之间的关注点分离。要么一直传递这个字段,要么将request.user存储在threadlocal中。Django CMS为他们的权限系统做了这件事。

from django.utils.deprecation import MiddlewareMixin

class CurrentUserMiddleware(MiddlewareMixin):
    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_current_user

kdfy810k

kdfy810k2#

对于带时间戳的模型,您可能希望查看django-model-utilsdjango-extensions。它们每个都包括抽象基类,这些基类自动处理创建的和最后修改的时间戳。您可以直接使用这些工具,也可以查看它们如何解决问题,然后提出自己的解决方案。
至于你的其他问题:
你能做一些像@login_required的事情吗?@audit_changes
可能是的,但是你必须非常小心地保持线程安全。您可以在@audit_changes装饰器中设置一个标志来启用threadlocal中的审计。然后,在模型的保存方法或信号处理程序中,您可以检查您的审计标志并记录您的审计信息(如果该标志已设置)。
你能访问模型中的请求和当前用户,并在那里集中逻辑吗?
是的,但你要做个交易。正如你所触及的,Django的ORM和它的请求/身份验证处理位之间有一个非常清晰和有意的分离。有两种方法可以从请求(当前用户)获取信息到ORM(您的模型)。您可以手动管理更新对象上的创建者/修改者信息,也可以设置一种机制来自动处理该维护工作。如果您采用手动方法(通过方法调用将信息从视图中的请求传递到ORM),则需要维护/测试更多的代码,但您可以保持关注点的分离。使用手动方法,如果您不得不在请求/响应周期之外使用对象(例如:cron-scripts、延迟任务、交互式shell)。如果你愿意打破关注点的分离,那么你可以在中间件中设置一个线程,然后在你的模型的保存方法中查看这个线程。与手动方法匡威,您需要处理的代码会更少,但如果您希望在请求/响应周期之外使用对象,则会遇到更大的困难。此外,您必须非常小心地使用更自动化的方法来保持所有内容的线程安全性。

d7v8vwbk

d7v8vwbk3#

可以导入User模型对象并调用get_current()吗?
另外,我认为你可以在admin.py中调用视图。

相关问题