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

时间:2011-01-21 01:14:04

标签: python django

有类似

的东西
  • created_by
  • created_date
  • modified_by
  • MODIFIED_DATE

很多桌子都是非常常见的模式。

1)您可以使用

在model.py中自动设置创建日期(但不能设置其他日期)
created_date = models.DateTimeField(auto_now_add=True, editable=False)

2)您可以使用

在model.py中创建/修改日期(但不是/ user,因为没有请求上下文)
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_required这样做吗@audit_changes
  • 您是否可以访问模型中的请求和当前用户并将逻辑集中在那里?

3 个答案:

答案 0 :(得分:90)

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

一样实现
class BaseModel(models.Model):
    created_date = models.DateTimeField(auto_now_add=True)
    modified_date = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

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

存储用户比较困难,因为request.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)

对于非网络环境(例如管理命令),您必须在脚本开头调用set_current_user

答案 1 :(得分:9)

对于带时间戳的模型,您可能希望查看django-model-utilsdjango-extensions。它们每个都包含抽象基类,可自动处理已创建和上次修改的时间戳。您可以直接使用这些工具,也可以查看他们如何解决问题并提出自己的解决方案。

至于你的其他问题:

  

你可以像@login_required那样做,例如@audit_changes

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

  

您是否可以访问模型中的请求和当前用户并将逻辑集中在那里?

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

答案 2 :(得分:-2)

您可以导入用户模型对象并调用get_current()吗?

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