Luffy之结算订单页面(订单模型表的创建,订单的生成,以及订单详情展示等)
订单页面
在前面我们已经构建了,购物车的页面,接下来到了结算页面
1.首先,在购物车页面点击去结算按钮时,我们需要做如下动作
.前端发送生成订单的请求,点击标签内触发事件 create_order
- template:
- <el-col :span="" class="cart-calc"><span @click="create_order">去结算</span></el-col>
- script,methods中:
- create_order(){
- // 生成订单
- this.$axios.post("http://127.0.0.1:8000/orders/",{},{
- headers: {
- // 附带已经登录用户的jwt token 提供给后端,一定不能疏忽这个空格
- 'Authorization': 'JWT ' + this.token
- },
- responseType: "json",
- }).then(response=>{
- //在session中保存订单ID,便于在结算页面发送请求时带上order_id,查询订单详情
- sessionStorage.order_id = response.data.order_id;
- // 跳转到结算页面
- this.$router.push("/order")
- }).catch(error=>{
- // 生成订单失败
- alert("生成订单失败")
- })
后端需要对该请求作出处理,将订单保存到mysql中,并返回对应的订单的ID值(不是订单号),但是在做订单保存之前,我们必须先创建订单的数据模型,其中模型如下所示
order.models:
订单的模型:
- # Create your models here.
- from django.db import models
- # Create your models here.
- from luffy.apps.user.models import User
- from luffy.apps.courses.models import Course
- class Order(models.Model):
- """订单记录"""
- status_choices = (
- (0, '未支付'),
- (1, '已支付'),
- (2, '已取消'),
- )
- total_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="订单总价", default=0)
- order_number = models.CharField(max_length=32,verbose_name="订单号")
- order_status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="订单状态")
- order_desc = models.CharField(max_length=120,verbose_name="订单描述")
- created_time = models.DateTimeField(verbose_name="订单生成时间", auto_now_add=True)
- pay_time = models.DateTimeField(verbose_name="订单支付时间", auto_now_add=True)
- user = models.ForeignKey(User, related_name='user_orders', on_delete=models.DO_NOTHING,verbose_name="用户ID")
- class Meta:
- db_table="ly_order"
- verbose_name= "订单记录"
- verbose_name_plural= "订单记录"
- class OrderDetail(models.Model):
- """订单详情"""
- order = models.ForeignKey("Order", related_name='order_course', on_delete=models.CASCADE, verbose_name="订单ID")
- course = models.ForeignKey(Course, related_name='course_order', on_delete=models.CASCADE, verbose_name="课程ID")
- user = models.ForeignKey(User, null=True, related_name="course", on_delete=models.DO_NOTHING, verbose_name="用户ID")
- unit_price = models.DecimalField(max_digits=8, decimal_places=2, null=True, verbose_name="课程价格")
- class Meta:
- db_table="ly_order_detail"
- verbose_name= "订单详情"
- verbose_name_plural= "订单详情"
而后端的处理代码如下所示
- class OrderAPIView(APIView):
- def post(self,request):
- # 获取用户ID
- try:
- user_id = request.user.id
- except:
- return Response({"message": "用户不存在!"})
- # 自己生成一个订单号,# 结合时间戳和当前用户ID来生成,才能保证整站唯一
- order_number = datetime.now().strftime("%Y%m%d%H%M%S") + "%07d" % int(user_id) + "%04d" % random.randint(0,9999)
- # 从redis中获取商品信息[先获取勾选集,然后根据勾选集,到购物车中查询对应的商品价格]
- redis = get_redis_connection("cart")
- course_id_list = redis.smembers("cart_select_%s" % user_id)
- # 计算总价格
- total_price = 0
- cart_info = redis.hgetall("cart_%s" % user_id) # 返回哈希数据中的键值对
- for course_id,course_price in cart_info.items():
- if course_id in course_id_list:
- total_price += Decimal(course_price.decode())
- # 创建订单数据
- order = Order.objects.create(
- user_id = user_id,
- order_number = order_number,
- order_status = 0, # 订单状态默认为未支付
- order_desc = "路飞学成课程购买", # # 订单描述信息
- total_price = total_price
- )
- # 返回响应信息给客户端
- print("order",order)
- print("order_type", type(order))
- if order:
- for course_id in course_id_list:
- # 记录订单相关的课程信息到订单详情
- OrderDetail.objects.create(
- course_id = course_id,
- order_id = order.id,
- user_id = user_id,
- unit_price = redis.hget("cart_%s" % user_id, course_id).decode(),
- )
- # 删除redis中已经生成订单的商品信息
- redis.hdel("cart_%s" % user_id, course_id.decode())
- redis.srem("cart_select_%s" % user_id, course_id.decode())
- return Response({"order_id": order.id}, status=status.HTTP_200_OK)
- else:
- return Response({"message": "生成订单失败!"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
2.在1步骤完成后,前端会跳转到order页面,在加载order页面,我们需要将order页面的数据加载过来,需要发送请求
- created() {
- // 判断用户是否已经登陆了。
- if( !this.token){
- this.$router.push("/login");
- }
- let _this = this;
- // 发起请求获取购物车中的商品信息,_this.order_id时在cart发送创建订单请求返回数据时,保存在session中的订单ID
- _this.$axios.get("http://127.0.0.1:8000/orders/detail/"+_this.order_id,{
- headers: {
- 'Authorization': 'JWT ' + _this.token
- },
- responseType: 'json',
- }).then(response=>{
- console.log("response.data",response.data)
- _this.course_list = response.data.order_course;
- _this.total = response.data.total_price
- })
当前端发送请求后,我们需要在后端作出处理来响应请求,返回对应订单的数据
order/views
- class OrderDetailAPIView(APIView):
- def get(self,request,order_id):
- """显示订单中的商品信息"""
- try:
- order = Order.objects.get(pk=order_id)
- except Order.DoesNotExist():
- return Response({"message":"当前订单不存在!"},status=status.HTTP_400_BAD_REQUEST)
- seriazlier = OrderSerializer(instance=order)
- return Response(seriazlier.data,status=status.HTTP_200_OK)
其中使用了序列化器:
- from rest_framework import serializers
- from .models import Order,OrderDetail
- from courses.models import Course
- class CourseSerializer(serializers.ModelSerializer):
- class Meta:
- model = Course
- fields = ("course_http_img","name")
- class OrderDetailSerializer(serializers.ModelSerializer):
- course = CourseSerializer()
- class Meta:
- model = OrderDetail
- fields = ("course","unit_price")
- class OrderSerializer(serializers.ModelSerializer):
- order_course = OrderDetailSerializer(many=True)
- class Meta:
- model= Order
- fields = ("id","total_price","order_course")
可以看到上面代码的序列化器中,有些字段嵌套了三层,
order_course ==> order_course = OrderDetailSerializer(many=True) ==> course = CourseSerializer()
注意:在CourseSerializer这个序列化器中,
- class CourseSerializer(serializers.ModelSerializer):
- class Meta:
- model = Course
- fields = ("course_http_img","name")
字段 course_http_img 原本是不在模型表中的,是我们自定义的一个字段,需要在对应的models中,做出定义,如下代码
courses/models:
- class Course(models.Model):
- .....
- # 自定义显示字段
- def course_http_img(self):
- return settings.HOST + self.course_img.url
3.前端接收到后端返回的数据,进行数据渲染即可
完整前后端代码如下:
order.vue:
- <template>
- <div class="cart">
- <Header/>
- <div class="cart-info">
- <h3 class="cart-top">购物车结算 <span>共1门课程</span></h3>
- <div class="cart-title">
- <el-row>
- <el-col :span="2"> </el-col>
- <el-col :span="10">课程</el-col>
- <el-col :span="8">有效期</el-col>
- <el-col :span="4">价格</el-col>
- </el-row>
- </div>
- <div class="cart-item" v-for="item in course_list" >
- <el-row>
- <el-col :span="2" class="checkbox"> </el-col>
- <el-col :span="10" class="course-info">
- <img :src="item.course.course_http_img" alt="">
- <span>{{item.course.name}}</span>
- </el-col>
- <el-col :span="8"><span>永久有效</span></el-col>
- <el-col :span="4" class="course-price">¥{{item.unit_price}}</el-col>
- </el-row>
- </div>
- <div class="calc">
- <el-row class="pay-row">
- <el-col :span="4" class="pay-col"><span class="pay-text">支付方式:</span></el-col>
- <el-col :span="4"><span class="alipay"><img src="../../static/images/1554167287107.png" alt=""></span></el-col>
- <el-col :span="12" class="count">实付款: <span>¥{{total}}</span></el-col>
- <el-col :span="4" class="cart-pay"><span >支付宝支付</span></el-col>
- </el-row>
- </div>
- </div>
- <Footer/>
- </div>
- </template>
- <script>
- import Header from "./common/Header"
- import Footer from "./common/Footer"
- export default {
- name:"Order",
- data(){
- return {
- total:0,
- course_list:[],
- token: localStorage.token || sessionStorage.token,
- id : localStorage.id || sessionStorage.id,
- order_id:sessionStorage.order_id || null,
- }
- },
- components:{
- Header,
- Footer,
- },
- methods:{
- },
- created() {
- // 判断用户是否已经登陆了。
- if( !this.token){
- this.$router.push("/login");
- }
- let _this = this;
- // 发起请求获取购物车中的商品信息
- _this.$axios.get("http://127.0.0.1:8000/orders/detail/"+_this.order_id,{
- headers: {
- 'Authorization': 'JWT ' + _this.token
- },
- responseType: 'json',
- }).then(response=>{
- console.log("response.data",response.data)
- _this.course_list = response.data.order_course;
- _this.total = response.data.total_price
- })
- },
- }
- </script>
- <style scoped>
- .cart{
- margin-top: 80px;
- }
- .cart-info{
- overflow: hidden;
- width: 1200px;
- margin: auto;
- }
- .cart-top{
- font-size: 18px;
- color: #666;
- margin: 25px 0;
- font-weight: normal;
- }
- .cart-top span{
- font-size: 12px;
- color: #d0d0d0;
- display: inline-block;
- }
- .cart-title{
- background: #F7F7F7;
- height: 70px;
- }
- .calc{
- margin-top: 25px;
- margin-bottom: 40px;
- }
- .calc .count{
- text-align: right;
- margin-right: 10px;
- vertical-align: middle;
- }
- .calc .count span{
- font-size: 36px;
- color: #333;
- }
- .calc .cart-pay{
- margin-top: 5px;
- width: 110px;
- height: 38px;
- outline: none;
- border: none;
- color: #fff;
- line-height: 38px;
- background: #ffc210;
- border-radius: 4px;
- font-size: 16px;
- text-align: center;
- cursor: pointer;
- }
- .cart-item{
- height: 120px;
- line-height: 120px;
- }
- .course-info img{
- width: 175px;
- height: 115px;
- margin-right: 35px;
- vertical-align: middle;
- }
- .alipay{
- display: block;
- height: 48px;
- }
- .alipay img{
- height: 100%;
- width:auto;
- }
- .pay-text{
- display: block;
- text-align: right;
- height: 100%;
- line-height: 100%;
- vertical-align: middle;
- margin-top: 20px;
- }
- </style>
order.views:
- import random
- from datetime import datetime
- from decimal import Decimal
- from django_redis import get_redis_connection
- from rest_framework import status
- from rest_framework.response import Response
- from rest_framework.views import APIView
- from luffy.apps.orders.models import Order, OrderDetail
- from luffy.apps.orders.serializers import OrderSerializer
- class OrderAPIView(APIView):
- def get(self,request):
- # 获取用户ID
- user_id = request.user.id
- return Response({"message":"ok"})
- def post(self,request):
- # 获取用户ID
- try:
- user_id = request.user.id
- except:
- return Response({"message": "用户不存在!"})
- # 自己生成一个订单号,# 结合时间戳和当前用户ID来生成,才能保证整站唯一
- order_number = datetime.now().strftime("%Y%m%d%H%M%S") + "%07d" % int(user_id) + "%04d" % random.randint(0,9999)
- # 从redis中获取商品信息[先获取勾选集,然后根据勾选集,到购物车中查询对应的商品价格]
- redis = get_redis_connection("cart")
- course_id_list = redis.smembers("cart_select_%s" % user_id)
- # 计算总价格
- total_price = 0
- cart_info = redis.hgetall("cart_%s" % user_id) # 返回哈希数据中的键值对
- for course_id,course_price in cart_info.items():
- if course_id in course_id_list:
- total_price += Decimal(course_price.decode())
- # 创建订单数据
- order = Order.objects.create(
- user_id = user_id,
- order_number = order_number,
- order_status = 0, # 订单状态默认为未支付
- order_desc = "路飞学成课程购买", # # 订单描述信息
- total_price = total_price
- )
- # 返回响应信息给客户端
- print("order",order)
- print("order_type", type(order))
- if order:
- for course_id in course_id_list:
- # 记录订单相关的课程信息到订单详情
- OrderDetail.objects.create(
- course_id = course_id,
- order_id = order.id,
- user_id = user_id,
- unit_price = redis.hget("cart_%s" % user_id, course_id).decode(),
- )
- # 删除redis中已经生成订单的商品信息
- redis.hdel("cart_%s" % user_id, course_id.decode())
- redis.srem("cart_select_%s" % user_id, course_id.decode())
- return Response({"order_id": order.id}, status=status.HTTP_200_OK)
- else:
- return Response({"message": "生成订单失败!"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
- class OrderDetailAPIView(APIView):
- def get(self,request,order_id):
- """显示订单中的商品信息"""
- try:
- order = Order.objects.get(pk=order_id)
- except Order.DoesNotExist():
- return Response({"message":"当前订单不存在!"},status=status.HTTP_400_BAD_REQUEST)
- seriazlier = OrderSerializer(instance=order)
- return Response(seriazlier.data,status=status.HTTP_200_OK)
order/serializer:
- from rest_framework import serializers
- from luffy.apps.courses.models import Course
- from luffy.apps.orders.models import Order, OrderDetail
- class CourseDetailSerializer(serializers.ModelSerializer):
- class Meta:
- model = Course
- fields=("course_http_img","name")
- class OrderDetailSerializer(serializers.ModelSerializer):
- course = CourseDetailSerializer()
- class Meta:
- model = OrderDetail
- fields=("unit_price","course")
- class OrderSerializer(serializers.ModelSerializer):
- order_course = OrderDetailSerializer(many=True)
- class Meta:
- model = Order
- fields=("id","total_price","order_course")
Luffy之结算订单页面(订单模型表的创建,订单的生成,以及订单详情展示等)的更多相关文章
- Django - 模型表单(创建、更新、删除)
urls.py # /music/alubm/add/ url(r'^album/add/$', views.AlbumCreate.as_view(), name="album-add&q ...
- 项目中 2个或者多个EF模型 表名称相同会导致生成的实体类 覆盖的解决方法
场景: 2个数据库, 一个新,一个旧, 把旧的 数据库中的数据,导入到新的数据库中, 使用到了2个 EF实体模型, 新数据库 和 旧数据库中的表,有的名称是相同的 (但是结构是不同的) 旧的数据 ...
- day85:luffy:购物车根据有效期不同切换价格&购物车删除操作&价格结算&订单页面前戏
目录 1.购物车有效期切换 2.根据有效期不同切换价格 3.购物车删除操作 4.价格结算 5.订单页面-初始化 1.购物车有效期切换 1.关于有效期表结构的设计 1.course/models.py ...
- DDD实战进阶第一波(十二):开发一般业务的大健康行业直销系统(订单上下文POCO模型)
在本系列前面的文章中,我们主要讨论了产品上下文与经销商上下文相关的实现,大家对DDD的方法与架构已经有了初步的了解. 但是在这两个界限上下文中,业务逻辑很简单,也没有用到更多的值对象的内容.从这篇文章 ...
- Django电商项目---完成订单页面day5
完成订单页面 创建订单项目 python manage.py startapp df_order manas/settings.py manas/urls.py 创建静态文件: templates/d ...
- day88:luffy:支付宝同步结果通知&接收异步支付结果&用户购买记录&我的订单
目录 1.支付宝同步结果通知 2.用户购买记录表 3.接受异步支付结果 4.善后事宜 5.我的订单 1.支付宝同步结果通知 1.get请求支付宝,支付宝返回给你的参数 当用户输入用户名和密码确认支付的 ...
- 在Ecshop后台打印订单页面将商品按货号排序
ECSHOP后台管理里的“打印订单" 页面里的商品排序有点乱,现在想改成按序号来排序,修改方法如下 下面是在2.7.2基础上做的修改 打开 admin/order.php 文件 找到(大约 ...
- django-用户中心订单页面
提交订单页面place_order.html,创建订单成功后跳转到用户订单页面 {% block bottomfiles %} <script type="text/javascrip ...
- 小程序swiper实现订单页面
小程序swiper实现订单页面 myOrder.wxml <!--pages/myorder/myorder.wxml--> <view class="swiper-tab ...
随机推荐
- 目标检测(七)YOLOv3: An Incremental Improvement
项目地址 Abstract 该技术报告主要介绍了作者对 YOLOv1 的一系列改进措施(注意:不是对YOLOv2,但是借鉴了YOLOv2中的部分改进措施).虽然改进后的网络较YOLOv1大一些,但是检 ...
- Unable to convert MySQL date/time value to System.DateTime问题解决方案
原因:可能是该字段(date/datetime)的值默认缺省值为:0000-00-00/0000-00-00 00:00:00,这样的数据读出来转换成System.DateTime时就会有问题: 解决 ...
- HttpResponse输出文件
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm3.aspx. ...
- 《linux就该这么学》第六节,计划任务和用户身份管理!
课本笔记: case条件测试语句 4.4:计划任务服务 at 设置一次性计划任务 at 时间 //设置执行的任务 a ...
- 第四章 DOM节点操作
1.什么是DOM:DOM(document object model)文档对象模型,把每一个元素看做是一个节点,然后对节点进行增删改查的操作 2.DOM的分类:(1)Core Dom:可以对html, ...
- fiddler学习总结--手机端(APP/微信小程序)抓包
步骤一.手机和电脑要在同一个局域网中 步骤二.完成fiddler的基本配置,与web端抓包一样: TOOLS-->options-->connections-->1.设置端口:2.勾 ...
- HDU 1114
在 ACM 能够开展之前,必须准备预算,并获得必要的财力支持.该活动的主要收入来自于 Irreversibly Bound Money (IBM).思路很简单.任何时候,某位 ACM 会员有少量的钱时 ...
- ArrayList 除重
看到一段简洁的 ArrayList 除重代码: protected final <T> List<T> removeDuplicates(List<T> list) ...
- 20165215 2017-2018-2《Java程序设计》课程总结
20165215 2017-2018-2<Java程序设计>课程总结 一.每周作业链接汇总 预备作业1:我期望的师生关系:令我记忆深刻的老师,期望的师生关系,本学期的学习规划. 预备作业二 ...
- spring 的web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java ...