【问题标题】:how to integrate vue.js with django?如何将 vue.js 与 django 集成?
【发布时间】:2019-10-25 11:24:14
【问题描述】:

这是带有 vue.js 的单页应用程序,它进行了一些简单的计算,我试图在 django 中实现这个计算,但它没有给我想要的结果。 在这里,我在 vue.js 中动态创建了数组,这只是完美地显示了产品的图像,而不是 product.nameproduct.sell_price 以及 @click.prevent="addToCart(product)"this 函数不起作用?我该如何解决?

vue.js

   <script src="{% static 'js/vue.js' %}"></script>

   <script type="text/javascript" src="{% static '/js/vue-resource.js' %}"></script>
    <script>

 new Vue({
    el: '#posApp',
    
    data: {
        total: 0,
        discount: 0,
        products: [
            {% for product in products %}
                {
                    "id": {{product.id}},
                    "name": "{{product.name}}",
                    "image": "/media/{{product.image}}",
                    "price": {{product.sell_price}}
                },
              {% endfor %}

        ],
        cart: [],
        search: ""
    },
    methods: {

        addToCart: function(product){

            var found = false;
            for (var i = 0; i < this.cart.length; i++){
                if (this.cart[i].id === product.id){
                    this.cart[i].quantity++;
                    found = true;
                }
            }
            if (!found) {
                this.cart.push({
                    id: product.id,
                    name: product.name,
                    sell_price: product.sell_price,
                    quantity: 1
                });
            }

            this.total += product.sell_price;
        },
        inc: function(item){
            item.quantity++;
            this.total += item.sell_price;
        },
        dec: function(item){
            item.quantity--;
            this.total -= item.sell_price;
            if (item.quantity <= 0){
                var i = this.cart.indexOf(item);
                this.cart.splice(i, 1);
            }
        },
        removeFromCart: function(item){
            this.cart.splice(this.cart.indexOf(item), 1);
            this.total = this.total - (item.sell_price * item.quantity);
        },
        clearCart: function(){
            this.cart = [];
            this.total = 0;
            this.discount = 0;
        },
        payment: function(){
            this.cart = [];
            this.total = 0;
            this.discount = 0;
            alert('Transaction Completed');
        }
    },
    computed: {
        filteredProducts(){
            // var lowerTitle = product.title.toLowerCase();
            return this.products.filter((product) => {
                return product.name.toLowerCase().match(this.search);
            });
        }
    }
});
</script>

html

 <div class="col-md-3" v-for="product in filteredProducts" :key="product.id"> <!-- Inner-Col .// -->
                  <a href="#" @click.prevent="addToCart(product)">
                    <div class="box box-default pos-product-card"> <!-- /.box -->
                      <img class="card-img-top img-responsive" :src="product.image" alt="Card image cap">
                      <div class="box-body"> <!-- /.box-body -->
                        <h4 class="box-title">{{ product.name }}</h4>
                        <!-- <p class="box-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> -->
                        <button class="btn btn-info"><i class="fas fa-shopping-cart"></i></button>
                      </div> <!-- /.box-body -->
                    </div> <!-- /.box -->
                  </a>
                </div>
{% for category in categories %}
            <div class="tab-pane fade" id="category-{{category.id}}">

                <div class="row"> <!-- Inner-Row .// -->
                    {% for product in category.product_set.all %}
                   <div class="col-md-3" v-for="product in filteredProducts" :key="product.id"> <!-- Inner-Col .// -->
                  <a href="#" @click.prevent="addToCart(product)">
                    <div class="box box-default pos-product-card"> <!-- /.box -->
                      <img class="card-img-top img-responsive" :src="product.image" alt="Card image cap">
                      <div class="box-body"> <!-- /.box-body -->
                        <h4 class="box-title">{{ product.name }}</h4>
                        <!-- <p class="box-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> -->
                        <button class="btn btn-info"><i class="fas fa-shopping-cart"></i></button>
                      </div> <!-- /.box-body -->
                    </div> <!-- /.box -->
                  </a>
                </div>
                    {% endfor %}
     <table class="table table-hover text-center">
                                  <!-- <thead class="thead-dark"> -->
                                    <tr>
                                      <th>Item</th>
                                      <th>Quantity</th>
                                      <th>Rate</th>
                                      <th>Subtotal</th>
                                      <th>&nbsp;</th>
                                    </tr>
                                  <!-- </thead> -->
                                      <tr v-for="item in cart" :key="{{item.id}}">

                    <td><a href="#">{{ item.name }}</a></td>
                    <td><button class="btn btn-flat btn-xs btn-info p-1 mx-1" @click="inc(item.id)">+</button>[[ item.quantity ]]<button class="btn btn-flat p-1 mx-1 btn-xs btn-info" @click="dec(item.id)">-</button></td>
                    <td><span class="text-muted">{{ item.sell_price }}</span> </td>
                    <td>Rs {{ item.sell_price * item.quantity }}</td>
                    <td><button class="btn btn-xs btn-outline-primary" @click="removeFromCart(item)"><i class="fas fa-trash-alt"></i></button></td>
                  </tr>
                                  </table>
                                </div>
                                <div class="no-item-msg" v-if="cart.length === 0">No items in the cart.</div>
                              </div>
         <table class="table">
                                    <tr>
                      <td>Total Items</td>
                      <td>{{ cart.length }}</td>
                    </tr>
                    <tr>
                      <td>Total Amount</td>
                      <td>{{ total }}</td>
                    </tr>
                    <tr>
                      <td><span class="height-control">Discount (In Amount)</span></td>
                      <td><input type="number" v-model="discount" class="form-control"></td>
                    </tr>
                    <tr class="bg-dark">
                      <td>TO PAY</td>
                      <td>{{ total-discount }}</td>
                    </tr>

【问题讨论】:

  • dynamic django variables 是什么意思?它们是如何“动态”的?

标签: javascript django vue.js


【解决方案1】:

有几点需要你考虑:

  1. 似乎您的 html 中有语法冲突,因为 Django 和 Vue.js 使用相同的 {{}} 来放置变量。但是,由于 Django 将在 Vue 之前处理您的 html,它将替换

    &lt;h4 class="box-title"&gt;{{ product.name }}&lt;/h4&gt;

    通过它将在上下文中找到的内容(服务器端的 Django tepmlate 上下文)。您可以在浏览器中查看源代码或您的页面,您可能会在该行看到:

    &lt;h4 class="box-title"&gt;&lt;/h4&gt;

    因为它不会找到 python product 变量(实际上你的意思是 js(vue) 变量)。

    解决方案:使用另一个 Vue 分隔符。见https://vuejs.org/v2/api/#delimiters。例如,在 Vue 中使用 [[ 而不是 {{:您的 Vue 实例 delimiters: ['[[', ']]'], 的一个选项并将该行(以及其他您指 Vue 变量的地方)更改为

    &lt;h4 class="box-title"&gt;[[ product.name ]]&lt;/h4&gt;

  2. 在 Vue 数据中你有 not product.sell_price 变量,就像你做的时候一样

  {% for product in products %}
     {
      "id": {{product.id}},
      "name": "{{product.name}}",
      "image": "/media/{{product.image}}",
      "price": {{product.sell_price}}
      },
  {% endfor %}

在 Vue 中你将拥有 product.price,而不是 product.sell_price。或者你必须 将上面的行更改为"sell_price": {{product.sell_price}}

  1. 很快您将面临item 变量的麻烦。正如您在 django 上下文中拥有 item 一样,而不是在 Vue 数据中。您应该像为 products 所做的那样将项目添加到 Vue 数据中。

  2. 一般考虑将您的方法从混合 django 模板和 Vue 代码更改为:

    • Django 向 Vue 传递数据
    • Vue 生成所有 html 并执行您的 js 功能

    • 使用Django Rest framework(https://www.django-rest-framework.org/)提供rest API
    • 仅在前端使用 Vue,从服务器加载数据并通过 REST 调用将更改放入服务器(例如使用 axios)

祝你好运。

【讨论】:

  • 我按照您的建议通过添加分隔符解决了这个问题,现在考虑到类别过滤器,我遇到了一些小问题。属于某些类别 ID 的产品没有正确显示。之前没有 addtoCart(product)功能,它现在工作我添加了这个链接,现在它不工作了。有什么解决方案吗?谢谢你的帮助
  • DRF (django-rest-framework) 不是在 Django 中实现 rest API 所必需的 - 您可以使用更轻(且侵入性更小的)包或手动执行(rest API 它只是 django 视图提供 json 而不是提供 html....)
  • 关于 categoriesproducts 再次你对 Vue 数据和 Django 上下文感到困惑。 django 循环中的product 将从category.product_set.all 获取,但在该循环内,Vue 将从filteredProducts 获取product - 不是来自django(不是来自类别)。 (注意:我看不到你对源文件的最后更改,如果有的话 - 最好在你的源中提供 github gist 左右)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-22
  • 1970-01-01
  • 2019-11-30
  • 1970-01-01
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多