问题描述: 我正在 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"),
观察到的行为:
cancel-order.html
表单可以正确呈现,操作 URL 指向 create_cancel
视图。create_cancel
视图。product_status
字段未进行任何更改。预期行为: 提交表单时,应触发
create_cancel
视图,并且应更新 product_status
和关联的 CartOrder
的 CartOrderItems
字段。应相应地显示 Success
或 error
消息。
问题:
create_cancel
视图在提交表单时不触发?oid
参数在 URL 中的传递方式或 POST
请求的处理方式有关?好的。我发现了问题 我在网址中犯了错误 我的看法:
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