如何使用Ajax在Django中将数据传递给模态? [英] How to pass data to a modal in Django with Ajax?

查看:89
本文介绍了如何使用Ajax在Django中将数据传递给模态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Django应用程序的Bootstrap模式下显示产品的详细信息.

I´m trying to show detail information of products within a Bootstrap modal in a Django app.

我将此主题作为参考:堆栈溢出问题.

I´m taking this topic as reference: Stack Overflow question .

  • HTML正确调用了AJAX函数
  • AJAX函数正在打开模态
  • 模式调用URL

但是我收到500个内部服务器错误.响应为:

But I´m getting an 500 internal server error. The response is:

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

关于我做错了什么的任何线索,或者关于如何实现我的弃绝的任何建议吗?

Any clue on what I´m doing wrong or any suggestion on how to achieve my abjective?

谢谢!

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"),

推荐答案

我认为有关此问题的最重要信息将在您项目的urls.py文件中,其中包含目录url 和在那使用了一个命名空间.您在评论中提供了此信息.看来您没有在urlpatterns列表上方的目录urls.py文件顶部定义应用程序,这是造成问题的原因.因此,请检查以下内容.

I think the most important info about this problem would be in your project's urls.py file in which you included the catalog urls and used a namespace there. You gave this info in the comments. It looks like that you did not defined the app on the top of the catalog urls.py file, above the urlpatterns list and that is causing the problem. So check the following.

在目录urls.py文件中:

in catalog urls.py file:

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

urlpatterns = [
...]

如果您给命名空间='catalog'

If you give the namespace='catalog'

然后您应该在目录urls.py文件中定义

Then you should define that in your catalog urls.py file

app_name = 'catalog'

在这种情况下

更简单的解决方案:

由于此名称空间在您的项目中尚不相关,因此您应该在包含之后从主urls.py文件中删除namespace ='system',所以它应该看起来像这样:

Since this namespace does not have relevance yet in your project, then you should just delete the namespace='system' from you main urls.py file after include, so it should just look like this:

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

(注意::最好使用path(),因为url()最有可能被弃用),因此:

(notice: it is better to use path() since url() will be deprecated most probably) so:

from django.urls import path

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

那样,您可以忽略我上面的建议(因此您不必在任何地方定义任何应用程序),并且也应解决您的问题.

And that way you can ignore my suggestion above (so you do not have to define any app anywhere) and your problem also should be solved.

然后,在继续进行项目时,您应该再研究一些如何以及何时使用url的名称空间,因为它是很多倍的.

Then a bit later as you proceed with your project you should study a bit more how and when to use namespaces for urls, since it's many times redundant.

如果网址仍然有问题:

您只需在主项目urls.py文件中定义视图的url,即可查看是否收到了ajax调用,因此:

You can just define the url of the view in your main project urls.py file, just to see if the ajax call is received, so:

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

在这最后一种情况下,请不要忘记也将视图导入到您的主urls.py文件中,否则它也将无法正常工作,因此:

In this last case, do not forget to import the views in your main urls.py file too, otherwise it's also not working, so:

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

最后,主要问题是AJAX调用网址中的反斜杠/...(没有引起反向匹配错误).因此,简单的结论是:如果有人用打开反斜杠的urlpatterns定义了一个url,则在ajax调用中应该是相同的方式,否则就不用打开反斜杠/.好吧,是的...继续...

And finally, the main problem was an opening backslash /... in the AJAX call url (it caused a no Reverse Match error). So, the simple conclusion: if someone define an url in urlpatterns with opening backslash then in the ajax call it should be the same way, otherwise without opening backslash/. Well, yeah... to be continued...

更新-使用DJANGO中的AJAX解决如何将数据传递到HTML模态的原始问题

所以,让我们看看.基本上,很多事情在这里都被误解了,我试图用一种可行的方法来解决这个问题.通过使用AJAx/jQuery/javascript,您实际上绕过了使用Django模板标签/变量的很大一部分.那就是使用jQuery/javascript的全部要点.

So, let's see. A lot of things were basically misunderstood here, I tried to clear that with a working approach. With using AJAx/jQuery/javascript, you actually bypass a big part of use of Django template tags/variables. That is the whole point of using jQuery/javascript.

首先,我仍然建议您在Django中定义urlpattern时使用 path() re-path()而不是url(). url()将如我上面提到的那样被弃用.还有使用path()的其他重要原因.

First, I still suggest you to use path() and re-path() and not url() when you are defining urlpatterns in Django. url() will be deprecated as I mentioned above. And there are other important reasons to use path().

因此,您的主urls.py 应该看起来像这样:

So your main urls.py should look something this:

# 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调用正常工作也非常重要.还有视图功能(我将其放在模板后面).

The javascript/ajax call and the response handling had to be structured again, and changed here and there. But again, the correct urls.py is also very important for the ajax call to work. And the view function too (I'll place it after the template).

这位于 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 的模板.

The template called artista.html had to be a bit reformulated.

{% 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(我在上文中给出)填充到每个产品的弹出模式中.

And finally, one of the most important thing, the views.py file where we have the view which is handling the ajax call and giving back all of the products data which will be filled in the pop up modal at every product, using javascript/jQuery (that I gave above).

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)

最后直观的图片显示了该模式如何与任何产品一起提供给点击的产品所有必需的数据:

And finally the visual which shows how the modal is working with any products providing all of the needed data to the clicked product:

因此,您在应用程序方面做得很好,非常出色的基础知识和模板工作,但是您应该更多地研究jQuery/javascript在Django项目中的作用和功能.他们在一起真的很强大.

So, you did a good job with your app, very nice basics and template work, but you should study more the role and power of jQuery/javascript in Django projects. They are really powerful together.

我希望您将使用和研究上述代码,并且也可以将其用于以后的项目中.干杯. :)

I hope that you will use and study the above codes and you can use it for your later projects too. Cheers. :)

这篇关于如何使用Ajax在Django中将数据传递给模态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆