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

override __str__(self) of a model from an imported app

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

  1. 摘要class'Base':

    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
    
  2. 基于'Base'抽象class,称为'AbstractClassA':

    class AbstractClassA(Base):
    
        display_name = models.CharField(max_length=200)
        ....
        ....
    
        class Meta(Base.Meta):
            abstract = True
    
        def get_display_name(self):
            ....
            ....
            return ....
    
  3. 非抽象classclassClassA(AbstractClassA)

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

    qs = ClassA.objects.filter(Q(name__icontains=query_term)....)
    return qs

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

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

   def __str__(self):
        display_name = getattr(self, 'display_name', None)
        if display_name:
            return display_name
        return self.name

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

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

有什么优雅的方法吗?

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

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

class NiceStrMixin():
    def __str__(self):
        return self.display_name

然后

class ClassA(AbstractClassA, NiceStrMixin):
     ...

如果您也无法访问 ClassA,您可以 monkey patch AbstractClassA

除了 monkeypatching 之外的另一种方法是使用 Proxy models.

class MyClassA(ClassA):

    class Meta:
        proxy = True

    def __str__(self)
        return self.attribute

然后使用 MyClassA 而不是 ClassA