失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Django框架实现可运营电商网站(二)-- 前台部分

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

时间:2022-07-17 12:36:56

相关推荐

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

文章目录

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 调用支付函数视图函数中路由设置网页路由绑定

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

1 前台模板修改

这里提供一个我找的前台模板,大家也可以自己去找,每个人审美不同的,我觉得好的,大家不一定觉得。方法都是一样的。

链接:/s/1ulgLs1SwuIfww_NUx6XYPA

提取码:5yry

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

1.1 模板制作

观察我给的模板页面,所有的页面都被分为了一下几个部分:

紫色框中内容基本一致,除了title和个别css文件数量不同,橙色框中是

所以将紫色框中的代码抽取出来作为模板,head部分当然要包含所有网页要用的css和 js包。

在templates中新建一个html网页为base.html

然后将共性代码放入base.html,并添加个性定位标记

修改所有的页面,继承模板,套用标记块,以下图方法修改所有页面

1.2 静态链接

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

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

前台视图文件:

from django.shortcuts import renderdef 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,输入以下三个命令

checkmakemigrationsmigarate

成功后表同步成功,可以用pycharm自带的数据库工具进行查看

3 注册与登陆

3.1 注册页面

3.1.1 样式

模板没有提供注册页,所以复制登录页进行修改。

绑定视图函数和路由后,样式变为:

至于邮箱验证注册的方法与逻辑参照我之前的博客(/weixin_39561473/article/details/86654561)

这里就粗略的写了:

3.1.2 需要导入的所有包:

from django.shortcuts import render,HttpResponseRedirectfrom django.core.mail import EmailMultiAlternativesfrom django.http import JsonResponseimport random,datetime,time,hashlibfrom 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 视图函数

@cookieVerifydef 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 视图函数

增加一个视图函数

#删除购物车函数@cookieVerifydef 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,来依次取出数量,存入数据库。

@cookieVerifydef 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="/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 支付

这里说一下 只能用支付宝进行支付目前(沙箱支付宝并不能真的付钱),微信需要营业执照,银联贼麻烦。

支付宝沙箱环境申请:

关于申请支付宝沙箱啥的参考这个(/lzz781699880/article/details/81045135)我就不多说了。

7.5.1 支付函数

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

#支付跳转函数from alipay import AliPaydef 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 "/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确认订单,所以需要正则

网页路由绑定

效果如下:

如果觉得《Django框架实现可运营电商网站(二)-- 前台部分》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。