当购物车结帐时,需要将订单保存到数据库中。订单将包含有关客户和他们正在购买的产品的信息。
使用以下命令创建一个用于管理客户订单的新应用程序:
INSTALLED_APPS = [
#...
"orders.apps.OrdersConfig",
]
创建order模型
from django.db import models
from shop.models import Product
class Order(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField()
address = models.CharField(max_length=250)
postal_code = models.CharField(max_length=20)
city = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
paid = models.BooleanField(default=False)
class Meta:
ordering = ('-created',)
def __str__(self):
return 'Order {}'.format(self.id)
def get_total_cost(self):
return sum(item.get_cost() for item in self.items.all())
class OrderItem(models.Model):
order = models.ForeignKey(Order,related_name='items',on_delete=models.CASCADE)
product = models.ForeignKey(Product,related_name='order_items',on_delete=models.CASCADE)
price = models.DecimalField(max_digits=10,decimal_places=2)
quantity = models.PositiveIntegerField(default=1)
def __str__(self):
return '{}'.format(self.id)
def get_cost(self):
return self.price * self.quantity
- Order模型包含几个用于存储客户信息的字段和一个付费布尔字段,默认值为False。稍后将使用该字段来区分已付订单和未付订单。get_total_cost()方法来获取在此订单中购买的商品的总成本。
- OrderItem模型用来存储产品、数量和为每个项目支付的价格。get_cost()返回项目的成本。
运行下一个命令为orders应用程序创建初始迁移:
注册管理站点
from django.contrib import admin
from .models import Order,OrderItem
class OrderItemInline(admin.TabularInline):
model = OrderItem
raw_id_fields = ['product']
@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
list_display = ['id','first_name','last_name','email','address','postal_code','city','paid','created','updated']
list_filter = ['paid','created','updated']
inlines = [OrderItemInline]
OrderItem模型使用一个ModelInline类,将其作为内联类包含在OrderAdmin类。内联允许在与其相关的模型相同的编辑页面上包含模型。
创建order视图
当用户最终下订单时,将使用创建的订单模型来持久化购物车中包含的商品。按照以下步骤创建一个新订单:
1. 向用户提供一个订单表单,以便填写他们的数据
2. 使用输入的数据创建一个新的Order实例,并创建一个关联的
购物车中每个项目的OrderItem实例
3. 清除所有购物车内容并将用户重定向到成功页面
在orders应用程序目录中创建一个新文件,并将其命名为forms.py。将以下代码添加到其中:
from django import forms
from .models import Order
class OrderCreateForm(forms.ModelForm):
class Meta:
model = Order
fields = ['first_name','last_name','email','address','postal_code','city']
这是用于创建新Order对象的表单。还需要一个视图来处理表单并创建一个新订单。
编辑orders应用程序的views.py文件,并向其中添加以下代码:
from django.shortcuts import render
from .models import OrderItem
from .forms import OrderCreateForm
from cart.cart import Cart
def order_create(request):
cart = Cart(request)
if request.method == 'POST':
form = OrderCreateForm(request.POST)
if form.is_valid():
order = form.save()
for item in cart:
OrderItem.objects.create(
order=order,
product = item['product'],
price=item['price'],
quantity=item['quantity'],
)
cart.clear()
return render(request,'orders/order/created.html',{'order':order})
else:
form = OrderCreateForm()
return render(request,'orders/order/create.html',{'cart':cart,'form':form})
在order_create视图中,我们将使用cart 从session中获取当前购物车(请求)。根据不同的请求方法,将执行以下任务:
- GET请求:实例化OrderCreateForm表单并呈现orders/order/create.html模板。
- POST请求:验证请求中发送的数据。如果数据有效,使用order = form.save()在数据库中创建一个新订单。遍历购物车项目,并为每个项目创建一个OrderItem。最后,我们清除购物车内容并呈现模板orders/order/created.html。
关于购物车cart的设计实现,请查看Django使用session管理购物车-优快云博客
创建order URL
在orders应用程序目录中创建一个新文件,并将其命名为urls.py。将以下代码添加到其中:
from django.urls import path
from . import views
app_name = 'orders'
urlpatterns = [
path('create/',views.order_create, name='order_create')
]
这是order_create视图的URL模式。编辑mysite的urls.py文件,并包含以下模式。记得把它放在shop.urls前面
urlpatterns = [
path('orders/', include('orders.urls', namespace='orders')),
path("shop/",include('shop.urls',namespace='shop')),
path("cart/",include('cart.urls',namespace='cart')),
]
编辑cart应用程序的cart/detail.html模板并编辑这一行:
<a href="{% url 'orders:order_create' %}" class="btn btn-primary">Checkout</a>
创建order模版
用户现在可以从购物车详细信息页面导航到订单表单。
在orders应用程序目录中创建以下文件结构:
templates/orders/order/create.html
templates/orders/order/created.html
编辑orders/order/create.html模板,并包含以下代码:
{% extends "shop/base.html" %}
{% load widget_tweaks %}
{% block title %}
Checkout
{% endblock %}
{% block content %}
<h1>Checkout</h1><br>
<div class="container" >
<div class="row">
<div class="col" style="padding-right: 50px;">
<form action="." method="post" class="form-group">
{% for field in form %}
{{ field.errors }}
<label for="{{ field.id_for_label }}" class="form-label" >
{{ field.label }}
</label>
{% render_field field class="form-control" %}
{% endfor %}
<p style="margin-top: 20px;"><input type="submit" value="Place order" class="btn btn-primary"></p>
{% csrf_token %}
</form>
</div>
<div class="col" >
<div style="background-color: rgb(223, 230, 230);padding: 50px;border-width: 0px 0px 2px 0px;border-style: solid;border-color: rgb(20, 180, 248);">
<h3>Your order</h3>
{% for item in cart %}
<div class="row">
<div class="col">
{{ item.quantity }}x {{ item.product.name }}
</div>
<div class="col" style="text-align: right;">
<span>${{ item.total_price }}</span>
</div>
</div>
{% endfor %}
<div style="text-align: right;margin-top: 20px;">
<strong>Total: ${{ cart.get_total_price }}</strong>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
此模板显示购物车(包括总数)和用于下订单的表单。
编辑orders/order/created.html模板,并添加以下代码:
{% extends "shop/base.html" %}
{% block title %}
Thank you
{% endblock %}
{% block content %}
<h1>Thank you</h1>
<p>Your order has been successfully completed. Your order number is
<strong>{{ order.id }}</strong>.</p>
{% endblock %}
这是在成功创建订单后呈现的模板。
用有效的数据填写表单,然后单击Place order按钮。订单将被创建,您将看到如下所示的成功页面: