Django: Добавление кнопки "Минус корзина" с помощью JQuery
Мои модели:
class Cart(models.Model):
cart_id = models.CharField(max_length=255, blank=True)
date_added = models.DateField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Cart'
def __str__(self):
return self.cart_id
class CartItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
quantity = models.IntegerField()
is_active = models.BooleanField(default=True)
def total(self):
return self.product.price * self.quantity
def __str__(self):
return self.product
Мои взгляды:
def _cart_id(request):
cart_id = request.session.session_key
if not cart_id:
cart_id = request.session.create()
return cart_id
def add_to_cart(request, product_id):
product = Product.objects.get(id=product_id)
try:
my_cart = Cart.objects.get(cart_id=_cart_id(request))
my_cart.save()
except ObjectDoesNotExist:
my_cart = Cart.objects.create(
cart_id=_cart_id(request),
)
my_cart.save()
try:
cart_item = CartItem.objects.get(product=product, cart=my_cart)
cart_item.quantity += 1
cart_item.save()
except ObjectDoesNotExist:
cart_item = CartItem.objects.create(
product=product,
cart=my_cart,
quantity=1,
)
cart_item.save()
return redirect('cart')
def cart(request, sub_total=0, quantity=0, cart_items=None, sale_tax=0):
try:
current_cart = Cart.objects.get(cart_id=_cart_id(request))
cart_items = CartItem.objects.filter(cart=current_cart, is_active=True)
for item in cart_items:
sub_total += (item.product.price * item.quantity)
quantity += item.quantity
sale_tax = round((7 * sub_total)/100, 2)
except ObjectDoesNotExist:
pass
context = {
'sub_total': sub_total,
'quantity': quantity,
'cart_items': cart_items,
'sale_tax': sale_tax,
'grand_total': sale_tax + sub_total,
}
return render(request, 'cart.html', context)
Моя часть шаблона:
<tbody>
{% for item in cart_items %}
<tr>
<td class="product-thumbnail"><a href="{{ item.product.get_url }}"><img src="{{ item.product.image_1.url }}" alt=""></a></td>
<td class="product-name"><a href="{{ item.product.get_url }}">{{ item.product.product_name }}</a></td>
<td class="product-price"><span class="amount">${{ item.product.price }}</span></td>
<td class="product-quantity">
<div class="cart-plus-minus"><input type="text" value="{{ item.quantity }}" /></div>
</td>
<td class="product-subtotal"><span class="amount">${{ item.total }}</span></td>
<td class="product-remove"><a href="#"><i class="fa fa-times"></i></a></td>
</tr>
{% endfor %}
</tbody>
Мой JQuery:
$(".cart-plus-minus").append('<div class="dec qtybutton">-</div><div class="inc qtybutton">+</div>');
$(".qtybutton").on("click", function () {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
if ($button.text() == "+") {
var newVal = parseFloat(oldValue) + 1;
} else {
// Don't allow decrementing below zero
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$button.parent().find("input").val(newVal);
});
Я не специалист по JQuery, и поэтому я запутался в том, как обновить общую цену товара плюс или минус, когда покупатель нажимает кнопку плюс или минус - что JQuery возьмет на себя. В Django мой urlpatterns для корзины выглядит так:
urlpatterns = [
path('', views.cart, name='cart'),
path('add_to_cart/<int:product_id>/', views.add_to_cart, name='add_to_cart'),
]
Это означает, что если клиент нажимает на знак минус или плюс, количество товара в корзине должно увеличиться или уменьшиться на единицу - что мне нужно, так это чтобы знак плюс перенаправлял клиента на представление add_to_cart, которое уже закодировано, и это представление автоматически перенаправляло клиента обратно в корзину для обновления количества товара в корзине. Как мне на самом деле достичь этого в JQuery части кода, которую я разместил? Это должен быть именно тот кусочек кода JQuery, который я разместил, поскольку он поставляется вместе с шаблоном. В Django, в любом обычном шаблоне, это должно быть легко сделано следующим образом:
<a href="{% url 'add_to_cart' item.product.id %}" class="btn btn-light" type="button" id="button-minus"> <i class="fa fa-plus"></i></a>
Но как это сделать с помощью JQuery?
Я нашел ответ и заставил его работать. Тем не менее, теперь меня беспокоит вопрос безопасности XSS-атак. Безопасно ли писать код так, как я только что сделал, чтобы решить свою проблему?
Часть шаблона:
<div class="cart-plus-minus"><input type="text" value="{{ item.quantity }}"/>
<input type="hidden" id="Url" data-url="{% url 'add_to_cart' item.product.id %}" />
</div>
порция jQuery:
<script>
// // // // ////////////////////////////////////////////////////
// // // // // 21. Cart Plus Minus Js
$(".cart-plus-minus").append(
'<div class="dec qtybutton">-</div><div class="inc qtybutton">+</div>'
);
$(".qtybutton").on("click", function () {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
if ($button.text() == "+") {
var newVal = parseFloat(oldValue) + 1;
window.location.href = $("#Url").attr("data-url")
} else {
// Don't allow decrementing below zero
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$button.parent().find("input").val(newVal);
});
</script>
Часть, которую я исправил и она теперь работает, находится там, где:
window.location.href = $("#Url").attr("data-url")
Теперь мне интересно, будет ли это уязвимостью безопасности, если это исправление будет введено? Согласно документации Django:
json_script¶ Безопасный вывод объекта Python в виде JSON, завернутого в тег, готовый для использования с JavaScript.
.
Аргумент: HTML "id" тега.
Например:
{{ value|json_script: "hello-data" }} Если value - это словарь {'hello': 'world'}, то вывод будет следующим:
{ "hello": "world"}Доступ к полученным данным можно получить в JavaScript следующим образом:
const value = JSON.parse(document.getElementById('hello-data').textContent); XSS-атаки смягчаются путем экранирования символов "<", ">" и "&". Например, если значение имеет вид {'hello': 'world&'}, будет выведено следующее:
{"hello": "world\\u003C/script\\u003E\\u0026amp;"}Это совместимо со строгой политикой безопасности содержимого, которая запрещает выполнение сценариев на странице. Он также поддерживает чистое разделение между пассивными данными и исполняемым кодом.