Django框架实现可运营电商网站(二)-- 前台部分

news/2024/5/9 10:35:43/文章来源:https://blog.csdn.net/weixin_39561473/article/details/87369856

文章目录

  • 1 前台模板修改
    • 1.1 模板制作
    • 1.2 静态链接
    • 1.3 在视图和路由中关联所有页面
    • 1.4 修改跳转链接
    • 1.5 运行项目
    • 1.6 收集静态文件
  • 2 建模
  • 3 注册与登陆
    • 3.1 注册页面
      • 3.1.1 样式
      • 3.1.2 需要导入的所有包:
      • 3.1.3 密码加密函数:
      • 3.1.4 邮箱发送函数:
      • 3.1.5 注册函数:
      • 3.1.6 路由配置:
    • 3.2 登陆页面
      • 3.2.1 修改登陆界面样式
      • 3.2.2 修改登陆的视图函数
      • 3.2.3 设置cookies
    • 3.3 登出逻辑
      • 3.3.1 登出页面效果
      • 3.3.2 登出逻辑
        • 首先是视图函数
        • 然后绑定路由
        • 页面按钮关联路由
  • 4 首页、模板页样式修改
    • 4.1 首页
    • 4.2 模板页
  • 5 商品列表与商品详情
    • 5.1 商品列表
      • 5.1.1 修改页面的关联的路由
      • 5.1.2 商品页视图函数
      • 5.1.3 商品页页面修改
        • 首先是类型展示在页面上:
        • 商品列表
    • 5.2 商品详情页
      • 5.2.1 修改视图函数
      • 5.2.2 修改路由
      • 5.2.3 修改页面
        • 图片
        • 商品概述修改
        • 详情修改
        • 最底下还有个商品推荐,也就是从视图中取出来的那三个最贵的商品
        • 最终效果
  • 6 购物车
    • 6.1 视图函数
    • 6.2 路由
    • 6.3 页面设置
      • 6.3.1 数据渲染
      • 6.3.2 点击增加
        • 修改增加按钮逻辑
        • 修改减少按钮逻辑
        • 给原有页添加js逻辑,用来进行手动输入数据,小计与总计变化关系
    • 6.4 删除按钮
      • 6.4.1 视图函数
      • 6.4.2 路由
      • 6.4.3 页面链接
    • 6.5 跳转至确认订单页面
      • 6.5.1 修改页面表单
      • 6.5.2 确认订单视图函数
      • 6.5.3 路由修改
      • 6.5.4 页面修改
  • 7 确认支付页面
    • 7.1 确认支付的视图函数
    • 7.2 路由设置
    • 7.3 页面设置
    • 7.5 支付
      • 7.5.1 支付函数
      • 7.5.2 调用支付函数
        • 视图函数中
        • 路由设置
        • 网页路由绑定

后台和前台基础部分有大量的相似之处,所以我已经讲过的就会一带而过,有疑问可以通过查看后台博客解决疑惑(https://blog.csdn.net/weixin_39561473/article/details/86775213)

1 前台模板修改

这里提供一个我找的前台模板,大家也可以自己去找,每个人审美不同的,我觉得好的,大家不一定觉得。方法都是一样的。
链接:https://pan.baidu.com/s/1ulgLs1SwuIfww_NUx6XYPA
提取码:5yry

  1. 把静态文件放在前台的app中(buyers)的static下的区分目录下,把网页放在前台app的templates下的区分目录下
  2. 制作模板
  3. 修改静态路径
  4. 在视图和路由中关联所有页面
  5. 修改跳转链接

1.1 模板制作

观察我给的模板页面,所有的页面都被分为了一下几个部分:
紫色框中内容基本一致,除了title和个别css文件数量不同,橙色框中是
在这里插入图片描述
所以将紫色框中的代码抽取出来作为模板,head部分当然要包含所有网页要用的css和 js包。

在templates中新建一个html网页为base.html
在这里插入图片描述
然后将共性代码放入base.html,并添加个性定位标记
在这里插入图片描述
修改所有的页面,继承模板,套用标记块,以下图方法修改所有页面
在这里插入图片描述

1.2 静态链接

修改所有的链接,基本都在模板页,这也体现了模板页的优势,分散了很多地方。注意别漏了,推荐使用Ctrl+R
在这里插入图片描述

1.3 在视图和路由中关联所有页面

前台视图文件:

from django.shortcuts import render
def index(request):return render(request,'buyers/index.html',locals())def login(request):return render(request,'buyers/login.html',locals())def cart(request):return render(request,'buyers/cart.html',locals())def products(request):return render(request,'buyers/products.html',locals())def product_details(request):return render(request,'buyers/product-details.html',locals())# Create your views here.

前台的url就有些不同了,因为大家在访问首页的时候直接输入网址就行,而不用加任何app名子。目前几个页面,除了购物车需要放在buyers app的子路由文件中,其他的页面都可以放在主路由文件中。
主路由文件:
在这里插入图片描述
子路由文件:
在这里插入图片描述

1.4 修改跳转链接

注意在base也上有很多的按钮,需要修改这些按钮的跳转页为我们设置的路由:
在这里插入图片描述

1.5 运行项目

现在就可以运行项目查看效果了
在这里插入图片描述

1.6 收集静态文件

为了方便以后部署,之前在做后台富文本编辑器的时候收集过一次,
方法一致,先注释了静态路径,添加静态根路径。
在这里插入图片描述
使用收集命令后再还原静态路径,注释静态根路径备用。
按ctrl+alt+r,输入以下命令
在这里插入图片描述
如果问你是否覆盖选择yes,收集后还原配置文件:
在这里插入图片描述

2 建模

用户建模涉及一下几个表:

  • 用户表:用户名,邮箱,密码(目前只需要这些,后期还可以扩充)
  • 地址表:收件人,电话,地址,地址所属用户(用户地址可以很多,给父母,给自己买东西地址不同)
  • 邮件验证表:验证码,邮箱,时间(注册用户需要通过邮件验证码)
  • 购物车表:商品id,商品名称,商品价格,商品照片,商品数量,购买用户
  • 订单页面:订单编号,订单时间,订单状态,总计,订单用户,订单地址
  • 订单商品:商品id,商品名称,商品价格,商品照片,商品数量,所属订单

在buyers app中model文件中建立模型

from django.db import modelsclass Buyer(models.Model):username = models.CharField(max_length = 32)email = models.EmailField(blank=True, null=True)password = models.CharField(max_length = 32)class Address(models.Model):address = models.TextField()phone = models.CharField(max_length = 32)username = models.CharField(max_length = 32)buyer = models.ForeignKey(Buyer,on_delete = True)class EmailValid(models.Model):value = models.CharField(max_length = 32)email_address = models.EmailField()times = models.DateTimeField()class BuyCar(models.Model):goods_id = models.CharField(max_length=32)goods_name = models.CharField(max_length=32)goods_price = models.FloatField()goods_picture = models.ImageField(upload_to="image")goods_num = models.IntegerField()user = models.ForeignKey(Buyer, on_delete=True)class Order(models.Model):order_num = models.CharField(max_length=32)order_time = models.DateTimeField(auto_now=True)order_statue = models.CharField(max_length=32)total = models.FloatField()user = models.ForeignKey(Buyer,on_delete=True)order_address = models.ForeignKey(Address,on_delete=True)class OrderGoods(models.Model):good_id = models.IntegerField()good_name = models.CharField(max_length=32)good_price = models.FloatField()good_num = models.IntegerField()goods_picture = models.ImageField()order = models.ForeignKey(Order,on_delete=True)

检查、生成、同步表:

按ctrl+alt+r,输入以下三个命令

check
makemigrations
migarate

成功后表同步成功,可以用pycharm自带的数据库工具进行查看
在这里插入图片描述

3 注册与登陆

3.1 注册页面

3.1.1 样式

模板没有提供注册页,所以复制登录页进行修改。
在这里插入图片描述
绑定视图函数和路由后,样式变为:
在这里插入图片描述
至于邮箱验证注册的方法与逻辑参照我之前的博客(https://blog.csdn.net/weixin_39561473/article/details/86654561)
这里就粗略的写了:

3.1.2 需要导入的所有包:

from django.shortcuts import render,HttpResponseRedirect
from django.core.mail import EmailMultiAlternatives
from django.http import JsonResponse
import random,datetime,time,hashlib
from Buyers.models import *
from EarphoneMall.settings import EMAIL_HOST_USER

3.1.3 密码加密函数:

#加密函数
def lockpw(pw):md5 = hashlib.md5()md5.update(pw.encode())result = md5.hexdigest()return result

3.1.4 邮箱发送函数:

#发送邮件函数
def sendMessage(request):result = {"status": "error","data":""}if request.method=='GET' and request.GET:receiver = request.GET.get('email')try:subject = "耳机商城的邮件"text_content = ""value = getRandomData()html_content = """<div><p>尊敬的耳机商城用户,您的用户验证码是:%s,打死不要告诉别人。</p></div>"""%valuemessage = EmailMultiAlternatives(subject,text_content,EMAIL_HOST_USER,[receiver])message.attach_alternative(html_content,"text/html")message.send()except Exception as e:result["data"] = str(e)else:result["status"] = "success"result["data"] = "验证码已发送"e = EmailValid()e.email_address = receivere.value = valuee.times = datetime.datetime.now()e.save()finally:return JsonResponse(result)

发送效果如图:
在这里插入图片描述

3.1.5 注册函数:

#注册页面
def register(request):result = {"status": "error", "data": ""}if request.method == 'POST' and request.POST:email = request.POST.get('email')username = request.POST.get('username')massage = request.POST.get('massage')pwd = request.POST.get('password')db_email = EmailValid.objects.filter(email_address=email).first()if db_email:if massage == db_email.value:now = time.mktime(datetime.datetime.now().timetuple())db_now = time.mktime(db_email.times.timetuple())if now - db_now > 86400:result['data'] = '验证码过期'db_email.delete()else:b = Buyer()b.username = usernameb.email = emailb.password = lockpw(pwd)b.save()db_email.delete()return HttpResponseRedirect('/login/') #注册成功跳转到登录页else:result['data'] = '验证码错误'else:result['data'] = '邮箱不匹配'return render(request, 'buyers/register.html', locals())

3.1.6 路由配置:

在这里插入图片描述
这样注册页面就完成了,可以自己尝试注册

3.2 登陆页面

前台登陆与后台登陆完全一致,也需要下发cookie和session

3.2.1 修改登陆界面样式

form添加属性,添加csrf防御,提交按钮改为input,链接到注册页面
在这里插入图片描述

3.2.2 修改登陆的视图函数

前台登陆逻辑与后台完全一致,不过多加了一个cookies:user-id,这是为了后面绑定用户与商品、购物车关系的。

# 登陆
def login(request):result = {'statue': 'error', 'date': ''}if request.POST and request.method == 'POST':email = request.POST.get('email')user = Buyer.objects.filter(email=email).first()if user:pwd = lockpw(request.POST.get('password'))if pwd == user.password:response = HttpResponseRedirect('/') #跳转到首页response.set_cookie('user_id', user.id, max_age=3600) #下发cookieresponse.set_cookie('username', user.username, max_age=3600) #下发cookierequest.session['username'] = user.username #上传sessionreturn responseelse:result['date'] = '密码错误'else:result['date'] = '用户名不存在'return render(request, 'buyers/login.html', locals())

3.2.3 设置cookies

再视图函数上面添加cookie装饰器,这里与后台的也完全一致

#COOKIE验证装饰器
def cookieVerify(fun):def inner(request,*args,**kwargs):username = request.COOKIES.get("username")session = request.session.get("username") #获取sessionuser = Buyer.objects.filter(username = username).first()if user and session == username: #校验sessionreturn fun(request,*args,**kwargs)else:return HttpResponseRedirect("/login/")return inner

然后给需要的页面添加cookie验证,例如购物车等,首页不需要,因为你即使不登陆也是可以浏览商品的。
在这里插入图片描述

3.3 登出逻辑

3.3.1 登出页面效果

由于模板没有提供登出的按钮,那就只能自己写一个了
对头像按钮进行修改在这里插入图片描述
这里也体现了设置session的好处,通过session有没有进行判断是否用户登陆了,没登陆的时候通过if标签判断,显示登陆按钮,点击后跳转到登录页。而登陆后显示用户名,点击头像后进入用户主页(还没做,先空着)。

这个按钮再base.html页面中
在这里插入图片描述
代码如下:
css样式:

 <style>.loginbotton {font-size: 16px;width:40px;display: inline-block;margin-left: -2px;margin-top:2px}</style>

html代码:

{% if request.session.username %}<div class="nav-item"><a href= class="text-primary"><i class="fas fa-user-circle fa-2x"></i>{{ request.session.username }}</a><a class="loginbotton" href="">登出</a></div>{% else %}<div class="nav-item"><a href="/login/" class="text-primary"><i class="fas fa-user-circle fa-2x"></i><span class="loginbotton" href="">登陆</span></a></div>{% endif %}

实现效果如下:
登陆前:
在这里插入图片描述
登陆后:
在这里插入图片描述

3.3.2 登出逻辑

首先是视图函数

这个与后台的也是一样的,点击登出后删除cookie和session就行了。

#登出
def logout(request):response = HttpResponseRedirect("/") #登出后跳转至首页response.delete_cookie("user_id") #删除cookieresponse.delete_cookie('username')del request.session["username"] #删除sessionreturn response

然后绑定路由

在这里插入图片描述

页面按钮关联路由

在这里插入图片描述
这样登陆登出也实现了。

4 首页、模板页样式修改

4.1 首页

主要是换图和改文字,全是英文很头疼,因为我们收集静态文件的缘故,图片需要放在根目录的静态文件里 ,而不是app的静态文件中。
在这里插入图片描述

4.2 模板页

模板页主要是修改英文说明为中文。
例如图中部分
在这里插入图片描述
修改完成后:
在这里插入图片描述
修改之后会发现,右侧关于耳机类型就是我们存在数据库中额类型表,点击类型后会跳转到该类型的商品页,所以接下来开始制作商品列表页。

5 商品列表与商品详情

5.1 商品列表

由于在模板页我们按照后台的商品类别对商品进行了分类,所以视图函数处理时也需要对商品进行区分,这里就需要用到正则来帮助匹配商品的id了

5.1.1 修改页面的关联的路由

这里需要按照分类的id进行修改,写错了就会类别与商品无法完全对应
在这里插入图片描述
修改商品展示页的路由,这时候可以发现,我们的主路由已经包含了非常多的路由了,很不方便进行修改查询,所以我们将商品的路由单独提取出来,并以列表的方式链接:
在这里插入图片描述

5.1.2 商品页视图函数

这里还有一点,我对网页做了修改,添加了一个全部商品,并把路由绑在了/0/上:
在这里插入图片描述
因为我们并没有id为0的类型,所以视图函数需要对传入的数进行判断,如果为0则取全部商品,如果不为0,按照类型取商品:
视图函数注意以下几点

  • 判断点击的是全部商品还是类型商品
  • 全部类型因为类型表中是没有的,需要自己写
  • 需要通过外链获取到图片
  • 因为图片是分离的,所以需要一个列表来容纳每个商品

代码如下:
代码有个小细节,就是返回值里我把local()改成了{‘data’:data,‘type’:type},local返回的是所有变量信息,可是我们用到的只有data这个列表和type,所以可以用字典的形式返回单个或多个变量,而不是所有变量。

#商品列表
def products(request,num):num = int(num)if num == 0:type = {'label':'全部耳机','description':'所有商品,尽情挑选,蓝牙、头戴、入耳、线材应有尽有'}goods = Goods.objects.all()else:type = Types.objects.get(id=num) #取出这个类型的详情goods = Goods.objects.filter(types=num)  #取出这个类型的全部商品data = []for i in goods:img = i.image_set.first().img_path  #取出商品的第一张图片路径data.append({'img':img,'goods':i})  #将每个商品图片和信息的字典写到data列表中return render(request,'buyers/products.html',{'data':data,'type':type})

5.1.3 商品页页面修改

我删除了好多没用的东西,大家也可以酌情修改,模板就是用来修改的

首先是类型展示在页面上:

在这里插入图片描述
修改后效果如下:
在这里插入图片描述

商品列表

商品列表使用for循环依次遍历出来
在这里插入图片描述
效果如下:
在这里插入图片描述
而且点击不同的类型显示的商品也不相同。

5.2 商品详情页

点击商品查看商品详情,所以还是需要使用正则匹配点击的商品。

5.2.1 修改视图函数

既然是详情页,那肯定需要商品的所有信息,还有商品所有图片。
一般详情页还会有商品推荐之类的东西,所以也要获取一些其他商品,模板提供了3个位置,所以从库中取出3个商品用作推广。

这里有个细节,就是我在取三个商品的时候使用了order_by(’-goods_now_price’),order_by是对取出的数据进行排序,排序的依据就是括号里的内容,而 - 代表逆序,也就是我取出的商品按照价钱从高到低取了3个。

#商品详情页
def product_details(request,id):id = int(id)goods = Goods.objects.get(id=id)imgs = goods.image_set.all()showGoods = Goods.objects.all().order_by('-goods_now_price')[0:3]data = []for i in showGoods:img = i.image_set.first().img_path  # 取出商品的第一张图片路径data.append({'img': img, 'goods': i})  # 将每个商品图片和信息的字典写到data列表中return render(request,'buyers/product-details.html',locals())

5.2.2 修改路由

在这里插入图片描述

5.2.3 修改页面

这个需要修改的地方有点多
方法都是一致的,就是把视图函数获取的数据渲染到页面上,熟能生巧

图片

在这里插入图片描述

商品概述修改

在这里插入图片描述

详情修改

这里可以自由发挥,我只保留了详情、问答和参数,参数理论上也是保存在数据库中的,方法都是一样的,只是商品表多了一些字段,有兴趣的可以去试试,做到以假乱真。
在这里插入图片描述

最底下还有个商品推荐,也就是从视图中取出来的那三个最贵的商品

在这里插入图片描述
效果:
在这里插入图片描述

最终效果

我还自己修改了很多css样式,这个就是看个人喜好了。
在这里插入图片描述

6 购物车

购物车涉及到以下几点

  • 数量的修改:增加,减少,手动输入,小计,总计
  • 数量修改后后台数据的获取,对数据库的修改

首先,设置模板右侧购物车按钮的路径,跳转至购物车页
在这里插入图片描述

6.1 视图函数

@cookieVerify
def cart(request):userId = request.COOKIES.get('user_id')buycarGoos = BuyCar.objects.filter(user=userId)alltotal = 0data = []for i in buycarGoos:goods = Goods.objects.get(id=i.goods_id)total = i.goods_num * i.goods_pricealltotal += totaldata.append({'total':total,'goods':i,'js':goods.goods_id})return render(request,'buyers/cart.html',locals())

首先需要通过列表将小计与商品对应传入数据库。

6.2 路由

在这里插入图片描述

6.3 页面设置

这里就很复杂了,主要的复杂在于三个框数据间的关系,模板提供了点击加减数字发生变化,但是特别坑,占用了name这个属性,所以只能将计就计。
在这里插入图片描述

6.3.1 数据渲染

首先解决购物车数据展示在页面
在这里插入图片描述

6.3.2 点击增加

由于模板提供了点击增加与减少,但是并没有关联,数量变化和小计总计价钱间的关系,首先找到模板的js文件,global.js
对器逻辑修改,增加小计和总计减的关系:

我添加的所有类名:
在这里插入图片描述

修改增加按钮逻辑

在global.js中

$("input[name='qty_plus']").on("click", function(e){e.preventDefault();// Get the field namevar fieldName = $(this).parent().parent().find("input[name='"+$(this).attr("data-field")+"']");// Get its current valuevar currentVal = parseInt($(fieldName).val());// If is not undefinedif (!isNaN(currentVal)){// Increment$(fieldName).val(currentVal + 1);var goods_allprice = $(this).parent().parent().parent().parent().children('td').eq(4).children('strong');var goods_price = $(this).parent().parent().parent().parent().children('td').eq(2).children('strong').text();var num = $(this).parent().parent().children('input').val();goods_allprice.text(Number(goods_price)*Number(num));var newtoal = Number($('.alltotal').text())+Number(goods_price);$('.alltotal').text(newtoal);}else{// Otherwise put a 1 there$(fieldName).val(1);}});

修改减少按钮逻辑

在global.js中

// This button will decrement the value till 1$("input[name='qty_minus']").on("click", function(e){e.preventDefault();// Get the field namevar fieldName = $(this).parent().parent().find("input[name='"+$(this).attr("data-field")+"']");// Get its current valuevar currentVal = parseInt($(fieldName).val());// If it isn't undefined or its greater than 1if (!isNaN(currentVal) && currentVal > 1){// Decrement one$(fieldName).val(currentVal - 1);var goods_allprice = $(this).parent().parent().parent().parent().children('td').eq(4).children('strong');var goods_price = $(this).parent().parent().parent().parent().children('td').eq(2).children('strong').text();var num = $(this).parent().parent().children('input').val();goods_allprice.text(Number(goods_price)*Number(num));var newtoal = Number($('.alltotal').text())-Number(goods_price);$('.alltotal').text(newtoal)}else{// Otherwise put a 1 therevar newtoal = Number($('.alltotal').text())-Number(0);$('.alltotal').text(newtoal);$(fieldName).val(1);}});

给原有页添加js逻辑,用来进行手动输入数据,小计与总计变化关系

购物车页

<script>$(function () {$('.quantity').focus(function () {num1 = $(this).val();});$('.quantity').blur(function () {var goods_allprice = $(this).parent().parent().parent().children('td').eq(4).children('strong');var goods_price = $(this).parent().parent().parent().children('td').eq(2).children('strong').text();var num2 = $(this).val();if(Number(num2) >= 1){var num = num2-num1;goods_allprice.text(Number(goods_price)*Number(num2));var newtoal = Number($('.alltotal').text())+Number(goods_price)*Number(num);$('.alltotal').text(newtoal)}else {num2 = $(this).val(1);var num=1-num1;goods_allprice.text(Number(goods_price));var newtoal = Number($('.alltotal').text())+Number(goods_price)*Number(num);$('.alltotal').text(newtoal)}})})</script>

6.4 删除按钮

在这里插入图片描述
这个很简单

6.4.1 视图函数

增加一个视图函数

#删除购物车函数
@cookieVerify
def delete_car_goods(request,id):userId = request.COOKIES.get('user_id')goods = BuyCar.objects.filter(user=int(userId),id=int(id))goods.delete()return HttpResponseRedirect("/buyers/cart/")

6.4.2 路由

因为要判断删除的是哪个,所以肯定会有正则
在这里插入图片描述

6.4.3 页面链接

在这里插入图片描述

6.5 跳转至确认订单页面

我们修改数量之后,在点击确认订单按钮的同时,也需要修改购物车数据库中商品的数量。

这里有一个坑,就是模板的js占用了商品数量的name属性,所以我们不能修改name属性,也就无法区分每个商品

经过我研究,所有的数量input框的name都是quantity,那传到前台会不会是个列表呢,经过debug之后,发现还真是,那就简单多了。

6.5.1 修改页面表单

form属性 提交按钮 还有csrf防御

因为我们点击去提交按钮后会跳转至其他页面,这时候就用到form标签的另一个属性ation了,action就是用作跳转的,我已经写好了确认订单页的路由。
在这里插入图片描述
在这里插入图片描述

6.5.2 确认订单视图函数

首先需要获取到修改过后的商品数量,传过来的quantity列表中有几个元素,就代表购物车里有几个商品,顺序与数据库的顺序是一致的,所以可以利用这一点,加上for循环递增的i,来依次取出数量,存入数据库。

@cookieVerify
def enterorder(request):alltotal = 0data = []userId = request.COOKIES.get('user_id')if request.method == 'POST' and request.POST:countLIST = request.POST.getlist('quantity')for i in range(0,len(countLIST)):buycar = BuyCar.objects.filter(user=userId)[i]buycar.goods_num = countLIST[i]buycar.save()total = int(buycar.goods_price)*int(buycar.goods_num)data.append({'total':total,'goods':buycar})alltotal += totalreturn render(request,'buyers/enterorder.html',locals())

6.5.3 路由修改

在这里插入图片描述

6.5.4 页面修改

在这里插入图片描述
样式:
我把没用的都删除了,邮寄方式目前只是个摆设,在后期版本会补全很多细节功能。
在这里插入图片描述
不过点击顺丰或者普通,总价发生变化还是可以通过js实现的:

 <script>$('#sf').click(function () {var alltotal= $('#alltotal').text();$('#alltotal').text(Number(alltotal)+15)});$('#free').click(function () {var alltotal= $('#alltotal').text();$('#alltotal').text(Number(alltotal)-15)})</script>

7 确认支付页面

点击确认订单按钮之后,提交页面所有填写的信息,模板没有提供确认支付页面,所以我用确认订单页面修改了一下

7.1 确认支付的视图函数

首先要将购物车里的数据放到订单表中,生成订单单号,还要将购物车中的商品存入订单商品表中,还有邮寄地址也需要存入数据库中。

#确认支付
def enterpay(request):if request.POST and request.method == 'POST':alltotal = 0goods_list = []userId = request.COOKIES.get('user_id')#取出购物车中用户确定要购买的商品buycar = BuyCar.objects.filter(user=userId)for goods in buycar:total = int(goods.goods_price) * int(goods.goods_num)goods_list.append({'total': total, 'goods': goods})alltotal += total#把地址存入地址表address = Address()address.address = request.POST.get('address')address.username = request.POST.get('name')address.phone = request.POST.get('phone')address.buyer = Buyer.objects.get(id = userId)address.save()#在订单表中生成订单order = Order()# 订单编号 日期(年月日时分秒) + 随机 + 用户idnow = datetime.datetime.now()order.order_num = now.strftime("%Y%m%d%H%M%S") + str(random.randint(10000, 99999)) + userId# 状态 未支付 1 支付成功 2 配送中 3 交易完成 4 已取消 0order.order_time = noworder.order_statue = 1order.total = alltotalorder.user = Buyer.objects.get(id = userId)order.order_address = addressorder.save()#订单商品for good in goods_list: #循环保存订单当中的商品g = good["goods"]g_o = OrderGoods()g_o.good_id = g.goods_idg_o.good_name = g.goods_nameg_o.good_price = g.goods_priceg_o.good_num = g.goods_numg_o.goods_picture = g.goods_pictureg_o.order = orderg_o.save()return render(request,'buyers/enterpay.html',locals())

7.2 路由设置

在这里插入图片描述

7.3 页面设置

修改了以下确认清单页

<!-- Content --><div class="content-right"><div class="container m-t-100 m-b-100"><div class="row"><div class="col-sm-12"><h1 class="text-xs-center">确认订单</h1><div class="separator-one"></div></div></div><div class="row m-t-70"><form><div class="col-xs-12 col-sm-6 col-md-7"><div class="row"><div class="col-sm-12"><h3 class="m-tb-30 text-xs-center" style="margin-top: 0" >你的订单</h3><p>订单编号:<span>{{ order.order_num }}</span></p><table class="table table-hover table-condensed"><tbody>{% for goods in goods_list %}<tr><td class="col-sm-2 hidden-xs"><a href="http://demo.intelcoder.net/staro/checkout.html#" class="thumbnail m-b-0"><img src="/static/{{ goods.goods.goods_picture }}" alt=""></a></td><td>{{ goods.goods.goods_num }} &nbsp;x&nbsp; {{ goods.goods.goods_name }}</td><td class="text-right">{{ goods.total }}RMB</td></tr>{% endfor %}</tbody><tfoot><tr><td colspan="2" class="b-t-0 text-right"><h3 class="m-b-0">总计</h3></td><td  class="b-t-0 text-right"><h3 id="alltotal" class="m-b-0">{{ order.total }}RMB</h3></td></tr></tfoot></table></div></div></div><div class="col-xs-12 col-sm-6 col-md-5"><div class="row"><div class="col-sm-12"><h3 class="m-xs-t-30 m-b-30 text-xs-center">邮寄方式</h3><div class="form-group form-group-default"><div class="radio"><label style="font-weight: bolder;font-size: 18px;color: black">普通快递</label><label class="pull-right">免运费</label></div></div></div></div><div class="row"><div class="col-sm-12"><h3 class="m-tb-30 text-xs-center">支付方式</h3><div class="form-group form-group-default"><div class="radio"><label style="font-weight: bolder;font-size: 18px;color: black">支付宝</label></div></div></div></div><div class="row"><div class="col-sm-12"><h3 class="m-tb-30 text-xs-center">邮寄地址</h3><div class="form-group form-group-default required"><label>姓名</label><p style="color: black" class="form-control">{{ address.username }}</p></div><div class="form-group form-group-default required"><label>手机号</label><p style="color: black" class="form-control">{{ address.phone }}</p></div><div class="form-group form-group-default required"><label>地址</label><p style="color: black" class="form-control">{{ address.address }}</p></div></div></div></div><div class="col-xs-12 col-sm-12 col-md-12 text-center"><div class="separator-two m-b-30"></div><a href="/buyers/payVerify/{{ order.id }}/" class="btn btn-success"><i class="fas fa-shopping-bag"></i>&nbsp; 确认支付</a><p class="small m-t-20"><a href="/buyers/cart/"><i class="fas fa-angle-left"></i> 取消支付</a></p></div></form></div></div></div><!-- Content -->

效果如下:
在这里插入图片描述

7.5 支付

这里说一下 只能用支付宝进行支付目前(沙箱支付宝并不能真的付钱),微信需要营业执照,银联贼麻烦。
支付宝沙箱环境申请:
关于申请支付宝沙箱啥的参考这个(https://blog.csdn.net/lzz781699880/article/details/81045135)我就不多说了。

7.5.1 支付函数

跳转函数需要两个参数,一个是订单号,一个是总价

#支付跳转函数
from alipay import AliPay
def paydata(order_num,count):alipay_public_key_string = '''-----BEGIN PUBLIC KEY-----你的沙箱公钥-----END PUBLIC KEY-----'''app_private_key_string = '''-----BEGIN RSA PRIVATE KEY-----你的沙箱密钥-----END RSA PRIVATE KEY-----'''alipay = AliPay(appid="你的沙箱支付宝app的id",  # 支付宝app的idapp_notify_url=None,  # 回调视图app_private_key_string=app_private_key_string,  # 私钥字符alipay_public_key_string=alipay_public_key_string,  # 公钥字符sign_type="RSA2",  # 加密方法)order_string = alipay.api_alipay_trade_page_pay(out_trade_no=str(order_num),total_amount=str(count),  #将Decimal类型转换为字符串交给支付宝subject="商贸商城",return_url=None,notify_url=None  # 可选, 不填则使用默认notify url)return  "https://openapi.alipaydev.com/gateway.do?" + order_string

7.5.2 调用支付函数

视图函数中

调用刚才的支付跳转函数

#支付
def payVerify(request,num):order = Order.objects.get(id=int(num))order_num = order.order_numorder_count = order.totalurl = paydata(order_num,order_count)return HttpResponseRedirect(url)

路由设置

因为需要根据订单id确认订单,所以需要正则
在这里插入图片描述

网页路由绑定

在这里插入图片描述
效果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_858990.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql 5.6.12源码_最新LAMP源码搭建网站平台PHP5.5.1 + Apache2.4.6 + mysql5.6.12

记录一下&#xff0c;今天配置的这台网站服务器&#xff0c;大部分都是在官方找的最新版源码包。 1.下载安装所需要的最新软件源码包&#xff0c;包括最新的apache、mysql、php以及相关库文件的源码包。 2.检查安装时使用的编译工具是否存在。 3.卸载默认的低版本环境及rpm包环…

网站服务器如何导入数据库,网站服务器如何导入数据库

网站服务器如何导入数据库 内容精选 换一换 PostgreSQL支持逻辑备份。您可使用pg_dump逻辑备份功能&#xff0c;导出备份文件&#xff0c;再通过psql导入到RDS中&#xff0c;实现将PostgreSQL的数据导入到云数据库RDS中。云数据库RDS服务支持开启公网访问功能&#xff0c;通过弹…

阿里云服务器ubuntu18-04下使用wordpress搭建网站/ ‎编辑

** 阿里云服务器ubuntu18-04下使用wordpress搭建网站/ ‎编辑 ** 一. 服务器领取 高校学生可以免费领取,此处不做详述: 二. 配置wordpress 首先进入控制台&#xff1a; 然后远程登陆服务器&#xff08;xshell、putty等&#xff09;。 输入以下两条命令&#xff1a; &…

身为Android程序猿,必不可少的十大网站

&#xfeff;&#xfeff; 身为Android程序猿&#xff0c;必不可少的十大网站&#xff0c;让你更加高效的去开发。 第一&#xff0c;Google&#xff08;http://www.google.com/&#xff09;谷歌是Google公司开发的互联网搜索引擎。主要提供网页搜索&#xff0c;图片搜索&#…

手把手教你每个人都可以拥有的个人博客网站

题记 ------去过的地方越多&#xff0c;越知道自己想回到什么地方去&#xff01; 雨又下了一夜&#xff0c;曾经多少次觉得下雨天是最适合睡觉的天气。而最近的雨&#xff0c;总感觉有些嘈杂&#xff0c;总怕吵醒远方睡梦中的星&#xff0c;晨。以至于翻来覆去睡不着。但是&…

手把手教你使用Hexo和github搭建免费个人博客网站

俗话说的好“吃水不忘挖井人”&#xff0c;当自己体验过Hexo搭建个人网站后&#xff0c;也来分享一下搭建过程遇到的乐趣以及遇到的坑&#xff01; 准备工作&#xff08;电脑配置工具&#xff09; 在搭建Hexo博客之前&#xff0c;首先需要简单在你电脑安装一些工具以及依赖包…

大型网站架构演变和知识体系

之前也有一些介绍大型网站架构演变的文章&#xff0c;例如LiveJournal的、ebay的&#xff0c;都是非常值得参考的&#xff0c;不过感觉他们讲的更多的是每次演变的结果&#xff0c;而没有很详细的讲为什么需要做这样的演变&#xff0c;再加上近来感觉有不少同学都很难明白为什么…

【Python 爬虫 CASE】使用Selenium+BeautifulSoup获取新闻网站文章列表

一、需求 获取腾讯新闻网站(https://news.qq.com/)首页的新闻标题和列表 F12打开开发者工具&#xff0c;查看源代码 二、实现 Step1&#xff1a;获取网页源代码 如果使用requests库获取源代码 import requests res requests.get(http://news.qq.com/)但是这种方式获取的…

【Python 爬虫 CASE】使用Requests+BeautifulSoup获取新闻网站文章内容并整理成表

一、需求 获取新浪新闻网站(http://news.sina.com.cn/china/)首页的新闻内容 F12打开开发者工具&#xff0c;查看源代码 打开新闻链接&#xff0c;获取该新闻文章的“内容”、“标题”、“来源” F12打开开发者工具&#xff0c;查看源代码 二、实现 Step1&#xff1a;构建…

Magento开发教程 - 后台设置多个网站,商店和商店视图

1: 创建产品根目录 登录到Magento 2后台.点击 Products > Categories.点击 Add Root Category.在 Category Name 输入分类名称. 确保 Enable Category 设置 Yes. 如下图&#xff1a; 点击 Save. 2: 创建 websites&#xff08;网站&#xff09; 点击 Stores > 设置 >…

visual studio 2010教程-创建网站项目

1.打开visual studio 2010 选择新建 - 网站 2.进行对应的设置 3.创建完毕之后&#xff0c;在解决方案资源管理器中出现对应的项目 4.在项目名称上 右键 - 添加新项 5.选择web窗体&#xff0c;并命名新建的页面为index.aspx 6.创建完毕之后的工程 7.首页的源代码如下 8.接下来…

项目总结——Java web之实现当当网网站

Java web之实现当当网网站 运行环境&#xff1a;JDK1.8tomcat8.4MySQL5servlet技术 源码结构 CategoryDAO.java package com.tarena.dao;import java.sql.SQLException; import java.util.List;import com.tarena.entity.Category;public interface CategoryDAO {public Lis…

如何使用IIS发布网站?

如何使用IIS发布网站&#xff1f; 1.搜索输入 IIS&#xff0c;找到IIS&#xff08;Internet Information Services&#xff09; 2.添加网站 3.填写相关内容属性 4.浏览默认文档 5.浏览发布界面 有任何疑问和和源码需求敬请关注公众号【蜗牛资源社】 欢迎交流学习&#x…

C++网站开发MVC框架TreeFrog Framework教程——2.简单示例

下面以一个博客文章管理网站的开发实例作为这个框架的使用入门教程。 1.安装TreeFrog Framework 下面以Ubuntu为例说明&#xff1a; 1.1.安装框架的依赖库&#xff1a; $ sudo apt-get install -y qt5-default qt5-qmake libqt5sql5-mysql libqt5sql5-psql libqt5sql5-odb…

C++网站开发MVC框架TreeFrog Framework教程——8.Otama模板

Otama模板系统的最大特点在于表现层的纯粹性&#xff0c;使用原生的HTML标签取代形如<%...%>这样的嵌入脚本代码。 使用之前&#xff0c;记得把配置文件&#xff08;development.ini&#xff09;中的模板系统设置为Otama&#xff1a; TemplateSystemOtamaOtama模板文件…

从零开始开发一个大型网站

从零开始开发一个大型网站 更新&#xff1a;前端代码已全部由TypeScript进行重写 这是本人第一个从零开始开发一个大型网站&#xff08;前后端部署代码&#xff09;&#xff0c;是一个内容分享社区&#xff0c;详细信息见github。目前还是开发中后期&#xff0c;随后还要进行…

使用MVC框架开发网站(一)

概述 本章您将学会&#xff1a; 1.MVC的概念及使用 2.MVC与ASP.NET的区别 3.路由和URL导向 4.控制器和视图 5.模型与模型状态 6.过滤器 7……. 第1章_MVC与ASP.NET的区别 1.1概述 MVC是一种流行的Web应用架构技术&#xff0c;他把Web应用划分成Model、Controller和V…

利用beego开发网站(一)

在这里&#xff0c;我将分享我这段时间学到的关于怎样搭建一个简单的beego项目&#xff0c;分享的东西仅仅是入门级别。 一&#xff0c;安装golang的开发工具和语言的编译工具&#xff08;如果本步骤不会的话&#xff0c;请去golang中国社区查阅资料进行开发搭建&#xff09; 我…

使用ThinkPHP框架快速开发网站(多图)

使用ThinkPHP框架快速搭建网站 这一周一直忙于做实验室的网站&#xff0c;基本功能算是完成了。比较有收获的是大概了解了ThinkPHP框架。写一些东西留作纪念吧。如果对于同样是Web方面新手的你有一丝丝帮助&#xff0c;那就更好了挖。 以前用PHP做过一个很蹩脚的网站&#xff0…

node爬虫_爬取斗图啦网站上的表情包

最近在学习node.js,做点不是人的事情&#xff1a;爬取网站上的表情包 实现步骤&#xff1a; 1、分析网站的结构&#xff1a; 斗图啦这个网站是服务器渲染的&#xff0c;直接打开网站就可以获取到完整的html信息。 我们可以看到下面两张图就是我们需要获取的信息 2、使用的插…