Динамическая фильтрация Django с помощью Ajax

#javascript #jquery #django

Вопрос:

Я хочу динамически фильтровать свой набор запросов, используя значение моего поля ввода с помощью Ajax.

Прямо сейчас я пытаюсь сделать что-то вроде этого:

Шаблон:

 <div class="card mt-3">
        <div class="card-body">
        <form action="" form="get">
            <input data-url="{% url 'klantbeheer' %}" class="zoekklanten" name="q" type="text" placeholder="Zoek op contactnaam...">
        </form>
        {% if object_list %}
                <div class="single-table">
                    <div class="table-responsive">
                        <table class="table text-center">
                            <thead class="text-uppercase bg-dark">
                                <tr class="text-white">
                                    <th scope="col">Bedrijfsnaam</th>
                                    <th scope="col">Contactnaam</th>
                                    <th scope="col">Locatie</th>
                                    <th scope="col">Actie</th>
                                </tr>
                            </thead>
                            <tbody>
                                {% for user in object_list %}
                                <tr>
                                    <td>{{ user.bedrijfsNaam }}</td>
                                    <td>{{ user.contactNaam }}</td>
                                    <td>{{ user.adres }}</td>
                                    <td>
                                        <a href="{% url 'klantupdaten' user.id  %}"><i class="fas fa-edit"></i></a>
                                        <a href="#" data-url="{% url 'klantverwijderen' user.id %}" class="deletegebruiker" data-bs-toggle="modal" data-bs-target="#dynamic-modal"><i class="fas fa-trash-alt"></i></a>
                                    </td>
                                </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
            {% else %}
            <p>Geen gebruikers gevonden</p>
                <p>
                    <a href="{% url 'klantaanmaken' user.id %}" class="btn btn-primary">Maak klant aan</a>
                </p>
            {% endif %}
        </div>
    </div>

 

Вид:

 class ManageUserView(SuperUserRequired, ListView):
    model = User
    template_name = 'webapp/klant/beheerklant.html'


    #Query based upon contactName
    def get_queryset(self, query):
        

        #Contactnaam bevat QUERY EN superuser is vals.
        object_list = self.model.objects.filter(contactNaam__icontains=query).exclude(is_superuser=True)
        
        return object_list

    def post(self, request, *args, **kwargs):
        query = self.request.POST.get('query', '')
        print(query)
        self.get_queryset(query)
 

Jquery:

 $('.zoekklanten').on('keyup', function(){
    var url = $(this).data('url')
    var query = $(this).val();

    $.ajax({
        url:url,
        type:'POST',
        data:{
            'query':query
        },
        dataType: 'json',
            beforeSend: function(xhr, settings){
                if(!csrfSafeMethod(settings.type) amp;amp; !this.crossDomain){
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            },
            success: function(result){
            },
            error: function(data){
            }

     })})
 

Я получаю ошибку «get_queryset() отсутствует 1 требуемый позиционный аргумент: ‘запрос’». Я предполагаю, что вызов функции get_queryset внутри функции запроса post-это не тот способ, которым можно это сделать.

Каков был бы лучший способ динамической фильтрации с использованием Ajax в Django?

Комментарии:

1. действительно ли ваш код имеет отступы, как показано выше? Если это так, вам нужно сделать отступ post() , и get_queryset() поэтому они вложены внутри класса ManageUserView . Если они уже вложены туда, пожалуйста, исправьте отступ в коде.

2. Нет, это не так, я исправил отступ.

Ответ №1:

Ваша проблема в том, что метод ListView.get_queryset() обычно определяется без какого-либо дополнительного параметра, поэтому, когда он вызывается Django неявно, он не передает никакого значения новому дополнительному параметру query , который вы туда добавили.

Поэтому либо используйте self.request.POST.get('query', '') in get_queryset() напрямую, а не передавайте его туда в качестве параметра, либо добавьте значение по умолчанию к параметру.

Однако использование пользовательского ввода и передача его непосредственно в SQL-запрос рискованно, так как это может привести к внедрению SQL (даже если Django пытается очистить значение).

 def get_queryset(self, query=None):
    # either set default value for `query` here^
    if not query:
        return super().get_queryset()

    # or take the value from `POST` here instead of passing it as a parameter to the method
    query = self.request.POST.get('query')
    object_list = self.model.objects.filter(contactNaam__icontains=query).exclude(is_superuser=True)
    
    return object_list
 

Комментарии:

1. Спасибо за помощь! Но когда я пробую ваш 2-й вариант, я получаю сообщение об ошибке 405 (Метод Не разрешен)

2. Да, конечно, потому что это не так… знаешь что? Всегда будет еще одна проблема, поэтому вместо того, чтобы копаться здесь до бесконечности, вам лучше открыть новую проблему. Подсказка: узнайте, какие методы запросов ListView поддерживаются.

3. Мне просто нужен способ динамической фильтрации с помощью AJAX. Каков был бы лучший способ (который работает)?

4. Я могу понять, откуда вы пришли, но опять же: это не имеет отношения к первоначальному вопросу, который был решен. Вы можете продолжать копаться здесь снова и снова, например: «Сейчас это работает, но теперь есть еще одна проблема… и посмотрите, еще одна… и еще один».