How to write common implementation of __str__ method for all my models in Django?
<p>I want all my models to override <code>__str__</code> method in similar fashion:</p>

<pre><code>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
</code></pre>

<p>I do not want to repeat the same code for all my models so I tried inheritance:</p>

<pre><code>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)
</code></pre>

<p>but it messes with <code>id</code> of <code>MyModel1</code> and <code>MyModel2</code> by replacing <code>id</code> with a pointer to <code>ShowModel</code>. How to write common implementation of <code>__str__</code> method for my models without inheritance or how to prevent treating <code>ShowModel</code> class as a Django model?</p>

<p><strong>Upd:</strong> I used <code>abstract</code> model as alecxe suggested but it ended with an error message:</p>

<pre><code>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'
</code></pre>

<p><strong>Upd</strong> Everything works fine if I assign value to the <code>name</code> field of my model object. Whole solution:</p>

<pre><code>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'
</code></pre>

<p>in test case:</p>

<pre><code>ua = MyModel1()
ua.name = 'hi'
print(ua)
#prints hi

ub = MyModel2()
ub.another_param = 'hi again'
print(ub)
#prints hi again
</code></pre>

<p>You need to create an <a href="https://docs.djangoproject.com/en/1.10/topics/db/models/#abstract-base-classes" rel="nofollow"><em><code>abstract</code> model</em></a>:</p>

<pre><code>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
</code></pre>

<p>And, as for your follow-up question and thanks to @itzmeontv, you should replace <code>self.to_show</code> with "to_show" when calling <code>hasattr()</code> and <code>getattr()</code>.</p>

python django inheritance django-models abstract