Django 1.10 использование выпадающего меню для фильтрации запросов

#jquery #python #django #django-models #django-templates

#jquery #python #django #django-модели #django-шаблоны

Вопрос:

У меня есть база данных с кучей фотографий и стран, в которых они были сделаны. Это для фотоальбома на этом сайте, который я создаю. В настоящее время у меня есть все изображения на одной странице. Мне это нравится. Теперь я хочу иметь возможность искать все изображения из определенной страны или города. Мой дизайн требует двух кнопок сверху (фильтр по стране, фильтр по городу), а все изображения из базы данных отображаются ниже, когда фильтр не используется. Я хочу, чтобы эти кнопки представляли собой выпадающий список всех стран и городов соответственно. Когда пользователь нажимает на кнопку «Страны», вызывается выпадающий список — с помощью bootstrap. Затем они могут щелкнуть по выбранной стране и просмотреть все имеющиеся там изображения, упорядоченные по городам. Если они нажимают на выпадающий список для городов, вызываются все картинки из этого города. Если они выбирают страны, то в раскрывающемся списке города отображаются только города в этой стране. Прямо сейчас я понятия не имею, как это сделать. Я могу заполнить выпадающие списки — но я получаю все страны фотографии — что означает повторения. Как я могу это сделать?

Вот мой views.py:

 def photo_album(request):
    queryset_list = Pictures.objects.all()
    query = request.GET.get("q")
    if query:
        queryset_list = queryset_list.filter(
            Q(pictures__icontains=query) |
            Q(picture_name__icontains=query) |
            Q(country__icontains=query) |
            Q(city__icontains=query)
        ).distinct()

    paginator = Paginator(queryset_list, 20)
    page_request_var = "page"
    page = request.GET.get(page_request_var)
    try:
        queryset = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        queryset = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        queryset = paginator.page(paginator.num_pages)

    context = {
        "object_list": queryset,
        "title": "List",
        "page_request_var": page_request_var,
    }
    return render(request, "in_country_pics/photo_album.html", context)
  

мой html:

 <div class="container">
    <div class="photo-title">
        <h1>Welcome to Our Photo Album</h1>
    </div>
    <div class="col-sm-12 photoalbum-buttons">
        <form method="GET" action="" class="row">
            <div class="col-sm-6">
                <div class="input-group">
                    <input class="form-control" type="text" name="q" placeholder="Search Posts" value="{{ request.GET.q }}"/>
                    <span class="input-group-btn">
                        <button class="btn btn-default" type="submit">Search <i class="fa fa-search"></i></button>
                    </span>
                </div>
            </div>
        </form>

        <div class="dropdown form-actions">
            <button class="btn btn-primary gradient dropdown-toggle" type="button" data-toggle="dropdown">
                <i class="fa fa-search"></i>
                By Country
            </button>
            <ul class="dropdown-menu">
                {% for obj in object_list %}
                    <li ><a href="#">{{ obj.country }}</a></li>
                {% endfor %}
            </ul>
        </div>

        <div class="dropdown form-actions">
            <button class="btn btn-primary gradient dropdown-toggle" type="button" data-toggle="dropdown">
                <i class="fa fa-search"></i>
                By City
            </button>
            <ul class="dropdown-menu">
                {% for obj in object_list %}
                    <li><a href="#">{{ obj.city }}</a></li>
                {% endfor %}
            </ul>
        </div>
    </div>
    <p id="photo-separator">______________________________________________</p>

    <div class="row photo-post">
        {% for obj in object_list %}
            <div class="col-sm-3">
                <div class="thumbnail">
                    <img src="{{ obj.pictures.url }}" class="img-responsive"/>
                    <div class="caption photo-description">
                        <p class="photo-location">{{obj.city}}, {{obj.country}}</p>
                        <p class="photo-time">Taken: Aug 04, 2016</p>
                         <p><a href="" class="btn btn-primary" type="button">View</a></p>
                    </div>
                </div>
            </div>
            {% if forloop.counter|divisibleby:4 %}
                <div class='col-sm-12'><hr/></div></div><div></div><div class='row'>
            {% endif %}
        {% endfor %}
    </div>

</div>

{% endblock %}
  

В html у меня работает первая строка поиска, но в виде текста. У меня есть следующие простые выпадающие списки начальной загрузки. Если лучше использовать ajax или jquery, я открыт для этого.

Ответ №1:

Для этого вам понадобится Ajax.

Следуйте этому руководству, чтобы помочь вам.

вам необходимо загрузить скрипт (он есть в руководстве), который поможет вам с csrf_token, в противном случае при отправке формы вы получите ошибку django, связанную с этим токеном.

при вызове URL-адреса Ajax, подобного этому

 $.ajax({
        url: "some path/", // endpoint
  

вам нужно будет создать этот URL в вашем urls.py файл:

 urlpatterns = [
    url(r'^path/$', views.your_view_name),
]
  

таким образом, вы можете вызвать представление (или просто функцию в данном случае), отправляющее необходимую информацию в ваш шаблон.

Позже, с помощью jquery, вы можете изменить html элемента с его идентификатором примерно так

 $('#your_element_id').html("<p>your updated code goes here</p>");
  

вы также можете добавлять наборы элементов, просто измените .html на .append .
Разница в том, что .html заменяет то, что у вас есть, на код, который вы предоставляете, а .apend только добавляет этот код к тому, что у вас есть.