|
| 1 | +from django import template |
| 2 | +from django.utils.safestring import mark_safe |
| 3 | + |
| 4 | +register = template.Library() |
| 5 | + |
| 6 | + |
| 7 | +@register.simple_tag(name='include_ajax') |
| 8 | +def include_ajax(template, minWidth='undefined', maxWidth='undefined', delWrap =False): |
| 9 | + """ |
| 10 | + Назначение: django-Тег для отложенной загрузки шаблона через ajax. Поддерживает, как внутренние так и внешние |
| 11 | + скрипты (через html-тег <sсript>). Имеет необязательное условие на минимальную и максимальную ширину экрана, при |
| 12 | + котором загружается шаблон. Также имеет необязательный аргумент delWrap, который убирает обертку вокруг содержимого. |
| 13 | + По умолчанию отключен.(ПРИ ВКЛЮЧЕНИИ НЕ ДАЕТ ЗАГРУЗИТСЯ ВНЕШНИМ СКРИПТАМ). |
| 14 | +
|
| 15 | + тестировалось на django 2.1.10 - 2.2.10 |
| 16 | + Создатель Вячеслав Уколов. вопросы и предложения по почте - (ukolovsl88@gmail.com) |
| 17 | + github - https://github.com/meat-source |
| 18 | +
|
| 19 | +
|
| 20 | + ВНИМАНИЕ: рабочие скрипты после загрузки и исполнения самоудаляются ! (это необходимо учитывать при тестировании и |
| 21 | + отладке) |
| 22 | + ВНИМАНИЕ №2: внешние скрипты записываются в конец блока (т.е после данных) |
| 23 | + ВНИМАНИЕ №3: ваш шаблон будет обернут в <div> вы можете убрать обертку использовав параметр delWrap='True', |
| 24 | + но при этом небудут успевать срабатывать внешние скрипты (допустим яндекс карта) |
| 25 | + смысл такой: на вход приходит имя шаблона. Допольнительно максимальная и/или минимальная ширина экрана браузера |
| 26 | + на выходе <div> с именем шаблона и солью + два скрипта один это ajax (загружает данные) и |
| 27 | + onload вешает обработчик событий на конец загрузки страницы с запуском ajax |
| 28 | + данная функция должна использоваться вместе вьъюхой и урл |
| 29 | + вьюха: |
| 30 | + def include_ajax(request, template): |
| 31 | + template = template.replace('&', '/') # для шаблонов вложенных в папку |
| 32 | + try: |
| 33 | + return render(request, template) |
| 34 | + except TemplateDoesNotExist: |
| 35 | + return HttpResponse(status=404) |
| 36 | + урл (в проекте!): |
| 37 | + path('include-ajax/<template>', include_ajax), |
| 38 | + """ |
| 39 | + # Функция Include - Ajax - запроса(непосредственно запрос) |
| 40 | + import random |
| 41 | + a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'm', 'i', 'k', 'l', 'o', 'p', 'r', 's', 't', 'n'] |
| 42 | + # соль |
| 43 | + sol = ''.join(map(str, random.sample(a, 5))) |
| 44 | + # удаляет скрипты после работы |
| 45 | + del_garbage = "document.getElementById('ajax_" + sol + "').remove();document.getElementById('onload_" + sol \ |
| 46 | + + "').remove();" |
| 47 | + # Если есть аргументы ширины сравниваем с окном браузера и выходим если не подходит |
| 48 | + if minWidth != 'undefined' or maxWidth != 'undefined': |
| 49 | + mobile_or_destktop = "if (screen.width < " + minWidth + " || screen.width > " \ |
| 50 | + + maxWidth + "){" + del_garbage + " return}" |
| 51 | + |
| 52 | + else: |
| 53 | + mobile_or_destktop = '' |
| 54 | + # выполняет скрипты в теле ajax |
| 55 | + execute_script = """function executeScripts (obj){ |
| 56 | + var head = document.getElementsByTagName('head')[0]; |
| 57 | + var scripts = obj.getElementsByTagName('script'); |
| 58 | + |
| 59 | + for(var i = 0; i < scripts.length; i++){ |
| 60 | + let str = scripts[i].outerHTML; |
| 61 | + let newSrc = str.match(/data-script-src=['"][^'"]*[^"]/gi); |
| 62 | + if(newSrc != null){ |
| 63 | + newSrc = newSrc[0].replace('data-script-src=',''); |
| 64 | + newSrc = newSrc.replace(/['"]/g,''); |
| 65 | + } |
| 66 | + eval(scripts[i].innerHTML); |
| 67 | + |
| 68 | + if(newSrc != null){ |
| 69 | + var script = document.createElement('script'); |
| 70 | + script.type = 'text/javascript'; |
| 71 | + script.src = newSrc; |
| 72 | + obj.appendChild(script); |
| 73 | + //scripts[i].src = ''; |
| 74 | + } |
| 75 | + } |
| 76 | + }""" |
| 77 | + # Сборка и вставка скриптов после пирнятия ответа серверра |
| 78 | + # (block.outerHTML=block.innerHTML убирает обертку, но при этом не успевают сработать внешние скрипты) |
| 79 | + if delWrap: |
| 80 | + post_send = execute_script + "executeScripts(block);" + del_garbage + "block.outerHTML= block.innerHTML" |
| 81 | + else: |
| 82 | + post_send = execute_script + "executeScripts(block);" + del_garbage # + "block.outerHTML= block.innerHTML" |
| 83 | + |
| 84 | + # непосредственно сам ajax |
| 85 | + include_ajax = """<script id='ajax_""" + sol + """'> |
| 86 | + function SendAjax_""" + sol + """(){ |
| 87 | + """ + mobile_or_destktop + """ |
| 88 | + var url =document.location.protocol +'//'+ document.location.host |
| 89 | + + '/include-ajax/""" + template.replace('/', '&') + """'; |
| 90 | + var request = new XMLHttpRequest(); |
| 91 | + request.open('GET', url); |
| 92 | + request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); |
| 93 | + request.addEventListener('readystatechange', () => { |
| 94 | + if (request.status === 200 && request.readyState === XMLHttpRequest.DONE) { |
| 95 | + var block = document.getElementById('""" + template + """'); |
| 96 | + function replace_src(str){return str.replace(/src/g,'data-script-src')}; |
| 97 | + block.innerHTML = request.responseText.replace(/<script.*<\/script>/g, replace_src); |
| 98 | + // console.log(block.innerHTML) |
| 99 | + console.log( 'include-ajax: подгружен template - ' + '""" + template + """'); |
| 100 | + """ + post_send + """ |
| 101 | + } |
| 102 | + if (request.status != 200){ |
| 103 | + console.error( 'include-ajax: подгрузка шаблона не удалась - ' + '""" + template + """ --- ' |
| 104 | + + request.status + ' --- ' + request.statusText) |
| 105 | + }; |
| 106 | + }); |
| 107 | + request.send(); |
| 108 | + } |
| 109 | + </script>""" |
| 110 | + # вешаем событие |
| 111 | + onload_body = """<script id='onload_""" + sol + """'> |
| 112 | + function addEvent_""" + sol + """(elem, type, handler){ |
| 113 | + if(elem.addEventListener){ elem.addEventListener(type, handler, false);} |
| 114 | + else { elem.attachEvent('on'+type, handler);} |
| 115 | + return false; |
| 116 | + }; |
| 117 | + addEvent_""" + sol + """(window, 'load', SendAjax_""" + sol + """); |
| 118 | + </script>""" |
| 119 | + # обертка для будущего блока |
| 120 | + block = "<div data-defer-template id='" + template + "'></div>" |
| 121 | + response = block + include_ajax + onload_body |
| 122 | + |
| 123 | + return mark_safe(response) |
0 commit comments