Как написать общую реализацию метода __str__ для всех моих моделей в Django?

Я хочу переопределить все мои модели __str__ метод аналогичным образом:

class MyModel1(models.Model):
    name = models.CharField(max_length=255)

    def __init__(self):
        self.to_show = 'name'

    def _show(self):
        if hasattr(self,self.to_show):
            return str(getattr(self, self.to_show))
        else:
            return str(getattr(self, 'id'))

    def __str__(self):
        return self._show()

class MyModel2AndSoOn(models.Model):
    another_param = models.CharField(max_length=255)
    # same implementation of `__str__` but with another_param

Я не хочу повторять один и тот же код для всех моих моделей, поэтому я попробовал наследование:

class ShowModel(models.Model):
    name = models.CharField(max_length=255)

    def __init__(self):
        self.to_show = 'name'

    def _show(self):
        if hasattr(self,self.to_show):
            return str(getattr(self, self.to_show))
        else:
            return str(getattr(self, 'id'))

    def __str__(self):
        return self._show()

class MyModel1(ShowModel):
    another_param = models.CharField(max_length=255)

class MyModel2(ShowModel):
    another_param = models.CharField(max_length=255)

но это портит id из MyModel1 а также MyModel2 заменив id с указателем на ShowModel, Как написать общую реализацию __str__ метод для моих моделей без наследования или как предотвратить лечение ShowModel класс как модель Django?

Upd: я использовал abstract модель, как предложила alecxe, но закончилась сообщением об ошибке:

in _show
    return str(getattr(self, self.to_show))
File "/path/to/my/project/env3/lib/python3.5/site-packages/django/db/models/fields/__init__.py", line 188, in __str__
model = self.model
AttributeError: 'CharField' object has no attribute 'model'

Upd Все работает нормально, если я назначу значение name поле моего модельного объекта. Целое решение:

class ShowModel(object):
    to_show = 'name'

    def _show(self):
            if hasattr(self,self.to_show):
                return str(getattr(self, self.to_show))
            elif hasattr(self,'id'):
                return str(getattr(self, 'id'))
            else:
                return str(self)

    def __str__(self):
         return self._show()

    class Meta:
        abstract = True

class MyModel1(ShowModel):
    name = models.CharField(max_length=255)
    to_show = 'name'

class MyModel2(ShowModel):
    another_param = models.CharField(max_length=255)
    to_show = 'another_param'

в тестовом случае:

ua = MyModel1()
ua.name = 'hi'
print(ua)
#prints hi

ub = MyModel2()
ub.another_param = 'hi again'
print(ub)
#prints hi again

1 ответ

Решение

Вам нужно создать abstract модель:

class ShowModel(models.Model):
    name = models.CharField(max_length=255)

    def __init__(self):
        self.to_show = 'name'

    def _show(self):
        if hasattr(self, "to_show"):
            return str(getattr(self, "to_show"))
        else:
            return str(getattr(self, 'id'))

    def __str__(self):
        return self._show()

    class Meta:
        abstract = True

И, что касается вашего дополнительного вопроса и благодаря @itzmeontv, вы должны заменить self.to_show с "to_show" при вызове hasattr() а также getattr(),

Другие вопросы по тегам