Set created by modified by dynamically with mixin

django, django-models, mixins

Solution

Just use existing functionality https://docs.djangoproject.com/en/1.11/topics/db/models/#abstract-related-name

class Trackable(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    created_by = models.ForeignKey(User, related_name='created_%(class)s')
    updated_by = models.ForeignKey(User, related_name='updated_%(class)s')
    class Meta:
        abstract = True

And for second part there is also solution https://stackoverflow.com/a/17173716/3627387

@receiver(pre_save)
def security_attributes(sender, instance, **kwargs):
    if not issubclass(sender, core_mixins.Trackable):
        return
    request = get_request()

    instance.updated_by = request.user

    if instance.id is None:
        instance.created_by = request.user

Basically you could filter senders inside signal processor.

Also there is `django-model-utils`https://django-model-utils.readthedocs.io/en/latest/models.html#timestampedmodel

Problem

Coming from the rails world, I was pleased to find out about mixins. I set up a Basic mixin core/mixins.py ``` from django.db import models from django.contrib.auth.models import User class Timestamps(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: abstract = True ``` And then my `Event` model in core/my_app/models.py ``` from core import mixins as core_mixins class Event(core_mixins.Timestamps): # ... ``` all jolly good, but what if I wanted to extend this a bit and create a more dynamic mixin? Advanced mixin core/mixins.py ``` from django.db import models from django.contrib.auth.models import User from django.dispatch import receiver from django.db.models.signals import pre_save from cw_core.requestprovider.signals import get_request class Trackable(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) created_by = models.ForeignKey(User, related_name='created_XXX') # <-- ??? updated_by = models.ForeignKey(User, related_name='updated_XXX') # <-- ??? class Meta: abstract = True @receiver(pre_save, sender=Event) # <-- ??? def security_attributes(sender, instance, **kwargs): request = get_request() instance.updated_by = request.user if instance.id is None: instance.created_by = request.user ``` core/my_app/models.py ``` from core import mixins as core_mixins class Event(core_mixins.Trackable): # ... ``` How would I dynamically set the `related_name`? I found this question but I have not found the variables I could use in strings, are there any docs? Also how would I dynamically set the sender in the `@receiver` call? My attempt would be to set: ``` @receiver(pre_save, sender=self.__class__) ``` But I am unsure if this will work? What is the suggested approach?

Original source

Related problems