微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尽管它显示在浏览器存储中,但传递给我的 Django 视图的请求中的“购物车”cookie 是空的

如何解决尽管它显示在浏览器存储中,但传递给我的 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' %}">&#x2190; 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 举报,一经查实,本站将立刻删除。