如何将 vue.js 与 django 集成?
Posted
技术标签:
【中文标题】如何将 vue.js 与 django 集成?【英文标题】:how to integrate vue.js with django? 【发布时间】:2019-10-25 11:24:14 【问题描述】:这是带有 vue.js 的单页应用程序,它进行了一些简单的计算,我试图在 django 中实现这个计算,但它没有给我想要的结果。
在这里,我在 vue.js 中动态创建了数组,这只是完美地显示了产品的图像,而不是 product.name
和 product.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" >
<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" >
<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> </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
是什么意思?它们是如何“动态”的?
【参考方案1】:
有几点需要你考虑:
似乎您的 html 中有语法冲突,因为 Django 和 Vue.js 使用相同的 和
来放置变量。但是,由于 Django 将在 Vue 之前处理您的 html,它将替换
<h4 class="box-title"> product.name </h4>
通过它将在上下文中找到的内容(服务器端的 Django tepmlate 上下文)。您可以在浏览器中查看源代码或您的页面,您可能会在该行看到:
<h4 class="box-title"></h4>
因为它不会找到 python product
变量(实际上你的意思是 js(vue) 变量)。
解决方案:使用另一个 Vue 分隔符。见https://vuejs.org/v2/api/#delimiters。例如,在 Vue 中使用 [[
而不是 :您的 Vue 实例
delimiters: ['[[', ']]'],
的一个选项并将该行(以及其他您指 Vue 变量的地方)更改为
<h4 class="box-title">[[ product.name ]]</h4>
在 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
很快您将面临item
变量的麻烦。正如您在 django 上下文中拥有 item
一样,而不是在 Vue 数据中。您应该像为 products
所做的那样将项目添加到 Vue 数据中。
一般考虑将您的方法从混合 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....)
关于 categories
和 products
再次你对 Vue 数据和 Django 上下文感到困惑。 django 循环中的product
将从category.product_set.all
获取,但在该循环内,Vue 将从filteredProducts
获取product
- 不是来自django(不是来自类别)。 (注意:我看不到你对源文件的最后更改,如果有的话 - 最好在你的源中提供 github gist 左右)。以上是关于如何将 vue.js 与 django 集成?的主要内容,如果未能解决你的问题,请参考以下文章
vue.js 和 Laravel - 我们如何将 vue js 与 laravel 集成?