Python二手商城交易系统

部署运行你感兴趣的模型镜像

1:项目简介

这是一个采用Python语言与Django框架开发的Full-Stack(全栈)Web项目,模拟实现了核心的二手商品在线交易流程。

1.1: 项目核心功能模块

1. 商品系统

  • 商品浏览:展示商品的图片、售价、种类、简介、库存等详细信息。

  • 商品搜索:支持按商品关键词及种类进行检索。

  • 商品评论:用户购买商品后,方可对商品进行评价。

2. 用户系统

  • 登录注册:支持用户注册与登录。

  • 密码重置:通过注册邮箱接收验证码,安全重置密码。

  • 使用协议:必须签署协议后方可使用平台。

  • 用户中心:集成化管理个人信息,包括:

    • 个人信息修改、实名认证。

    • 收货地址管理。

    • 发布商品、管理已发布商品。

    • 购物车管理。

    • 订单生成与查看。

3. 交易与互动

  • 商品下单:完整的下单流程,采用原子事务处理,确保下单过程的数据一致性,异常时自动终止。

  • 消息中心:支持用户与商家之间的实时信息交流。

  • 卖家中心:在商品详情页可通过“联系卖家”入口与卖家沟通。

4. 后台管理

  • 提供完整的后台管理功能,支持对商品种类、商品信息、用户数据及其他平台信息进行增、删、改、查操作。

1.2: 技术栈

  • 后端:Python, Django

  • 数据库:MySQL

  • 前端:Web前端技术 (HTML/CSS/JavaScript)

2:项目核心代码

2.1: 数据库设计

2.1.1 用户数据表 (UserInfo)

功能:存储平台所有用户的核心信息

  • 基础信息:用户名、密码、邮箱、性别、年龄、个人简介、头像

  • 实名认证:真实姓名、证件类型、证件号码、证件图片、认证审批状态

  • 收货信息:收货人姓名、地址、邮编、手机号

  • 账户控制:允许登录状态、唯一性约束(用户名、邮箱)

2.1.2 浏览记录表 (GoodsBrowser)

功能:记录用户的商品浏览行为

  • 关联关系:用户ID ↔ 商品ID

  • 时间记录:浏览时间,用于分析用户兴趣偏好

2.1.3 消息信息表 (Information)

功能:管理用户与卖家之间的沟通记录

  • 消息内容:使用HTMLField支持富文本消息

  • 状态管理:消息已读/未读状态、逻辑删除标志

  • 参与者:买家昵称、卖家昵称、关联用户外键

  • 时间戳:消息发表时间

2.1.4 退货信息表 (tuihuoInfo)

功能:处理商品退货退款流程

  • 订单信息:商品名称、订单号、快递信息

  • 用户信息:收件人、寄件人、身份证号码

  • 退货详情:收货/发货地址、退货理由

  • 审批流程:同意退款状态、逻辑删除、时间记录

技术特点

  • 数据完整性:通过外键关联确保数据一致性

  • 软删除支持:使用isDelete字段实现逻辑删除

  • 富文本支持:使用HTMLField处理复杂文本内容

  • 时间管理:自动记录各类操作的时间戳

  • 状态控制:多状态字段(认证、登录、消息、退款)支持业务流程

这套模型设计完整覆盖了用户管理、商品交互、消息通讯和售后服务的核心业务场景。

详细数据表代码如下:

from datetime import datetime

from django.db import models
from tinymce.models import HTMLField

from df_goods.models import GoodsInfo


# 01用户信息表
class UserInfo(models.Model):
    uname = models.CharField(max_length=20, verbose_name="用户名", unique=True)
    usex = models.CharField(max_length=10, verbose_name="性别", default="")
    uage = models.CharField(max_length=10, verbose_name="年龄", default="")
    upersonInf = models.CharField(max_length=200, verbose_name="个人简介", default="")
    ulogo = models.FileField(verbose_name="用户头像", upload_to='images', default='default.jpg')
    upwd = models.CharField(max_length=40, verbose_name="用户密码", blank=False)
    uemail = models.EmailField(verbose_name="邮箱", unique=True)
    urealname = models.CharField(max_length=20, default="", verbose_name="真实姓名")
    uzhengjian_type = models.CharField(max_length=20, default="", verbose_name="证件类型")
    uzhengjian_tel = models.CharField(max_length=18, default="", verbose_name="证件号码")
    uzhengjian_img = models.FileField(upload_to='images/zhengjian_img', default="", verbose_name="证件图片")
    ucheck_passOrfail = models.BooleanField(verbose_name="认证审批", default=False)
    ushou = models.CharField(max_length=20, default="", verbose_name="收货名称")
    uaddress = models.CharField(max_length=100, default="", verbose_name="地址")
    uyoubian = models.CharField(max_length=6, default="", verbose_name="邮编")
    uphone = models.CharField(max_length=11, default="", verbose_name="手机号")
    uname_passOrfail = models.BooleanField(verbose_name="允许登录", default=True)

    class Meta:
        verbose_name = "用户信息表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.uname


# 02浏览记录表
class GoodsBrowser(models.Model):
    user = models.ForeignKey(UserInfo, on_delete=models.CASCADE, verbose_name="用户ID")
    good = models.ForeignKey(GoodsInfo, on_delete=models.CASCADE, verbose_name="商品ID")
    browser_time = models.DateTimeField(default=datetime.now, verbose_name="浏览时间")

    class Meta:
        verbose_name = "用户浏览记录"
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{0}浏览记录{1}".format(self.user.uname, self.good.gtitle)


# 03联系卖家消息信息表
class Information(models.Model):
    isDelete = models.BooleanField(default=False)  # 逻辑删除
    ctitle = models.CharField(max_length=20, verbose_name="商品名称")
    cusername = models.CharField(max_length=20, verbose_name="买家昵称")
    cusername1 = models.CharField(max_length=20, verbose_name="卖家昵称")
    ccontent_chart = HTMLField(max_length=200, verbose_name="消息内容")
    ccheck = models.BooleanField(verbose_name="消息是否已读", default=False)
    date_publish = models.DateTimeField(verbose_name="发表时间", default=datetime.now)
    cinformation = models.ForeignKey(UserInfo, on_delete=models.CASCADE, verbose_name="消息")  # 外键关联GoodsContent表

    class Meta:
        verbose_name = "用户消息表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.cusername1


# 04退货信息表
class tuihuoInfo(models.Model):
    isDelete = models.BooleanField(default=False)  # 逻辑删除
    title = models.CharField(max_length=20, verbose_name="商品名称")
    username = models.CharField(max_length=20, verbose_name="收件人姓名")
    username1 = models.CharField(max_length=20, verbose_name="寄件人姓名")
    person_number = models.CharField(max_length=20, verbose_name="身份证号码")
    order_number = models.CharField(max_length=20, verbose_name="订单号")
    kuaidi = models.CharField(max_length=20, verbose_name="快递类型")
    kuaidi_number = models.CharField(max_length=20, verbose_name="快递单号")
    address = models.CharField(max_length=50, verbose_name="收货地址", default=None)
    address1 = models.CharField(max_length=50, verbose_name="发货地址", default=None)
    text = HTMLField(max_length=200, verbose_name="退货理由", default=None)
    passOrdefault = models.BooleanField(verbose_name="同意退款", default=False)
    date_publish = models.DateTimeField(verbose_name="发表时间", default=datetime.now)

    class Meta:
        verbose_name = "退款订单信息表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

# python manage.py makemigrations
# python manage.py migrate

2.1.2  商品数据表

🗂️ 1. 商品分类信息表 (TypeInfo)

功能描述:管理商品的分类体系

字段结构

字段名数据类型说明
ttitleCharField分类名称
isDeleteBooleanField逻辑删除标志

🛍️ 2. 商品信息表 (GoodsInfo)

功能描述:存储平台所有商品的核心信息

字段类别字段名称数据类型说明
基础信息gtitleCharField商品名称(唯一)
gpicImageField商品图片
gpriceDecimalField商品价格(精确到分)
卖家信息gunitCharField卖家昵称
商品数据gclickIntegerField点击量
gkucunIntegerField库存数量
商品描述gjianjieCharField商品简介
gcontentHTMLField富文本商品详情
分类关联gtypeForeignKey商品分类外键
系统字段isDeleteBooleanField逻辑删除标志

💬 3. 用户评论信息表 (GoodsContent)

功能描述:管理用户对商品的评价信息

字段类型功能
ctitleCharField商品名称
cpicImageField评论上传图片
cusernameCharField买家昵称
clogoCharField买家头像
cuser_contentHTMLField富文本用户评论
date_publishDateTimeField评论发表时间
cgoodsnameForeignKey关联商品外键
isDeleteBooleanField逻辑删除标志

🔄 4. 评论回复信息表 (ContentChart)

功能描述:管理评论区的互动回复

交互字段说明

参与者字段说明
商品信息ctitle商品名称
评论者cusername评论者昵称
回复者cusername1回复者昵称
回复内容ccontent_chart富文本评论回复
时间信息date_publish回复时间
关联关系ccontent关联评论外键
数据安全isDelete逻辑删除标志

🔗 模型关联关系

TypeInfo (商品分类)
    ↓
GoodsInfo (商品信息) ← 外键关联
    ↓
GoodsContent (商品评论) ← 外键关联  
    ↓
ContentChart (评论回复) ← 外键关联

✨ 核心特性

🎯 商品管理

  • 完整的商品信息架构:从分类→商品→评论→回复的完整数据链路

  • 富文本详情支持:商品详情使用HTMLField,支持图文混排

  • 图片管理:商品图片和评论图片分开存储,按年月分类

💰 交易支持

  • 精确价格计算:DecimalField确保价格计算准确

  • 库存实时监控:库存字段支持库存管理

  • 热度追踪:点击量字段记录商品受欢迎程度

👥 用户互动

  • 多层评论体系:支持评论和回复的两级互动

  • 富文本互动:评论和回复均支持富文本格式

  • 时间线管理:完整的时间戳记录互动过程

🛡️ 数据安全

  • 统一的逻辑删除:所有表均支持软删除

  • 外键约束:确保数据关联的完整性

  • 唯一性约束:商品名称唯一,避免重复


📈 业务价值

  1. 完整的电商数据模型:覆盖商品展示、用户互动、内容管理全流程

  2. 灵活的富文本支持:满足商品详情和用户互动的多样化内容需求

  3. 可扩展的架构设计:通过外键关联支持系统的持续扩展

  4. 安全的数据管理:逻辑删除机制保障重要数据不丢失

这套商品模块设计为二手交易平台提供了专业级的商品管理和用户互动解决方案。

from datetime import datetime

from django.db import models
from tinymce.models import HTMLField  # 使用富文本编辑框要在settings文件中安装


# 商品分类信息
class TypeInfo(models.Model):
    isDelete = models.BooleanField(default=False)
    ttitle = models.CharField(max_length=20, verbose_name="分类")

    class Meta:
        verbose_name = "商品类型表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.ttitle


# 商品信息表
class GoodsInfo(models.Model):
    isDelete = models.BooleanField(default=False)
    gtitle = models.CharField(max_length=128, verbose_name="商品名称", unique=True)
    gpic = models.ImageField(verbose_name='商品图片', upload_to='df_goods/image/%Y/%m', null=True, blank=True)  # 商品图片
    gprice = models.DecimalField(max_digits=7, decimal_places=2, verbose_name="商品价格")  # 商品价格小数位为两位,整数位为3位
    gunit = models.CharField(max_length=20, verbose_name="卖家昵称")
    gclick = models.IntegerField(verbose_name="点击量", default=0, null=False)
    gjianjie = models.CharField(max_length=200, verbose_name="简介")
    gkucun = models.IntegerField(verbose_name="库存", default=0)
    gcontent = HTMLField(max_length=100000, verbose_name="详情")
    gtype = models.ForeignKey(TypeInfo, on_delete=models.CASCADE, verbose_name="分类")  # 外键关联TypeInfo表

    class Meta:
        verbose_name = "商品信息表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.gtitle


# 用户评论信息表
class GoodsContent(models.Model):
    isDelete = models.BooleanField(default=False)
    ctitle = models.CharField(max_length=20, verbose_name="商品名称")
    cpic = models.ImageField(verbose_name='上传图片', upload_to='df_goods/image/%Y/%m', null=True, blank=True)  # 商品图片
    cusername = models.CharField(max_length=20, verbose_name="买家昵称")
    clogo = models.CharField(verbose_name='买家头像', max_length=200, default=None)
    cuser_content = HTMLField(max_length=200, verbose_name="用户评论")
    date_publish = models.DateTimeField(verbose_name="发表时间", default=datetime.now)
    cgoodsname = models.ForeignKey(GoodsInfo, on_delete=models.CASCADE, verbose_name="外键商品")  # 外键关联GoodsInfo表

    class Meta:
        verbose_name = "商品评论"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.ctitle


# 评论回复信息表
class ContentChart(models.Model):
    isDelete = models.BooleanField(default=False)
    ctitle = models.CharField(max_length=20, verbose_name="商品名称")
    cusername = models.CharField(max_length=20, verbose_name="评论者昵称")
    cusername1 = models.CharField(max_length=20, verbose_name="回复者昵称")
    ccontent_chart = HTMLField(max_length=200, verbose_name="评论回复")
    date_publish = models.DateTimeField(verbose_name="发表时间", default=datetime.now)
    ccontent = models.ForeignKey(GoodsContent, on_delete=models.CASCADE, verbose_name="评论id")  # 外键关联GoodsContent表

    class Meta:
        verbose_name = "评论回复"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.ctitle

2.1.3 购物车表

🛒 购物车信息表 (CartInfo)

📋 功能描述

管理用户的购物车数据,实现商品添加、数量管理和购物车状态跟踪


🏗️ 数据表结构

字段类别字段名称数据类型约束说明
用户关联userForeignKeyUserInfo用户外键 - 关联购物车所属用户
商品关联goodsForeignKeyGoodsInfo商品外键 - 关联购物车中的商品
数量管理countIntegerFielddefault=0商品数量 - 用户购买的商品单位数量

🔗 关联关系示意图

UserInfo (用户信息)
    ↓ 一对多关系
CartInfo (购物车)
    ↓ 一对多关系  
GoodsInfo (商品信息)

💡 核心功能特性

✅ 用户购物车隔离

  • 用户外键关联:确保每个用户的购物车数据独立

  • 数据归属清晰:通过外键明确购物车与用户的所属关系

✅ 商品数量管理

  • 数量计数器count字段准确记录每种商品的购买数量

  • 默认值保护:数量默认为0,避免空值异常

✅ 数据完整性保障

  • 级联删除:用户或商品删除时自动清理相关购物车记录

  • 外键约束:确保购物车中的用户和商品数据真实有效

from django.db import models

from df_user.models import UserInfo
from df_goods.models import GoodsInfo


# 购物车信息表
class CartInfo(models.Model):
    user = models.ForeignKey(UserInfo, on_delete=models.CASCADE, verbose_name="用户")
    goods = models.ForeignKey(GoodsInfo, on_delete=models.CASCADE, verbose_name="商品")
    count = models.IntegerField(verbose_name="", default=0)  # 记录用户买个多少单位的商品

    class Meta:
        verbose_name = "购物车信息表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.user.uname + '的购物车'

2.1.4 订单数据表

from django.db import models
from datetime import datetime

from df_goods.models import GoodsInfo
from df_user.models import UserInfo


# 订单状态信息表
class OrderInfo(models.Model):
    oid = models.CharField(max_length=20, primary_key=True, verbose_name="大订单号")
    user = models.ForeignKey(UserInfo, on_delete=models.CASCADE, verbose_name="订单用户")
    odate = models.DateTimeField(auto_now=True, verbose_name="时间")
    oIsPay = models.BooleanField(default=False, verbose_name="是否支付")
    ototal = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="总价")
    oaddress = models.CharField(max_length=150, verbose_name="订单地址")

    class Meta:
        verbose_name = "未付款订单"
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{0}在的订单{1}".format(self.user.uname, self.odate) 


# 订单详细信息表
class OrderDetailInfo(models.Model):
    goods = models.ForeignKey(GoodsInfo, on_delete=models.CASCADE, verbose_name="商品")
    username = models.CharField(max_length=20, verbose_name="买家昵称", default=None)
    shopername = models.CharField(max_length=20, verbose_name="卖家昵称", default="")
    datatime = models.DateTimeField(verbose_name="交易时间", default=datetime.now)
    order = models.ForeignKey(OrderInfo, on_delete=models.CASCADE, verbose_name="订单")
    price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="商品价格")
    count = models.IntegerField(verbose_name="商品数")

    class Meta:
        verbose_name = "付款订单"
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{0}(数量为{1})".format(self.goods.gtitle, self.count)

2.2: 核心后台业务逻辑代码

2.2.1 用户数据表业务逻辑代码

📋 功能概览

这个Django视图文件实现了完整的用户认证系统用户中心功能,涵盖用户注册、登录、密码管理、个人信息维护、商品交易和消息通讯等核心业务。


🔐 用户认证模块

1. 注册功能

  • register: 跳转注册页面

  • register_handle: 处理注册请求,密码SHA1加密

  • register_exist: AJAX验证用户名/邮箱是否存在

2. 登录功能

  • login: 显示登录页面,支持记住用户名

  • login_handle: 综合验证(密码、验证码、账户状态)

  • logout: 清空session,退出登录

3. 密码管理

  • random_str: 生成8位随机密码

  • findpwdView: 邮箱重置密码,发送新密码邮件


👤 用户中心模块

1. 个人信息管理

  • info: 用户中心首页,显示基本信息+浏览记录

  • site: 修改收货地址信息

  • changeInformation: 修改个人资料和头像

  • changeInPwd: 修改登录密码

2. 实名认证

  • check_user: 提交实名认证信息(姓名、证件类型、证件号、证件照)

3. 订单管理

  • order: 分页显示用户订单列表(每页2条)


🛍️ 商品交易模块

1. 商品发布

  • publishers: 发布新商品(需实名认证)

    • 验证商品信息完整性

    • 价格限制(≤9999元)

    • 自动关联当前用户为卖家

2. 卖家中心

  • shoper_information: 查看任意卖家信息和商品

  • myself_information: 查看自己作为卖家的信息

3. 退货处理

  • tuihuo: 提交退货申请,包含完整的退货信息


💬 消息通讯模块

1. 消息中心

  • message: 消息列表,按联系人分组显示

  • person_message: 与特定用户的对话页面

    • 消息状态标记为已读

    • 支持消息回复

2. 联系卖家

  • 在卖家中心页面直接发送消息


🛡️ 安全特性

1. 密码安全

# SHA1加密
s1 = sha1()
s1.update(password.encode('utf8'))
encrypted_pwd = s1.hexdigest()

2. 会话管理

  • Session控制request.session 存储用户状态

  • Cookie记忆: 记住用户名功能

  • 登录装饰器@user_decorator.login 保护敏感页面

3. 验证机制

  • 图形验证码验证

  • 邮箱验证(密码重置)

  • 实名认证验证(商品发布)


📧 邮件服务

密码重置邮件

  • 发件人bhml2023@163.com

  • 内容: 包含随机生成的新密码

  • 状态反馈: 操作结果消息提示


🎯 业务规则

1. 状态控制

  • 账户封禁uname_passOrfail 控制登录权限

  • 实名认证ucheck_passOrfail 控制商品发布权限

  • 消息已读ccheck 标记消息阅读状态

2. 数据验证

  • 表单字段非空验证

  • 价格范围验证(≤9999)

  • 密码一致性验证

  • 邮箱匹配验证

3. 用户体验

  • 消息提示messages.success() 反馈操作结果

  • 分页显示: 订单列表分页

  • 数据预加载: 购物车数量、浏览记录等


🔗 关联模型

视图函数关联数据模型
用户信息UserInfoGoodsBrowserCartInfo
订单相关OrderInfoOrderDetailInfotuihuoInfo
消息相关Information
商品相关GoodsInfoTypeInfo

💡 核心亮点

  1. 完整的用户生命周期管理:从注册→登录→认证→交易→售后

  2. 多层次的安全防护:密码加密、会话管理、权限验证

  3. 丰富的交互功能:消息系统、商品发布、退货流程

  4. 良好的用户体验:实时验证、状态反馈、数据记忆

  5. 模块化设计:功能清晰分离,便于维护扩展

这套用户系统为二手交易平台提供了稳定可靠的用户管理和交易支撑。

from hashlib import sha1
from random import Random

from django.contrib import messages
from django.core.mail import send_mail
from django.core.paginator import Paginator
from django.http import JsonResponse
from django.shortcuts import render, redirect, HttpResponseRedirect, reverse

from df_cart.models import CartInfo
from df_goods.models import TypeInfo
from df_order.models import *
from . import user_decorator
from .models import GoodsBrowser, Information, tuihuoInfo


# 跳转到注册页面
def register(request):
    context = {
        'title': '用户注册',
    }
    return render(request, 'df_user/register.html', context)


# 注册处理
def register_handle(request):
    username = request.POST.get('user_name')
    password = request.POST.get('pwd')
    confirm_pwd = request.POST.get('confirm_pwd')
    email = request.POST.get('email')

    # 判断两次密码一致性
    if password != confirm_pwd:
        return redirect('/user/register/')
    # 密码加密
    s1 = sha1()
    s1.update(password.encode('utf8'))
    # 作为十六进制数据字符串值加密
    encrypted_pwd = s1.hexdigest()

    # 创建对象
    UserInfo.objects.create(uname=username, upwd=encrypted_pwd, uemail=email)
    # 注册成功
    context = {
        'title': '用户登陆',
        'username': username,
    }
    return render(request, 'df_user/login.html', context)


# 注册时判断用户是否已经存在
def register_exist(request):
    username = request.GET.get('uname')
    uemail = request.GET.get('uemail')
    count = UserInfo.objects.filter(uname=username).count()
    email_count = UserInfo.objects.filter(uemail=uemail).count()
    return JsonResponse({'count': count, 'email_count': email_count})


# 登录界面显示
def login(request):
    uname = request.COOKIES.get('uname', '')
    context = {
        'title': '用户登陆',
        'error_name': 0,
        'error_pwd': 0,
        'error_vc': 0,
        'uname': uname,
    }
    return render(request, 'df_user/login.html', context)


# 验证码显示
def verify_show(request):
    return render(request, 'df_user/login.html')


# 登录处理
def login_handle(request):
    # 接受请求信息
    uname = request.POST.get('username')
    upwd = request.POST.get('pwd')
    jizhu = request.POST.get('jizhu', 0)  # 记住密码
    vc = request.POST.get('vc')  # 输入的验证码
    verifycode = request.session['verifycode']
    user = UserInfo.objects.filter(uname=uname)
    if len(user) == 1:  # 判断用户密码并跳转
        s1 = sha1()
        s1.update(upwd.encode('utf8'))
        # 验证通过
        if s1.hexdigest() == user[0].upwd and vc == verifycode and user[0].uname_passOrfail is True:
            url = request.COOKIES.get('url', '/')  # 跳转首页
            red = HttpResponseRedirect(url)  # 继承与HttpResponse 在跳转的同时 设置一个cookie值
            # 是否勾选记住用户名,设置cookie
            if jizhu != 0:
                red.set_cookie('uname', uname)
            else:
                red.set_cookie('uname', '', max_age=-1)  # 设置过期cookie时间,立刻过期
            request.session['user_id'] = user[0].id
            request.session['user_name'] = uname
            return red
        # 验证码输入错误
        elif s1.hexdigest() == user[0].upwd and vc != verifycode:
            context = {
                'title': '用户名登陆',
                'error_name': 0,
                'error_pwd': 0,
                'error_vc': 1,
                'uname': uname,
                'upwd': upwd,
                'user': user,
                'vc': vc,
            }
            return render(request, 'df_user/login.html', context)

        # 账号不允许登录
        elif user[0].uname_passOrfail is False:
            messages.success(request, "你的账号存在违规行为,已被封禁!")
            context = {
                'title': '用户名登陆',
                'uname': uname,
                'upwd': upwd,
                'user': user,
                'vc': vc,
            }
            return render(request, 'df_user/login.html', context)
        # 账号密码输入有误
        else:
            context = {
                'title': '用户名登陆',
                'error_name': 0,
                'error_pwd': 1,
                'error_vc': 1,
                'uname': uname,
                'upwd': upwd,
                'user': user,
                'vc': vc,
            }
            return render(request, 'df_user/login.html', context)
    # 不存在该账户
    else:
        context = {
            'title': '用户名登陆',
            'error_name': 1,
            'error_pwd': 0,
            'error_vc': 0,
            'uname': uname,
            'upwd': upwd,
            'user': user,
            'vc': vc,
        }
        return render(request, 'df_user/login.html', context)


# 退出登录
def logout(request):  # 用户登出
    request.session.flush()  # 清空当前用户所有session
    return redirect(reverse("df_goods:index"))


# 忘记密码时,发送邮件生成的随机密码
def random_str(randomlength=8):  # 8位数
    str = ''
    chars = 'abcdefghijklmnopqrstuvwsyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
    length = len(chars) - 1
    random = Random()
    # 随机生成验证码
    for i in range(randomlength):
        str += chars[random.randint(0, length)]
    return str


# 发送邮件重置密码
def findpwdView(request):
    context = {
        'title': '重置密码',
    }
    if request.method == "POST":
        username = request.POST.get("username")
        email = request.POST.get("email")
        user = UserInfo.objects.get(uname=username)
        context = {
            'title': '重置密码',
            'user': user,
        }
        # 邮箱号验证
        if user.uemail == email:
            email_title = "Django二手商城系统-重置密码"
            code = random_str()  # 随机生成的验证码
            request.session["MarketSystem"] = code  # 将验证码保存到session
            email_body = "Django二手商城系统提醒您:您的密码已重置,为了您的账号安全,请勿将密码泄露!您的新的密码为:{0}".format(code)
            # send_mail的参数分别是 邮件标题,邮件内容,发件箱(settings.py中设置过的那个),收件箱列表(可以发送给多个人),失败静默(若发送失败,报错提示我们)
            send_status = send_mail(email_title, email_body, 'bhml2023@163.com', [email], fail_silently=False)
            code = request.session["MarketSystem"]  # 获取传递过来的验证码
            # 密码加密后存入数据库
            s1 = sha1()
            s1.update(code.encode('utf8'))
            encrypted_pwd = s1.hexdigest()
            user.upwd = encrypted_pwd
            user.save()
            del request.session["MarketSystem"]  # 删除session
            messages.success(request, "密码已重置,请登录邮箱查看重置后的密码!")
        else:
            messages.success(request, "用户邮箱与输入邮件不匹配,重置密码失败!")

        return render(request, "df_user/change_password1.html", context)
    return render(request, "df_user/change_password1.html", context)


# 用户中心,需要登录验证
@user_decorator.login
def info(request):
    uid = request.session['user_id']
    user = UserInfo.objects.get(id=uid)
    browser_goods = GoodsBrowser.objects.filter(user=user).order_by("-browser_time")  # 浏览记录
    cart_num = CartInfo.objects.filter(user_id=int(uid)).count()  # 购物车数量
    goods_list = []
    if browser_goods:
        goods_list = [browser_good.good for browser_good in browser_goods]  # 从浏览商品记录中取出浏览商品
        explain = '最近浏览'
    else:
        explain = '无最近浏览'

    context = {
        'title': '用户中心',
        'page_name': 1,
        'guest_cart': 1,
        'cart_num': cart_num,
        'user_phone': user.uphone,
        'user_address': user.uaddress,
        'user_name': user.uname,
        'user': user,
        'ucheck_passOrfail': user.ucheck_passOrfail,
        'goods_list': goods_list,
        'explain': explain,
    }
    return render(request, 'df_user/user_center_info.html', context)


# 用户订单信息,需要登录验证
@user_decorator.login
def order(request, index):
    user_id = request.session['user_id']
    orders_list = OrderInfo.objects.filter(user_id=int(user_id)).order_by('-odate')  # 订单列表
    cart_num = CartInfo.objects.filter(user_id=int(user_id)).count()
    tuohuo_infos = tuihuoInfo.objects.filter()  # 退货信息
    paginator = Paginator(orders_list, 2)  # 分页显示
    page = paginator.page(int(index))
    user = UserInfo.objects.get(id=request.session['user_id'])
    context = {
        'paginator': paginator,
        'page': page,
        'title': "用户中心",
        'user': user,
        'page_name': 1,
        'guest_cart': 1,
        'cart_num': cart_num,
        'tuohuo_infos': tuohuo_infos,
    }
    return render(request, 'df_user/user_center_order.html', context)


# 用户信息修改
@user_decorator.login
def site(request):
    user = UserInfo.objects.get(id=request.session['user_id'])
    cart_num = CartInfo.objects.filter(user_id=user.id).count()
    if request.method == "POST":
        user.ushou = request.POST.get('ushou')
        user.uaddress = request.POST.get('uaddress')
        user.uyoubian = request.POST.get('uyoubian')
        user.uphone = request.POST.get('uphone')
        user.save()
    context = {
        'page_name': 1,
        'title': '用户中心',
        'user': user,
        'guest_cart': 1,
        'cart_num': cart_num,
    }
    return render(request, 'df_user/user_center_site.html', context)


# 发布商品,需要登录验证、实名验证
@user_decorator.login
def publishers(request):
    user = UserInfo.objects.get(id=request.session['user_id'])
    cart_num = CartInfo.objects.filter(user_id=user.id).count()
    typeinfos = TypeInfo.objects.all()
    # 实名认证验证
    if user.ucheck_passOrfail is False:
        messages.success(request, "请先进行实名认证!")
        context = {
            'page_name': 1,
            'title': '用户中心',
            'user': user,
            'typeinfos': typeinfos,
            'guest_cart': 1,
            'cart_num': cart_num,
        }
        return render(request, 'df_user/user_publishers.html', context)
    if request.method == "POST":
        gtitle = request.POST.get('title')  # 标题
        gpic = request.FILES.get('pic')  # 图片
        gunit = user.uname  # 卖家信息
        gprice = request.POST.get('price')  # 价格
        gjianjie = request.POST.get('jianjie')  # 商品简介
        gkucun = request.POST.get('kucun')  # 库存数量
        gcontent = request.POST.get('content')  # 商品内容介绍
        gtype_id = request.POST.get('type_id')  # 商品类型
        if gtitle == "" or gpic == "" or gprice == "" or gjianjie == "" or gkucun == "" or gcontent == "":
            messages.success(request, "请完整并正确填充信息!")
        elif float(gprice) >= 9999:
            messages.success(request, "价格不能大于9999元!")
        else:
            GoodsInfo.objects.create(gtitle=gtitle, gpic=gpic, gunit=gunit, gprice=gprice, gjianjie=gjianjie,
                                     gkucun=gkucun, gcontent=gcontent, gtype_id=gtype_id)
            messages.success(request, "发布商品成功")

    context = {
        'page_name': 1,
        'title': '用户中心',
        'user': user,
        'typeinfos': typeinfos,
        'guest_cart': 1,
        'cart_num': cart_num,
    }
    return render(request, 'df_user/user_publishers.html', context)


# 修改资料、头像,需要登录验证
@user_decorator.login
def changeInformation(request):
    uid = request.session['user_id']
    user = UserInfo.objects.get(id=uid)
    cart_num = CartInfo.objects.filter(user_id=user.id).count()
    context = {
        'page_name': 1,
        'title': '用户中心',
        'user': user,
        'guest_cart': 1,
        'cart_num': cart_num,
    }

    if request.method == "POST":
        logo = request.FILES.get('logo')
        if logo:
            user.ulogo = logo
        else:
            user.ulogo = user.ulogo
        user.usex = request.POST.get('sex')
        user.uage = request.POST.get('age')
        user.upersonInf = request.POST.get('personinf')
        user.save()
    return render(request, 'df_user/user_changeInformation.html', context)


# 修改密码,需要登录验证
@user_decorator.login
def changeInPwd(request):
    uid = request.session['user_id']
    user = UserInfo.objects.get(id=uid)
    cart_num = CartInfo.objects.filter(user_id=user.id).count()
    context = {
        'page_name': 1,
        'title': '用户中心',
        'user': user,
        'guest_cart': 1,
        'cart_num': cart_num,
    }

    if request.method == "POST":
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        if password == "" or password2 == "":
            messages.success(request, "请输入要修改的密码!")
        elif password == password2:
            # 密码加密
            s1 = sha1()
            s1.update(password.encode('utf8'))
            encrypted_pwd = s1.hexdigest()
            user.upwd = encrypted_pwd
            user.save()
            messages.success(request, "修改成功!")
        else:
            messages.success(request, "两次密码输入不正确!")
    return render(request, 'df_user/user_changePwd.html', context)


# 实名认证,需要登录验证
@user_decorator.login
def check_user(request):
    user = UserInfo.objects.get(id=request.session['user_id'])
    cart_num = CartInfo.objects.filter(user_id=user.id).count()
    if request.method == "POST":
        user.urealname = request.POST.get('name')  # 真实姓名
        user.uzhengjian_type = request.POST.get('type_id')  # 证件类型
        user.uzhengjian_tel = request.POST.get('tel')  # 证件号码
        user.uzhengjian_img = request.FILES.get('pic')  # 证件图片
        if user.urealname is None or user.uzhengjian_type is None or \
                user.uzhengjian_tel is None or user.uzhengjian_img is None:
            messages.success(request, "请填写完整的信息")
        else:
            user.save()
            messages.success(request, "提交成功,请等待管理员审批!")
    context = {
        'page_name': 1,
        'title': '用户中心',
        'user': user,
        'guest_cart': 1,
        'cart_num': cart_num,
    }
    return render(request, 'df_user/user_check_username.html', context)


# 卖家中心-查看卖家信息
def shoper_information(request, cname):
    shoper = UserInfo.objects.get(uname=cname)  # 卖家信息
    content_username = cname # 卖家信息
    # 列举卖家上架的商品
    goods = GoodsInfo.objects.filter(gunit=content_username)
    # 获取订单中的货物id,有多少该卖家的商品
    orderinfs = OrderDetailInfo.objects.filter(shopername=cname).order_by('-datatime')
    infors = GoodsInfo.objects.filter()
    # 创建Paginator一个分页对象
    # 发送信息
    if 'user_id' in request.session:
        uid = request.session['user_id']
        user = UserInfo.objects.get(id=uid)
        # 给卖家发消息
        if request.method == "POST":
            ctitle = request.POST.get('title')
            cusername = user.uname
            cusername1 = content_username
            ccontent_chart = request.POST.get('Message')
            cinformation_id = shoper.id
            if ctitle == "" or ccontent_chart == "":
                messages.success(request, "请把信息填完整,卖家能够够快回复你哦!")
            else:
                Information.objects.create(ctitle=ctitle, cusername=cusername, cusername1=cusername1,
                                           ccontent_chart=ccontent_chart, cinformation_id=cinformation_id)
                messages.success(request, "消息发送成功")
        context = {
            'goods': goods,
            'orderinfs': orderinfs,
            'name': content_username,
            'user': user,
            'shoper': shoper,
            'infos': infors,
        }
        return render(request, 'df_user/shoper_information.html', context)
    else:
        if request.method == "POST":
            return render(request, 'df_user/login.html')
    context = {
        'goods': goods,
        'orderinfs': orderinfs,
        'name': content_username,
        'shoper': shoper,
        'infos': infors,
    }
    return render(request, 'df_user/shoper_information.html', context)


# 卖家中心-查看自己作为卖家的卖家信息
def myself_information(request):
    if 'user_id' in request.session:
        uid = request.session['user_id']
        user = UserInfo.objects.get(id=uid)
        # 列举卖家上架的商品
        goods = GoodsInfo.objects.filter(gunit=user.uname)
        # 获取订单中的货物id,有多少该卖家的商品
        orderinfs = OrderDetailInfo.objects.filter(shopername=user.uname).order_by('-datatime')
        infors = GoodsInfo.objects.filter()

        context = {
            'goods': goods,
            'orderinfs': orderinfs,
            'user': user,
            'infors': infors,
        }
        return render(request, 'df_user/myself_information.html', context)


# 用户消息中心
@user_decorator.login
def message(request):
    user = UserInfo.objects.get(id=request.session['user_id'])
    cart_num = CartInfo.objects.filter(user_id=user.id).count()
    # 消息用户名去重
    persons = Information.objects.filter(cinformation_id=user.id).values('cusername', 'ccheck').distinct().\
        order_by('cusername')
    # 查询发消息者的头像
    imgs = UserInfo.objects.filter()
    context = {
        'title': '消息中心',
        'page_name': 1,
        'user': user,
        'persons': persons,
        'imgs': imgs,
        'guest_cart': 1,
        'cart_num': cart_num,
        'username': user.uname,
    }
    return render(request, 'df_user/user_messages.html', context)


# 消息内容展示
@user_decorator.login
def person_message(request):
    user = UserInfo.objects.get(id=request.session['user_id'])  # 当前登录用户
    cart_num = CartInfo.objects.filter(user_id=user.id).count()
    # 消息用户名去重
    persons = Information.objects.filter(cinformation_id=user.id).values('cusername', 'ccheck').distinct().\
        order_by('cusername')
    # 查询发消息者的头像
    imgs = UserInfo.objects.filter()
    # 展示消息
    username = request.GET['username']
    informations = Information.objects.filter()
    # print(type(informations[1].ctitle))
    # print(informations[1].ctitle=="")
    logo = UserInfo.objects.get(uname=username)
    # 展示消息后使消息变为已读状态
    for information in informations:
        if information.cusername == username:
            information.ccheck = True
            information.save()
    # 消息回复
    user_name = UserInfo.objects.get(uname=username)  # 获取当前消息用户信息
    # 展示回复消息
    if request.method == "POST":
        cusername = user.uname
        cusername1 = user_name.uname
        ccontent_chart = request.POST.get('title')
        cinformation_id = user_name.id
        if ccontent_chart == "":
            messages.success(request, "请输入内容!")
        else:
            Information.objects.create(cusername=cusername, cusername1=cusername1,
                                       ccontent_chart=ccontent_chart, cinformation_id=cinformation_id)
            messages.success(request, "消息发送成功")
            return redirect(reverse("df_user:message"))
    context = {
        'title': '消息中心',
        'page_name': 1,
        'user': user,
        'informations': informations,
        'persons': persons,
        'imgs': imgs,
        'logo': logo,
        'username': username,
        'user_name': user_name,
        'guest_cart': 1,
        'cart_num': cart_num,
    }
    # print(user.ulogo)
    # print(logo.ulogo)
    return render(request, 'df_user/user_messages.html', context)


# 退货处理
@user_decorator.login
def tuihuo(request):
    uid = request.session['user_id']
    user = UserInfo.objects.get(id=uid)
    if request.method == "POST":
        title = request.POST.get('title')
        username = request.POST.get('username')
        username1 = request.POST.get('username1')
        person_number = request.POST.get('person_number')
        order_number = request.POST.get('order_number')
        kuaidi = request.POST.get('kuaidi')
        kuaidi_number = request.POST.get('kuaidi_number')
        address = request.POST.get('address')
        address1 = request.POST.get('address1')
        text = request.POST.get('text')
        if title == "" or username == "" or username1 == "" or person_number == "" or order_number == "" or kuaidi == "" or kuaidi_number == "" or address == "" or address1 == "":
            messages.success(request, "请填写完整信息!")
        else:
            tuihuoInfo.objects.create(title=title, username=username, username1=username1, person_number=person_number,
                                      order_number=order_number, kuaidi=kuaidi, kuaidi_number=kuaidi_number,
                                      address=address, address1=address1, text=text)
            messages.success(request, "提交成功,请等待审批!")
            return redirect(reverse("df_user:info"))

    context = {
        'title': '填写退货信息',
        'page_name': 1,
        'user': user,
    }
    return render(request, 'df_user/tuihuo.html', context)

2.2.2 商品数据表后台业务处理

📋 功能概览

这个Django视图文件实现了商品展示系统的核心功能,包括首页展示、商品列表、详情页面、评论系统、搜索功能等,为二手交易平台提供完整的前台商品浏览体验。


🏠 首页功能 (index)

核心特性

  • 多分类商品展示:6个商品分类,每个分类显示最新4条和最热4条商品

  • 智能客服消息:用户与客服的消息互动系统

  • 实时数据统计:购物车数量动态显示

数据加载逻辑

# 分类商品数据加载示例
type0 = typelist[0].goodsinfo_set.order_by('-id')[0:4]    # 最新商品
type01 = typelist[0].goodsinfo_set.order_by('-gclick')[0:4] # 最热商品

消息系统

  • 已登录用户可与客服实时沟通

  • 消息状态管理和历史记录显示


📂 商品列表 (good_list)

参数说明

参数说明取值
tid商品分类ID整数
pindex页码整数
sort排序方式1:最新, 2:价格, 3:人气

排序功能

if sort == '1':   # 最新商品
    goods_list = GoodsInfo.objects.filter(gtype_id=int(tid)).order_by('-id')
elif sort == '2': # 价格排序
    goods_list = GoodsInfo.objects.filter(gtype_id=int(tid)).order_by('-gprice')
elif sort == '3': # 人气排序
    goods_list = GoodsInfo.objects.filter(gtype_id=int(tid)).order_by('-gclick')

分页显示

  • 每页显示4个商品

  • 左侧显示最新商品推荐


🔍 商品详情 (detail)

核心功能

  1. 商品信息展示:完整商品详情、图片、价格等

  2. 点击量统计:每次访问自动增加点击量

  3. 浏览记录管理

    • 记录用户浏览历史

    • 最多保存5条最新记录

    • 自动清理过期记录

浏览记录算法

# 浏览记录管理逻辑
browsed_good_count = browsed_goods.count()
if browsed_good_count > 5:
    ordered_goods = browsed_goods.order_by("-browser_time")
    for _ in ordered_goods[5:]:
        _.delete()  # 删除最早记录

访客支持

  • 未登录用户可浏览商品详情

  • 登录用户享受个性化功能


💬 商品评论 (content)

评论功能

  • 分页显示:每页2条评论

  • 图片评论:支持上传图片评论

  • 用户验证:确保评论真实性

评论提交

# 评论创建逻辑
GoodsContent.objects.create(
    ctitle=ctitle, 
    cpic=cpic, 
    cusername=cusername, 
    cuser_content=cuser_content,
    cgoodsname_id=cgoodsname_id, 
    clogo=clogo
)

订单验证

  • 关联订单信息验证购买真实性

  • 防止虚假评论


🔎 搜索系统

1. 普通搜索 (ordinary_search)

  • 多字段搜索:商品标题、详情、简介

  • 智能推荐:无结果时显示热门商品

  • 分页显示:每页4个搜索结果

# Q对象实现多字段搜索
goods_list = GoodsInfo.objects.filter(
    Q(gtitle__icontains=search_keywords) |
    Q(gcontent__icontains=search_keywords) |
    Q(gjianjie__icontains=search_keywords)).order_by("gclick")

2. 分类查看更多 (show_more)

  • 按商品分类查看更多商品

  • 支持分页浏览

  • 空状态处理


🛒 购物车辅助

购物车计数 (cart_count)

@user_decorator.login
def cart_count(request):
    if 'user_id' in request.session:
        return CartInfo.objects.filter(user_id=request.session['user_id']).count
    else:
        return 0

功能特点

  • 登录装饰器保护

  • 实时返回购物车商品数量

  • 多处视图函数调用


🔄 用户状态管理

登录状态处理

# 统一登录状态检查
if 'user_id' in request.session:
    # 登录用户逻辑
    user = UserInfo.objects.get(id=request.session['user_id'])
    cart_num = CartInfo.objects.filter(user_id=user.id).count()
else:
    # 访客逻辑
    cart_num = 0

数据传递

  • 用户信息传递到模板

  • 购物车数量实时更新

  • 个性化内容展示


📊 性能优化

1. 数据查询优化

  • 使用select_relatedprefetch_related减少查询次数

  • 分页机制避免大数据量加载

2. 缓存策略

  • 热门商品数据缓存

  • 分类信息缓存

3. 浏览记录清理

  • 自动维护浏览记录数量

  • 基于时间的记录管理


🎯 用户体验特性

1. 智能推荐

  • 最新商品推荐

  • 热门商品展示

  • 相关商品推荐

2. 交互反馈

  • 操作成功消息提示

  • 错误状态明确提示

  • 加载状态显示

3. 响应式设计

  • 支持不同设备访问

  • 分页适应各种屏幕


🔗 数据关联

视图函数关联模型主要功能
indexTypeInfoGoodsInfoInformation首页聚合展示
good_listGoodsInfoTypeInfo分类商品列表
detailGoodsInfoGoodsBrowser商品详情浏览
contentGoodsContentOrderDetailInfo评论系统
ordinary_searchGoodsInfo全局搜索
show_moreTypeInfoGoodsInfo分类扩展浏览

💡 核心价值

  1. 完整的商品展示体系:从首页→列表→详情→评论的全链路

  2. 智能的内容推荐:基于点击量和时间的智能排序

  3. 个性化的用户体验:浏览记录、购物车状态、消息互动

  4. 高效的搜索系统:多字段搜索+智能推荐

  5. 稳定的性能表现:分页机制、数据优化、缓存策略

这套商品视图系统为二手交易平台提供了专业级的商品展示和用户交互体验。

from django.contrib import messages
from django.core.paginator import Paginator
from django.shortcuts import render, redirect
from django.urls import reverse

from df_cart.models import CartInfo
from df_order.models import OrderDetailInfo
from df_user import user_decorator
from df_user.models import GoodsBrowser
from df_user.models import UserInfo, Information
from .models import GoodsInfo, TypeInfo, GoodsContent


# 01首页数据
def index(request):
    # 查询各个分类的最新4条,最热4条数据
    username = request.session.get('user_name')
    print(username)
    user = UserInfo.objects.filter(uname=username).first()
    print(user)
    import datetime
    nowTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')  # 现在
    informations = Information.objects.filter()
    if user is not None:
        # 联系客服
        # 展示消息
        username1 = user.uname
        # print(informations)
        # 判断用户是否给客服发过信息
        informations1 = Information.objects.filter(cusername1=username, cusername=username1)
        # print(informations1)
        # 消息回复
        user_name = UserInfo.objects.get(uname=username1)  # 获取当前消息用户信息
        print(user_name)
    else:
        informations1 = None
        username1 = None
        user_name = None
    # 展示回复消息
    # persons1=Information.objects.filter(cusername=cusername).values('cusername1').distinct().order_by('cusername1')
    if request.method == "POST":
        cusername = user.uname
        cusername1 = user_name.uname
        ccontent_chart = request.POST.get('title')
        cinformation_id = user_name.id
        if ccontent_chart == "":
            messages.success(request, "请输入内容!")
        else:
            Information.objects.create(cusername=cusername, cusername1=cusername1,
                                       ccontent_chart=ccontent_chart, cinformation_id=cinformation_id)
            messages.success(request, "消息发送成功")
            return redirect(reverse("df_goods:index"))
    typelist = TypeInfo.objects.all()

    if len(typelist[0].goodsinfo_set.order_by('-id')) <= 4:
        type0 = typelist[0].goodsinfo_set.order_by('-id')  # 按照上传顺序
        type01 = typelist[0].goodsinfo_set.order_by('-gclick')  # 按照点击量
    else:
        type0 = typelist[0].goodsinfo_set.order_by('-id')[0:4]
        type01 = typelist[0].goodsinfo_set.order_by('-gclick')[0:4]

    if len(typelist[1].goodsinfo_set.order_by('-id')) <= 4:
        type1 = typelist[1].goodsinfo_set.order_by('-id')
        type11 = typelist[1].goodsinfo_set.order_by('-gclick')
    else:
        type1 = typelist[1].goodsinfo_set.order_by('-id')[0:4]
        type11 = typelist[1].goodsinfo_set.order_by('-gclick')[0:4]

    if len(typelist[2].goodsinfo_set.order_by('-id')) <= 4:
        type2 = typelist[2].goodsinfo_set.order_by('-id')
        type21 = typelist[2].goodsinfo_set.order_by('-gclick')
    else:
        type2 = typelist[2].goodsinfo_set.order_by('-id')[0:4]
        type21 = typelist[2].goodsinfo_set.order_by('-gclick')[0:4]

    if len(typelist[3].goodsinfo_set.order_by('-id')) <= 4:
        type3 = typelist[3].goodsinfo_set.order_by('-id')
        type31 = typelist[3].goodsinfo_set.order_by('-gclick')
    else:
        type3 = typelist[3].goodsinfo_set.order_by('-id')[0:4]
        type31 = typelist[3].goodsinfo_set.order_by('-gclick')[0:4]

    if len(typelist[4].goodsinfo_set.order_by('-id')) <= 4:
        type4 = typelist[4].goodsinfo_set.order_by('-id')
        type41 = typelist[4].goodsinfo_set.order_by('-gclick')
    else:
        type4 = typelist[4].goodsinfo_set.order_by('-id')[0:4]
        type41 = typelist[4].goodsinfo_set.order_by('-gclick')[0:4]

    if len(typelist[5].goodsinfo_set.order_by('-id')) <= 4:
        type5 = typelist[5].goodsinfo_set.order_by('-id')
        type51 = typelist[5].goodsinfo_set.order_by('-gclick')
    else:
        type5 = typelist[5].goodsinfo_set.order_by('-id')[0:4]
        type51 = typelist[5].goodsinfo_set.order_by('-gclick')[0:4]

    cart_num = 0
    # 判断是否存在登录状态
    # if request.session.has_key('user_id'):
    if 'user_id' in request.session:
        user_id = request.session['user_id']
        cart_num = CartInfo.objects.filter(user_id=int(user_id)).count()

    context = {
        'title': '首页',
        'cart_num': cart_num,
        'guest_cart': 1,
        'type0': type0, 'type01': type01,
        'type1': type1, 'type11': type11,
        'type2': type2, 'type21': type21,
        'type3': type3, 'type31': type31,
        'type4': type4, 'type41': type41,
        'type5': type5, 'type51': type51,
        'user': user,
        'informations': informations,
        'informations1': informations1,
        'username1': username1,
        'user_name': user_name,
        # 'nowTime': nowTime,
    }

    return render(request, 'df_goods/index.html', context)


# 02获取商品列表
def good_list(request, tid, pindex, sort):
    username = request.session.get('user_name')
    user = UserInfo.objects.filter(uname=username).first()
    # tid:商品种类信息  pindex:商品页码 sort:商品显示分类方式
    typeinfo = TypeInfo.objects.get(pk=int(tid))

    # 根据主键查找当前的商品分类
    news = typeinfo.goodsinfo_set.order_by('-id')[0:2]
    # list.html左侧最新商品推荐
    goods_list = []
    # list中间栏商品显示方式
    cart_num, guest_cart = 0, 0

    try:
        user_id = request.session['user_id']
    except:
        user_id = None
    if user_id:
        guest_cart = 1
        cart_num = CartInfo.objects.filter(user_id=int(user_id)).count()

    if sort == '1':  # 默认最新
        goods_list = GoodsInfo.objects.filter(gtype_id=int(tid)).order_by('-id')
    elif sort == '2':  # 按照价格
        goods_list = GoodsInfo.objects.filter(gtype_id=int(tid)).order_by('-gprice')
    elif sort == '3':  # 按照人气点击量
        goods_list = GoodsInfo.objects.filter(gtype_id=int(tid)).order_by('-gclick')

    # 创建Paginator一个分页对象
    paginator = Paginator(goods_list, 4)
    # 返回Page对象,包含商品信息
    page = paginator.page(int(pindex))
    context = {
        'title': '商品列表',
        'guest_cart': guest_cart,
        'cart_num': cart_num,
        'page': page,
        'paginator': paginator,
        'typeinfo': typeinfo,
        'sort': sort,  # 排序方式
        'news': news,
        'user': user,
    }
    return render(request, 'df_goods/list.html', context)

# 03查看商品详情
def detail(request, gid):
    if 'user_id' in request.session:
        uid = request.session['user_id']
        user = UserInfo.objects.get(id=uid)
        good_id = gid
        goods = GoodsInfo.objects.get(pk=int(good_id))
        goods.gclick = goods.gclick + 1  # 商品点击量
        goods.save()

        news = goods.gtype.goodsinfo_set.order_by('-id')[0:2]
        context = {
            'title': goods.gtype.ttitle,
            'guest_cart': 1,
            'cart_num': cart_count(request),
            'goods': goods,
            'news': news,
            'id': good_id,
            'user': user,
        }
        response = render(request, 'df_goods/detail.html', context)

        try:
            browsed_good = GoodsBrowser.objects.get(user_id=int(uid), good_id=int(good_id))
        except Exception:
            browsed_good = None
        if browsed_good:
            from datetime import datetime
            browsed_good.browser_time = datetime.now()
            browsed_good.save()
        else:
            GoodsBrowser.objects.create(user_id=int(uid), good_id=int(good_id))
            browsed_goods = GoodsBrowser.objects.filter(user_id=int(uid))
            browsed_good_count = browsed_goods.count()
            if browsed_good_count > 5:
                ordered_goods = browsed_goods.order_by("-browser_time")
                for _ in ordered_goods[5:]:
                    _.delete()
        return response

    else:
        good_id = gid
        goods = GoodsInfo.objects.get(pk=int(good_id))
        news = goods.gtype.goodsinfo_set.order_by('-id')[0:2]
        context = {
            'title': goods.gtype.ttitle,
            'guest_cart': 0,
            'cart_num': cart_count(request),
            'goods': goods,
            'news': news,
            'id': good_id,
        }
        return render(request, 'df_goods/detail.html', context)


# 04评论商品
def content(request, gid, pindex):
    if 'user_id' in request.session:
        uid = request.session['user_id']
        user = UserInfo.objects.get(id=uid)
        good_id = gid
        goods = GoodsInfo.objects.get(pk=int(good_id))
        # 获取当前货物信息
        news = goods.gtype.goodsinfo_set.order_by('-id')[0:2]
        # 条件查询
        goodsContents = GoodsContent.objects.filter(cgoodsname_id=good_id).order_by('-date_publish')

        # 订单信息
        goodsOrderDetailInfos = OrderDetailInfo.objects.filter()

        # 创建Paginator一个分页对象
        paginator = Paginator(goodsContents, 2)
        # 返回Page对象,包含商品信息
        page = paginator.page(int(pindex))
        for goodsContent in page:
            if goodsContent.cgoodsname_id == goods.id:
                content_id = goodsContent.id

        context = {
            'title': goods.gtype.ttitle,
            'guest_cart': 1,
            'cart_num': cart_count(request),
            'goods': goods,
            'id': good_id,
            'news': news,
            'user': user,
            'goodsContents': goodsContents,
            'paginator': paginator,
            'page': page,
            'goodsOrderDetailInfos': goodsOrderDetailInfos,
            # 'xinxi':xinxi,
        }
        if request.method == "POST":
            ctitle = goods.gtitle
            cpic = request.FILES.get('pic')
            cusername = user.uname
            clogo = user.ulogo
            cuser_content = request.POST.get('text')
            cgoodsname_id = goods.id
            if cpic == "":
                GoodsContent.objects.create(ctitle=ctitle, cusername=cusername, cuser_content=cuser_content,
                                            cgoodsname_id=cgoodsname_id, clogo=clogo)
                messages.success(request, "评论成功!")
            else:
                GoodsContent.objects.create(ctitle=ctitle, cpic=cpic, cusername=cusername, cuser_content=cuser_content,
                                            cgoodsname_id=cgoodsname_id, clogo=clogo)
                messages.success(request, "评论成功!")

        return render(request, 'df_goods/content.html', context)
    else:
        good_id = gid
        goods = GoodsInfo.objects.get(pk=int(good_id))
        # 获取当前货物信息
        news = goods.gtype.goodsinfo_set.order_by('-id')[0:2]
        # 条件查询
        goodsContents = GoodsContent.objects.filter(cgoodsname_id=good_id).order_by('-date_publish')

        print("当前商品评论数:")
        print(goodsContents.count())
        # 订单信息
        goodsOrderDetailInfos = OrderDetailInfo.objects.filter()

        # 创建Paginator一个分页对象
        paginator = Paginator(goodsContents, 2)
        # 返回Page对象,包含商品信息
        page = paginator.page(int(pindex))
        for goodsContent in page:
            if goodsContent.cgoodsname_id == goods.id:
                content_id = goodsContent.id

        context = {
            'title': goods.gtype.ttitle,
            'guest_cart': 0,
            'cart_num': cart_count(request),
            'goods': goods,
            'id': good_id,
            'news': news,
            'goodsContents': goodsContents,
            'paginator': paginator,
            'page': page,
            'goodsOrderDetailInfos': goodsOrderDetailInfos,
            # 'xinxi':xinxi,
        }
        return render(request, 'df_goods/content.html', context)


# 05获取购物车数量
@user_decorator.login
def cart_count(request):
    if 'user_id' in request.session:
        return CartInfo.objects.filter(user_id=request.session['user_id']).count
    else:
        return 0


# 06搜索商品
def ordinary_search(request):
    username = request.session.get('user_name')
    user = UserInfo.objects.filter(uname=username).first()
    from django.db.models import Q

    search_keywords = request.GET.get('q', '')
    pindex = request.GET.get('pindex', 1)
    search_status = 1
    cart_num, guest_cart = 0, 0

    try:
        user_id = request.session['user_id']
    except:
        user_id = None

    if user_id:
        guest_cart = 1
        cart_num = CartInfo.objects.filter(user_id=int(user_id)).count()

    goods_list = GoodsInfo.objects.filter(
        Q(gtitle__icontains=search_keywords) |
        Q(gcontent__icontains=search_keywords) |
        Q(gjianjie__icontains=search_keywords)).order_by("gclick")

    if goods_list.count() == 0:
        # 商品搜索结果为空,返回推荐商品
        search_status = 0
        goods_list = GoodsInfo.objects.all().order_by("gclick")[:4]

    paginator = Paginator(goods_list, 4)
    page = paginator.page(int(pindex))

    context = {
        'title': '搜索列表',
        'search_status': search_status,
        'guest_cart': guest_cart,
        'cart_num': cart_num,
        'page': page,
        'paginator': paginator,
        'user': user,
    }
    return render(request, 'df_goods/ordinary_search.html', context)


# 06查看更多
def show_more(request, type_):
    username = request.session.get('user_name')
    user = UserInfo.objects.filter(uname=username).first()
    type_title = ['图书', '电器', '衣物', '出行', '乐器', '数码']
    type = type_title[int(type_)]
    pindex = request.GET.get('pindex', 1)
    search_status = 1
    cart_num, guest_cart = 0, 0
    try:
        user_id = request.session['user_id']
    except:
        user_id = None

    if user_id:
        guest_cart = 1
        cart_num = CartInfo.objects.filter(user_id=int(user_id)).count()

    type = TypeInfo.objects.filter(ttitle=type).first()
    if type is None:
        goods_list = None
    else:
        goods_list = GoodsInfo.objects.filter(gtype_id=type.id).order_by("gclick")

    if goods_list is None or goods_list.count() == 0:
        # 商品搜索结果为空,返回推荐商品
        search_status = 0
        goods_list = GoodsInfo.objects.all().order_by("gclick")[:4]

    paginator = Paginator(goods_list, 4)
    page = paginator.page(int(pindex))

    context = {
        'title': '搜索列表',
        'search_status': search_status,
        'guest_cart': guest_cart,
        'cart_num': cart_num,
        'page': page,
        'paginator': paginator,
        'user': user,
    }
    return render(request, 'df_goods/ordinary_search.html', context)

2.2.3 购物车业务处理代码

from django.http import JsonResponse
from django.shortcuts import render, redirect, reverse

from .models import *
from df_user import user_decorator


# 查看购物车信息
@user_decorator.login
def user_cart(request):
    uid = request.session['user_id']
    username = request.session.get('user_name')
    user = UserInfo.objects.filter(uname=username).first()
    carts = CartInfo.objects.filter(user_id=uid)
    cart_num = CartInfo.objects.filter(user_id=uid).count()
    context = {
        'title': '购物车',
        'page_name': 1,
        'guest_cart': 1,
        'carts': carts,
        'cart_num': cart_num,
        'user': user,
    }
    if request.is_ajax():
        count = CartInfo.objects.filter(user_id=request.session['user_id']).count()
        # 求当前用户购买了几件商品
        return JsonResponse({'count': count})
    else:
        return render(request, 'df_cart/cart.html', context)


# 添加购物车
@user_decorator.login
def add(request, gid, count):
    uid = request.session['user_id']
    gid, count = int(gid), int(count)
    # 查询购物车中是否已经有此商品,如果有则数量增加,如果没有则新增
    carts = CartInfo.objects.filter(user_id=uid, goods_id=gid)
    if len(carts) >= 1:
        cart = carts[0]
        cart.count = cart.count + count
    else:
        cart = CartInfo()
        cart.user_id = uid
        cart.goods_id = gid
        cart.count = count
    cart.save()
    # 如果是ajax提交则直接返回json,否则转向购物车
    if request.is_ajax():
        count = CartInfo.objects.filter(user_id=request.session['user_id']).count()
        # 求当前用户购买了几件商品
        return JsonResponse({'count': count})
    else:
        return redirect(reverse("df_cart:cart"))


# 编辑购物车
@user_decorator.login
def edit(request, cart_id, count):
    data = {}
    try:
        cart = CartInfo.objects.get(pk=int(cart_id))
        cart.count = int(count)
        cart.save()
        data['count'] = 0
    except Exception as e:
        print(e)
        data['count'] = count
    return JsonResponse(data)


# 删除购物车
@user_decorator.login
def delete(request, cart_id):
    data = {}
    try:
        cart = CartInfo.objects.get(pk=int(cart_id))
        cart.delete()
        data['ok'] = 1
    except Exception as e:
        print(e)
        data['ok'] = 0
    return JsonResponse(data)

2.2.4 订单业务处理代码

from django.db import transaction
from django.http import JsonResponse
from django.shortcuts import render, HttpResponse

from datetime import datetime
from decimal import Decimal

from .models import OrderInfo, OrderDetailInfo
from df_cart.models import CartInfo
from df_user.models import UserInfo
from df_user import user_decorator


# 查看订单
@user_decorator.login
def order(request):
    uid = request.session['user_id']
    user = UserInfo.objects.get(id=uid)
    cart_ids = request.GET.getlist('cart_id')
    carts = []
    total_price = 0
    for goods_id in cart_ids:
        cart = CartInfo.objects.get(id=goods_id)
        carts.append(cart)
        total_price = total_price + float(cart.count) * float(cart.goods.gprice)

    total_price = float('%0.2f' % total_price)
    trans_cost = 5  # 默认运费设置
    total_trans_price = trans_cost + total_price
    context = {
        'title': '提交订单',
        'page_name': 1,
        'user': user,
        'carts': carts,
        'total_price': float('%0.2f' % total_price),
        'trans_cost': trans_cost,
        'total_trans_price': total_trans_price,
    }
    return render(request, 'df_order/place_order.html', context)


'''
提交订单必须是一个连续的过程,所以需要用到事务
事务提交:
这些步骤中,任何一环节一旦出错则全部退回
1. 创建订单对象
2. 判断商品库存是否充足
3. 创建 订单 详情 ,多个
4,修改商品库存
5. 删除购物车
'''

# 生成订单
@user_decorator.login
@transaction.atomic()  # 事务
def order_handle(request):
    uid = request.session['user_id']
    user = UserInfo.objects.get(id=uid)
    tran_id = transaction.savepoint()  # 保存事务发生点
    cart_ids = request.POST.get('cart_ids')  # 用户提交的订单购物车,此时cart_ids为字符串,例如'1,2,3,'
    user_id = request.session['user_id']  # 获取当前用户的id
    data = {}
    try:
        order_info = OrderInfo()  # 创建一个订单对象
        now = datetime.now()
        order_info.oid = '%s%d' % (now.strftime('%Y%m%d%H%M%S'), user_id)  # 订单号为订单提交时间和用户id的拼接
        order_info.odate = now  # 订单时间
        order_info.user_id = int(user_id)  # 订单的用户id
        order_info.ototal = Decimal(request.POST.get('total'))  # 从前端获取的订单总价
        order_info.oaddress = user.uaddress  # 从用户信息中获取收获地址
        order_info.save()  # 保存订单

        for cart_id in cart_ids.split(','):  # 逐个对用户提交订单中的每类商品即每一个小购物车
            cart = CartInfo.objects.get(pk=cart_id)  # 从CartInfo表中获取购物车对象
            order_detail = OrderDetailInfo()  # 订单中的每一个小商品订单
            order_detail.order = order_info  # 外键关联,小订单与大订单绑定
            goods = cart.goods  # 具体商品
            if cart.count <= goods.gkucun:  # 判断库存是否满足订单,如果满足,修改数据库
                goods.gkucun = goods.gkucun - cart.count
                goods.save()
                order_detail.goods = goods
                order_detail.price = goods.gprice
                order_detail.count = cart.count
                order_detail.username = user.uname
                order_detail.shopername = goods.gunit
                order_detail.save()
                cart.delete()  # 并删除当前购物车
            else:  # 否则,则事务回滚,订单取消
                transaction.savepoint_rollback(tran_id)
                return HttpResponse('库存不足')
        data['ok'] = 1
        transaction.savepoint_commit(tran_id)
    except Exception as e:
        print("%s" % e)
        print('未完成订单提交')
        transaction.savepoint_rollback(tran_id)  # 事务任何一个环节出错,则事务全部取消
    return JsonResponse(data)


# 支付
@user_decorator.login
def pay(request):
    pass

2.3: 项目路由显示

2.3.1 用户路由

from django.conf.urls import url, re_path
from django.views.static import serve

from MarketSystem import settings
from . import viewsUtil
from .views import *

app_name = 'df_user'

# 用户模块子路由
urlpatterns = [
    url(r'^register/$', register, name="register"),  # 注册
    url(r'^register_handle/$', register_handle, name="register_handle"),  # 注册处理
    url(r'^register_exist/$', register_exist, name="register_exist"),  # 退出注册
    url(r'^login/$', login, name="login"),  # 登录
    url(r'^login_handle/$', login_handle, name="login_handle"),  # 登录注册
    url(r'^info/$', info, name="info"),  # 用户中心
    url(r'^order/(\d+)$', order, name="order"),  # 订单信息
    url(r'^site/$', site, name="site"),  # 用户信息修改
    url(r'^publishers/$', publishers, name="publishers"),  # 发布商品
    url(r'^changeInformation/$', changeInformation, name="changeInformation"),  # 修改资料、头像
    url(r'^check_user/$', check_user, name="check_user"),  # 实名认证
    url('^myself_information/$', myself_information, name="myself_information"),  # 卖家中心-查看自己作为卖家的卖家信息
    url('^shoper_information/(.+)/$', shoper_information, name="shoper_information"),  # 卖家中心-查看卖家信息
    url('^message/$', message, name="message"),  # 用户消息中心
    url('^person_message/$', person_message, name="person_message"),  # 消息内容展示
    url(r'^logout/$', logout, name="logout"),  # 退出登录
    # 显示验证码
    url(r'^verify_show/$', verify_show, name="verify_show"),  # 验证码显示
    url(r'^verifycode/$', viewsUtil.verify_code, name="verifycode"),  # 生成验证码图片
    # 修改密码
    url(r'^changeInPwd/$', changeInPwd, name="changeInPwd"),  # 修改密码
    # 重置密码
    url(r'^findpwdView/$', findpwdView, name="findpwdView"),  # 发送邮件重置密码
    # 退货
    url(r'^tuihuo/$', tuihuo, name="tuihuo"),  # 退货处理
    re_path('^media/(?P<path>.*)/$', serve, {'document_root': settings.MEDIA_ROOT}),  # 文件上传路径配置
]

2.3.2 商品路由

from django.conf.urls import url, re_path
from django.views.static import serve

from MarketSystem import settings
from . import views

app_name = 'df_goods'

# 商品子路由
urlpatterns = [
    url('^$', views.index, name="index"),  # 首页
    url('^index/$', views.index, name="index"),  # 首页
    url('^list(\d+)_(\d+)_(\d+)/$', views.good_list, name="good_list"),  # 商品列表
    url('^detail/(\d+)/$', views.detail, name="detail"),  # 商品详情
    url('^content/(\d+)/(\d+)/$', views.content, name="content"),  # 商品评论
    url(r'^search/', views.ordinary_search, name="ordinary_search"),  # 搜索商品
    url(r'^show_more/(\d+)/$', views.show_more, name="show_more"),  # 查看更多
    re_path('^media/(?P<path>.*)/$', serve, {'document_root': settings.MEDIA_ROOT}),
]

2.3.3 购物车路由

from django.conf.urls import url

from . import views

app_name = 'df_cart'

# 购物车子路由
urlpatterns = [
    url(r'^$', views.user_cart, name="cart"),  # 查看购物车
    url(r'^add(\d+)_(\d+)/$', views.add, name="add"),  # 添加购物车
    url(r'^edit(\d+)_(\d+)/$', views.edit, name="edit"),  # 编辑购物车
    url(r'^delete(\d+)/$', views.delete, name="delete"),  # 删除购物车
]

2.3.4 订单路由

from django.conf.urls import url
from . import views

app_name = 'df_order'

# 订单子路由
urlpatterns = [
    url(r'^$', views.order, name="order"),  # 订单信息
    url(r'^push/$', views.order_handle, name="push"),  # 订单处理
]

3: 项目截图展示

4: 结语

该项目适合用于普通高校的本科课程设计和毕业设计,项目整体不错,项目工作量中等偏上,有很大的学习和参考意义!

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追寻定义的熊百涛!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值