Две (почти) идентичные функции Veiw.py ведут себя по-разному

Итак, я разрабатываю систему корзины для сайта электронной коммерции, используя Django. Есть две отдельные функции для обработки добавления и удаления элементов корзины. (Я не могу объединить их в одну функцию, не изменив структуру базы данных и шаблона)

Первая функция, 'update_cart', работает просто отлично. Она правильно обновляет соответствующую модель.

Однако, вторая функция 'remove_item' запускается, когда пользователь нажимает кнопку 'remove' в списке элементов, и функция действительно выполняется и перенаправляет правильно.

Однако при этом не удается обновить объект модели "многие-ко-многим", идентифицированный по внешнему ключу и связанный с элементом.

Это так странно, потому что я обращаюсь к объекту одинаково в обеих функциях. Разница лишь в том, что в первой используется .add(), а во второй .remove().

Кроме того, шаблон должен загружать id товара в данные GET, но не показывает его в URL, как в другом шаблоне, который запускает функцию 'update_cart'.

Но он показывает mycart/?id=86 при наведении курсора на кнопку. (это особенность хрома). Это очень сбивает с толку.

Можете ли вы, ребята, помочь мне понять, что я упускаю из виду? Спасибо за ваше время :)

view.py functions:

def update_cart(request):
    context={}
    
    if request.user.is_authenticated:
        print('triggered')
        owner = request.user.id
        cart = Cart.objects.get(cart_owner=owner)


        productID = request.GET['id']
        product = Product.objects.get(pk=productID) 
        cart.products.add(product)


        new_total = 0.00
        for item in cart.products.all():
            new_total += float(item.priceNotax)

        cart.total = new_total
        cart.save()

def remove_item(request):
    if request.user.is_authenticated:
        owner = request.user.id
        cart = Cart.objects.get(cart_owner=owner)


        productID = request.GET['id']
        print(productID)
        product = Product.objects.get(pk=productID) 
        cart.products.remove(product)
        cart.save()


        new_total = 0.00
        for item in cart.products.all():
            new_total += float(item.priceNotax)

        cart.total = new_total
        cart.save()
        return HttpResponseRedirect(reverse("myCart"))
    else:
        return HttpResponseRedirect(reverse("login"))

Файл model.py, содержащий затронутую модель 'Cart':

class Cart(models.Model):
    cart_owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    products = models.ManyToManyField(Product, null=True, blank=True)
    #held_items = models.ManyToManyField(Order_holding, null=True, blank=True)
    total = models.DecimalField(max_digits=100, decimal_places=2, default=0.00)
    timestamp = models.DateTimeField(auto_now_add=False, auto_now=True)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)
    active = models.BooleanField(default=True)

    def __unicode__(self):
        return "Cart id: %s" %(self.id)

Шаблон, вызывающий функцию 'remove_item':

{% extends 'base.html' %}
{% load static %}

{% block content %}


<div class="container-fluid mb-2">
    <div class="card">
        <div class="card-header"><h3>Shopping Cart</h3></div>
    </div>
</div>

{% for item in cart.products.all %}
<div class="container-fluid mb-2">
    <div class=".row-4 .row-sm-4 m-4 card justify-content-center">
        <div><h4>{{ item.name }}</h4></div>
        <div><h4>Price: ${{ item.priceNotax }}</h4><a href="{% url 'remove_item'%}?id={{item.id}}"><button class='btn-danger justify-content-right'>Remove</button></div></a>

    </div>
</div>

{% endfor %}
<h2>Sub-Total: ${{total}}</h2>

<a href="{% url 'products'%}"><button  class="btn-primary">Continue Shoping</button></a>



{% endblock content %}

Не видя остальной части вашего кода, я не могу ответить на первоначальный вопрос, почему две функции представления ведут себя по-разному.

Что касается проблемы с якорем, вы можете просто стилизовать ссылку под кнопку в bootstrap, например, так:

<a href="{% url 'remove_item'%}?id={{item.id}}" class='btn btn-danger justify-content-right'>Remove</a>

Или, вы можете обернуть кнопку в тег формы, например, так (я не тестировал это):

<form style="display: inline" action="{% url 'remove_item' %}" method="get">
  <button class='btn-danger justify-content-right'>Remove</button>
</form>

Но GET-запросы небезопасны и никогда не должны использоваться для изменения базы данных. Вместо этого вы можете использовать POST-запрос, например, такой:

<form action="{% url 'remove_item' %}" method="post">
    {% csrf_token %}
    <input type="hidden" name="item_id" value="{{ item.id }}">
    <button type='submit' class='btn-danger justify-content-right'>Remove</button>
</form>

Это отправит id элемента через скрытый ввод, а затем в ваших представлениях вы сможете получить доступ к той же информации более безопасным способом, чем как часть URL, что происходит при GET-запросе.

def remove_item(request):
    if request.method == 'POST':
        item_id = request.POST.get('item_id')
        # Here you have your code that actually removes the item

Я понял это, ребята. Я пропустил URL файла главного приложения. У меня вызывались разные представления, но у них был один и тот же путь, и неправильное представление было указано первым, поэтому оно вызывалось раньше, чем то, которое было нужно. lol Извините!

Вернуться на верх