自动保存在数据库中创建或修改行的人的最佳方法是什么?

时间:2014-02-04 17:05:45

标签: python django django-models

我的目标是构建一个抽象的BaseModel模型,它具有以下属性:

  1. DATE_CREATED
  2. created_by - 链接到USER模型
  3. 日期date_updated
  4. updated_by - 链接到USER模型
  5. 对于date_created和date_updated,没关系,我可以使用auto_nowauto_now_add参数。

    对于created_by和updated_by,我找不到如何以线程安全的方式自动执行此操作。 当然,我可以为视图中的每个模型做到这一点,但我想避免重复自己并在一个地方进行。

    所以我想在我的抽象模型上自己访问会话请求或请求对象......

    任何想法?

1 个答案:

答案 0 :(得分:1)

您无权访问模型中的请求(以及当前用户)。这是Django的设计。

更简单的方法是DRY更少但更明确:

  1. Create a reusable ModelForm that automatically saves the user to the model when the form is saved
  2. Create reusable class based View that automatically saves the user to your model
  3. Create or a reuseable ModelAdmin that automatically saves the user to the model(或this answer
  4. 但如果你想真正透明地保存创作者/修饰符,那就更干,但不那么明确,你可以:

    1. Write some middleware that transparently saves the user information to the model on save using signals
    2. 或者,您可以使用threadlocal通过more simple piece of middleware设置当前用户,然后在模型save()方法中再次访问该threadlocal。 You need to be careful with threadlocals
    3. 这是第一个更透明的选项:

      from django.db.models import signals
      from django.utils.functional import curry
      
      class WhodidMiddleware(object):
          def process_request(self, request):
              if not request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
                  if hasattr(request, 'user') and request.user.is_authenticated():
                      user = request.user
                  else:
                      user = None
      
                  mark_whodid = curry(self.mark_whodid, user)
                  signals.pre_save.connect(mark_whodid,  dispatch_uid = (self.__class__, request,), weak = False)
      
          def process_response(self, request, response):
              signals.pre_save.disconnect(dispatch_uid =  (self.__class__, request,))
              return response
      
          def mark_whodid(self, user, sender, instance, **kwargs):
              if 'created_by' in instance._meta.fields and not instance.created_by:
                  instance.created_by = user
              if 'modified_by' in instance._meta.fields:
                  instance.modified_by = user