2

I am running django 1.8, I am trying to save the current logged in user in the created by and modified by fields in my database. I have tried many different combination of getting this to work, but I am not running into any luck. I have to code working with hard coding in a user id like so:

@python_2_unicode_compatible  # only if you need to support Python 2
class Project(models.Model):
    name = models.CharField(max_length=50, verbose_name="Name")
    jobNumber = models.CharField(max_length=8)
    shopOut = models.DateTimeField(null=True)
    shopIn = models.DateTimeField(null=True)
    completion = models.DateTimeField(null=True)
    installation_date = models.DateTimeField(null=True)
    contractor = models.ForeignKey(Contractor, on_delete=models.CASCADE, default=101)
    created_by = models.ForeignKey(User, related_name='Project_created_by')
    created_date = models.DateTimeField(auto_now_add=True)
    modified_by = models.ForeignKey(User, related_name='Project_modified_by')
    modified_date = models.DateTimeField(auto_now=True)
    assigned_to = models.ForeignKey(User, related_name='Project_assigned_to', default=1)
    status = models.ForeignKey('Status', related_name='Project_status', default=1)
    def __str__(self):
        return self.name
    def save(self, *args, **kwargs):
        if not self.id:
            self.created_by = User.objects.get(id=1)
            #self.created_by = User.objects.get(id=kwargs['request'].user)
            #self.created_by = User.objects.get(id=request.user)
            self.modified_by = User.objects.get(id=1)
            #self.modified_by = User.objects.get(id=kwargs['request'].user)
            #self.modified_by = User.objects.get(id=request.user)
            super(Project, self).save(*args, **kwargs)
            year = datetime.datetime.now().year
            self.jobNumber = '{}{:04d}'.format(year, self.id)
        self.modified_by = User.objects.get(id=1)
        #self.modified_by = User.objects.get(id=kwargs['request'].user)
        #self.modified_by = User.objects.get(id=request.user)
        super(Project, self).save(*args, **kwargs)

If I try any of the code commented out:

self.created_by = User.objects.get(id=kwargs['request'].user)

or

self.created_by = User.objects.get(id=request.user)

I get the following error:

KeyError at /admin/project/project/add/ 'request'

or

NameError at /admin/project/project/add/ global name 'request' is not defined

Once again my question is how do I save the current logged in user in my created_by and modified_by fields?

Any help would be greatly appreciated!

Dan Swain
  • 2,910
  • 1
  • 16
  • 36
user908759
  • 1,355
  • 8
  • 26
  • 48
  • 1
    There is not `request` object available in the place you are looking. You need to be inside a view function/class to have access to a `request`. Moreover, models can be modified outside the context of a request (e.g., in the shell, from signals), so you cannot assume that whenever `save()` is called there is a request and a logged in user. – solarissmoke Jul 17 '16 at 04:27
  • Also note that the Django admin already keeps a history of model changes made through the admin (every model has a "History" view). – solarissmoke Jul 17 '16 at 04:55

2 Answers2

1

After searching a little more I found this post I followed most of their code, but here is mine:

This is my app folder structure:

myapp

  • project
    • admin.py # changed this
    • models.py # changed this
    • ...
  • myapp
    • setting.py
    • url.py
    • ...

my new admin.py

from django.contrib import admin
from . import models

class ProjectAdmin(admin.ModelAdmin):
    fields = ('name', 'jobNumber', 'contractor', 'assigned_to', 'status')
    def save_model(self, request, obj, form, change):
        instance = form.save(commit=False)
        if not hasattr(instance, 'created_by'):
            instance.created_by = request.user
        instance.modified_by = request.user
        instance.save()
        form.save_m2m()
        return instance

admin.site.register(models.Project,ProjectAdmin)

models.py

import datetime
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.contrib.auth.models import User
from contractor.models import Contractor

@python_2_unicode_compatible  # only if you need to support Python 2
class Project(models.Model):
    name = models.CharField(max_length=50, verbose_name="Name")
    jobNumber = models.CharField(max_length=8)
    shopOut = models.DateTimeField(null=True)
    shopIn = models.DateTimeField(null=True)
    completion = models.DateTimeField(null=True)
    installation_date = models.DateTimeField(null=True)
    contractor = models.ForeignKey(Contractor, on_delete=models.CASCADE, default=101)
    created_by = models.ForeignKey(User, related_name='Project_created_by')
    created_date = models.DateTimeField(auto_now_add=True)
    modified_by = models.ForeignKey(User, related_name='Project_modified_by')
    modified_date = models.DateTimeField(auto_now=True)
    assigned_to = models.ForeignKey(User, related_name='Project_assigned_to', default=1)
    status = models.ForeignKey('Status', related_name='Project_status', default=1)
    def __str__(self):
        return self.name
    def save(self, *args, **kwargs):
        if not self.id:
            super(Project, self).save(*args, **kwargs)
            year = datetime.datetime.now().year
            self.jobNumber = '{}{:04d}'.format(year, self.id)
        super(Project, self).save(*args, **kwargs)

I guess the trick is catching the request in the admin.py file. Thanks solarissmoke for your input!

Community
  • 1
  • 1
user908759
  • 1,355
  • 8
  • 26
  • 48
1

you can use django-currentuser package.

for example:

from django_currentuser.middleware import get_current_authenticated_user

class Project(models.Model):
    ....

    self.modifier = get_current_authenticated_user()
    if not self.id:
        self.creator = get_current_authenticated_user()
    
    ....
rmaleki
  • 581
  • 1
  • 9
  • 31