Как предотвратить сброс формы Django после нажатия кнопок страницы - PullRequest
1 голос
/ 28 июня 2019

У меня есть форма Django, которая принимает входные значения от пользователей. Затем эти значения используются при создании запроса к таблице ResourceBase, которая в итоге возвращает список отфильтрованных результатов.

Поскольку результаты могут быть длинным списком, я добавил функцию разбивки на страницы с помощью кнопок «Prev» и «Next». Моя проблема в том, что когда я нажимаю кнопку «Предыдущий» или «Следующий», форма восстанавливается в значения по умолчанию. И все возвращенные результаты все ушли. Как я могу предотвратить это?

Я думаю, что форма сбрасывается из-за "form1 = QueryForm ()", когда запрос не "POST". Однако мне просто трудно найти подходящее решение, так как я новичок в Django и веб-разработчике.

В views.py:


def search(request):

    if request.method == "POST":

        form1 = QueryForm(data=request.POST)

        layer_dict = []

        if form1.is_valid():

            inp_ct = form1.cleaned_data['country']

            q1 = ResourceBase.objects.filter(country_name__iexact=inp_ct)

            for layer in q1:

                down_url = 'xxxxxxx'.format(layer.title)
                view_url = 'xxxxxxx'.format(layer.title)
                layer_dict.append((layer.title, down_url, view_url))

            layer_dict = sorted(layer_dict, key = lambda x:x[0])

            paginator = Paginator(layer_dict, 10)

            page = request.GET.get('page', 1)

            try:
                layers = paginator.page(page)
            except PageNotAnInteger:
                # If page is not an integer, deliver first page.
                layers = paginator.page(1)
            except EmptyPage:
                # If page is out of range (e.g. 9999), deliver last page of results.
                layers = paginator.page(paginator.num_pages)

            context = {'form1': form1, 'layers': layers}

    else:

        form1 = QueryForm()

        context = {'form1': form1}


    return render(request, 'my_app/search.html', context)


В search.html:

<br />
<h3>Pagination Test</h3>
<br /><br/>


<div class="row">
    <div class="col-md-4">
        <form method="POST">
            {% csrf_token %}

              <div class="form-controls">
                {{ form1|as_bootstrap }}
              </div>
            <button class="btn btn-primary" type="submit" style="float: right;" title = "Click to search" ><i class="fa fa-search"></i></button>
        </form>

        <form method="GET">
            <button class="btn btn-primary" type="submit" value="Reset" name="Reset" title="Reset all choices">Reset</button>
        </form>
    </div>
</div>


{% if layers %}

<div class="row">

    <div class="col-md-8">

        <div id = "search_results" >

            <table class="table table-hover">
              <thead>
                <tr>
                  <th scope="col">Select</th>
                  <th scope="col">Layer Name</th>
                  <th scope="col">Download</th>
                  <th scope="col">View Layer</th>
                </tr>
              </thead>

              <tbody>
                {% for layer in layers %}
                <tr>
                  <td><input class= messageCheckbox type="checkbox" name="checks" value="{{layer.1}}"/></td>
                  <td>{{layer.0}}</td>
                  <td><a href="{{layer.1}}" target="_blank"> Download Layer </a></td>
                  <td><input class="btn btn-primary" onclick="window.open('{{layer.2}}')" id="view" type="button" name="view" value="View"></td>
                </tr>
                {% endfor %}

                <tr>
                    <td><input type="checkbox" onClick="toggle(this, 'checks')"/> Select All</td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>

              </tbody>
            </table>

            <button class="btn btn-primary" type="button" name="download" style="float: left;" onClick= "open_all_links();">Download Selected</button>

        </div>


     <div class="a_pagination" align="right">
            <span class="step-links">

                {% if layers.has_previous %}

                    <a class="btn btn-primary btn-sm" name="prev_page" href="?page={{ layers.previous_page_number }}" role="button">Prev.</a>
                {% endif %}

                <span class="current" style ="color:#2C689C;font-size:16px;padding:8px;">
                    page {{ layers.number }} of {{ layers.paginator.num_pages }}
                </span>

                {% if layers.has_next %}
                    <a class= "btn btn-primary btn-sm"  href="?page={{ layers.next_page_number }}" role="button">Next</a>

                {% endif %}

            </span>
        </div>
    </div>
</div>

{% endif %}

<script type="text/javascript" >
.......
</script>

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Вам не нужно использовать метод POST , чтобы передать свои аргументы вашему views.py. Следуйте приведенному ниже примеру и перепишите свой view и свой HTML form. Вот простая форма для ввода пользователем слова для поиска:

<form method="get" action="">
    <input type="text" name="search4" class="search_input" placeholder="Search" required="required">                                       
    <input type="submit" value="Search">
</form>

Следующим шагом является то, что вы должны проверить ввод в вашем views.py, мы назвали входную метку name = "search4" , поэтому мы проверяем, есть ли какие-либо входные данные в нашей форме, используя этот код в наш views.py:

from django.db.models import Q
from django.core.paginator import Paginator

def search(request):
    query = request.GET.get("search4")
    if query:
        queryset = ResourceBase.objects.objects.all() # this will get all of your object of your model
        results = queryset.filter(Q(country_name__iexact=query)).all() 
        number_of_objects = results.count() # get the exact number of object to show in your html file
        paginator = Paginator(results, 12)  # Show 12 contacts per page
        page_var = 'page' # this will use for pagination in your html file
        page = request.GET.get(page_var) # this will use for pagination in your html file
        contacts = paginator.get_page(page)  # send only 12 object to your html file to show to user
         context = {
            "items": contacts,
            "key": str(query),
            'page': page_var, 
            "number_of_objects": number_of_objects,
        }
        return render(request=request, template_name='search.html', context=context, content_type=None, status=None,
                  using=None)
    else:
        ... # if user didn't enter anything to search

После получения и поиска пользовательского ввода в вашей базе данных, вы должны показать его пользователю в файле search.html, например:

{% for item  in items %}
<div>
    <div>
            <div class="product_title">{{ item.title }}</div> # show the part that you want the users to see
            ...                                               # rest of your item parts to show
    </div>
</div>
{% endfor %}

<div class="pagination">
                    <span class="step-links">
                        {% if items.has_previous %} # check the pagination that if there is perivious pages 
                            <a href="?{{ page }}=1">&laquo; first</a>

                            <a href="?{{ page }}={{ items.previous_page_number }}">previous</a>
                        {% endif %}

                        <span class="current">
                            Page {{ items.number }} of {{ items.paginator.num_pages }} # example of result : Page 1 of 13
                        </span>

                        {% if items.has_next %}
                            <a href="?{{ page }}={{ items.next_page_number }}"</a> # check the pagination that if there is any next or perivious pages 

                            <a href="?{{ page }}={{ items.paginator.num_pages }}">last &raquo;</a> # a link to last page
                        {% endif %}
                    </span>
                    {{ pagination }}

это базовая страница поиска с Paginator , если вам нужна дополнительная помощь или вопрос, я буду рад помочь.

1 голос
/ 28 июня 2019

Код <a class= "btn btn-primary btn-sm" href="?page={{ layers.next_page_number }}" role="button">Next</a> действительно ПОЛУЧИТ страницу, а код form1 = QueryForm() приведет к пустой форме.Вы находитесь на правильном пути.

У вас есть два варианта:

1) Измените кнопки «следующий / предыдущий», чтобы они находились внутри формы form1, и они выполняли POST.Переместить их внутри одного тега формы может быть затруднительно.

Если вы ориентируетесь на современные браузеры, вы можете использовать тег формы HTML5 при отправке (https://www.w3schools.com/tags/att_button_form.asp).

<form method="POST" id="form1">
    {{ form1|as_bootstrap }}
</form>
 ... outside the form tag, then
<button class="btn btn-primary btn-sm" form="form1" name="next" value="{{ layers.next_page_number }}" role="button">Next</button>

Вы должны иметь в request.POST следующее значение.

2) Инициализируйте QueryForm из параметров GET.

form1 = QueryForm(data=request.GET)

и включите параметры формы в URL.Для этого вам понадобится Javascript (например, Как использовать поле ввода в качестве параметра запроса к месту назначения? ), поскольку Django не знает о значениях в форме во время рендеринга до того, как пользователь вставит их.

...