Alex V
Alex V

Reputation: 63

how get django current user's name both in shell and in request

I have to update a "modified by" field in models with current user's name. It's very easy to get username in views with request like this:

request.user.username

However, when an model's instance is modified using shell (I have scripts to batch update and process entries) there's no request.

What would be a good way to get current user's name both from request (if any) and from shell process?

Updates based on comments:

Custom save, assuming one shell user

Yes, I am using a custom save() method. It looks like:

So, I know how to manually assign a value to the field. The problem is to how to know if a particular transaction was done with or without a request, and if without request (shell), then which admin/user done it.

What I tried:

  1. Passing request as a required parameter from any view to the abstract models, method: it did not work (at least, I do not know how to safely code a required parameter to and abstract model's method as opposed to a plain function in a view); also, I do not know how to pass request when calling the same method from shell.

  2. In shell, I easily got User.objects.all() and tried to check: if user is authenticated, then use his/her username, else assume it's a shell user and manually assign "shell user" value to "modified by".

To my surprise, any returned user is authenticated in shell:

>>> users = User.objects.all()
>>> users
[<User: teddy>, <User: alexander>]
>>> users[0].is_authenticated()
True
>>> users[1].is_authenticated()
True
>>>

So, this easy scenario failed to me...

When custom save() is not enough

Further thought:

  1. Batch model updates triggered in admin app do not use save(), so any custom logic here will not work...
  2. Updating with a Celery task: did not check it yet.
  3. More than one shell user: will have to use a plain old user input to ask for the name and pass to the script?

Any idea to help?

This is how I solved it:

An abstract-class model with a parameter (who) to be manually assigned when saving a model.

class ModifiedAwareModel(models.Model):
"""
ABC to keep track of when and by whom a model was created and updated.
"""
created_on = models.DateTimeField(_('created on'), blank=True, editable=False)
created_by = models.CharField(_('created by'), max_length=100, blank=True, editable=False)
modified_on = models.DateTimeField(_('modified on'), blank=True, editable=False)
modified_by = models.CharField(_('modified by'), max_length=100, blank=True, editable=False)

class Meta:
    abstract = True

def save(self, who="Django", *args, **kwargs):

    if not self.pk:
        self.created_on = timezone.now()
        self.created_by = who
        self.modified_on = timezone.now()
        self.modified_by = who
    else:
        self.modified_on = timezone.now()
        self.modified_by = who
    return super(ModifiedAwareModel, self).save(*args, **kwargs)

Upvotes: 0

Views: 4106

Answers (1)

techydesigner
techydesigner

Reputation: 1691

When using the Django shell, there is no current User. A method of working around this would be get the person who is using the shell to assign a User to the modified by field manually. This User would probably be dedicated for shell operations, but it doesn't have to be that way. Another option could be to write a custom save() function for the model if you will only be changing it through the shell.

Upvotes: 1

Related Questions