Django: Как динамически обновлять количество товара на складе при выборе его разновидности?

Я работаю над проектом электронной коммерции, где продукт имеет несколько вариаций (например, разные цвета, размеры и т. д.), и каждая вариация имеет свой собственный запас. Когда пользователь выбирает вариацию, я хочу динамически обновлять отображаемый запас, но это работает неправильно.

Вот моя модель ProductStock:

class ProductStock(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="stocks")
    variation = models.ForeignKey(Variation, on_delete=models.CASCADE, blank=True, null=True)
    uploaded_stock_quantity = models.PositiveIntegerField(default=0)
    stock_quantity = models.PositiveIntegerField(default=0)
    reserved_stock = models.PositiveIntegerField(default=0)  # For pending orders

    def available_stock(self):
        return self.stock_quantity - self.reserved_stock

В моем шаблоне HTML я отображаю варианты в виде радиокнопок:

{% for v in variations %}
    <div class="variation__radio">
        <input type="radio" id="variation_{{ v.id }}" name="variation" 
               onclick="updateStock(this);" value="{{ v.id }}">
        <label for="variation_{{ v.id }}">{{ v.name }}</label>
    </div>
{% endfor %}

<div class="stock-info">
    <span id="uploaded-stock">-</span> in stock, <span id="remaining-stock">-</span> left
</div>

И моя JavaScript-функция для динамического обновления запасов:

function updateStock(element) {
    var variationId = element.value;
    var stockData = JSON.parse('{{ size_stock_data|safe }}');  // Pass stock data

    if (stockData[variationId]) {
        document.getElementById("uploaded-stock").textContent = stockData[variationId].uploaded_stock_quantity;
        document.getElementById("remaining-stock").textContent = stockData[variationId].stock_quantity;
    } else {
        document.getElementById("uploaded-stock").textContent = "-";
        document.getElementById("remaining-stock").textContent = "-";
    }
}

Выпуск

  • Складской запас не обновляется при выборе вариации.
  • Иногда он показывает неправильные значения или вообще не меняется.

Проблема возникает из-за того, что данные о запасах неправильно передаются в JavaScript, а функция updateStock не имеет доступа к данным о запасах в реальном времени.

Шаг 1: Передайте данные о запасах в формате JSON в представлении Django

В моем представлении Django мне нужно получить данные о продукте на складе, преобразовать их в объект JSON и отправить в шаблон.

import json

def product_variant_detail_view(request, pid):
    product = Product.objects.get(pid=pid)
    product_stocks = ProductStock.objects.filter(product=product)

    # Prepare stock data for JavaScript
    size_stock_data = {
        str(stock.variation.id): {
            'stock_quantity': stock.stock_quantity,
            'uploaded_stock_quantity': stock.uploaded_stock_quantity
        }
        for stock in product_stocks if stock.variation
    }

    context = {
        "product": product,
        "size_stock_data": json.dumps(size_stock_data),  # Convert to JSON
    }
    
    return render(request, "core/product_variant_detail.html", context)

Объяснение

  • Я запрашиваю модель ProductStock, чтобы получить все запасы, связанные с продуктом.
  • Я преобразую данные о запасах в формат JSON (size_stock_data) для передачи в JavaScript.
  • Это гарантирует, что каждый вариант содержит правильные данные о запасах при доступе к ним в интерфейсе.
<время работы/>

Шаг 2: Вставьте биржевые данные в JavaScript

В моем HTML-шаблоне я включаю это в тег <script>:

<script>
    var stockData = JSON.parse('{{ size_stock_data|safe }}');
</script>

Объяснение

  • Это делает данные о запасах доступными в JavaScript.
  • stockData теперь содержит словарь, в котором идентификатор каждой разновидности соответствует информации о ее запасе.
<время работы/>

Шаг 3: Обновите JavaScript, чтобы использовать правильные данные

Измените мою функцию updateStock:

function updateStock(element) {
    var variationId = element.value;  // Get selected variation ID

    if (stockData[variationId]) {
        document.getElementById("uploaded-stock").textContent = stockData[variationId].uploaded_stock_quantity + " in stock";
        document.getElementById("remaining-stock").textContent = stockData[variationId].stock_quantity + " left";
    } else {
        document.getElementById("uploaded-stock").textContent = "0 in stock";
        document.getElementById("remaining-stock").textContent = "0 left";
    }
}

Объяснение

  • Когда пользователь нажимает на вариант, вызывается эта функция.
  • Он извлекает данные о запасах для выбранного варианта.
  • Это динамически обновляет отображение запасов.
<время работы/>

Окончательный результат

Запасы обновляются динамически при выборе варианта.
Нет необходимости обновлять страницу для отображения обновленного ассортимента.
Отображаются правильные значения для каждого варианта.

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