0

I have a number of models that need to refer back to the user that created/updated them. Generally this just involves passing request.user to the relevant attribute, however I'd like to make this automatic if possible.

There's an extension for Doctrine (a PHP ORM) called Blameable that will set a reference to the currently authenticated user when persisting a model instance, e.g.:

class Post
{
    /**
     * Will set this to the authenticated User on the first persist($model)
     * @ORM\ManyToOne(targetEntity="User", inversedBy="posts")
     * @Gedmo\Blameable(on="create")
     */
    private $createdBy;

    /**
     * Sets this to the authenticated User on the first and subsequent persists
     * @ORM\ManyToOne(targetEntity="User")
     * @Gedmo\Blameable(on="update")
     */
    private $updatedBy;
}

To get the same functionality in Django, my first thought was to try and use pre_save signal hooks to emulate this - however I'd need to access the request outside of a view function (looks possible with some middleware but a bit hacky).

Is there something similar already available for Django? Am I better off explicitly passing the authenticated user?

Community
  • 1
  • 1
Ross
  • 46,186
  • 39
  • 120
  • 173

2 Answers2

0

The level of decoupling Django has makes it impossible to automatically set the user in a model instance.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
0

The middleware solution is the way to go. When I need to do this, I just add to the save() method, like so:

class MyObject(models.Model):
  def save(self, *args, **kwargs):
    if not self.created_by:
      self.created_by = get_requests().user

    super(MyObject, self).save(*args, **kwargs)

as for the "hackyness" of storing the requests in a global dictionary, I think you'll get over it. Someone once said of this pattern, "It's the worst one, except for all the others".

P.S. You'll also find it really useful if you want to use django.contrib.messages from deep within your code.

Chris Curvey
  • 9,738
  • 10
  • 48
  • 70