Django - 在抽象方法中获取原始 class 名称

Django - getting the original class name in abstact method

以下示例最能说明我正在尝试做的事情:

class MyAbstractClass(models.Model):
    abstract_field = IntegerField()

    class Meta:
        abstract = True

    def abstract_method(self):
         # THE ISSUE LIES IN THE LINE BELOW 
         ParentClass.objects.filter(..).update(....)
         return self

class InheritedClass(MyAbstractClass):
     # Field

def my_view(request):
    obj = InheritedClass.objects.get(id=1)
    obj.save()
    return obj

所以基本上,问题是,abstract_method 中是否有任何方法告诉 Django 处理调用 class(即 InheritedClass)?

你可以做到 self.objects.filter(...).update(..)

抽象 class 只是实现由其具体 class 继承的方法,此处 InheritedClass。因此,方法和字段的所有内容都可以在继承 class 中使用。

但是,对于这种情况,我建议您考虑制作自定义模型管理器。模型中的方法旨在处理该特定行的字段,而管理器旨在工作 table-wide,如 model methods

中所述

Define custom methods on a model to add custom “row-level” functionality to your objects. Whereas Manager methods are intended to do “table-wide” things, model methods should act on a particular model instance.

如果您有一个方法在模型方法中进行过滤,那是一种代码味道,它属于自定义管理器。

技术回答:嗯,很简单,是的:

def abstract_method(self):
     type(self).objects.filter(..).update(....)
     return self

请注意,这是 Python 方法是使用 "calling" 对象(调用该方法的对象)作为第一个参数调用的,所有属性查找都将在此对象上进行,它是class - 否则继承根本行不通。这里唯一特定于 Django 的部分是 Django 阻止您在模型实例上使用 ModelManager,因此您需要明确获取对象的 class,它由 type(self).

返回

但是:

编码风格注意事项

Django 建议作用于整个 table 的模型方法应该属于 ModelManager(与仅作用于当前行的方法形成对比,这些方法将作为普通方法实现),因此显然您的方法整体上 table 它 可能 作为 ModelManager 方法更好。

我说 "might" 因为有一个灰色区域,其中更新一行意味着也更新其他一些行 - 一个典型的例子是当你有一个应该总是只为一个记录设置的标志时,所以你还想在所有其他记录上取消设置。您的问题中(当然)没有足够的上下文来判断哪个是正确的选择。