Как передать данные модалу в Django с помощью Ajax?

Я пытаюсь показать подробную информацию о продуктах в модале Bootstrap в приложении Django.

Я беру эту тему в качестве ссылки: вопрос переполнения стека.

  • HTML-код правильно вызывает функцию AJAX
  • Функция AJAX открывает модальный
  • Модал вызывает URL

Но я получаю 500 внутренняя ошибка сервера. Ответ:

NoReverseMatch at /catalog/product-detail/
'system' is not a registered namespace

Любая подсказка о том, что я делаю неправильно или какие-либо предложения о том, как достичь моей цели?

Спасибо!

HTML - вызов функции AJAX

<div class="row">
        {% for y in productos %}
            {% if y.categoria_producto|stringformat:"s" == objetivo %}
                    <button data-id="{{y.id}}" type="button" class="btn btn-warning margin-bottom delete-company" >delete</button>   
            {% endif %}
        {% endfor %}
        {% csrf_token %}
</div>

Код AJAX

$(document).on('click','.delete-company',function(){
    var id = $(this).data('id');

    $.ajax({
        url:'/catalog/product-detail/',
        type:'POST',
        data:{
            'id':id,
            'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
        },
        success:function(data){
            $('#modalQuickView .modal-dialog').html($('#modalQuickView .modal-dialog',data));
            $('#modalQuickView').modal('show');
        },
        error:function(){
            console.log('error')
        },
    });
});

HTML модальный

<div class="modal fade" id="modalQuickView" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
    <div class="modal-content">
        <div class="modal-body">
            <div class="row">
                <div class="col-lg-5">
                    <!--Carousel Wrapper-->
                    <div id="carousel-thumb" class="carousel slide carousel-fade carousel-thumbnails" data-ride="carousel">
                        <!--Slides-->
                        <div class="carousel-inner" role="listbox">
                            <div class="carousel-item active">
                                  <img class="d-block w-100" src="{% static 'img/Cinta1.jpg' %}" alt="Kinemed - ">
                            </div>
                            <div class="carousel-item">
                                  <img class="d-block w-100" src="{% static 'img/Cinta2.jpg' %}" alt="Kinemed - ">
                            </div>
                        </div>
                        <!--/.Slides-->
                        <!--Controls-->
                        <a class="carousel-control-prev" href="#carousel-thumb" role="button" data-slide="prev">
                            <span class="carousel-control-prev-icon" aria-hidden="true"></span>
                            <span class="sr-only">Previous</span>
                        </a>
                        <a class="carousel-control-next" href="#carousel-thumb" role="button" data-slide="next">
                            <span class="carousel-control-next-icon" aria-hidden="true"></span>
                            <span class="sr-only">Next</span>
                        </a>
                          <!--/.Controls-->
                    </div>
                    <!--/.Carousel Wrapper-->
                </div>
                <div class="col-lg-7" style="padding-left: 10px; margin-top: 1rem;">
                    {% if company %} <!-- this company instance will come from AJAX -->
                        <form method="post" action="{% url 'system:company_delete' id=company.id %}">
                        {% csrf_token %}
                            <div class="modal-content">
                                <div class="modal-body">
                                    <input type="text" name="name" maxlength="100" required="" id="id_name" value="{{ company.id }}">
                                    <input type="submit" class="btn btn-primary" value="Delete">
                                </div>
                            </div>
                        </form>
                    {% endif %}
                </div>
                <div style="padding-top: 1.5rem;">
                    <button type="button" class="btn btn-outline-info waves-effect ml-auto" data-dismiss="modal">Cerrar</button>
                </div>
            </div>
        </div>
    </div>
</div>

Посмотреть

def companyListView(request):
    context = {}
    companys = ProductosBase.objects.all()
    if request.method == 'POST' and request.is_ajax():
        ID = request.POST.get('id')
        company = companys.get(id=ID) # So we send the company instance
        context['company'] = company
    context['companys'] = companys
    return render(request,'catalog/artista.html',context)

URL

url(r'^product-detail/$', views.companyListView, name="companyListView"),

1 ответ

Решение

Я думаю, что самая важная информация об этой проблеме была бы в файле urls.py вашего проекта, в который вы включили URL-адреса каталога и использовали там пространство имен. Вы дали эту информацию в комментариях. Похоже, что вы не определили приложение в верхней части файла каталога urls.py, над списком urlpatterns, и это является причиной проблемы. Поэтому проверьте следующее.

в каталоге urls.py файл:

app_name = 'system' # if your namespace is 'system.

urlpatterns = [
...]

Если вы дадите пространство имен ='каталог'

Затем вы должны определить, что в вашем каталоге файл urls.py

app_name = 'catalog'

ПРОСТОЕ РЕШЕНИЕ в данном конкретном случае:

Поскольку это пространство имен еще не имеет релевантности в вашем проекте, то вам нужно просто удалить namespace='system' из вашего основного файла urls.py после include, так что оно должно выглядеть так:

url(r'^catalog/', include('catalog.urls')),

(обратите внимание: лучше использовать path(), так как url ​​(), скорее всего, не рекомендуется), поэтому:

from django.urls import path

path('/catalog/', include('catalog.urls')),

Таким образом, вы можете игнорировать мое предложение выше (чтобы вам не приходилось нигде определять приложения), и ваша проблема также должна быть решена.

Затем, немного позже, когда вы приступите к работе над своим проектом, вам следует немного больше изучить, как и когда использовать пространства имен для URL, поскольку он во многих случаях избыточен.

И если все еще есть проблемы с URL:

Вы можете просто определить URL представления в файле urls.py вашего основного проекта, просто чтобы увидеть, получен ли вызов ajax, так:

url(r'^catalog/product-detail/', views.companyListView, name='companylist'),

В последнем случае не забудьте также импортировать представления в ваш основной файл urls.py, иначе он также не работает, поэтому:

from catalog import views # in main urls.py file, if catalog is your app name

И, наконец, основной проблемой была открывающая обратная косая черта /... в URL-адресе вызова AJAX (это вызвало ошибку отсутствия обратного соответствия). Итак, простой вывод: если кто-то определяет URL в urlpatterns с открывающим обратным слешем, то в вызове ajax он должен быть таким же, в противном случае без открытия обратного слеша /. Ну да... продолжение следует...

ОБНОВЛЕНИЕ - РЕШЕНИЕ ОРИГИНАЛЬНОГО ВОПРОСА О ПЕРЕДАЧЕ ДАННЫХ В МОДАЛЬ HTML, ИСПОЛЬЗУЯ AJAX В DJANGO

Итак, посмотрим. Здесь многое было неправильно понято, и я попытался объяснить это с помощью рабочего подхода. Используя AJAx/jQuery/javascript, вы фактически игнорируете большую часть использования шаблонных тегов / переменных Django. В этом весь смысл использования jQuery/javascript.

Во-первых, я все еще предлагаю вам использовать path() и re-path(), а не url(), когда вы определяете urlpatterns в Django. url() будет устаревшим, как я упоминал выше. И есть другие важные причины для использования path().

Так что ваш основной urls.py должен выглядеть примерно так:

# main project urls.py
from django.contrib import admin
from django.urls import include, path
from django.conf.urls import url

urlpatterns = [
    path('catalog/', include('catalog.urls')),
    path('admin/', admin.site.urls),
]

Ваш каталог urls.py должен быть таким:

# catalog urls.py
from django.conf.urls import url
from django.urls import include, path
from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

urlpatterns += [
    url(r'^marcas/(?P<person_id>[\d\D]+)/$', views.MarcasView, name="marcas"),
    url(r'^categorias_productos/(?P<person_id>[\d\D]+)/$', views.CategoriasView, name="categoria"),
    url(r'^your-name/$', views.create_user, name="create_user"),
    path('product-detail/', views.companyListView, name="companylist"),
]

Вызов javascript/ajax и обработка ответа должны были быть снова структурированы и изменены здесь и там. Но опять же, правильный urls.py также очень важен для вызова ajax. И функция просмотра тоже (я помещу это после шаблона).

Это внизу шаблона base_generic.html

{% block scripts %}

    <script>

        $(function(){
            $('.show_product').on('click', function (e) {
                e.preventDefault();
                let product_id = $(this).attr('id');

                $.ajax({
                    url:'/catalog/product-detail/',
                    type:'POST',
                    data: $('#form_have_product_'+product_id).serialize(),
                    success:function(response){
                        console.log(response);
                        $('.show_product').trigger("reset");
                        openModal(response);
                    },
                    error:function(){
                        console.log('something went wrong here');
                    },
                });
            });
        });

        function openModal(product_data){
          $('#product_name').text(product_data.company.producto);
          $('#marcas_name').text(product_data.marca);
          $('#category_name').text(product_data.categoria_producto_id);
          $('#sizes').text(product_data.company.largo);
          $('#color_name').text(product_data.company.color);
          $('#packaging').text(product_data.company.packaging);
          $('.description1 > p:eq(0)').html(product_data.company.descripcion);
          $('#product_target').text(product_data.usos);
          $('#modal_img_1').attr('src', '/static/img/'+product_data.company.foto_1 );
          $('#modal_img_2').attr('src', '/static/img/'+product_data.company.foto_2 );
          $('#modalQuickView').modal('show');
        };

    </script>

{% endblock %}

Шаблон с именем artista.html должен быть немного переформулирован.

{% extends "base_generic.html" %}

{% load static %}

{% block content %}

<!-- Productos por categoría -->

<!-- Modal: modalQuickView -->

<div class="modal fade" id="modalQuickView" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
  aria-hidden="true">
  <div class="modal-dialog modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-body">
        <div class="row">
          <div class="col-lg-5">
            <!--Carousel Wrapper-->
            <div id="carousel-thumb" class="carousel slide carousel-fade carousel-thumbnails" data-ride="carousel">
              <!--Slides-->

                      <div class="carousel-inner" role="listbox">
                        <div class="carousel-item active">
                          <img id="modal_img_1" class="d-block w-100" src="{% static 'img/Cinta1.jpg' %}" alt="Kinemed - ">
                        </div>
                        <div class="carousel-item">
                          <img id="modal_img_2" class="d-block w-100" src="{% static 'img/Cinta2.jpg' %}" alt="Kinemed - ">
                        </div>

              </div>
              <!--/.Slides-->
              <!--Controls-->
              <a class="carousel-control-prev" href="#carousel-thumb" role="button" data-slide="prev">
                <span class="carousel-control-prev-icon" aria-hidden="true"></span>
                <span class="sr-only">Previous</span>
              </a>
              <a class="carousel-control-next" href="#carousel-thumb" role="button" data-slide="next">
                <span class="carousel-control-next-icon" aria-hidden="true"></span>
                <span class="sr-only">Next</span>
              </a>
              <!--/.Controls-->

            </div>
            <!--/.Carousel Wrapper-->

          </div>

          <!--This popup modal will be opened by the ajax call - Important-->

          <div class="col-lg-7" style="padding-left: 10px; margin-top: 1rem;">

              <h1 id="product_name">Product name</h1>
              <h3 id="marcas_name"><a href="" class="artist-style" style="color: #21518A; font-size: 1rem; margin-top: 1rem; padding-left: 0px;">SpiderTech</a></h3>
              <h4 id="category_name"><p class="artist-info" style="font-size: 1rem; color: black; padding-left: 0; margin-top: 0.5rem; margin-bottom: 5px;">Cintas kinesiológicas</p></h4>
              <h4 id="sizes"><p class="artist-info" style="font-size: 1rem; color: black; padding-left: 0; margin-top: 1rem; margin-bottom: 5px;">3,8 cms X 5,0 mts</p></h4>
              <h4 id="color_name"><p class="artist-info" style="font-size: 1rem; color: black; padding-left: 0; margin-top: 1rem; margin-bottom: 5px;">Beige</p></h4>
              <h4 id="packaging"><p class="artist-info" style="font-size: 1rem; color: black; padding-left: 0; margin-top: 1rem; margin-bottom: 5px;">Retail PET box</p></h4>
              <h4 id=""><p class="artist-info" style="font-size: 1rem; color: black; padding-left: 0; margin-top: 1rem; margin-bottom: 5px;"></p></h4>
              <div id="description1" class="description1" style="color: #21518A;">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
                      Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.</p>
                  <h6 id="product_target_label" style="color: black;">Usos: </h6>
                  <p id="product_target">Protección muscular, Recuperación</p>
              </div>

          </div>

            <div style="padding-top: 1.5rem;">
                     <button type="button" class="btn btn-outline-info waves-effect ml-auto" data-dismiss="modal">Cerrar</button>
            </div>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- Fin Modal product detail -->

<!-- Productos por categoría -->

    {% for x in categorias %}

            {% if x.categoria_producto|stringformat:"s" == objetivo %}

                <div class="jumbotron" style="background-color: #1986E6">
                  <div class="container">
                    <div class="row">
                        <div class="barra" style="background-color: white;"></div>
                          <div class="col-12 text-center">
                              <h1 style="color: #FCFCFC">{{ objetivo }}</h1>
                          </div>

                            <div class="col-sm-12 col-md12 col-lg-12 col-xl-6 text-center" style="padding-top: 1rem;">
                              <h6 style="color: #FCFCFC">{{ x.descripcion_brief }}</h6>
                          </div>
                    </div>

                  <div style="padding-top: 1rem;">
                      <button type="button" class="btn btn-secondary btn-sm" data-toggle="collapse"
                               data-target="#demo"><i class="fas fa-info-circle"></i> Más información</button>
                  </div>


                  </div>

                <div class="container collapse" id="demo">
                    <div class="row" style="padding-top: 40px; padding-bottom: 20px;">
                        <div class="col-lg-6 col-lg-6-custom col-sm-12">
                                <div class="videoWrapper">
                                    <!-- Copy & Pasted from YouTube -->
                                    <iframe src="{{ x.video }}" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
                                </div>

                            <div class="row">
                                <div class="col-lg-6 col-md6 col-sm-6 col-xl-6 text-center">
                                   <img style="width: 100%; position: relative;" border="0"alt="{{ objetivo }}" src=" {{ x.foto_1.url }} " class="esconder">
                                  </div>

                                <div class="col-lg-6 col-md63 col-sm-6 col-xl-6 text-center">
                                    <img style="width: 100%; position: relative;" border="0" alt="{{ objetivo }}" src=" {{ x.foto_2.url }} " class="esconder">
                                </div>
                            </div>

                        </div>

                        <div class="col-lg-6 col-lg-6-custom col-sm-12">
                            <div class="texto-brief">
                                <p>{{ x.descripcion_long }}  </p>
                                <h6 style="color: white;">Usos</h6></br>
                                <p>{{ x.usos }}  </p>
                            </div>
                        </div>


                    </div>
                    <div style="padding-top: 1rem;">
                      <button type="button" class="btn btn-secondary btn-sm" data-toggle="collapse"
                               data-target="#demo"><i class="fas fa-info-circle"></i> Menos información</button>
                  </div>
                 </div>
            </div>

            {% endif %}
    {% endfor %}



<div class="jumbotron" style="background-color: white;">
     <div class="container">
          <div class="row">
            {% for y in productos %}
                {% if y.categoria_producto|stringformat:"s" == objetivo %}
                    <div class="col-sm-6 col-md-4 col-lg-2 col-xl-2 text-center" style="padding-bottom: 20px;">

                        <form name="form" action="#" id="form_have_product_{{y.id}}" method="POST">
                          {% csrf_token %}
                          <input name="id" id="product_id_submit" type="text" value="{{y.id}}" hidden="true"/>
                        <button id="{{y.id}}" "type="button" class="btn btn-warning margin-bottom show_product">Product details</button>
                        </form>
                         <!--<a id="" href="" data-toggle="modal" data-target="#modalQuickView"><img border="0" alt="W3Schools" src="{{ y.foto_1.url }}" class="artist-foto"></a> we don't need this-->
                           <div>
                            <a href="" id="{{y.id}}" data-id="{{y.id}}" class="artist-title show_product" style="color: black; padding-left: 0;" data-toggle="modal" >{{ y.producto }}</a> <!--data-target="#modalQuickView"-->
                        </div>
                        <div><a href="{% url 'marcas' person_id=y.marca %}" class="artist-style" style="color: #21518A; padding-left: 0;">{{ y.marca }}</a></div>
                        <div><p class="artist-info" style="color: #21518A; padding-left: 0; margin-bottom: 5px; margin-top: 5px;">{{ y.packaging }}</p></div>
                        <div><p class="artist-info" style="color: #21518A; padding-left: 0; margin-bottom: 5px;">{{ y.color }}</p></div>
                        <div><p class="artist-info" style="color: #21518A; padding-left: 0; margin-bottom: 5px;">{{ y.ancho }} cms. X {{ y.largo }} mts.</p></div>
                     </div>
                {% endif %}
            {% endfor %}

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

<div class="jumbotron" style="background-color: lightgrey;">
     <div class="container">
                 <div class="row">
                        <div class="barra" style="background-color: #21518A;"></div>
                          <div class="col-12 text-center">
                              <h1 style="color: #21518A">Más productos</h1>
                          </div>


                </div>

                  <div class="row" style="margin-top: 1rem;">
                      <div class="col-sm-12 col-md-12 col-lg-12 col-xl-12 text-center" style="padding-bottom: 20px;">
                        {% for z in categorias %}
                                {% if z.categoria_producto|stringformat:"s" != objetivo %}

                                    <h3><a  style="color: #21518A;" href=" {% url 'categoria' person_id=z.categoria_producto %} ">  {{ z.categoria_producto }}</a></h3>

                                {% endif %}
                        {% endfor %}
                      </div>
                  </div>
     </div>
</div>

{% endblock %}

И, наконец, одна из самых важных вещей, файл views.py, в котором у нас есть представление, которое обрабатывает вызов ajax и возвращает все данные о продуктах, которые будут заполнены во всплывающем модале для каждого продукта, используя javascript /. JQuery (что я дал выше).

from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse, HttpRequest
from django.urls import reverse
from .models import ProductosBase, Marcas, Categorias_Producto
from .forms import FormularioContacto
from django.http import JsonResponse
import copy
import json
from django.forms.models import model_to_dict
from django.core import serializers

## other views functions are here.... ##

def companyListView(request):

    context = {}
    companys = ProductosBase.objects.values()
    context[companys] = ProductosBase.objects.all()

    if request.method == 'POST' and request.is_ajax():

        ID = request.POST.get('id')
        company = companys.get(pk=ID)  # So we send the company instance
        marca_name = ProductosBase.objects.get(pk=ID).marca # to have the related fields - marca
        marca_name = model_to_dict(marca_name) # better in dict
        marca_name = marca_name['marca'] # to define marca for the product
        usos_product = ProductosBase.objects.get(pk=ID).categoria_producto  # we need usos field from categories
        usos_product = model_to_dict(usos_product)
        usos_product = usos_product['usos']
        return JsonResponse({ 'company' : company, 'marca' : marca_name, 'usos' : usos_product })
    else:
        return render(request, 'catalog/artista.html', context)

И, наконец, наглядное изображение, показывающее, как мод работает с любыми продуктами, предоставляющими все необходимые данные для продукта, на который нажали:

Итак, вы хорошо поработали со своим приложением, с очень хорошими основами и работой с шаблонами, но вам следует больше изучить роль и мощь jQuery / javascript в проектах Django. Они действительно сильны вместе.

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

Другие вопросы по тегам