How to save user name after deleting user for any report which is generated by user?

I don’t want to remove name of the user in my report module after deleting user in user module.

My part/models.py

class PartLog(models.Model):
    ACTION_ADD = 'Added Part'
    ACTION_REMOVED = 'Removed Part'
    ACTION_ADD_STOCK_TO_PART = 'Added %s items to stock'
    ACTION_REMOVE_FROM_STOCK = 'Removed %s items from stock'
    ACTION_CREATED_STOCK = 'Created Stock Item'
    ACTION_DELETED_STOCK = 'Removed Stock Item'
    ACTION_CHOICES = (
        (ACTION_ADD, ACTION_ADD),
        (ACTION_REMOVED, ACTION_REMOVED),
        (ACTION_ADD_STOCK_TO_PART, ACTION_ADD_STOCK_TO_PART),
        (ACTION_REMOVE_FROM_STOCK, ACTION_REMOVE_FROM_STOCK),
        (ACTION_CREATED_STOCK, ACTION_CREATED_STOCK),
        (ACTION_DELETED_STOCK, ACTION_DELETED_STOCK)
    )
    part = models.ForeignKey(to=Part, on_delete=models.SET_NULL, null=True)
    transaction_time = models.DateTimeField('Transaction Time')
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    change_quantity = models.PositiveSmallIntegerField('Change Quantity')
    action = models.CharField(max_length=40, choices=ACTION_CHOICES)

    @property
    def message(self):
        if self.action in [self.ACTION_REMOVE_FROM_STOCK, self.ACTION_ADD_STOCK_TO_PART]:
            return self.action % self.change_quantity
        return self.action

    @staticmethod
    def log(part, user, change_quantity, action):
        PartLog.objects.create(part=part, user=user,
                               change_quantity=change_quantity,
                               action=action, transaction_time=datetime.now())

    class Meta:
        ordering = ('-transaction_time',)


class ReportHistory(models.Model):
    report_id = models.CharField(max_length=128)
    report_name = models.CharField(max_length=256)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    time = models.DateTimeField()

    @staticmethod
    def generate_report_id():
        report_history = ReportHistory.objects.last()
        if report_history is None:
            return 'TR1'
        report_id = report_history.report_id.replace('TR', '')
        report_id = int(report_id) + 1
        report_id = 'TR%s' % report_id
        return report_id

    @staticmethod
    def submit(user, report_name):
        report_id = ReportHistory.generate_report_id()
        ReportHistory.objects.create(
            user=user, report_name=report_name,
            report_id=report_id, time=datetime.now())

    class Meta:
        ordering = ('-time',)

There are two different directions you can go with this, depending upon your specific needs throughout the rest of your system.

  • The method we use, and it has a number of advantages when addressing issues of data integrity, is that we never delete a User. We use the is_active flag to indicate that a user can’t log on. (This is the technique also suggested by django itself - first paragraph in the linked doc.)

  • If you are absolutely sure that you will never need to use the other fields in User in your reports, you could create those reports by saving the username field rather than a reference to your User model. (We also use this method for generating reports that are being archived - they’re reports that represent the state of the system at a given point in time, so we don’t want foreign key references to be updated.)

Notice that these two solutions are not contradictory - you can do both. But I always suggest never actually deleting a User object.

Ken

Ken

Thanks KenWhitesell for your suggestions