A partir d'un clique : trier des données déjà affichées dans le désordre, puis les mettre à jour

Besoin d'aide pour identifier le problème.

a marqué ce sujet comme résolu.

Bonjour,

Je bloque depuis plusieurs jours… S’il vous plaît, aidez-moi à comprendre l’origine de mon problème! Il y a vraisemblablement quelque chose que je ne comprends pas bien puisque l’exécution de mon code ne fonctionne pas : lorsque je clique sur une des options de mon sélect, je veux que la liste des livres de mon catalogue soit triée de A à Z ou du plus petit au plus grand, ou bien de Z à A ou du plus grand au plus petit (selon l’option sélectionnée).

Actuellement, je soupçonne la view de mon application de ne pas être correctement intégrée dans celle de mon projet…

Ci-après, voici le contexte d’exécution :

Je débute avec Django. J’ai créé une application nommée "books" qui se rattache à un projet "sgbj". Le template catalog.html de mon application est appelée par le template index.html de mon projet "sgbj". Donc l’url d’affichage de mon application "books" est la même que celle utilisée par mon projet "sgbj" :

Mon ficher urls.py du projet "sgbj":

from django.contrib import admin
from django.urls import path, include
from books import views as books_views
from . import views as project_views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', books_views.catalog_view, name='index'),
    path('contact/', project_views.contact_view, name='contact'),
    path('publications/', include('articles.urls'), name='articles'),
]

Le fichier views.py du projet "sgbj" :

from django.shortcuts import render
    from books.views import catalog_view as books_catalog_view
    def index_view(request):
        catalog_context = books_catalog_view(request)
        books = catalog_context.get('catalog')
        return render(request, 'index.html', {'catalog': books})

Le template index.html du projet "sgbj" :

{% extends 'template_base.html' %}
{% block title %}Home_page{% endblock %}
{% block content %}
    
    {% block catalog_content %}
        <div id="catalog_content">
            {% include 'catalog.html' %}
        </div>
    {% endblock %}
    {% block sort_books %}
    {% endblock %}
{% endblock %}

Le template catalog.html de l’application "books":

{% extends 'template_base.html' %}
{% block title %}Catalog_page{% endblock %}
{% block content %}
    {% block sort_books %}
        <div class="sort_books">
            Tri par :
            <select id="sort_lastname" class="select_books sort_lastname" name="lastname">
                <option id="sort_lastname_author" class="sort_label" disabled selected hidden value="no_specific">auteur </option>
                <option id="sort_lastname_AZ" class="display_asc option_transparent" value="asc">A ... Z</option>
                <option id="sort_lastname_ZA" class="display_desc option_transparent" value="desc">Z ... A</option>
            </select>
            <select id="sort_title" class="select_books" name="titre">
                <option id="sort_title_title" class="sort_label" disabled selected hidden value="no_specific">titre </option>      
                <option id="sort_title_AZ" class="display_asc option_transparent" value="asc">A ... Z</option>
                <option id="sort_title_ZA" class="display_desc option_transparent" value="desc">Z ... A</option>
            </select>
            <select id="sort_date" class="select_books" name="date">
                <option id="sort_date_date" class="sort_label" disabled selected hidden value="no_specific">date </option>
                <option id="sort_date_-+" class="display_asc option_transparent" value="asc">- ... +</option>
                <option id="sort_date_+-" class="display_desc option_transparent" value="desc">+ ... -</option>
            </select>
        </div>
    {% endblock %}
    {% block catalog_title %}
        <h1>Ma bibliothèque</h1>
    {% endblock %}
    {% for book in catalog %}
        <p class="catalog">
            <span class="lastname">{{ book.lastname }}</span>
            <span class="firstname">{{ book.firstname }}</span>
            <span class="title"><b>{{ book.title }}</b></span>
            <span>ISBN : <span class="isbn">{{ book.isbn }}</span>
        </p>
    {% endfor %}
{% endblock %}

La vue views.py de l’application "books" :

from django.shortcuts import render
from django.http import JsonResponse
from django.db.models.functions import Lower
from .models import Book
def catalog_view(request):
    books = Book.objects.all()
    return render(request, 'books/catalog.html', {'catalog': books})
def sort_books_view(request):
    if request.is_ajax() and 'selected_option' in request.GET:
        selected_column_option = request.GET.get('selected_option')
        column_mapping = {
            'sort_lastname_AZ': 'lastname',
            'sort_lastname_ZA': '-lastname',
            'sort_firstname_AZ': 'firstname',
            'sort_firstname_ZA': '-firstname',
            'sort_title_AZ': 'title',
            'sort_title_ZA': '-title',
            'sort_date_-+': Lower('date'),
            'sort_date_+-': Lower('-date'),
        }
        
        if selected_column_option in column_mapping:
            sort_column = column_mapping[selected_column_option]
            books = Book.objects.all().order_by(sort_column)
            sorted_books = [{'lastname': book.lastname, 'firstname': book.firstname, 'title': book.title, 'isbn': book.isbn} for book in books]
            return JsonResponse(sorted_books, safe=False)
        else:
            return JsonResponse({'error': 'Option de tri non valide.'})
    else:
        return JsonResponse({'error': 'Cette vue ne peut être appelée que via AJAX.'})

Mon script selector_books.js de l’application "books" (voir les lignes 46 à 82):

document.addEventListener('DOMContentLoaded', function() {
    var selectElements = document.querySelectorAll('#sort_lastname, #sort_firstname, #sort_title, #sort_date');
    var defaultLabelOptions = {};
    selectElements.forEach(function(selectElement) {
        var defaultLabelOption = selectElement.querySelector('option');
        defaultLabelOptions[selectElement.id] = defaultLabelOption.textContent;
        defaultLabelOption.style.display = 'none';
        selectElement.addEventListener('change', function() {
            var selectedOption = this.options[this.selectedIndex];
            var optionClass = selectedOption.getAttribute('class');
            var optionText = selectedOption.textContent;
            selectElements.forEach(function(otherSelect) {
                if (otherSelect !== selectElement) {
                    var defaultOption = otherSelect.querySelector('option[value="no_specific"]');
                    defaultOption.style.display = '';
                    defaultOption.selected = true;
                    otherSelect.querySelectorAll('option').forEach(function(option) {
                        option.style.display = '';
                    });
                }
            });  
            // Afficher toutes les options
            var options = selectElement.querySelectorAll('option');
            options.forEach(function(option) {
                option.style.display = '';  
            });
            // Cacher l'option sélectionnée
            selectedOption.style.display = 'none';
            if (optionClass === 'sort_label' || (optionText !== 'auteur A ... Z' && optionText !== 'auteur Z ... A' && optionText !== 'titre A ... Z' && optionText !== 'titre Z ... A' && optionText !== 'date - ... +' && optionText !== 'date + ... -')) {
                selectedOption.textContent = defaultLabelOptions[selectElement.id] + optionText;
            }
            // Masquer les options appropriées sans masquer l'élément sélectionné
            if (optionClass === 'display_asc') {
                var descOptions = selectElement.parentNode.querySelectorAll('.display_desc');
                descOptions.forEach(function(option) {
                    option.style.display = '';
                });
            } else if (optionClass === 'display_desc') {
                var ascOptions = selectElement.parentNode.querySelectorAll('.display_asc');
                ascOptions.forEach(function(option) {
                    option.style.display = '';
                });
            }
        });
    });
    $('#sort_lastname, #sort_firstname, #sort_title, #sort_date').on('change', function() {
        var selectedOption = $(this).val();
        if (selectedOption === "AZ" || selectedOption === "-+" || selectedOption === "ZA" || selectedOption === "+-" ) {
            var dataToSend = {};
            var selectedColumn = '';
            
            if ($(this).attr('id') === 'sort_lastname') {
                selectedColumn = 'lastname';
                dataToSend['selected_lastname_option'] = 'sort_' + selectedColumn + '_' + selectedOption.toUpperCase();
                dataToSend['selected_firstname_option'] = 'sort_firstname_' + selectedOption.toUpperCase();
            } else if ($(this).attr('id') === 'sort_firstname') {
                selectedColumn = 'firstname';
                dataToSend['selected_firstname_option'] = 'sort_' + selectedColumn + '_' + selectedOption.toUpperCase();
                dataToSend['selected_lastname_option'] = 'sort_lastname_' + selectedOption.toUpperCase();
            } else if ($(this).attr('id') === 'sort_title') {
                selectedColumn = 'title';
            } else if ($(this).attr('id') === 'sort_date') {
                selectedColumn = 'date';
            }
            
            $.ajax({
                url: '',
                data: dataToSend,
                dataType: 'json',
                success: function(data) {
                    updateIndexData(data, selectedColumn);
                }
            });
        }
    });
    function updateIndexData(data, selectedColumn) {
        $('#catalog_content .catalog p').each(function(index) {
            $(this).find('.' + selectedColumn).text(data[index][selectedColumn]);
            $(this).find('.isbn').text('ISBN : ' + data[index].isbn);
        });
    }
});

L’affichage web en local fonctionnait bien avant que j’essaye de trier les données par ordre croissant/décroissant. J’espère que vous voudrez bien m’aider à identifier l’origine de la non exécution de mon code!

Salut,

Est-ce que tu vois bien les requêtes HTTP survenir lorsque tu utilises tes <select> ? Est-ce qu’elles réussissent ?

Si oui tu pourrais afficher clairement ce qu’elles contiennent pour voir si cela correspond bien au format attendu.

Si non, quelle erreur obtiens-tu ?

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte