Вариант универсального шаблона для альтернативного описания картинки в статье

Через дописания модели.
Вы совершенно правы, шаблон должен быть универсальным и адаптироваться под любую статью. В таком случае лучше всего использовать динамическое значение для alt, которое будет извлекаться из базы данных или контекста представления. Вот как это можно реализовать:

1. Добавляем поле для альтернативного описания в модель
Предположим, у вас есть модель Post, в которой хранится информация о статье. Добавьте туда новое поле для хранения альтернативного описания изображения:

class Post(models.Model):
# Другие поля модели
image = models.ImageField(upload_to='images/', blank=True)
image_alt = models.CharField(max_length=255, blank=True)
2. Передаем значение image_alt в контекст
В представлении, которое отвечает за рендеринг шаблона, убедитесь, что image_alt передаётся в контекст:

def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
context = {'post': post}
return render(request, 'notes/show_post.html', context)
3. Используем image_alt в шаблоне
Теперь в шаблоне вы можете использовать значение image_alt для динамического формирования альтернативного описания:

<p><img class="img-article-left" src="{{ post.image.url }}" alt="{{ post.image_alt }}"></p>
Итоговый шаблон:

{% extends 'base.html' %}

{% block canonical_url %}
<link rel="canonical" href="{% url 'home' %}" />
{% endblock %}

{% block breadcrumbs %}
<!-- Метки -->
{% with post.tags.all as tags %}
{% if tags %}
<ul class="tags-list">
<li>Метки:</li>
{% for tag in tags %}
<li><a href="{{ tag.get_absolute_url }}">{{ tag.tag }}</a></li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}

{% if perms.notes.change_note %}
<p><a href="{{ post.get_update_url }}">Изменить статью</a></p>
{% endif %}

{% if perms.notes.delete_note %}
<p><a href="{{ post.get_delete_url }}">Удалить статью</a></p>
{% endif %}
{% endblock %}

{% block content %}
<h1>{{ post.title }}</h1>
{% if post.image %}
<p><img class="img-article-left" src="{{ post.image.url }}" alt="{{ post.image_alt }}"></p>
{% endif %}
<p>{{ post.content|linebreaks }}</p>
{% endblock %}
Что мы сделали:
Добавили поле image_alt в модель Post, чтобы хранить альтернативное описание для каждого изображения.
Передали значение image_alt в контекст представления.
Использовали image_alt в шаблоне для динамической генерации альтернативного описания изображения.
Теперь ваше решение гибкое и масштабируемое, позволяя автоматически подставлять подходящее описание для каждой статьи.