DRY的方式添加创build/修改和时间
有类似的东西
- 由…制作
- 创builddate
- modified_by
- 修改date
对于很多表格来说,这将是一个非常常见的模式。
1)您可以在model.py中自动设置创build的date(但不是其他)
created_date = models.DateTimeField(auto_now_add=True, editable=False)
2)您可以在model.py中使用创build/修改的date(但不能通过/ user,因为没有请求上下文)
def save(self): if self.id: self.modified_date = datetime.now() else: self.created_date = datetime.now() super(MyModel,self).save()
3)你可以设置创build/修改的date,并在admin.py – 但这不处理非pipe理更新
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,但不包括pipe理更新。
所以现实中必须有逻辑分散,至less在3和4中重复(或从两个模型中调用的方法,这将被错过)
最好的方法是什么? (我一直在使用python / django几天,所以很容易丢失一些明显的东西)
- 你能像@login_required这样做@audit_changes
- 你可以访问模型中的请求和当前用户,并集中逻辑吗?
创build/修改date现在可以由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)
对于非Web环境(例如pipe理命令),您必须在脚本开始时调用set_current_user
。
对于时间戳模型,您可能需要查看django-model-utils或django-extensions 。 它们每个都包含抽象基类,它们自动处理创build的和上次修改的时间戳。 您可以直接使用这些工具,也可以看看他们如何解决问题,并提出自己的解决scheme。
至于你的其他问题:
你能像@login_required这样做@audit_changes
有可能是的,但你必须非常小心,保持线程安全的东西。 你可能可以做的是在你的@audit_changes修饰器中,设置一个标志来启用在threadlocal中的审计。 然后,无论是在模型的保存方法中还是在信号处理程序中,都可以检查您的审计标志并logging您的审计信息(如果标志已设置)。
你可以访问模型中的请求和当前用户,并集中逻辑吗?
是的,但是你会做一个权衡。 正如你已经谈到的那样,Django的ORM和它的请求/authentication处理位之间有一个非常明确和有意识的分离。 有两种方法从请求(当前用户)获取信息到ORM(您的模型)。 您可以手动pipe理更新对象的创build者/修改者信息,也可以设置机制来自动处理该维护工作。 如果采取手动方法(通过从视图中的请求到ORM的方法调用来传递信息),那么将会有更多的代码来维护/testing,但是保持关注的分离。 使用手动方法,如果您不得不在请求/响应周期之外处理对象(例如,cron脚本,延迟任务,交互式shell),那么您的状态会更好。 如果可以分解问题的分离,那么你可以设置一些东西,你可以在当前用户的中间件中设置一个本地线程,然后在模型的保存方法中查看本地线程。 与手动方法相反,如果您希望在请求/响应周期之外处理对象,那么处理的代码就会less一些,但是要花费更多的时间。 此外,您将必须非常小心,以更自动化的方式保持一切线程安全。
你可以导入用户模型对象,并调用get_current()?
另外,我想你可以在admin.py中调用views。