Django : динамическое получение контекстных данных
Я работаю над музыкальным веб-приложением и пытаюсь отобразить диаграмму (с помощью Chart.js) для жанров по семействам (т.е. жанр инди-рок находится в семействе рок). У меня есть 14 семейств (рок, металл, джаз и т.д...), и я хочу иметь возможность выбрать одно из них, чтобы отобразить количество альбомов для каждого жанра выбранного семейства.
Вот мой код:
Мой взгляд, в котором я отправляю жанры метал, рок и хип хоп семей и номер альбома в контексте :
class StatsAlbumView(ListView):
model = Album
queryset = Album.objects.all()
template_name = "statistic/album.html"
context_object_name = "albums"
def get_queryset(self):
queryset = super().get_queryset()
self.filterset = AlbumFilter(self.request.GET, queryset=queryset)
return self.filterset.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
all_families = api.get_all_families()
context['all_families'] = all_families
metal, albums_metal = api.get_album_by_family_genres("Metal")
context['metal'] = metal
context['albums_metal'] = albums_metal
rock, albums_rock = api.get_album_by_family_genres("Rock")
context['rock'] = rock
context['albums_rock'] = albums_rock
hip_hop, albums_hip_hop = api.get_album_by_family_genres("Hip-Hop")
context['hip_hop'] = hip_hop
context['albums_hip_hop'] = albums_hip_hop
context['form'] = self.filterset.form
return context
Мой api файл, в котором я получаю нужные мне данные :
def get_album_by_family_genres(family):
genres = Genre.objects.filter(family=family)
albums = Album.objects.all()
albums_from_family = []
for album in albums:
album_list_genre = list(album.genre_primary.all())
for genre in album_list_genre:
if genre in genres:
albums_from_family.append(album)
print(albums_from_family)
if albums_from_family:
list_genres, list_albums_number = get_album_by_primary_genre(albums_from_family, family)
return list_genres, list_albums_number
return [], []
def get_album_by_primary_genre(albums, family):
albums_by_primary_genre = {}
for album in albums:
album_list_genre = list(album.genre_primary.all())
for genre in album_list_genre:
if genre.family == family:
if genre.name in albums_by_primary_genre:
albums_by_primary_genre[genre.name] += 1
else:
albums_by_primary_genre[genre.name] = 1
genres, albums_number = zip(*albums_by_primary_genre.items())
list_genres = list(genres)
list_albums_number = list(albums_number)
return list_genres, list_albums_number
И мой шаблон, в котором у меня есть селектор семей, график и javascript для обновления графика:
<div id="familySelector" style="display: none;">
<label for="familyChartSelector">Voir la famille: </label>
<select name="familyChartSelector" id="familyChartSelector" onchange="displayFamily()">
{% for family in all_families %}
<option value="{{ family }}">{{ family }}</option>
{% endfor %}
</select>
</div>
<div id="albumByGenre" class="chart" style="display: none;">
<canvas id="canvasByGenre" width="400px" height="400px"></canvas>
<script>
const ctx3 = document.getElementById('canvasByGenre').getContext('2d');
const chartGenre = new Chart(ctx3, {
type: 'radar',
data: {
labels: {{ metal|safe }},
datasets: [{
label: 'Albums par genre de métal',
data: {{ albums_metal }},
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgb(255, 99, 132)',
pointBackgroundColor: 'rgb(255, 99, 132)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgb(255, 99, 132)'
}]
},
options: {
scales: {
r: {
angleLines: {
display: false
},
suggestedMin: 0,
suggestedMax: 5,
stepSize: 1
},
},
}
});
</script>
</div>
<script>
function displayFamily(){
const metalLabel = {{ metal|safe }}
const metalData = {{ albums_metal }}
const rockLabel = {{ rock|safe }}
const rockData = {{ albums_rock}}
const hipHopLabel = {{ hip_hop|safe }}
const hipHopData = {{ albums_hip_hop}}
var value = document.getElementById("familyChartSelector").value;
if ( value == "Metal"){
chartGenre.data.labels = metalLabel;
chartGenre.data.datasets[0].data = metalData;
chartGenre.update();
} else if (value == "Rock") {
chartGenre.data.labels = rockLabel;
chartGenre.data.datasets[0].data = rockData;
chartGenre.update();
} else if (value == "Hip-Hop") {
chartGenre.data.labels = hipHopLabel;
chartGenre.data.datasets[0].data = hipHopData;
chartGenre.update();
} else {
console.log("Data not found")
}
}
</script>
Теперь все это прекрасно работает, но есть много лишнего как в представлении, так и в javascript, потому что мне нужно получить данные для каждой семьи и загрузить их в контекст, и это нелепое "если", которое займет у меня 14 итераций, чтобы добраться до конца.
Так что мой вопрос в следующем: Возможно ли перезагрузить контекст при выборе семейства с помощью селектора, чтобы получить правильные данные динамически?
Извините за длинный пост, я новичок в python/django и новичок в SOF. Спасибо