有类似
的东西很多桌子都是非常常见的模式。
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工作了几天所以很容易丢失一些明显的东西)
答案 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-utils或django-extensions。它们每个都包含抽象基类,可自动处理已创建和上次修改的时间戳。您可以直接使用这些工具,也可以查看他们如何解决问题并提出自己的解决方案。
至于你的其他问题:
你可以像@login_required那样做,例如@audit_changes
可能是的,但你必须非常小心保持线程安全。您可能做的是在@audit_changes装饰器中,设置一个标志以在threadlocal中启用审计。然后,在模型的save方法或信号处理程序中,您可以检查审计标志并记录您的审计信息(如果已设置标志)。
您是否可以访问模型中的请求和当前用户并将逻辑集中在那里?
是的,但你会做出权衡。正如您稍微谈到的那样,Django的ORM与它的请求/认证处理位之间存在非常明确且有意的分离。有两种方法可以从请求(当前用户)到ORM(您的模型)获取信息。您可以手动管理更新对象上的创建者/修改器信息,也可以设置自动处理维护工作的机制。如果采用手动方法(通过方法调用将信息从视图中的请求传递到ORM),维护/测试的代码将更多,但您可以保持关注点的分离。使用手动方法,如果您必须在请求/响应周期之外处理对象(例如,cron脚本,延迟任务,交互式shell),您将会处于更好的状态。如果您可以分解关注点的分离,那么您可以设置一些内容,在中间件中将当前用户设置为本地线程,然后在模型的save方法中查看本地线程。与手动方法相反,您将需要处理的代码较少,但如果您希望在请求/响应周期之外处理对象,则会遇到更难的时间。此外,您必须非常小心地使用更自动化的方法保持所有线程安全。
答案 2 :(得分:-2)
您可以导入用户模型对象并调用get_current()吗?
另外,我认为您可以在admin.py中调用视图。