当前位置:   article > 正文

Django入门项目实战_django实战

django实战

一、redis通用命令

redis默认有16个 数据库(0-15) select 3 切换到数据库3

info 查看redis服务的信息 info replication查看主从复制的状况

keys * 查看所有的key, 生产环境中不使用 可能阻塞redis

查看key的数据类型 type key1

key 是否存在 exists key1

删除一个key del key1

重命名 rename key key1

flushdb # 清空当前数据库

flushall # 清空所有数据库

二、git 常用命令

1.初始化仓库:git init

2.查看状态:git status

3.添加文件:git add 文件名(*指的是全部)

4.配置个人信息:

git config user.name 你的名字

git config user.email 你的邮箱

5.提交代码:git commit -m 版本信息

6.查看日志信息:git log --oneline

7.回退:git reset --hard HEAD/版本号

8.关联远程仓库:git remote add origin ‘码云地址’

9.提交代码到远程仓库:git push -u origin "master"

10.获取远程仓库的代码:git pull origin master

11.分支操作:

#查看分支 git branch

#创建分支 git branch b1

#切换到b1分支 git switch b1

#将b1分支合并到master git switch master git merge b1

项目实战配置文件

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'corsheaders', # 跨域
  9. 'user', # user应用名
  10. 'rest_framework', # drf框架
  11. 'goods' # goods应用名
  12. ]
  13. MIDDLEWARE = [
  14. 'django.middleware.security.SecurityMiddleware',
  15. 'django.contrib.sessions.middleware.SessionMiddleware',
  16. 'django.middleware.common.CommonMiddleware',
  17. # 'django.middleware.csrf.CsrfViewMiddleware', # 注册drf 中间件
  18. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  19. 'django.contrib.messages.middleware.MessageMiddleware',
  20. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  21. 'corsheaders.middleware.CorsMiddleware', # 添加跨域中间件
  22. 'middleware.middleware.CheckUserMiddleware',
  23. ]
  24. CORS_ORIGIN_WHITELIST = [
  25. # 配置ip白名单
  26. 'http://127.0.0.1:8080',
  27. 'http://localhost:8080'
  28. ]
  29. # credentials
  30. # methods
  31. # headers
  32. CORS_ALLOW_CREDENTIALS = True # 配置允许cookie
  33. CORS_ALLOW_METHODS = ['*'] # 允许的请求方式
  34. CORS_ALLOW_HEADERS = ['*'] # 允许的请求头
  35. DATABASES = {
  36. 'default': {
  37. 'ENGINE': 'django.db.backends.mysql', # 配置mysql数据库
  38. 'NAME': 'djangoproject',
  39. 'USER':'root',
  40. 'PASSWORD':'123',
  41. 'HOST':'localhost',
  42. 'PORT':3306
  43. }
  44. }
  45. AUTH_USER_MODEL = 'user.User' # 使用自定义 用户模型类 app.模型类
  46. STATICFILES_DIRS = [
  47. os.path.join(BASE_DIR,'static')
  48. ]

三、django,vue前后端注册代码

1.手机号跟用户名判断是否重复

  1. from django.shortcuts import render
  2. from rest_framework.views import APIView
  3. from rest_framework.response import Response
  4. import re
  5. from user.models import User
  6. # Create your views here.
  7. # 用户名
  8. class CheckUsername(APIView):
  9. def get(self,request,username):
  10. # 1.判断用户名格式
  11. # 要求字母开头,中间为字母,数字,下划线,长度5-16
  12. if not re.findall(r'^[a-zA-Z]\w{4,15}$',username):
  13. return Response({
  14. 'code':404,
  15. 'msg':'用户名格式不正确'
  16. })
  17. # 2.判断用户是否存在
  18. if User.objects.filter(username=username):
  19. return Response({'msg':'用户名重复','code':400})
  20. else:
  21. return Response({'msg':'ok','code':200})
  22. # 手机号
  23. class MobileAPIView(APIView):
  24. def get(self,request,mobile):
  25. # 1. 判断手机号格式是否满足要求
  26. if not re.findall(r'^1[3-9]\d{9}$',mobile):
  27. return Response({
  28. 'msg':'手机号格式不正确',
  29. 'code':404
  30. })
  31. # 2. 判断手机号是否存在
  32. if User.objects.filter(mobile=mobile):
  33. return Response({
  34. 'msg':'手机号重复',
  35. 'code':400
  36. })
  37. else:
  38. return Response({
  39. 'msg':'ok',
  40. 'code':200
  41. })

2.前端用户名手机号,判断密码是否一致请求

  1. // 用户名的校验方法
  2. let validateName = (rule, value, callback) => {
  3. if (!value) {
  4. return callback(new Error("用户名不能为空"));
  5. }
  6. // 用户名以字母开头,长度在5-16之间,允许字母数字下划线
  7. const userNameRule = /^[a-zA-Z][a-zA-Z0-9_]{4,15}$/;
  8. if (userNameRule.test(value)) {
  9. // 前端校验,用户名复合规则
  10. //请求后端, 判断用户名是否重复
  11. this.$axios
  12. .get("/users/check/username/" + value + "/"
  13. )
  14. .then((res) => {
  15. // 200代表用户名不重复,可以注册
  16. console.log("校验用户名是否重复:", res);
  17. if (res.data.code == 200) {
  18. this.$refs.ruleForm.validateField("checkPass");
  19. return callback();
  20. } else {
  21. // 用户名重复或者不符合规则
  22. return callback(new Error(res.data.msg));
  23. }
  24. })
  25. .catch((err) => {
  26. return Promise.reject(err);
  27. });
  28. } else {
  29. // 前端校验,用户名不符合规则
  30. return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
  31. }
  32. };
  33. // 手机号的校验方法
  34. let validateMobile = (rule, value, callback) => {
  35. if (value === "") {
  36. return callback(new Error("请输入手机号"));
  37. }
  38. // 手机号以1开头,第二位3-9之间的数字,长度为11,只允许数字
  39. const mobileRule = /^1[3-9]\d{9}$/;
  40. if (mobileRule.test(value)) {
  41. this.$axios.get("/users/check/mobile/" + this.RegisterUser.mobile + "/")
  42. .then(res=>{
  43. console.log("验证手机号是否可用:", res)
  44. if(res.data.code == 200){
  45. this.$refs.ruleForm.validateField("checkPass");
  46. return callback();
  47. }else{
  48. return callback(new Error(res.data.msg))
  49. }
  50. }).catch(err=>{
  51. return Promise.reject(err)
  52. })
  53. } else {
  54. return callback(new Error("手机号不符合格式"));
  55. }
  56. };
  57. // 密码的校验方法
  58. let validatePass = (rule, value, callback) => {
  59. if (value === "") {
  60. return callback(new Error("请输入密码"));
  61. }
  62. // 密码以字母开头,长度在6-18之间,允许字母数字和下划线
  63. const passwordRule = /^[a-zA-Z]\w{5,17}$/;
  64. if (passwordRule.test(value)) {
  65. this.$refs.ruleForm.validateField("checkPass");
  66. return callback();
  67. } else {
  68. return callback(
  69. new Error("字母开头,长度6-18之间,允许字母数字和下划线")
  70. );
  71. }
  72. };
  73. // 确认密码的校验方法
  74. let validateConfirmPass = (rule, value, callback) => {
  75. if (value === "") {
  76. return callback(new Error("请输入确认密码"));
  77. }
  78. // 校验是否以密码一致
  79. if (this.RegisterUser.pass != "" && value === this.RegisterUser.pass) {
  80. this.$refs.ruleForm.validateField("checkPass");
  81. return callback();
  82. } else {
  83. return callback(new Error("两次输入的密码不一致"));
  84. }
  85. };

3.django后端实现图形验证码及注册功能

  1. # 图形验证码
  2. class ImgCode(APIView):
  3. def get(self,request,uuid):
  4. # 1.生成4位验证码
  5. # string.ascii_letters 随机字母 a-zA-Z
  6. # string.digits 随机数字 0-9
  7. code = ''.join(random.sample(string.ascii_letters+string.digits,4))
  8. # 2.生成图形验证码
  9. cap = ImageCaptcha() # 定义对象
  10. img_code = cap.generate(code) # 生成图形验证码 de 图片
  11. # 3.保存验证码
  12. r = redis.Redis(host='localhost',port=6379,password='password',db=0)
  13. r.set(uuid,code,ex=60)
  14. r.close()
  15. # 4.返回图形验证码,使用httpResponse返回,需要加上数据类型context_type
  16. return HttpResponse(img_code,content_type='image/png')
  17. # 校验图形验证码
  18. class CheckImageCode(APIView):
  19. def post(self,request):
  20. # 1.提取get参数中的uuid和验证码
  21. uuid = request.data.get('imageCodeID')
  22. img_code = request.data.get('imageCode')
  23. # 2.读取redis数据库中的验证码
  24. r = redis.Redis(host='localhost',password='password',port=6379,db=0)
  25. r_code = r.get(uuid).decode()
  26. if not r_code:
  27. return Response({
  28. 'msg':'验证码过期',
  29. 'code':204
  30. })
  31. # redis数据库中存的是二进制
  32. # lower()都转换为小写
  33. # decode()解码
  34. if img_code.lower() == r_code.lower():
  35. return Response({'msg':'ok','code':200})
  36. else:
  37. return Response({'msg':'验证码错误','code':404})
  38. # 用户注册
  39. class Register(APIView):
  40. def post(self,request):
  41. # 获取前端提交数据
  42. username = request.data.get('userName')
  43. pwd = request.data.get('pwd')
  44. mobile = request.data.get('mobile')
  45. aggree = request.data.get('aggree')
  46. # 2.判断数据是否齐全
  47. if not all([username,pwd,mobile]):
  48. return Response({
  49. 'msg':'用户的注册信息不完整',
  50. 'code':204
  51. })
  52. # 3.判断是否同意协议
  53. if not aggree:
  54. return Response({
  55. 'msg':'用户未同意协议',
  56. 'code':204
  57. })
  58. # 4.往数据库中保存数据 create_user是AbstractUser提供的注册方法,会对密码进行加密
  59. User.objects.create_user(username=username,password=pwd,mobile=mobile)
  60. return Response({'msg':'注册成功','code':200})

4.vue前端实现图形验证码及用户注册

  1. // 校验图片验证码
  2. let validateImageCode = (rule, value, callback) => {
  3. if (value === "") {
  4. return callback(new Error("请输入图片验证码"));
  5. }
  6. // 图片验证码是由字母、数字组成,长度为4
  7. const iamgeCodeRule = /^[a-zA-Z0-9]{4}$/;
  8. if (iamgeCodeRule.test(value)) {
  9. this.$axios.post("/users/check_image_code/", {imageCode:this.RegisterUser.imageCode,imageCodeID:this.imageCodeID})
  10. // this.$axios.post("/users/test/", {username:'laufing1', password:"laufing123",mobile:123})
  11. .then(res => {
  12. if(res.data.code == 200){
  13. this.$refs.ruleForm.validateField("checkPass");
  14. return callback();
  15. }else{
  16. return callback(new Error(res.data.msg))
  17. }
  18. }).catch(err => {
  19. return Promise.reject(err)
  20. })
  21. } else {
  22. return callback(new Error("图片验证码不正确!"));
  23. }
  24. };
  1. // 用户注册
  2. Register() {
  3. // 是否同意用户协议
  4. if(!this.aggree){
  5. this.flag = true
  6. return
  7. }
  8. // 已勾选,则不显示提示信息
  9. this.flag = false
  10. // 通过element自定义表单校验规则,校验用户输入的用户信息
  11. this.$refs["ruleForm"].validate((valid) => {
  12. //如果通过校验开始注册
  13. if (valid) {
  14. this.$axios
  15. .post("/users/register/", {
  16. userName: this.RegisterUser.name,
  17. pwd: this.RegisterUser.pass,
  18. mobile: this.RegisterUser.mobile,
  19. aggree: this.aggree,
  20. })
  21. .then((res) => {
  22. // 200代表注册成功,其他的均为失败
  23. if (res.data.code == 200) {
  24. // 隐藏注册组件
  25. this.isRegister = false;
  26. // 弹出通知框提示注册成功信息
  27. this.notifySucceed(res.data.msg);
  28. } else {
  29. // 弹出通知框提示注册失败信息
  30. this.notifyError(res.data.msg);
  31. }
  32. })
  33. .catch((err) => {
  34. return Promise.reject(err);
  35. });
  36. } else {
  37. return false;
  38. }
  39. });
  40. },

 四、登录及退出登录

  1. from django.db.models import Q
  2. # 用户登录
  3. class Login(APIView):
  4. def post(self,request):
  5. username = request.data.get('username')
  6. pwd = request.data.get('password')
  7. try:
  8. user = User.objects.get(Q(username=username)|Q(mobile=username))
  9. except Exception as e:
  10. print(e)
  11. return Response({
  12. 'msg': '用户名不存在',
  13. 'code': 204
  14. })
  15. if not user.check_password(pwd):
  16. return Response({
  17. 'msg':'用户名或密码不正确',
  18. 'code':204
  19. })
  20. token = generate_jwt_token(user)
  21. return Response({
  22. 'msg':'登录成功',
  23. 'code':200,
  24. 'user':{
  25. 'username':user.username,
  26. 'uid':user.id
  27. },
  28. 'token':token,
  29. })
  30. # jwt token
  31. def generate_jwt_token(user):
  32. payload = {
  33. 'id':user.id,
  34. 'username':user.username,
  35. 'mobile':user.mobile,
  36. 'exp':datetime.datetime.now() + datetime.timedelta(seconds=300)
  37. }
  38. # 进行加密,生成 jwt token
  39. token = jwt.encode(payload=payload,key=settings.SECRET_KEY,algorithm='HS256')
  40. # 返回token
  41. return token
  1. // 退出登录
  2. logout() {
  3. // 不显示退出登录框
  4. this.visible = false;
  5. this.$axios.get("/users/exit/").then((res) => {
  6. console.log("@@退出登录的响应:", res);
  7. if (res.data.code == 200) {
  8. // 清空本地登录信息
  9. // localStorage.setItem("user", "");
  10. localStorage.removeItem("user");
  11. localStorage.removeItem("token")
  12. // 清空vuex登录信息
  13. this.setUser("");
  14. this.notifySucceed("成功退出登录");
  15. } else {
  16. console.log("退出请求失败")
  17. }
  18. }).catch(err => {
  19. return Promise.reject(err)
  20. })
  21. },
  1. // 点击登录触发
  2. Login() {
  3. // 通过element自定义表单校验规则,校验用户输入的用户信息
  4. this.$refs["ruleForm"].validate(valid => {
  5. //如果通过校验开始登录
  6. if (valid) {
  7. // 发送ajax
  8. this.$axios.post("/users/login/", {
  9. user: this.LoginUser.name,
  10. pwd: this.LoginUser.pass,
  11. // withCredentials: true,
  12. })
  13. .then(res => {
  14. console.log("@@登录的响应:", res)
  15. // 200代表登录成功,其他的均为失败
  16. if (res.data.code == 200) {
  17. // res.data为后端响应的json
  18. // 隐藏登录组件
  19. this.isLogin = false;
  20. // 登录信息存到本地缓存
  21. let user = JSON.stringify(res.data.user);
  22. console.log("@@user", user)
  23. //要求后台返回什么样的数据?
  24. //{
  25. // "code":200,
  26. // 'msg': "欢迎user",
  27. // "user":{
  28. // userName:"xxx",
  29. // },
  30. //
  31. //}
  32. // 前端存储用户信息,表示登录成功
  33. localStorage.setItem("user", user);
  34. localStorage.setItem("token", res.data.token)
  35. // sessionStorage.setItem("")
  36. // 登录信息存到vuex,控制页面欢迎信息
  37. // console.log("@@res.data.user", res.data.user)
  38. this.setUser(res.data.user);
  39. // 弹出通知框提示登录成功信息
  40. this.notifySucceed(res.data.msg);
  41. } else {//响应不是200
  42. // 清空输入框的校验状态
  43. this.$refs["ruleForm"].resetFields();
  44. // 弹出通知框提示登录失败信息
  45. this.notifyError(res.data.msg);
  46. }
  47. })
  48. .catch(err => {
  49. console.log(err)
  50. return Promise.reject(err);
  51. });
  52. } else {//未通过用户校验
  53. return false;
  54. }
  55. });
  56. }

五、商品模型类

  1. from django.db import models
  2. # 商品类别表Category:类别名 cate_name
  3. class Category(models.Model):
  4. cate_name = models.CharField("类别名",max_length=50)
  5. class Meta:
  6. db_table = 'category'
  7. verbose_name_plural = '商品类别表'
  8. def __str__(self):
  9. return self.cate_name
  10. # 商品信息表Goods:商品名sku_name 价格price 售价selling_price 默认图片img 商品标题title 描述instruction 销量 count 库存stock cate类别**外键** 是否在销售online
  11. class Goods(models.Model):
  12. sku_name = models.CharField("商品名",max_length=100)
  13. price = models.DecimalField("价格",max_digits=9,decimal_places=2)
  14. selling_price = models.DecimalField("售价",max_digits=9,decimal_places=2)
  15. img = models.CharField("默认图片",max_length=200)
  16. title = models.CharField("商品标题",max_length=30,null=True)
  17. instruction = models.TextField("商品的描述信息")
  18. count = models.IntegerField("商品的销售数量",default=0)
  19. stock = models.IntegerField("商品的库存数量",default=0)
  20. cate = models.ForeignKey(Category,on_delete=models.CASCADE,verbose_name='商品类别')
  21. online = models.BooleanField("是否在售",default=True)
  22. class Meta:
  23. db_table = 'goods'
  24. verbose_name_plural = '商品信息'
  25. def __str__(self):
  26. return self.sku_name
  27. # 商品图片表GoodImg: 图片img 图片描述title good外键所属商品
  28. class Goodimg(models.Model):
  29. img = models.CharField(max_length=200,verbose_name='图片')
  30. title = models.CharField("图片描述",max_length=200,null=True)
  31. good = models.ForeignKey(to=Goods,on_delete=models.CASCADE,verbose_name='所属商品')
  32. class Meta:
  33. db_table = 'goodimg'
  34. verbose_name_plural = '商品图片'
  35. def __str__(self):
  36. return self.title
  37. # 轮播图Carousel: imgPath图片路径 describes图片描述
  38. class Carousel(models.Model):
  39. imgPath = models.CharField("轮播图路径",max_length=200)
  40. describes = models.CharField("图片描述",max_length=200,null=True)
  41. class Meta:
  42. db_table = 'carousel_t'
  43. verbose_name_plural = "轮播图"
  44. def __str__(self):
  45. return self.describes

六、获取首页轮播图商品

  1. class CarouselAPIVIew(APIView):
  2. def get(self,request):
  3. try:
  4. car_data = Carousel.objects.all()
  5. ser = CarouselSerializer(car_data,many=True)
  6. return Response({
  7. 'code':200,
  8. 'msg':'获取轮播图成功!',
  9. 'carousel':ser.data
  10. })
  11. except Exception as e:
  12. return Response({
  13. 'code': 200,
  14. 'msg': '获取轮播图失败',
  15. })
  1. created() {
  2. // 获取轮播图数据
  3. this.$axios
  4. .get("/goods/carousel/")
  5. .then(res => {
  6. console.log("@@carousel res:",res)
  7. /***
  8. *
  9. * return Response({
  10. * "code":"",
  11. * "msg":"",
  12. * "carousel":[{
  13. * ”imgPath“:”“,
  14. * ”describes“:”“,
  15. * },{...},{...},{...}])
  16. */
  17. this.carousel = res.data.carousel;
  18. })
  19. .catch(err => {
  20. return Promise.reject(err);
  21. });

七、根据类型获取商品和热门商品

  1. # 获取一类商品信息
  2. class OneCategory(APIView):
  3. # 获取一类商品信息
  4. def get(self,request):
  5. # 1.获取种类信息
  6. cate_name = request.query_params.get('categoryName')
  7. # 2.ORM操作,获取种类信息
  8. try:
  9. cate_data = Category.objects.get(cate_name=cate_name)
  10. except Exception as e:
  11. print(e)
  12. return Response({
  13. 'code':204,
  14. 'msg':'此商品不存在'
  15. })
  16. # 3.根据类别 获取 商品信息
  17. goods_data = cate_data.goods_set.all()
  18. # 4.序列化商品信息
  19. ser = GoodsSerializer(goods_data,many=True)
  20. return Response({
  21. 'msg':'成功获取商品信息',
  22. 'code':200,
  23. 'result':ser.data
  24. })
  25. # 热门商品
  26. class HotProduct(APIView):
  27. def get(self,request):
  28. # 获取种类信息,热门商品是一个列表
  29. cate_list = request.query_params.getlist('categoryName[]')
  30. # 根据类别名获取种类信息(orm数据)
  31. cate_data_list = []
  32. for i in cate_list:
  33. cate_data = Category.objects.get(cate_name=i)
  34. cate_data_list.append(cate_data)
  35. # 根据类别 获取 商品信息
  36. goods_date_list = []
  37. for i in cate_data_list:
  38. goods_date_list.append(i.goods_set.all())
  39. # 将商品信息合并
  40. from functools import reduce
  41. goods_data_queryset = reduce((lambda x,y:x|y),goods_date_list)
  42. # 序列化
  43. ser = GoodsSerializer(goods_data_queryset,many=True)
  44. return Response({
  45. 'msg':'获取热门商品成功',
  46. 'code':200,
  47. 'result':ser.data
  48. })
  1. getPromo(categoryName, val, api) {
  2. // 有API传入时,例子
  3. // categoryName:["电视机", "空调", "洗衣机"],
  4. // val:"applianceList",
  5. // api:"/goods/getHotProduct/"
  6. // 判断是否有api传进来
  7. api = api != undefined ? api : "/goods/oneCategory/all/";
  8. // if (api == undefined){
  9. // api = "/goods/oneCategory/all/"
  10. // }else{
  11. // api = api
  12. // }
  13. //
  14. this.$axios
  15. .get(api, {
  16. params: {categoryName:categoryName},
  17. })
  18. .then(res => {
  19. console.log("@@获取"+categoryName+"的响应", res)
  20. //获取属性,并赋值,如'phoneList'
  21. this[val] = res.data.result;
  22. })
  23. .catch(err => {
  24. return Promise.reject(err);
  25. });
  26. }
  27. }

八、点击商品获取商品信息

  1. # 获取一个商品的信息
  2. class oneGoodAPIView(APIView):
  3. def get(self,request):
  4. # 1.获取商品id
  5. good_id = request.query_params.get('productID')
  6. # 2.根据id查询数据
  7. try:
  8. good_data = Goods.objects.get(id=good_id)
  9. except Exception as e:
  10. return Response({'msg':'商品不存在','code':204})
  11. # 3.序列化数据
  12. ser = GoodsSerializer(good_data)
  13. return Response(ser.data)
  14. # 获取一个商品的轮播图
  15. class OneImg(APIView):
  16. def get(self,request):
  17. good_id = request.query_params.get('productID')
  18. try:
  19. good_data = Goods.objects.get(id=good_id)
  20. except Exception as e:
  21. return Response({
  22. 'msg':'图片不存在',
  23. 'code':204
  24. })
  25. img_data = good_data.goodimg_set.all()
  26. ser = GoodimgSerializer(img_data,many=True)
  27. return Response(ser.data)
  1. getDetails(val) {//val为商品id
  2. this.$axios
  3. .get("/goods/onegood/", {
  4. params:{productID: val}
  5. })
  6. .then(res => {
  7. console.log("@@一个商品:", res)
  8. this.productDetails = res.data;
  9. // 然后模板就可以解析数据了
  10. })
  11. .catch(err => {
  12. return Promise.reject(err);
  13. });
  14. },
  15. // 获取商品图片
  16. getDetailsPicture(val) {//通过商品id获取其图片
  17. this.$axios
  18. .get("/goods/onegood/imgs/", {
  19. params:{productID: val}
  20. })
  21. .then(res => {
  22. console.log("@详情页轮播图:",res)
  23. this.productPicture = res.data;
  24. })
  25. .catch(err => {
  26. return Promise.reject(err);
  27. });
  28. },

九、浏览历史记录

  1. # 添加历史记录
  2. class History(APIView):
  3. def post(self,request):
  4. # 1.判断用户是否登录
  5. try:
  6. user = User.objects.get(id=request.user_info.get('id'))
  7. except Exception as e:
  8. print(e)
  9. return Response({'msg': '用户不存在或未登录', 'code': 204})
  10. # 2.获取商品id
  11. good_id = request.data.get('productID')
  12. # 3.判断商品是否存在
  13. try:
  14. good_data = Goods.objects.get(id=good_id)
  15. except Exception as e:
  16. print(e)
  17. return Response({'msg':'商品不存在','code':204})
  18. # 4.添加历史记录
  19. history_key = "history_%s"%user.username
  20. r = redis.Redis(host='localhost',port=6379,password='password',db=0)
  21. r.lrem(history_key,0,good_id)
  22. r.lpush(history_key,good_id)
  23. r.ltrim(history_key,0,4)
  24. r.close()
  25. return Response({'msg':'历史记录添加成功','code':200})
  1. // 加入历史记录
  2. addHistory(productID){
  3. // 页面挂载完成,请求后端加入历史记录
  4. this.$axios.post('/goods/oneGood/history/', {
  5. productID: productID,
  6. },{
  7. headers:{
  8. token: localStorage.getItem('token')||'' // JWT token
  9. }})
  10. .then(res => {
  11. console.log("加入历史记录的响应:", res)
  12. })
  13. .catch(err => {
  14. return Promise.reject(err)
  15. })
  16. },

十、收藏商品

  1. # 收藏模型类
  2. class GoodsCollect(models.Model):
  3. user = models.ForeignKey(to=User,on_delete=models.CASCADE,verbose_name='用户')
  4. goods = models.ForeignKey(to=Goods,on_delete=models.CASCADE,verbose_name='商品')
  5. class Meta:
  6. db_table = 'goods_collect'
  7. verbose_name_plural = '商品收藏'
  8. def __str__(self):
  9. return '%S:%S' % (self.user.username,self.goods.sku_name)
  10. from .models import GoodsCollect
  11. # 收藏
  12. class Collection(APIView):
  13. # 添加收藏
  14. def post(self,request):
  15. # 1.判断用户是否登录
  16. try:
  17. user = User.objects.get(id=request.user_info.get('id'))
  18. except Exception as e:
  19. print(e)
  20. return Response({'msg': '用户不存在或未登录', 'code': 204})
  21. # 2.判断收藏是否存在
  22. good_id = request.data.get('productID')
  23. collect_data = GoodsCollect.objects.filter(user=user,goods_id=good_id)
  24. if collect_data.count()>0:
  25. return Response({'msg': '收藏已存在', 'code': 204})
  26. # 3.收藏不存在,添加收藏
  27. try:
  28. GoodsCollect.objects.create(
  29. user=user,
  30. goods_id=good_id
  31. )
  32. except Exception as e:
  33. print(e)
  34. return Response({'msg': '添加收藏失败', 'code': 204})
  35. return Response({'msg': '添加收藏成功', 'code': 200})
  36. # 查询收藏
  37. def get(self,request):
  38. # 1.判断用户是否登录
  39. try:
  40. user = User.objects.get(id=request.user_info.get('id'))
  41. except Exception as e:
  42. print(e)
  43. return Response({'msg': '用户不存在或未登录', 'code': 204})
  44. # 2.查询用户的收藏
  45. collec_data = GoodsCollect.objects.filter(user=user)
  46. if collec_data.count() == 0:
  47. return Response({'msg':'没有任何收藏','code':204})
  48. # 3.处理收藏的数据
  49. collec_list = []
  50. for i in collec_data:
  51. collec_list.append({
  52. "id": i.goods.id,
  53. "sku_name": i.goods.sku_name,
  54. "title": i.goods.title,
  55. "price": i.goods.price,
  56. "selling_price": i.goods.selling_price,
  57. "img": i.goods.img,
  58. })
  59. # 4.返回结果
  60. return Response({'code':200,'collectList':collec_list})
  61. # 删除收藏
  62. def delete(self,request):
  63. # 1.判断用户是否登录
  64. try:
  65. user = User.objects.get(id=request.user_info.get('id'))
  66. except Exception as e:
  67. print(e)
  68. return Response({'msg': '用户不存在或未登录', 'code': 204})
  69. # 2.根据商品id删除收藏
  70. good_id = request.data.get('productID')
  71. try:
  72. GoodsCollect.objects.get(user=user,goods_id=good_id).delete()
  73. except Exception as e:
  74. print(e)
  75. return Response({'msg':'删除收藏失败','code':204})
  76. return Response({'msg':'删除收藏成功','code':200})
  1. addCollect() {
  2. // 判断是否登录,没有登录则显示登录组件
  3. if (!this.$store.getters.getUser) {
  4. this.$store.dispatch("setShowLogin", true);
  5. return;
  6. }
  7. this.$axios
  8. // 修改接口为goods
  9. .post("/goods/user/collection/", {
  10. productID: this.productID
  11. },{headers:{token:localStorage.getItem("token") || ""}})
  12. .then(res => {
  13. console.log("@@添加收藏的响应:", res)
  14. if (res.data.code == 200) {
  15. // 添加收藏成功
  16. this.notifySucceed(res.data.msg);
  17. } else {
  18. // 添加收藏失败
  19. this.notifyError(res.data.msg);
  20. }
  21. })
  22. .catch(err => {
  23. return Promise.reject(err);
  24. });
  25. }
  26. }
  27. };

十一、加入购物车

  1. # 购物车
  2. class UserCart(APIView):
  3. def post(self,reqeust):
  4. # 1.判断用户是否登录
  5. try:
  6. user = User.objects.get(id=reqeust.user_info.get('id'))
  7. except Exception as e:
  8. print(e)
  9. return Response({'msg': '用户不存在或未登录', 'code': 204})
  10. # 2.获取商品信息
  11. good_id = reqeust.data.get('productID')
  12. good_data = Goods.objects.get(id=good_id)
  13. # 拼接购物车的键
  14. cart_key = "cart_%s"%user.username
  15. # 添加购物车的商品自动勾选上
  16. cart_selected_key = "cart_selected_%s"%user.username
  17. # 3.判断库存
  18. if good_data.stock<=0:
  19. return Response({'msg':'库存不足,无法购买','code':203})
  20. # 4.判断购物车是否存在该商品
  21. r = redis.Redis(host='localhost',port=6379,db=0,password='password')
  22. # 获取商品在购物车中的数量
  23. num = r.hget(cart_key,good_id)
  24. if num: # 购物车已存在商品
  25. num = int(num.decode()) + 1
  26. if num > good_data.stock:
  27. return Response({'code':202,'msg':'加购达到限购数量'})
  28. r.hset(cart_key,good_id,str(num)) # 购物车数量+1
  29. r.sadd(cart_selected_key,good_id) # 选中商品
  30. return Response({'code': 201, 'msg': '该商品已存在购物车,数量+1'})
  31. else: # 购物车不存在该商品
  32. r.hset(cart_key,good_id,1) # 添加商品到购物车
  33. r.sadd(cart_selected_key, good_id) # 选中商品
  34. r.close()
  35. return Response({
  36. 'msg':'加入购物车成功',
  37. 'code':200,
  38. 'shoppingCartData':{
  39. 'id':cart_key, # 购物车名字
  40. 'productID':good_id, # 商品id
  41. 'productName':good_data.sku_name, # 商品名
  42. 'productImg':good_data.img,
  43. 'price':good_data.price,
  44. 'num':1,
  45. 'maxNum':good_data.stock,
  46. 'check':True
  47. }
  48. })
  49. def get(self,reqeust):
  50. # 1.判断用户是否登录
  51. try:
  52. user = User.objects.get(id=reqeust.user_info.get('id'))
  53. except Exception as e:
  54. print(e)
  55. return Response({'msg': '用户不存在或未登录', 'code': 204})
  56. # 拼接redis数据库中的键
  57. cart_key = "cart_%s" % user.username
  58. # 添加购物车的商品自动勾选上
  59. cart_selected_key = "cart_selected_%s" % user.username
  60. # 2.获取数据
  61. r = redis.Redis(host='localhost',port=6379,password='password',db=0)
  62. cart_list = r.hgetall(cart_key) # 读取购物车中的数据
  63. select_list = r.smembers(cart_selected_key) # 读取选中的商品
  64. select_list_2 = [i.decode() for i in select_list] # 解码
  65. result_data = []
  66. # key 商品id value 商品数量
  67. for key,value in cart_list.items():
  68. good_id = key.decode()
  69. good_data = Goods.objects.get(id=good_id)
  70. result_data.append({
  71. 'id':cart_key,
  72. 'productId':good_data.id,
  73. 'productName':good_data.sku_name,
  74. 'productImg':good_data.img,
  75. 'price':good_data.price,
  76. 'num':value.decode(),
  77. 'maxNum':good_data.stock,
  78. # 如果商品id在 select_list_2里,就是选中的
  79. 'check':good_id in select_list_2,
  80. })
  81. return Response({
  82. 'msg':'查询购物车成功',
  83. 'code':200,
  84. 'shoppingCartData':result_data,
  85. })
  1. this.$axios
  2. // 接口cart要改成goods
  3. .post("/goods/user/cart/", {
  4. productID: this.productID
  5. }, {headers:{token:localStorage.getItem("token")||""}})
  6. .then(res => {
  7. console.log("@@添加购物车res:", res)
  8. //
  9. // 处理购物车的响应
  10. switch (res.data.code) {
  11. case 200:
  12. // 新加入购物车成功
  13. this.unshiftShoppingCart(res.data.shoppingCartData);
  14. this.notifySucceed(res.data.msg);
  15. break;
  16. case 201:
  17. // 该商品已经在购物车,数量+1
  18. this.addShoppingCartNum(this.productID);
  19. this.notifySucceed(res.data.msg);
  20. break;
  21. case 202:
  22. // 商品数量达到限购数量(即库存量)
  23. this.dis = true; //购物车按钮不可点击
  24. this.notifyError(res.data.msg);
  25. break;
  26. case 203:
  27. default:
  28. this.notifyError(res.data.msg);
  29. }
  30. })
  31. .catch(err => {
  32. return Promise.reject(err);
  33. });
  34. },

十二、购物车中全选与数量加减

  1. def put(self,request):
  2. try:
  3. user_info = request.user_info
  4. user = User.objects.get(id=user_info.get('id'))
  5. except Exception as e:
  6. print(e)
  7. return Response({'msg':'用户不存在或未登录!','code':404})
  8. # 2.获取商品id和商品数量
  9. good_id =request.data.get('productID')
  10. num = request.data.get('num')
  11. cart_key = 'cart_%s'%user.username
  12. r = redis.Redis(host='localhost',port=6379,db=0,password='password')
  13. r.hset(cart_key,good_id,num)
  14. r.close()
  15. return Response({'code':200,'msg':'数量修改成功'})
  1. class GoodsSelect(APIView):
  2. def put(self,request):
  3. try:
  4. user_info = request.user_info
  5. user = User.objects.get(id=user_info.get('id'))
  6. except Exception as e:
  7. print(e)
  8. return Response({'msg':'用户不存在或未登录!','code':204})
  9. # 2.获取商品id和商品数量
  10. good_id =request.data.get('productID')
  11. select_flag = request.data.get('val')
  12. cart_selected_key = 'cart_selected_%s' %user.username
  13. # 3.修改redis数据库中的数据
  14. r = redis.Redis(host='localhost', port=6379, db=0,password='password')
  15. if select_flag:
  16. r.sadd(cart_selected_key,good_id)
  17. r.close()
  18. return Response({'code': 200, 'msg': '%s修改成功' % good_id})
  19. else:
  20. r.srem(cart_selected_key,good_id)
  21. r.close()
  22. return Response({'code': 200, 'msg': '%s取消修改成功' % good_id})
  23. def post(self, request):
  24. # 1.判断用户是否登录
  25. try:
  26. user_info = request.user_info
  27. user = User.objects.get(id=user_info.get("id"))
  28. except Exception as e:
  29. print(e)
  30. return Response({
  31. "code": 204,
  32. "msg": '用户不存在或未登录'
  33. })
  34. # 2.获取全选的状态
  35. all_flag = request.data.get("val")
  36. cart_key = "cart_%s" % user.username
  37. cart_selected_key = "cart_selected_key_%s" % user.username
  38. # 3.修改选中状态
  39. r = redis.Redis(host="localhost", port=6379,db=0,password='password')
  40. if all_flag: # 全选
  41. # 获取购物车中的商品id
  42. good_id_list = r.hkeys(cart_key)
  43. # 添加选中的商品
  44. for i in good_id_list:
  45. r.sadd(cart_selected_key, i.decode())
  46. r.close()
  47. return Response({
  48. "code": 200,
  49. "msg": '全选成功'
  50. })
  51. else: # 取消全选
  52. # 删掉全选中的商品
  53. r.delete(cart_selected_key)
  54. r.close()
  55. return Response({
  56. "code": 200,
  57. "msg": '取消全选成功'
  58. })
  1. this.$axios
  2. // cart改成goods
  3. .put("/goods/user/cart/", {
  4. productID: productID,
  5. num: currentValue,//更新过后的值
  6. }, {headers: {'token': localStorage.getItem("token") || ""}})
  7. .then(res => {
  8. console.log("@@更新购物车的后端响应:", res)
  9. switch (res.data.code) {
  10. case 200:
  11. // 200代表更新成功
  12. // 更新vuex状态
  13. this.updateShoppingCart({
  14. key: key,
  15. prop: "num",
  16. val: currentValue
  17. });
  18. // 提示更新成功信息
  19. this.notifySucceed(res.data.msg);
  20. break;
  21. default:
  22. // 提示更新失败信息
  23. this.notifyError(res.data.msg);
  24. }
  25. })
  26. .catch(err => {
  27. return Promise.reject(err);
  28. });
  29. },
  30. // 单选
  31. checkChange(val, key, cartID) {
  32. console.log("单选的勾选状态:", val, key, cartID)
  33. const productID = this.getShoppingCart[key].productID
  34. // carts 改goods
  35. this.$axios.put("/goods/user/selection/", {
  36. productID,
  37. val,
  38. }, {headers: {token: localStorage.getItem("token") || ""}})
  39. .then(res => {
  40. if (res.data.code == 200) {
  41. // 更新前端vuex中购物车商品勾选状态
  42. this.updateShoppingCart({key: key, prop: "check", val: val});
  43. this.notifySucceed(res.data.msg)
  44. } else {
  45. this.notifyError(res.data.msg)
  46. }
  47. })
  48. .catch(err => {
  49. return Promise.reject(err)
  50. })
  51. },

十三、实现获取用户信息、修改,添加,删除,地址

  1. class UserCenter(APIView):
  2. # 用户信息更新
  3. def put(self,request):
  4. # 1.判断用户是否登录
  5. try:
  6. user_info = request.user_info
  7. user = User.objects.get(id=user_info.get('id'))
  8. except Exception as e:
  9. return Response({'code': 204, 'msg': '用户不存在或未登录!'})
  10. # 2.获取前端提交的数据
  11. phone = request.data.get('phone')
  12. addrs_list = request.data.get('addrs')
  13. # 3.修改用户的手机号
  14. if not re.findall(r'^1[3-9]\d{9}$',phone):
  15. return Response({'code':204,'msg':'手机号不正确'})
  16. user.mobile = phone
  17. user.save()
  18. # 4.修改地址 循环 一个一个去改
  19. for i in addrs_list:
  20. Addr.objects.filter(id=i.get('id')).update(
  21. receiver =i.get('receiver'),
  22. receive_mobile = i.get('receive_mobile'),
  23. receive_addr = i.get('receive_addr'),
  24. is_default = i.get("is_default")
  25. )
  26. return Response({'msg':'修改信息成功','code':200})
  27. # 获取用户信息
  28. def get(self,request):
  29. # 1.判断用户是否登录
  30. try:
  31. user_info = request.user_info
  32. user = User.objects.get(id=user_info.get('id'))
  33. except Exception as e:
  34. return Response({'code':204,'msg':'用户不存在或未登录!'})
  35. # 2.返回前端需要的数据
  36. # addrs_list = []
  37. # 查询用户的地址信息
  38. addrs_data = user.addr_set.all()
  39. ser = Addrser(addrs_data,many=True)
  40. # for i in addrs_data:
  41. # addrs_list.append({
  42. # 'id':i.id,
  43. # 'receiver':i.receiver,
  44. # 'receive_mobile':i.receive_mobile,
  45. # 'receive_addr':i.receive_addr,
  46. # 'is_default':i.is_default
  47. # })
  48. return Response({
  49. 'code':200,
  50. 'msg':'获取用户信息成功',
  51. 'userInfo':{
  52. 'username':user.username,
  53. 'phone':user.mobile,
  54. 'addrs':ser.data
  55. }
  56. })
  1. # 添加用户收货地址
  2. class UserAddr(APIView):
  3. def post(self,request):
  4. # 1.判断用户是否登录
  5. try:
  6. user_info = request.user_info
  7. user = User.objects.get(id=user_info.get('id'))
  8. except Exception as e:
  9. return Response({'code':204,'msg':'用户不存在或未登录!'})
  10. # 2.获取前端提交的数据
  11. receiver = request.data.get('receiver')
  12. receive_mobile = request.data.get('receive_mobile')
  13. receive_addr = request.data.get('receive_addr')
  14. is_default = request.data.get('is_default')
  15. # 3.判断数据是否齐全,手机号是否符合要求
  16. if not all([receive_addr,receive_mobile,receiver]):
  17. return Response({'msg':'信息不全','code':200})
  18. if not re.findall(r'^1[3-9]\d{9}$',receive_mobile):
  19. return Response({'msg':'手机不正确','code':204})
  20. # 4.默认收货地址处理:只能有一个
  21. if is_default:
  22. # 查看该用户是否有默认地址
  23. default_addr = Addr.objects.filter(user=user,is_default=True)
  24. default_addr.update(is_default=False)
  25. # 5.添加新地址
  26. new_addr = Addr.objects.create(
  27. receiver=receiver,
  28. receive_mobile=receive_mobile,
  29. receive_addr=receive_addr,
  30. is_default=is_default,
  31. user=user
  32. )
  33. ser = Addrser(new_addr)
  34. return Response({'msg':'地址添加成功','code':200,'addr':ser.data})
  35. # 删除地址
  36. def delete(self,request):
  37. # 1.判断用户是否登录
  38. try:
  39. user_info = request.user_info
  40. user = User.objects.get(id=user_info.get('id'))
  41. except Exception as e:
  42. return Response({'code':204,'msg':'用户不存在或未登录!'})
  43. addr_id = request.data.get('addr_id')
  44. Addr.objects.filter(id=addr_id).delete()
  45. return Response({'msg':'删除成功','code':200})
  1. activated() {
  2. // 未登录时,弹出登录组件
  3. if (!this.$store.getters.getUser.userName) {
  4. this.$store.dispatch("setShowLogin", true);
  5. }
  6. // 已登录,发送ajax请求,获取用户信息
  7. this.$axios
  8. .get("/users/user/", {
  9. headers: {token: localStorage.getItem('token') || ""}
  10. })
  11. .then((res) => {
  12. console.log("@@获取用户的信息:", res);
  13. if (res.data.code == 200) {
  14. this.userInfo = res.data.userInfo;
  15. } else {
  16. this.notifyError(res.data.msg);
  17. }
  18. })
  19. .catch((err) => {
  20. return Promise.reject(err);
  21. });
  22. },
  23. methods: {
  24. // 修改个人信息
  25. updateUserInfo() {
  26. console.log("修改个人信息...");
  27. this.$axios.put("/users/user/", {
  28. phone: this.userInfo.phone,
  29. addrs: this.userInfo.addrs,
  30. }, {
  31. headers: {
  32. token: localStorage.getItem("token") || ""
  33. }
  34. }).then(res => {
  35. if (res.data.code == 200) {
  36. this.notifySucceed(res.data.msg)
  37. } else {
  38. this.notifyError(res.data.msg)
  39. }
  40. })
  41. },
  42. // 添加地址
  43. addAddr() {
  44. console.log("增加地址...");
  45. this.$axios
  46. .post("/users/user/addr/", {
  47. receiver: this.receiver,
  48. receive_mobile: this.receive_mobile,
  49. receive_addr: this.receive_addr, //字符串地址
  50. is_default: this.is_default, //是否默认地址}
  51. }, {
  52. headers: {
  53. token: localStorage.getItem("token") || ""
  54. }
  55. })
  56. .then((res) => {
  57. console.log("添加地址的响应:", res);
  58. if (res.data.code == 200) {
  59. this.userInfo.addrs.push(res.data.addr);
  60. this.receiver = ""
  61. this.receive_mobile = ""
  62. this.receive_addr = ""
  63. this.notifySucceed(res.data.msg);
  64. } else {
  65. this.notifyError(res.data.msg);
  66. }
  67. })
  68. .catch((err) => {
  69. return Promise.reject(err);
  70. });
  71. deleteAddr(e, addr_id) {
  72. // 删除该地址
  73. this.$axios.delete("/users/user/addr/", {
  74. data: {addr_id: addr_id},
  75. headers: { // 补上header
  76. token: localStorage.getItem("token") || ""
  77. },
  78. }).then(res => {
  79. if (res.data.code == 200) {
  80. // 删除User组件中的对应地址
  81. for (let i = 0; i < this.userInfo.addrs.length; i++) {
  82. let temp = this.userInfo.addrs[i]
  83. if (temp.id == addr_id) {
  84. this.userInfo.addrs.splice(i, 1)
  85. }
  86. }
  87. this.notifySucceed(res.data.msg)
  88. } else {
  89. // this.notifyError
  90. this.notifyError(res.data.msg) // 补上
  91. }
  92. })
  93. },

 十四、修改密码

  1. # 修改密码
  2. class UpadatePass(APIView):
  3. def put(self,request):
  4. # 1.判断用户是否登录
  5. try:
  6. user_info = request.user_info
  7. user = User.objects.get(id=user_info.get('id'))
  8. except Exception as e:
  9. return Response({'code':204,'msg':'用户不存在或未登录!'})
  10. # 2.获取前端提交的数据
  11. originPw = request.data.get('originPw')
  12. newPw = request.data.get('newPw')
  13. confirmNewPw = request.data.get('confirmNewPw')
  14. # 3.判断原始密码是否正确
  15. if not user.check_password(originPw):
  16. return Response({'msg':'密码错误','code':204})
  17. # 4.判断新密码和原密码是否一样
  18. if originPw == newPw:
  19. return Response({'msg': '密码没有修改', 'code': 204})
  20. # 5.新密码两次密码不一致
  21. if newPw != confirmNewPw:
  22. return Response({'msg': '两次密码不一致', 'code': 204})
  23. # 6.保存新密码
  24. user.set_password(newPw)
  25. user.save()
  26. return Response({'msg': '修改密码成功', 'code': 200})
  1. // 更改个人密码
  2. updatePassword() {
  3. console.log("修改个人密码...");
  4. this.$store.dispatch("setUpdatePw", true);
  5. },
  6. // 点击修改密码触发
  7. updatePassword() {
  8. // 通过element自定义表单校验规则,校验用户输入的用户信息
  9. this.$refs["ruleForm"].validate((valid) => {
  10. //如果通过校验开始请求后端
  11. if (valid) {
  12. // 发送ajax
  13. // this.$axios
  14. console.log("开始发送请求,修改密码...")
  15. axios
  16. .put("/users/user/password/", {
  17. originPw: this.LoginUser.originPw,
  18. newPw: this.LoginUser.newPw,
  19. confirmNewPw: this.LoginUser.confirmNewPw,
  20. // withCredentials: true,
  21. }, { // 补上header
  22. headers: {
  23. token: localStorage.getItem("token") || ""
  24. },
  25. })
  26. .then((res) => {
  27. console.log("@@res", res);
  28. // 200代表登录成功,其他的均为失败
  29. if (res.data.code == 200) {
  30. // res.data为后端响应的json
  31. // 隐藏修改密码组件
  32. this.isUpdatePw = false;
  33. // 重新登录
  34. // this.setUser("");
  35. // 弹出通知框提示登录成功信息
  36. this.notifySucceed(res.data.msg);
  37. } else {
  38. //响应不是200
  39. // 清空输入框的校验状态
  40. this.$refs["ruleForm"].resetFields();
  41. // 弹出通知框提示登录失败信息
  42. this.notifyError(res.data.msg);
  43. }
  44. })
  45. .catch((err) => {
  46. console.log(err);
  47. return Promise.reject(err);
  48. });
  49. } else {
  50. //未通过用户校验
  51. return false;
  52. }
  53. });
  54. },

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/723097
推荐阅读
相关标签
  

闽ICP备14008679号