Получить модальные данные с Ajax из Django Модель - PullRequest
0 голосов
/ 13 апреля 2020

Извините за повторение этого вопроса и за интеграцию Ajax, поскольку это очень широкий вопрос, но я просто не могу понять.

У меня есть таблица html с 4k + строками данных, и каждая строка имеет некоторую основную c информацию, такую ​​как имя, адрес, фамилия, телефон, и кнопку, которая запускает модальный bootstrap, который содержит дополнительные данные, такие как phone2, address 2, et c.

Моя проблема в том, что мой модал находится внутри a для l oop вот так -

<tbody>
    {% for opp in optika %}
        <tr>
            <td>{{ opp.example }}</td>
            <td>{{ opp.some_field }}</td>
            <td>            
                <button id="testbtn" type="button" class="btn btn-success btn-sm btn-detail"
                    data-toggle="modal"
                    data-target="#detalji_modal{{ opp.pk }}"
                    Detalji
                </button>
            </td>
...
        </tr>
    {% include "opportunity/partials/_detalji_modal.html" %}
    {% endfor %}
</tbody>

И это модальная деталь -


<div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog"
     id="detalji_modal{{ opp.pk }}"
     aria-labelledby="detalji_modalLabel">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="detalji_modalLabel">Detalji</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body" id="">
                <div class="container-fluid">
                    <h5>{{ opp.... }}</h5>
                    <p>{{ opp.....title }}</p>
                    ...
                </div>
            </div>
            <div class="modal-footer">
                <p style="margin-right: auto">Zahtev uneo/la : {{ opp.... }}</p>
                ...
                ...
                <button type="button" class="btn btn-outline-primary" data-dismiss="modal">
                    Close
                </button>
            </div>
        </div>
    </div>
</div>

Я передам вид также:

@login_required(login_url='registration/login')
def OptikaList(request):
    user_groups = request.user.groups.all()
    optika_svi = OpportunityList.objects.all().defer(
        ...
    ).filter(opp_type__exact='optika').exclude(opp_status='zakazan', is_locked=True).order_by('eluid',
                                                                                              '-opp_status').exclude(
        opp_status='odustao')
    optika = [o for o in list(optika_svi)]

    counter = 1000

    context = {
        'optika': optika[:counter],
        'broj_poslova': counter,
        'ukupno_poslova': optika_svi.count(),
        'user_groups': user_groups,
    }

    #Ajax is not used for now, since idk how to implement it right.
    if request.is_ajax():
        data = {
            'rendered_table': render_to_string('opportunity/get_more_tables.html', context=context,
                                               request=request)}

        return JsonResponse(data)

    return render(request, 'opportunity/opp_optika.html', context)

И это мой ajax вызов, который является беспорядком -

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
    $(document).ready(function () {

        // Our ajax function. Specifically declared as we are
        // using it in multiple places
        let ajax_function = function () {
            fetch_modal();
            page_changing = false;
            $.ajax({
                url: '{% url 'opportunity:optika' %}',
                type: "get",
                cache: true,
                data_type: 'html',

                success: function (data) {
                    console.log("Ajaxed");
                    var page = dt.page(); // save page we are on
                    var order = dt.order(); // save ordering
                    var search = dt.search();
                    var page_length = dt.page.len();
                    dt.destroy(); // put table back to new

                    $('#dataTable').find('tbody').empty().append(data.rendered_table);
                    dt = $('#dataTable').DataTable(table_options); // Re-init datatable
                    dt.order(order); // Put back our ordering
                    dt.search(search);
                    dt.page.len(page_length);
                    dt.page(page).draw('page'); // Draw the page
                    dt.draw(false); // Put in our ordering an all the stuff

                    if (focused_search) {
                        $('input[type=search]').first().focus();
                        console.log('focused');
                    }
                    focus_set();
                    focus_lost();
                    page_changer();
                    set_detail_btn();
                },
                error: function (data) {
                    console.log("Ajax stopped!");
                }
            });
        };

        // Variables to hold our urls to the body and footer views
        let body_update_link = '{% url 'opportunity:fetch_body' %}';
        let footer_update_link = '{% url 'opportunity:fetch_footer' %}';

        // id of opportunity currently in our modal
        let modal_opp = false;

        // ajax function for getting data for modal
        let fetch_modal = function () {
            if (modal_opp) {
                $('#detalji_modal .modal-body').load(body_update_link, modal_opp.toString());
                $('#detalji_modal .modal-footer').load(footer_update_link, modal_opp.toString());
            }
        };

        // function for activating getting modal data on click on details
        let set_detail_btn = function () {
            $('.btn-detail').click(function () {
                modal_opp = $(this).data('opp');
                fetch_modal();
            });
        };

        // Set modal_opp to false after our modal has disappeared to avoid
        // unnecessary updates of an invisible modal
        $('#detalji_modal').on('hidden.bs.modal', function (e) {
            modal_opp = false;
        });

        // A central variable for putting in table options
        let table_options = {
            // searching: false,
            // paging: false
            order: [[0, "asc"]]
        };

        // variable holding our setInterval function so we can disable
        // it if we want to
        let my_timer;

        // variable set to true if we are currently in the filter
        let focused_search = false;

        // Set our focused_search variable if our filter has focus
        let focus_set = function () {
            $('input[type=search]').focus(function () {
                console.log('HAS FOCUS');
                focused_search = true;
                clearInterval(my_timer);
                my_timer = false;
            });
        };

        // Reset our focused_search variable if our filter loose focus
        const focus_lost = function () {
            $('input[type=search]').blur(function () {
                    console.log('LOST_FOCUS');
                    focused_search = false;
                },
                function () {
                    console.log('LOST_FOCUS');
                    conditional_timer_restart();
                    focused_search = false;
                }
            );
        };

        // Restart our timer
        const conditional_timer_restart = function () {
            if (!my_timer) {
                my_timer = setInterval(ajax_function, 2000);
            }
        };

        // variable set to true if we have changed paging
        // needed when we click on our paging select so
        // our timer restart raliably
        let page_changing = false;

        // Function to add some behaviour to our pager
        // Will stop reloading page if we click on that select
        // Will restart the reloading cycle automatically after 5
        // seconds
        const page_changer = function () {
            $('select[name=dataTable_length]').click(function () {
                console.log('Page changer init');
                if (page_changing) {
                    page_changing = false;
                } else {
                    clearInterval(my_timer);
                    my_timer = false;
                    setTimeout(conditional_timer_restart, 5000);
                }
            });
            $('select[name=dataTable_length]').change(function () {
                console.log('Page changer done');
                page_changing = true;
                my_timer = setInterval(ajax_function, 5000);
            });
            $('select[name=dataTable_length]').blur(function () {
                console.log('Page changer lost focus');
                if (!my_timer) {
                    my_timer = setInterval(ajax_function, 5000);
                }

            });

        };
        set_detail_btn = function () {
            $('.btn-detail').click(function () {
                modal_opp = $(this).data('opp');
                fetch_modal();
            });
            $('.btn-detail').hover(
                function () {
                    console.log('hovered');
                    clearInterval(my_timer);
                    my_timer = false;
                },
                function () {
                    console.log('hoveroff ');
                    conditional_timer_restart();
                }
            );
        };

        // Our intial init of the table
        let dt = $('#dataTable').DataTable(table_options);
        focus_set();
        focus_lost();
        page_changer();
        set_detail_btn();
        // my_timer = setInterval(ajax_function, 1000);

    });

</script>


функции fetch_body и fetch_footer из views.py -

def fetch_body(request):
    id = list(request.GET.keys())[0]
    opp = OpportunityList.objects.get(pk=id)

    return HttpResponse(
        render_to_string('opportunity/partials/_modal_body.html', context={'opp': opp}, request=request))


def fetch_footer(request):
    id = list(request.GET.keys())[0]
    opp = OpportunityList.objects.get(pk=id)

    return HttpResponse(
        render_to_string('opportunity/partials/_modal_footer.html', context={'opp': opp}, request=request))

Сама страница требует 5+ секунд для загрузки, и она содержит более 20 МБ данных, что является огромным перебором.

В основном мне нужно, чтобы модальное тело (данные) извлекалось при нажатии на кнопку модального открытия / включения ( testbtn) click.

Или, возможно, загрузить детали (модальные) только для показа объектов с помощью th pagination.

И поскольку я не очень хорошо разбираюсь с Ajax (это все еще сбивает с толку для меня) и jQuery, может кто-нибудь объяснить, пожалуйста, лучший подход для этого (пример будет отличным!).

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...