由使用 mixin 动态修改创建的集合

dav*_*son 4 django django-models mixins

来自 Rails 世界,我很高兴了解 mixin。我设置了一个

基本混合

核心/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
Run Code Online (Sandbox Code Playgroud)

然后我Eventcore/my_app/models.py 中的模型

from core import mixins as core_mixins

class Event(core_mixins.Timestamps):
    # ...
Run Code Online (Sandbox Code Playgroud)

一切都很好,但是如果我想稍微扩展一下并创建一个更动态的 mixin 呢?

高级混入

核心/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
Run Code Online (Sandbox Code Playgroud)

核心/my_app/models.py

from core import mixins as core_mixins

class Event(core_mixins.Trackable):
    # ...
Run Code Online (Sandbox Code Playgroud)
  • 我将如何动态设置related_name?我发现了这个问题,但我还没有找到可以在字符串中使用的变量,有没有文档?

  • 另外我将如何在@receiver呼叫中动态设置发件人?

我的尝试是设置:

@receiver(pre_save, sender=self.__class__)
Run Code Online (Sandbox Code Playgroud)

但我不确定这是否有效?建议的方法是什么?

Sar*_*iev 5

只需使用现有功能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
Run Code Online (Sandbox Code Playgroud)

对于第二部分,还有解决方案/sf/answers/1202160151/

@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
Run Code Online (Sandbox Code Playgroud)

基本上你可以过滤信号处理器内的发件人。

django-model-utilshttps://django-model-utils.readthedocs.io/en/latest/models.html#timestampedmodel