如何解决尽管它显示在浏览器存储中,但传递给我的 Django 视图的请求中的“购物车”cookie 是空的
我的网站上有一个商店页面(用 Django 编写,带有一个乘客服务器),用户可以在其中将产品添加到他们的购物车中。购物车存储为 cookie。当他们从商店页面进入购物车页面时,购物车视图应该列出他们购物车中的所有项目(它从请求中的购物车 cookie 中获取)。当我在本地运行它时,这很好用。但是,当我在生产中运行它时,它几乎总是说购物车是空的。如果我硬刷新页面,它只会正确列出购物车项目。
我向服务器添加了一些打印语句,我可以看到页面的视图在 prod 中被调用了两次(在 dev 中只调用了一次)。第一次调用视图时,购物车 cookie 具有正确的值。然而,第二次调用时,请求中的购物车 cookie 是一个空对象 {}。请求中的所有其他 cookie 看起来都正常(会话 ID、csrftoken 等)。非常奇怪的是,我可以在浏览器的开发人员面板中看到,购物车 cookie 填充在请求的标头 cookie 选项卡和存储选项卡中。
Django 视图/实用函数:
def cart_view(request):
data = cart_data(request)
context = {
'items': data['items'],'order': data['order'],'cart_items': data['cart_items'],}
return render(request,'store/cart.html',context)
def cart_cookie(request):
try:
cart = json.loads(request.COOKIES['cart'])
except:
cart = {}
return cart
def cart_data(request):
cart = cart_cookie(request)
items = []
order = {'get_cart_total': 0,'get_cart_items': 0,'shipping': False}
cart_items = order['get_cart_items']
'''
Logic to parse the cart cookie
'''
return {
'items': items,'order': order,'cart_items': cart_items,}
var updateBtns = document.getElementsByClassName('update-cart');
for (var i = 0; i < updateBtns.length; i++) {
updateBtns[i].addEventListener('click',function() {
var productId = this.dataset.product;
var action = this.dataset.action;
updateCartCookie(productId,action);
})
}
function updateCartCookie(productId,action) {
if (action == 'add') {
if (cart[productId] === undefined) {
cart[productId] = {'quantity':0};
}
cart[productId]['quantity'] += 1;
} else if (action == 'remove') {
cart[productId]['quantity'] -= 1;
if (cart[productId]['quantity'] <= 0) {
delete cart[productId];
}
}
document.cookie = 'cart=' + JSON.stringify(cart) + ";domain=;path=/;SameSite=Strict;Secure;";
location.reload();
}
此代码位于页眉中以初始化 cookie。导航到购物车页面时不会调用它。
<script type="text/javascript">
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++){
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0,name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1))
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken'); // this is just a string
var cart = JSON.parse(getCookie('cart')); // this is a json object,so we need to parse it
if (cart == undefined) {
cart = {};
document.cookie = 'cart=' + JSON.stringify(cart) + ";domain=;path=/;SameSite=Strict;Secure;";
}
</script>
最后,这里是商店和购物车页面的模板 #商店
{% block content %}
{% load static %}
<div class="container">
<h1 class="page-title">Store</h1>
<div class="row" style="margin-bottom: 20px">
{% for product in products %}
<div class="col-lg-4" style="margin-bottom: 20px">
<img class="thumbnail" src="{{product.imageURL}}">
<br>
<div class="Box-element product">
<div>
<h4><strong>{{product.name}}</strong></h4>
<hr>
<p>
{{product.description}}
</p>
</div>
<div style="display: flex; justify-content: space-between; align-items: center;">
<h4>{{ product.price|floatformat:-2 }}</h4>
<button data-product={{product.id}} data-action="add" class="btn light update-cart">Add</button>
</div>
</div>
</div>
{% endfor %}
</div>
<div>
<a style="float: right; margin: 5px;" class="btn dark" href="{% url 'cart' %}">Cart</a>
</div>
</div>
{% endblock content %}
#购物车
{% block content %}
<div class="container">
<h1 class="page-title">Cart</h1>
<div class="">
<a class="btn button light" href="{% url 'store' %}">← Store</a>
<br>
<br>
{% if cart_items == 0 %}
<p style="text-align: center;">Your cart is empty.</p>
{% else %}
<div>
<div class="cart-row">
<div class="shrinking-flex-column-2-1"><strong>Item</strong></div>
<div class="static-flex-column-1"><strong>Price</strong></div>
<div class="static-flex-column-1"><strong>Quantity</strong></div>
<div class="static-flex-column-1"><strong>Total</strong></div>
</div>
{% for item in items %}
<div class="cart-row" style="align-items: center;">
<div class="shrinking-flex-column-2-1">{{item.product.name}}</div>
<div class="static-flex-column-1">${{item.product.price}}</div>
<div class="static-flex-column-1">
<p class="quantity">x{{item.quantity}}</p>
<div class="quantity">
<img class="chg-quantity update-cart" src="{% static 'store/images/arrow-up.png' %}" data-product={{item.product.id}} data-action="add" >
<img class="chg-quantity update-cart" src="{% static 'store/images/arrow-down.png' %}" data-product={{item.product.id}} data-action="remove" >
</div>
</div>
<div class="static-flex-column-1">${{item.get_total}}</div>
</div>
{% endfor %}
<div style="display: flex; justify-content: space-between; align-items: center;">
<div>
<h5>Total Order Items: <strong>{{order.get_cart_items}}</strong></h5>
<h5>Total Order Amount: <strong>${{order.get_cart_total}}</strong></h5>
</div>
<a class="btn dark" role="button" href="{% url 'checkout' %}">Checkout</a>
</div>
</div>
{% endif %}
</div>
</div>
{% endblock content %}
解决方法
这最终完全是一个缓存问题。添加 @never_cache 装饰到购物车/结帐视图解决了这个问题。
How to set cache control headers in a Django view class (no-cache)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。