Django 表单提交未触发 `create_cancel` 视图

问题描述 投票:0回答:1

问题描述: 我正在 Django 应用程序中实现订单取消功能。该过程涉及使用

cancel-order.html
视图显示取消表单 (
cancel_order
),并使用
create_cancel
视图处理表单提交,以更新
product_status
CartOrder
CartOrderItems

但是,问题是提交表单时不会触发

create_cancel
视图。不会显示成功或错误消息,并且不会对数据库进行任何更新。

浏览次数: 以下是相关观点:

def cancel_order(request, oid):
    sub_category = SubCategory.objects.all()
    categories = Category.objects.prefetch_related('subcategories').order_by('?')[:4]
    wishlist = wishlist_model.objects.filter(user=request.user) if request.user.is_authenticated else None
    nav_category = Category.objects.filter(special_category=True).prefetch_related('subcategories').order_by('?')[:4]
    order = CartOrder.objects.get(user=request.user, id=oid)
    products = CartOrderItems.objects.filter(order=order)

    # Calculate discounts for each product
    total_old_price = 0
    total_price = 0

    for item in products:
        product = item.product  # Assuming a ForeignKey from CartOrderItems to Product
        qty = item.qty  # Assuming a quantity field in CartOrderItems
        total_old_price += (product.old_price or 0) * qty
        total_price += (product.price or 0) * qty

    # Calculate total discount percentage
    if total_old_price > 0:  # Prevent division by zero
        discount_percentage = ((total_old_price - total_price) / total_old_price) * 100
    else:
        discount_percentage = 0

    context = {
        "order": order,
        "products": products,
        "sub_category": sub_category,
        "categories": categories,
        "wishlist": wishlist,
        "nav_category": nav_category,
        "discount_percentage": round(discount_percentage, 2),  # Round to 2 decimal places
    }

    return render(request, 'core/cancel-order.html', context)


def create_cancel(request, oid):
    if request.method == "POST":
        user = request.user

        # Fetch POST data
        reason = request.POST.get('reason')
        description = request.POST.get('description')

        try:
            # Fetch the CartOrder instance
            order_cancel = get_object_or_404(CartOrder, id=oid, user=user)
            order_cancel.product_status = "cancelled"
            order_cancel.save()

            # Fetch related CartOrderItems instances
            order_items = CartOrderItems.objects.filter(order=order_cancel)
            for item in order_items:
                item.product_status = "cancelled"
                item.save()

            # Log the reason and description (if you want to save this somewhere)
            # Example: save to a cancellation model (optional)
            # CancellationReason.objects.create(order=order_cancel, reason=reason, description=description)

            messages.success(request, "Order successfully cancelled.")

        except Exception as e:
            messages.error(request, f"An error occurred: {e}")

        return redirect("core:dashboard")
    else:
        messages.error(request, "Invalid request method.")
        return redirect("core:dashboard")

模板: 这是

cancel-order.html
模板中的表单:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" href="{% static './assets/images/logo/favicon.ico'  %}" type="image/x-icon">
    <title>Cancel Order</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: Arial, sans-serif;
        }

        body {
            background-color: #f8f9fa;
            display: flex;
            justify-content: center;
            align-items: center;
            align-items: flex-start; /* Align items at the top to allow vertical scrolling */
            min-height: 100vh;/* Ensure the body covers the viewport */
            padding: 20px;
        }

        .cancel-order-container {
            display: flex;
            align-items: flex-start;
            gap: 20px;
            background: #ffffff;
            width: 100%;
            max-width: 800px;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }

        .cancel-order-container img {
            max-width: 150px;
            height: auto;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }

        .cancel-order-form {
            flex: 1;
        }

        .cancel-order-form h2 {
            margin-bottom: 20px;
            color: #343a40;
        }

        .form-group {
            margin-bottom: 15px;
        }

        .form-group label {
            display: block;
            margin-bottom: 5px;
            color: #495057;
            font-weight: bold;
        }

        .form-group input, .form-group select, .form-group textarea {
            width: 100%;
            padding: 10px;
            border: 1px solid #ced4da;
            border-radius: 4px;
            font-size: 16px;
        }

        .form-group textarea {
            resize: vertical;
            min-height: 100px;
        }

        .form-actions {
            text-align: right;
        }

        .btn {
            display: inline-block;
            padding: 10px 20px;
            font-size: 16px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        .btn-cancel {
            background-color: #dc3545;
            color: #ffffff;
        }

        .btn-cancel:hover {
            background-color: #c82333;
        }

        .btn-back {
            background-color: #6c757d;
            color: #ffffff;
            margin-right: 10px;
        }

        .btn-back:hover {
            background-color: #5a6268;
        }

        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            justify-content: center;
            align-items: center;
            z-index: 1000;
        }

        .modal-content {
            background: #ffffff;
            padding: 20px;
            border-radius: 8px;
            text-align: center;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }

        .modal-content p {
            margin-bottom: 20px;
            font-size: 18px;
            color: #343a40;
        }

        .modal-buttons {
            display: flex;
            justify-content: center;
            gap: 10px;
        }

        @media (max-width: 576px) {
            .cancel-order-container {
                flex-direction: column;
                align-items: center;
            }

            .cancel-order-container img {
                max-width: 100%;
                margin-bottom: 20px;
            }

            .cancel-order-form {
                width: 100%;
            }

            .btn {
                width: 100%;
                margin-bottom: 10px;
            }

            .btn-back {
                margin-right: 0;
            }

            .form-actions {
                display: flex;
                flex-direction: column;
            }
        }
    </style>
    <script>
        function showConfirmationModal(event) {
            event.preventDefault();
            const modal = document.getElementById('confirmation-modal');
            modal.style.display = 'flex';
        }

        function hideModal() {
            const modal = document.getElementById('confirmation-modal');
            modal.style.display = 'none';
        }

        function confirmAndSubmit() {
            document.querySelector('.cancel-order-form').submit();
        }
    </script>
</head>
<body>
    <div class="cancel-order-container">
        <img src="{{order.images}}" alt="Product Image">
        <form class="cancel-order-form" action="{% url 'core:create_cancel' oid=order.id %}" enctype="multipart/form-data" onsubmit="showConfirmationModal(event)" method="POST">
            {% csrf_token %}
            <h2>Cancel Your Order</h2>
            <div class="form-group">
                <label for="order-number">Order Number</label>
                <input type="text" id="order-number" name="order-number" value="{{order.oid}}" readonly>
            </div>
            <div class="form-group">
                <label for="product-name">Product Name</label>
                <input type="text" id="product-name" name="product-name" value="{{order.title}}" readonly>
            </div>
            <div class="form-group">
                <label for="product-price">Product Price</label>
                <input type="text" id="product-price" name="product-price" value="{{order.price}}" readonly>
            </div>
            <div class="form-group">
                <label for="product-price">Product Old Price</label>
                <input type="text" id="product-price" name="product-price" value="{{order.old_price}}" readonly>
            </div>
            {% if order.size %}
            <div class="form-group">
                <label for="product-price">Product Size</label>
                <input type="text" id="product-price" name="product-price" value="{{order.size}}" readonly>
            </div>
            {% endif %}
            <!-- <div class="form-group">
                <label for="product-price">Product Color</label>
                <input type="text" id="product-price" name="product-price" value="{{order.color}}" readonly>
            </div> -->
            <div class="form-group">
                <label for="reason">Reason for Cancellation</label>
                <select id="reason" name="reason" required>
                    <option value="">Select a reason</option>
                    <option value="delay">Order Delay</option>
                    <option value="changed_mind">Changed My Mind</option>
                    <option value="found_cheaper">Found a Cheaper Option</option>
                    <option value="other">Other</option>
                </select>
            </div>
            <div class="form-group">
                <label for="comments">Additional Comments</label>
                <textarea id="comments" name="comments" placeholder="Provide additional details (optional)"></textarea>
            </div>
            <div class="form-actions">
                <button type="button" class="btn btn-back" onclick="history.back()">Go Back</button>
                <button type="submit" class="btn btn-cancel">Submit</button>
            </div>
        </form>
    </div>

    <!-- Modal -->
    <div id="confirmation-modal" class="modal">
        <div class="modal-content">
            <p>Are you sure to cancel the order? You are saving {{ discount_percentage }}% on this order.</p>
            <div class="modal-buttons">
                <button class="btn btn-back" onclick="hideModal()">No</button>
                <button class="btn btn-cancel" onclick="confirmAndSubmit()">Yes</button>
            </div>
        </div>
    </div>
</body>
</html>

型号: 以下是

CartOrder
CartOrderItems
型号:

STATUS_CHOICE = (
    ("processing", "Processing"),
    ("shipped", "Shipped"),
    ("out_for_delivery", "Out for delivery"),
    ("delivered", "Delivered"),
    ("return_accepted", "Return Accepted"),
    ("pick_up", "Pick Up"),
    ("refund_completed", "Refund Completed"),
    ("cancelled", "Cancelled"),
)

class CartOrder(models.Model):
    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    oid = ShortUUIDField(length=10, max_length=100, prefix="oid", alphabet="1234567890")
    product_status = models.CharField(max_length=50, choices=STATUS_CHOICE, default="processing")
    # Other fields...

class CartOrderItems(models.Model):
    order = models.ForeignKey(CartOrder, on_delete=models.CASCADE, related_name="items")
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    qty = models.PositiveIntegerField(default=1)
    product_status = models.CharField(max_length=50, choices=STATUS_CHOICE, default="processing")
    # Other fields...

网址: 以下是 URL 模式:

path("cancel_order/<int:oid>", cancel_order, name="cancel_order"),
path("create_cancel/<int:oid>", create_cancel, name="create_cancel"),

观察到的行为:

  1. cancel-order.html
    表单可以正确呈现,操作 URL 指向
    create_cancel
    视图。
  2. 提交表单时,不会触发
    create_cancel
    视图。
  3. 不显示成功或错误消息。
  4. 数据库中的
    product_status
    字段未进行任何更改。

预期行为: 提交表单时,应触发

create_cancel
视图,并且应更新
product_status
和关联的
CartOrder
CartOrderItems
字段。应相应地显示
Success
error
消息。

问题:

  1. 什么可能导致
    create_cancel
    视图在提交表单时不触发?
  2. Django 中的表单提交或 URL 解析是否存在我可能忽略的常见问题?
  3. 这是否与
    oid
    参数在 URL 中的传递方式或
    POST
    请求的处理方式有关?
python html django
1个回答
0
投票

好的。我发现了问题 我在网址中犯了错误 我的看法:

def cancel_order(request, oid):
    sub_category = SubCategory.objects.all()
    categories = Category.objects.prefetch_related('subcategories').order_by('?')[:4]
    wishlist = wishlist_model.objects.filter(user=request.user) if request.user.is_authenticated else None
    nav_category = Category.objects.filter(special_category=True).prefetch_related('subcategories').order_by('?')[:4]
    order = CartOrder.objects.get(user=request.user, id=oid)
    products = CartOrderItems.objects.filter(order=order)

    # Calculate discounts for each product
    total_old_price = 0
    total_price = 0

    for item in products:
        product = item.product  # Assuming a ForeignKey from CartOrderItems to Product
        qty = item.qty  # Assuming a quantity field in CartOrderItems
        total_old_price += (product.old_price or 0) * qty
        total_price += (product.price or 0) * qty

    # Calculate total discount percentage
    if total_old_price > 0:  # Prevent division by zero
        discount_percentage = ((total_old_price - total_price) / total_old_price) * 100
    else:
        discount_percentage = 0

    context = {
        "order": order,
        "products": products,
        "sub_category": sub_category,
        "categories": categories,
        "wishlist": wishlist,
        "nav_category": nav_category,
        "discount_percentage": round(discount_percentage, 2),  # Round to 2 decimal places
    }

    return render(request, 'core/cancel-order.html', context)


def create_cancel(request, oid):
    if request.method == "POST":
        user = request.user

        # Fetch POST data
        reason = request.POST.get('reason')
        description = request.POST.get('description')

        try:
            # Fetch the CartOrder instance
            order_cancel = get_object_or_404(CartOrder, id=oid, user=user)
            order_cancel.product_status = "cancelled"
            order_cancel.save()

            # Fetch related CartOrderItems instances
            order_items = CartOrderItems.objects.filter(order=order_cancel)
            for item in order_items:
                item.product_status = "cancelled"
                item.save()

            # Log the reason and description (if you want to save this somewhere)
            # Example: save to a cancellation model (optional)
            # CancellationReason.objects.create(order=order_cancel, reason=reason, description=description)

            messages.success(request, "Order successfully cancelled.")

        except Exception as e:
            messages.error(request, f"An error occurred: {e}")

        return redirect("core:dashboard")
    else:
        messages.error(request, "Invalid request method.")
        return redirect("core:dashboard")

在 urls.py 中:

path("cancel_order/<int:oid>", cancel_order, name="cancel_order"),
path("create_cancel/<int:oid>", create_cancel, name="create_cancel"),

之前我触发了相同的视图

cancel_order
而不是
create_cancel

© www.soinside.com 2019 - 2024. All rights reserved.