从导入的应用程序覆盖模型的 __str__(self)

Mic*_* Xu 3 django django-models django-autocomplete-light

我面临以下情况:我有一个 django 项目,它使用外部应用程序 [App1]。在 App1 中,它具有以下结构:

  1. 抽象类“基础”:

    class Base(models.Model):
        """
        Base model with boilerplate for all models.
        """
    
        name = models.CharField(max_length=200, db_index=True)
        alternate_names = models.TextField(null=True, blank=True, 
        default='')
        ..............
        ..............
        class Meta:
            abstract = True
    
       def __str__(self):
            display_name = getattr(self, 'display_name', None)
            if display_name:
                return display_name
    
       return self.name
    
    Run Code Online (Sandbox Code Playgroud)
  2. 基于“Base”的抽象类,称为“AbstractClassA”:

    class AbstractClassA(Base):
    
        display_name = models.CharField(max_length=200)
        ....
        ....
    
        class Meta(Base.Meta):
            abstract = True
    
        def get_display_name(self):
            ....
            ....
            return ....
    
    Run Code Online (Sandbox Code Playgroud)
  3. 非抽象类类 ClassA(AbstractClassA)

现在,当我在视图中对此 ClassA 进行查询时,例如:

    qs = ClassA.objects.filter(Q(name__icontains=query_term)....)
    return qs
Run Code Online (Sandbox Code Playgroud)

我将这个 qs 输入另一个外部应用程序(自动完成),这样当我在我的网络表单上输入“xxxx”时,表单会根据这个 qs 向我提供有关数据库中可用匹配项的建议。

这一切都很好,唯一的问题是,显示给我的潜在匹配列表是 ClassA 对象的默认表示,我可以追溯到

   def __str__(self):
        display_name = getattr(self, 'display_name', None)
        if display_name:
            return display_name
        return self.name
Run Code Online (Sandbox Code Playgroud)

在我之前提到的基本抽象模型中定义。我想要的是,将其他内容显示为潜在匹配项的列表(例如,代替 'display_name' 或 'name',向我显示 qs 中每个过滤项目的 'fieldA' + ';'+ 'fieldB')。

我的想法是在__str__某个地方覆盖这个方法。但是因为我的流程的上游和下游方面都是在我不想直接修改的外部应用程序中完成的(即直接复制到我的 Django 项目中并重写某些部分),所以我不确定如何实现我的目标.

有没有什么优雅的方法可以做到这一点?

如果有任何不清楚的地方,请告诉我,或者我是否可以为您提供任何进一步的信息。谢谢!

小智 6

除了monkeypatching 之外的另一种方法是使用代理模型

class MyClassA(ClassA):

    class Meta:
        proxy = True

    def __str__(self)
        return self.attribute
Run Code Online (Sandbox Code Playgroud)

然后使用MyClassA代替ClassA


Sel*_*cuk 3

从你的问题来看,并不清楚非抽象类是否是由你编写的,但你可以做的是创建一个 mixin 并将其添加到具体类的类签名中,例如:

class NiceStrMixin():
    def __str__(self):
        return self.display_name
Run Code Online (Sandbox Code Playgroud)

然后

class ClassA(AbstractClassA, NiceStrMixin):
     ...
Run Code Online (Sandbox Code Playgroud)

如果您无法访问ClassA其中任何一个,您可以进行猴子补丁 AbstractClassA