大数据毕业设计:基于python在线商品购物系统 商品推荐系统 Flask框架-程序员宅基地

技术标签: python  毕业设计  推荐系统  biyesheji0001  biyesheji0002  flask  商品推荐  课程设计  大数据  

博主介绍:全网粉丝10W+,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久,选择我们就是选择放心、选择安心毕业感兴趣的可以先收藏起来,点赞、关注不迷路

毕业设计:2023-2024年计算机专业毕业设计选题汇总(建议收藏)

毕业设计:2023-2024年最新最全计算机专业毕设选题推荐汇总

1、项目介绍

项目技术栈:
Python语言、Flask框架、MySQL数据库、HTML

2、项目界面

(1)商品分类
在这里插入图片描述

(2)系统首页

在这里插入图片描述

(3)商品购物车功能

在这里插入图片描述

(4)我的购物车
在这里插入图片描述
(5)我的商品订单
在这里插入图片描述

(6)后台管理登录

在这里插入图片描述

(7)后台数据管理界面
在这里插入图片描述

3、项目说明

一个完整的在线购物商城系统通常包括多个功能模块,涉及用户管理、商品管理、购物车、订单处理、支付等方面。下面是一个基本的功能介绍:

1.用户注册和登录:

2.允许用户注册账户,提供用户名、密码、邮箱等信息。已注册用户可以通过登录进入系统,通常使用Flask的用户认证插件来管理用户身份。

3.商品管理:

4.提供商品列表,展示商品的基本信息,如名称、描述、价格等。
5.具备商品分类功能,使用户能够方便地浏览和搜索商品。

6.购物车功能:

7.用户可以将喜欢的商品添加到购物车中,实时更新购物车的商品数量和总价。
8.允许用户调整购物车中商品的数量或删除不需要的商品。

9.订单处理:

10.用户可以查看已下的订单,订单中包含购买的商品、数量、总价等信息。
11.提供订单状态,例如已支付、待发货、已发货等。
12.允许用户取消未支付的订单。

13.支付系统:

14.整合支付系统,允许用户选择支付方式(如信用卡、支付宝、微信支付等)进行支付。
15.处理支付成功或失败的反馈,确保订单状态正确更新。

16.用户个人中心:

17.提供用户个人信息的管理,包括修改密码、更改个人资料等。
18.用户可以查看订单历史记录和当前的购物车状态。

19.商品详情页:

20.提供详细的商品信息,包括商品图片、规格、用户评价等。
21.允许用户加入购物车或直接购买。

22.搜索和过滤:

23.提供搜索功能,让用户通过关键字查找商品。
24.允许用户通过价格、品牌、类别等条件过滤商品列表。

25.推荐系统:

26.可选的功能,通过用户历史购买记录或浏览行为,向用户推荐可能感兴趣的商品。

27.后台管理:

28.管理员可以对商品信息、用户信息、订单状态等进行管理和监控。
29.提供数据统计功能,如销售报表、用户活跃度等。
30.安全性和用户体验:

31.保障用户数据的安全性,包括密码加密存储、安全的用户会话管理等。
32.提供友好的用户界面,确保用户在购物过程中的流畅体验。

4、核心代码



# _*_ coding: utf-8 _*_
from . import home
from app import db
from app.home.forms import LoginForm,RegisterForm,PasswordForm
from app.models import User ,Goods,Orders,Cart,OrdersDetail
from flask import render_template, url_for, redirect, flash, session, request,make_response
from werkzeug.security import generate_password_hash
from functools import wraps
import random
import string
from PIL import Image, ImageFont, ImageDraw
from io import BytesIO

def rndColor():
    '''随机颜色'''
    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

def gene_text():
    '''生成4位验证码'''
    return ''.join(random.sample(string.ascii_letters+string.digits, 4))

def draw_lines(draw, num, width, height):
    '''划线'''
    for num in range(num):
        x1 = random.randint(0, width / 2)
        y1 = random.randint(0, height / 2)
        x2 = random.randint(0, width)
        y2 = random.randint(height / 2, height)
        draw.line(((x1, y1), (x2, y2)), fill='black', width=1)

def get_verify_code():
    '''生成验证码图形'''
    code = gene_text()
    # 图片大小120×50
    width, height = 120, 50
    # 新图片对象
    im = Image.new('RGB',(width, height),'white')
    # 字体
    font = ImageFont.truetype('app/static/fonts/arial.ttf', 40)
    # draw对象
    draw = ImageDraw.Draw(im)
    # 绘制字符串
    for item in range(4):
        draw.text((5+random.randint(-3,3)+23*item, 5+random.randint(-3,3)),
                  text=code[item], fill=rndColor(),font=font )
    return im, code


@home.route('/code')
def get_code():
    image, code = get_verify_code()
    # 图片以二进制形式写入
    buf = BytesIO()
    image.save(buf, 'jpeg')
    buf_str = buf.getvalue()
    # 把buf_str作为response返回前端,并设置首部字段
    response = make_response(buf_str)
    response.headers['Content-Type'] = 'image/gif'
    # 将验证码字符串储存在session中
    session['image'] = code
    return response

def user_login(f):
    """
    登录装饰器
    """
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if "user_id" not in session:
            return redirect(url_for("home.login"))
        return f(*args, **kwargs)

    return decorated_function

@home.route("/login/", methods=["GET", "POST"])
def login():
    """
    登录
    """
    if "user_id" in session:        # 如果已经登录,则直接跳转到首页
        return redirect(url_for("home.index"))
    form = LoginForm()              # 实例化LoginForm类
    if form.validate_on_submit():   # 如果提交
        data = form.data            # 接收表单数据
        # 判断验证码
        if session.get('image').lower() != form.verify_code.data.lower():
            flash('验证码错误',"err")
            return render_template("home/login.html", form=form)  # 返回登录页
        # 判断用户名是否存在
        user = User.query.filter_by(username=data["username"]).first()    # 获取用户信息
        if not user :
            flash("用户名不存在!", "err")           # 输出错误信息
            return render_template("home/login.html", form=form)  # 返回登录页
        # 判断用户名和密码是否匹配
        if not user.check_password(data["password"]):     # 调用check_password()方法,检测用户名密码是否匹配
            flash("密码错误!", "err")           # 输出错误信息
            return render_template("home/login.html", form=form)  # 返回登录页

        session["user_id"] = user.id                # 将user_id写入session, 后面用户判断用户是否登录
        session["username"] = user.username                # 将user_id写入session, 后面用户判断用户是否登录
        return redirect(url_for("home.index")) # 登录成功,跳转到首页

    return render_template("home/login.html",form=form) # 渲染登录页面模板

@home.route("/register/", methods=["GET", "POST"])
def register():
    """
    注册功能
    """
    if "user_id" in session:
        return redirect(url_for("home.index"))
    form = RegisterForm()           # 导入注册表单
    if form.validate_on_submit():   # 提交注册表单
        data = form.data            # 接收表单数据
        # 为User类属性赋值
        user = User(
            username = data["username"],            # 用户名
            email = data["email"],                  # 邮箱
            password = generate_password_hash(data["password"]),# 对密码加密
            phone = data['phone']
        )
        db.session.add(user) # 添加数据
        db.session.commit()  # 提交数据
        return redirect(url_for("home.login"))  # 登录成功,跳转到首页
    return render_template("home/register.html", form=form) # 渲染模板

@home.route("/logout/")
def logout():
    """
    退出登录
    """
    # 重定向到home模块下的登录。
    session.pop("user_id", None)
    session.pop("username", None)
    return redirect(url_for('home.login'))

@home.route("/modify_password/",methods=["GET","POST"])
@user_login
def modify_password():
    """
    修改密码
    """
    form = PasswordForm()
    if form.validate_on_submit():
        data = form.data
        user = User.query.filter_by(username=session["username"]).first()
        from werkzeug.security import generate_password_hash
        user.password = generate_password_hash(data["password"])
        db.session.add(user)
        db.session.commit()
        return "<script>alert('密码修改成功');location.href='/';</script>"
    return render_template("home/modify_password.html", form=form)

@home.route("/")
def index():
    """
    首页
    """
    # 获取2个热门商品
    hot_goods = Goods.query.order_by(Goods.views_count.desc()).limit(2).all()
    # 获取12个新品
    new_goods = Goods.query.filter_by(is_new=1).order_by(
                    Goods.addtime.desc()
                        ).limit(12).all()
    # 获取12个打折商品
    sale_goods = Goods.query.filter_by(is_sale=1).order_by(
                    Goods.addtime.desc()
                        ).limit(12).all()
    return render_template('home/index.html',new_goods=new_goods,sale_goods=sale_goods,hot_goods=hot_goods) # 渲染模板

@home.route("/goods_list/<int:supercat_id>/")
def goods_list(supercat_id=None):  # supercat_id 为商品大分类ID
    """
    商品页
    """
    page = request.args.get('page', 1, type=int)  # 获取page参数值
    page_data = Goods.query.filter_by(supercat_id=supercat_id).paginate(page=page, per_page=12)
    hot_goods = Goods.query.filter_by(supercat_id=supercat_id).order_by(Goods.views_count.desc()).limit(7).all()
    return render_template('home/goods_list.html',page_data=page_data,hot_goods=hot_goods,supercat_id=supercat_id)

@home.route("/goods_detail/<int:id>/")
def goods_detail(id=None):  # id 为商品ID
    """
    详情页
    """
    user_id = session.get('user_id', 0)  # 获取用户ID,判断用户是否登录
    goods = Goods.query.get_or_404(id) # 根据景区ID获取景区数据,如果不存在返回404
    # 浏览量加1
    goods.views_count += 1
    db.session.add(goods) # 添加数据
    db.session.commit()   # 提交数据
    # 获取左侧热门商品
    hot_goods = Goods.query.filter_by(subcat_id=goods.subcat_id).order_by(Goods.views_count.desc()).limit(5).all()
    # 获取底部相关商品
    similar_goods = Goods.query.filter_by(subcat_id=goods.subcat_id).order_by(Goods.addtime.desc()).limit(5).all()
    return render_template('home/goods_detail.html',goods=goods,hot_goods=hot_goods,similar_goods=similar_goods,user_id=user_id)   # 渲染模板


@home.route("/search/")
def goods_search():
    """
    搜素功能
    """
    page = request.args.get('page', 1, type=int) # 获取page参数值
    keywords = request.args.get('keywords','',type=str)

    if keywords :
        # 使用like实现模糊查询
        page_data = Goods.query.filter(Goods.name.like("%"+keywords+"%")).order_by(
            Goods.addtime.desc()
        ).paginate(page=page, per_page=12)
    else :
        page_data = Goods.query.order_by(
            Goods.addtime.desc()
        ).paginate(page=page, per_page=12)
    hot_goods = Goods.query.order_by(Goods.views_count.desc()).limit(7).all()
    return render_template("home/goods_search.html", page_data=page_data,keywords=keywords,hot_goods=hot_goods)

@home.route("/cart_add/")
@user_login
def cart_add():
    """
    添加购物车
    """
    cart = Cart(
        goods_id = request.args.get('goods_id'),
        number = request.args.get('number'),
        user_id=session.get('user_id', 0)  # 获取用户ID,判断用户是否登录
    )
    db.session.add(cart) # 添加数据
    db.session.commit()   # 提交数据
    return redirect(url_for('home.shopping_cart'))

@home.route("/cart_clear/")
@user_login
def cart_clear():
    """
    清空购物车
    """
    user_id = session.get('user_id', 0)  # 获取用户ID,判断用户是否登录
    Cart.query.filter_by(user_id=user_id).update({
    'user_id': 0})
    db.session.commit()
    return redirect(url_for('home.shopping_cart'))

@home.route("/shopping_cart/")
@user_login
def shopping_cart():
    user_id = session.get('user_id',0)
    cart = Cart.query.filter_by(user_id = int(user_id)).order_by(Cart.addtime.desc()).all()
    if cart:
        return render_template('home/shopping_cart.html',cart=cart)
    else:
        return render_template('home/empty_cart.html')

@home.route("/cart_order/",methods=['GET','POST'])
@user_login
def cart_order():
    if request.method == 'POST':
        user_id = session.get('user_id',0) # 获取用户id
        # 添加订单
        orders = Orders(
            user_id = user_id,
            recevie_name = request.form.get('recevie_name'),
            recevie_tel = request.form.get('recevie_tel'),
            recevie_address = request.form.get('recevie_address'),
            remark = request.form.get('remark')
        )
        db.session.add(orders)  # 添加数据
        db.session.commit()      # 提交数据
        # 添加订单详情
        cart = Cart.query.filter_by(user_id=user_id).all()
        object = []
        for item in cart :
            object.append(
                OrdersDetail(
                    order_id=orders.id,
                    goods_id=item.goods_id,
                    number = item.number,)
            )
        db.session.add_all(object)
        # 更改购物车状态
        Cart.query.filter_by(user_id=user_id).update({
    'user_id': 0})
        db.session.commit()
    return redirect(url_for('home.index'))

@home.route("/order_list/",methods=['GET','POST'])
@user_login
def order_list():
    """"
    我的订单
    """
    user_id = session.get('user_id',0)
    orders = OrdersDetail.query.join(Orders).filter(Orders.user_id==user_id).order_by(Orders.addtime.desc()).all()
    return render_template('home/order_list.html',orders=orders)


@home.route("/collect_add/")
@user_login
def collect_add():
    """
    收藏景区
    """
    scenic_id = request.args.get("scenic_id", "")   # 接收传递的参数scenic_id
    user_id   = session.get('user_id',0)            # 获取当前用户的ID
    collect = Collect.query.filter_by(              # 根据用户ID和景区ID判断是否该收藏
        user_id =int(user_id),
        scenic_id=int(scenic_id)
    ).count()
    # 已收藏
    if collect == 1:
        data = dict(ok=0)     # 写入字典
    # 未收藏进行收藏
    if collect == 0:
        collect = Collect(
            user_id =int(user_id),
            scenic_id=int(scenic_id)
        )
        db.session.add(collect)  # 添加数据
        db.session.commit()      # 提交数据
        data = dict(ok=1)        # 写入字典
    import json                 # 导入模块
    return json.dumps(data)     # 返回json数据

@home.route("/collect_cancel/")
@user_login
def collect_cancel():
    """
    收藏景区
    """
    id = request.args.get("id", "")    # 获取景区ID
    user_id = session["user_id"]       # 获取当前用户ID
    collect = Collect.query.filter_by(id=id,user_id=user_id).first() # 查找Collect表,查看记录是否存在
    if collect :                      # 如果存在
        db.session.delete(collect)     # 删除数据
        db.session.commit()             # 提交数据
        data = dict(ok=1)               # 写入字典
    else :
        data = dict(ok=-1)           # 写入字典
    import json                     # 引入json模块
    return json.dumps(data)         # 输出json格式


@home.route("/collect_list/")
@user_login
def collect_list():
    page = request.args.get('page', 1, type=int) # 获取page参数值
    # 根据user_id删选Collect表数据
    page_data = Collect.query.filter_by(user_id = session['user_id']).order_by(
        Collect.addtime.desc()
    ).paginate(page=page, per_page=3)                                     # 使用分页方法
    return render_template('home/collect_list.html',page_data=page_data) # 渲染模板



感兴趣的可以先收藏起来,点赞关注不迷路,想学习更多项目可以查看主页,大家在毕设选题,项目代码以及论文编写等相关问题都可以给我留言咨询,希望可以帮助同学们顺利毕业!

源码获取:

由于篇幅限制,获取完整文章或源码、代做项目的,拉到文章底部即可看到个人联系方式。

点赞、收藏、关注,不迷路,下方查看获取联系方式

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/2201_75772776/article/details/135017483

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签