交作业啦
前端:html+css+js+Vue+Element-ui
后端:Django+DRF+celery+haystack+django_crontab
数据库:Mysql+Redis
一些技术和功能:
- 为session、短信验证码、用户浏览记录、购物车、异步任务队列 创建缓存
- whoosh搜索引擎
- 异步任务队列 用于发送邮件、短信
- 定时任务 定时更新静态页面、刷新日志等
- 腾讯云短信服务
- chatGPT客服(New)
- 支付宝沙盒
- 客服群聊
- 数据库乐观锁
- 页面静态化
- JWT认证
- 发货地址、不同的商品的详情、售后服务等都可以通过后台设置
- 自选CPU、内存、显卡
- "点击此处确认验证邮箱"
- 对于未登录的用户,购物车数据使用浏览器cookie保存 登陆后合并购物车 对于已登录的用户,购物车数据在后端使用Redis保存
效果如下:
代码过多,这里只展示一部分,欢迎感兴趣的小伙伴一起讨论学习:
import os
from alipay import AliPay
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from MyApps.orders.models import OrderInfo
from MyApps.payment.models import Payment
from django.conf import settings
class PaymentView(APIView):
"""
支付
"""
permission_classes = (IsAuthenticated,)
def get(self, request, order_id):
"""
获取支付链接
"""
# 判断订单信息是否正确
try:
order = OrderInfo.objects.get(order_id=order_id, user=request.user,
pay_method=OrderInfo.PAY_METHODS_ENUM["ALIPAY"],
status=OrderInfo.ORDER_STATUS_ENUM["UNPAID"])
except OrderInfo.DoesNotExist:
return Response({'message': '订单信息有误'}, status=status.HTTP_400_BAD_REQUEST)
# 构造支付宝支付链接地址
alipay = AliPay(
appid=settings.ALIPAY_APPID,
app_notify_url=None, # 默认回调url
app_private_key_string=open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "keys",
"app_private_key.pem")).read(),
# app_private_key_string=settings.app_private_key_string,
alipay_public_key_string=open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'keys',
'alipay_public_key.pem')).read(),
# alipay_public_key_string=settings.alipay_public_key_string, # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
sign_type="RSA2", # RSA 或者 RSA2
debug=settings.ALIPAY_DEBUG # 默认False
)
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=order_id,
total_amount=str(order.total_amount),
subject="联想商城%s" % order_id,
return_url="http://localhost:63342/BMyStore/front_end_pc/pay_success.html",
)
# 需要跳转到https://openapi.alipay.com/gateway.do? + order_string
# 拼接链接返回前端
alipay_url = settings.ALIPAY_URL + "?" + order_string
return Response({'alipay_url': alipay_url})
# 支付宝回调函数接口 put /payment/status/?支付宝参数
class PaymentStatusView(APIView):
def put(self, request):
# 接收参数,效验参数
# 构造支付宝支付链接地址
alipay_req_data = request.query_params
if not alipay_req_data:
return Response({"message": "缺少参数"}, status=status.HTTP_400_BAD_REQUEST)
alipay_req_dict = alipay_req_data.dict()
sign = alipay_req_dict.pop("sign")
alipay = AliPay(
appid=settings.ALIPAY_APPID,
app_notify_url=None, # 默认回调url
app_private_key_string=open(os.path.join(os.path.dirname(os.path.abspath(__file__)),
"keys/app_private_key.pem")).read(),
alipay_public_key_string=open(os.path.join(os.path.dirname(os.path.abspath(__file__)),
"keys/alipay_public_key.pem")).read(),
# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
sign_type="RSA2", # RSA 或者 RSA2
debug=settings.ALIPAY_DEBUG # 默认False
)
result = alipay.verify(alipay_req_dict, sign)
# 保存数据,保存支付结果数据
if result:
order_id = alipay_req_dict.get("out_trade_no")
trade_id = alipay_req_dict.get("trade_no")
# 修改订单状态
Payment.objects.create(
order_id=order_id,
trade_id=trade_id
)
OrderInfo.objects.filter(order_id=order_id).update(status=OrderInfo.ORDER_STATUS_ENUM["UNCOMMENT"])
print('支付成功!')
return Response({"trade_id": trade_id})
return Response({"message": "参数有误"}, status=status.HTTP_400_BAD_REQUEST)
from django_filters.rest_framework import DjangoFilterBackend
from drf_haystack.viewsets import HaystackViewSet
from rest_framework.filters import OrderingFilter
from rest_framework.generics import ListAPIView, CreateAPIView, DestroyAPIView, RetrieveAPIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet
from MyApps.goods import models
from MyApps.goods.models import SKU, GoodsCategory, Collect, Comment1, SKUImage
from MyApps.goods.serializers import SKUSerializer, SKUIndexSerializer, CollectSerializer, Comment1Serializer
from rest_framework.permissions import IsAuthenticated
from django_redis import get_redis_connection
from rest_framework.filters import BaseFilterBackend
from django_filters import FilterSet, filters
class SKUListView(ListAPIView):
"""
sku列表数据
"""
serializer_class = SKUSerializer
# 分页与排序
filter_backends = (OrderingFilter,)
ordering_fields = ("create_time", "price", "sales")
def get_queryset(self):
category_id = self.kwargs["category_id"]
return SKU.objects.filter(category_id=category_id, is_launched=True)
class SKUSearchViewSet(HaystackViewSet):
"""
SKU搜索
"""
index_models = [SKU]
serializer_class = SKUIndexSerializer
# 分页与排序
# filter_backends = (OrderingFilter,)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
ordering_fields = ("create_time", "price", "sales")
od = request.query_params.get("ordering", None)
if od in ordering_fields:
queryset = queryset.order_by(od)
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
class CategoriesView(APIView):
"""获取当前分类信息"""
def get(self, request, pk):
"""
1.获取前端数据
2. 查询当前三级分类信息
3.通过三级分类信息获取一二集分类
4. 返回
:param request:
:return:
"""
cat3 = GoodsCategory.objects.get(id=pk) # 获取三级
cat2 = cat3.parent # 自关联获取二级,
cat1 = cat2.parent # 自关联获取一级
# 返回数据
return Response({
"cat1": cat1.name,
"cat2": cat2.name,
"cat3": cat3.name
})
class GetGoodsView(APIView):
"""获取当前分类信息"""
def get(self, request, pk):
SKU1 = models.SKU.objects.filter(pk=pk).first()
comment_count = SKU1.goods.comment_count
collect_count = SKU1.goods.collect_count
goods_id = SKU1.goods_id
# 返回数据
return Response({"goods_id": goods_id, 'comment_count': comment_count, 'collect_count': collect_count})
class IsCollectedView(APIView):
def post(self, request):
print(request.data)
sku_id = int(request.data.get("sku_id", -5))
user_id = request.data.get("user_id", 1)
if sku_id == -5:
return Response({"res_data": 0})
collecs = models.Collect.objects.filter(user_id=user_id)
sku_id_list = [i.sku_id for i in collecs]
print(sku_id in sku_id_list)
res = 0
if sku_id in sku_id_list:
res = 1
return Response({"res_data": res})
##################################
class MyPageNumberPagination(PageNumberPagination):
page_size_query_param = 'size'
page_size = 10
max_page_size = 100
class CommentFilterSet(FilterSet):
goods = filters.NumberFilter(field_name='goods', required=True)
class Meta:
model = models.Comment1
fields = ['goods']
class Comment1View(ListAPIView, GenericViewSet):
filter_backends = [DjangoFilterBackend]
filterset_class = CommentFilterSet
queryset = models.Comment1.objects
serializer_class = Comment1Serializer
################################################
class SelfFilterBackend(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
return queryset.filter(user=request.user)
class CollectViewSet(ListAPIView, CreateAPIView, GenericViewSet):
permission_classes = [IsAuthenticated]
filter_backends = [SelfFilterBackend, DjangoFilterBackend]
pagination_class = MyPageNumberPagination
# 当前登录用户的所有收藏记录
queryset = models.Collect.objects
serializer_class = CollectSerializer
def perform_create(self, serializer):
user = self.request.user
instance = Collect.objects.filter(user=user, **serializer.validated_data).first()
if not instance:
instance = serializer.save(user=user)
instance.sku.goods.collect_count += 1
instance.sku.goods.save()
return Response({"message": 'ok', 'data': {'active': True}})
else:
instance.delete()
instance.sku.goods.collect_count -= 1
instance.sku.goods.save()
return Response({"message": 'ok', 'data': {'active': False}})
class HotSkus(ListAPIView):
serializer_class = SKUSerializer
# 分页与排序
filter_backends = (OrderingFilter,)
ordering_fields = ("sales", "create_time", "price")
def get_queryset(self):
category_id = self.kwargs["category_id"]
return SKU.objects.filter(category_id=category_id, is_launched=True).order_by('-sales')[:2]
class ImgListView(APIView):
def get(self, request):
s_id = request.query_params.get("sku_id")
img_list = SKUImage.objects.filter(sku_id=s_id)
img_list = [i.image.path.split("BMyStore\\")[1] for i in img_list]
return Response({"img_list": img_list})
有些代码写的略显丑陋 不过能跑就不改了 哈哈