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. Спасибо

Вернуться на верх