zoukankan      html  css  js  c++  java
  • 【100Days of 100 line Code】9 day and 10 day

    前两天在帮一哥们做一个往数据库加数据的页面,基于python Flask框架。

    赶鸭子上架简直,之前加入的时候大言不惭的告诉那哥们会Django和Flask。

    说实话,Django也就看了个基础。Flask也就这是知道一个名字。数据库也没有用过,花了一天时间到晚上一点,数据库才弄好。

    又是整整一天研究了pymysql和SQLAlchemy才把python和数据库连上。

    周六周日都没怎么有空,今天把代码回顾一下。

    割一下--------------

    需求:

    必要参数(在数据库中保存的就是这样的):
    commodityName    商品名称
    
    commodityPic         商品图片
    考虑到一种商品会有多张图片的情况,在数据库以图片路径的形式保存,
    路径格式为:/image/commodityImg/商品编号/img_图片I.jpg   多张图片路径中间以英文逗号隔开 
    例如/image/commodityImg/1/img_1.jpg,/image/commodityImg/1/img_2.jpg   即为第一件商品的第一张和第二张图片
    
    briefInfo                  简要信息
    商品的简要信息
    
    
    detailedInfo            详细信息
    详细信息目前暂定也是用图片的形式来展现,所以详细信息这里也是存放图片路径的,
    格式只有在图片命名上略有不同:/image/commodityImg/1/detail_1.jpg  多张图片路径中间以英文逗号隔开 
    例如/image/commodityImg/1/detail_1.jpg,/image/commodityImg/1/detail_2.jpg   即为第一件商品的第一张和第二张详情
    
    
    price                        价格
    
    like                          点赞数量(暂定) 
    每次填300就行了 暂定功能,以后可能会改
    sex                           面向人群性别
    1代表男性 0代表女性 填1或0就完事了
    
    
    有个地方要说一下,后台更新商品是肯定要上传图片的,
    商品图片上传路径是/home/static/commodityImg/商品编号/img_商品编号.jpg
    详情图片上传路径是/home/static/commodityImg/商品编号/detail_商品编号.jpg

    一,数据库的安装

    工具:

    MySql-8.0.11,Navicat 12 for MySQL

    MySQL下载地址:https://dev.mysql.com/downloads/mysql/

    Navicat 12 for MySQL下载地址:https://www.navicat.com/en/download/navicat-for-mysql

    MySQL的安装真是要了老命,花了N种方法N个小时。

    1.下载,解压到路径

    2.配置环境变量

    我的电脑>>属性>>环境变量>>系统环境变量>>path,将mysql的解压路径/bin复制到变量内

    3.配置文件

    我下载下来的时候 是没有配置文件的,听说大部分人都没有。。

    配置文件命名:my.ini

    代码:

    [mysqld]
    # 设置3306端口
    port=3306
    # 设置mysql的安装目录
    basedir=G:mysql   
    # 设置mysql数据库的数据的存放目录
    datadir=G:mysqlin 
    # 允许最大连接数
    max_connections=200
    # 允许连接失败的次数。这是为了防止有人从该主机试图攻击数据库系统
    max_connect_errors=10
    # 服务端使用的字符集默认为UTF8
    character-set-server=utf8
    # 创建新表时将使用的默认存储引擎
    default-storage-engine=INNODB
    # 默认使用“mysql_native_password”插件认证
    default_authentication_plugin=mysql_native_password
    [mysql]
    # 设置mysql客户端默认字符集
    default-character-set=utf8
    [client]
    # 设置mysql客户端连接服务端时默认使用的端口
    port=3306
    default-character-set=utf8

    4.安装MySQL

    务必使用管理员权限进入命令行

    cd到安装目录的/bin

    输入命令对mysql进行初始化

    mysqld --initialize --console

    执行结果会有一段: [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: rI5rvf5x5G,E 其中root@localhost:后面的“rI5rvf5x5G,E”就是初始密码(不含首位空格)。在没有更改密码前,需要记住这个密码,后续登录需要用到。

    输入命令安装MySQL

    mysqld --install [服务名]

    有多个MySQL服务的话,服务名要对应相应的MySQL服务

    输入命令开启MySQL服务

    net start mysql

    开启之后,就可以登陆数据库了

    登陆数据库命令

    mysql -u root -p

    后面会叫你输入密码,这个时候输入刚刚的密码

    更改数据库登陆密码

    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';  

    (ps:分号一定要有,python写多了习惯了不写分号,但是数据库是不会执行命令的)

    后连接Navicat 12 for MySQL,创建表即可。

    二,Flask虚拟环境

    我直接用的是PyCharm,可以生成Flask所需的虚拟环境。

    注意一下,Flask所需要的模块,需要下载到虚拟环境的编译器文件夹内,否则会无法运行

    下载方式和正常的下载模块方式一致,有路径的区别

    三.Flask连接数据库

    我用的是flask_sqlalchemy这个模块连接的数据库。

    引入的库:

    from flask_sqlalchemy import SQLAlchemy

    安装方法:

    虚拟环境下安装flask_sqlalchemy模块

    (venv) G:commodity>pip install flask_sqlalchemy

    数据库配置:

    配置代码我直接写在app.py里面了,这样是不好的听说,要专门新建一个confit.py保存配置是最好的

    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:111111@127.0.0.1:3306/commodity?charset=utf8'
    app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
    app.config['SECRET_KEY'] = 'xcax0cx86x04x98@x02bx1b7x8cx88]x1bxd7"+xe6px@xc3#\'

    第一行是数据库的配置文件:规范是mysql+pymysql://用户名:密码@地址:端口/数据库名?编码

    第二行该配置为True,则每次请求结束都会自动commit数据库的变动

    第三行是生成一个密匙,CSRF需要用到

    定义模型

    定义模型主要是关联数据库的表,

    class Commpdity(db.Model):
        __tablename__ = 'commodity'
        commodityID = db.Column(db.Integer, primary_key=True)
        commodityName = db.Column(db.Text)
        briefInfo = db.Column(db.Text)
        price = db.Column(db.Float)
        like = db.Column(db.Integer)
        sex = db.Column(db.Text)

    一定要有一个primary_key 的值为true,否则会报错

    四.表单

    引入的库

    from wtforms import StringField, IntegerField, SubmitField, FloatField
    from wtforms.validators import DataRequired, Length, Regexp
    from flask_wtf import FlaskForm
    from flask_wtf.file import FileField

    第一行是表单所引用的字段类型

    第二行是表单验证所引用的验证函数。空值验证,长度验证,正则表达式验证

    第三行是引入表单

    第四行是文件处理所使用的模型

    下面是具体的表单代码

    class AddCommodity(FlaskForm):
        commodityName = StringField('商品名称', validators=[DataRequired(message=u'商品名不能为空'), Length(1, 60),
                Regexp('^[A-Za-z][A-Za-z0-9/ ]*$', 0, '商品名称只允许使用汉字,英文,数字,空格和右斜杠')])  # 商品名称 文字
        briefInfo = StringField(u'商品卖点', validators=[DataRequired(message=u'商品卖点不能为空'), Length(1, 60),
                Regexp('^[A-Za-z][A-Za-z0-9/ ]*$', 0, '商品卖点只允许使用汉字,英文,数字,空格和右斜杠')])   # 商品卖点 文字
        price = FloatField(u'商品价格', validators=[DataRequired(message=u'商品价格不能为空')])  # 价格 浮点类型
        like = IntegerField(u'点赞次数', validators=[DataRequired(message=u'点赞次数不能为空')])  # 点赞
        sex = IntegerField(u'面向人群', validators=[DataRequired(message=u'面向人群不能为空')])  # 选择 男或女
        submit = SubmitField(u'发布商品')

    五.对数据库的操作

    @app.route('/', methods=['GET', 'POST'])  # 路由设置
    def hello_world():
        form = AddCommodity() 
        if form.validate_on_submit():  # 当表单内容提交
            new_id = db.session.query(func.count(Commpdity.commodityID)).scalar() + 1
            path = '/home/static/commodityImg/' + str(new_id)
            os.makedirs(path)
            filename = form.commodityPic.data.filename
            form.commodityPic.data.save(path + filename)
            commodity = Commpdity(                     # 数据库内容提交
                commodityID=new_id,
                commodityName=form.commodityName.data,
                commodityPic=form.commodityPic.data,
                briefInfo=form.briefInfo.data,
                detailedInfo=form.detailedInfo.data,
                price=form.price.data,
                like=form.like.data,
                sex=form.sex.data
            )
            db.session.add(commodity)  # 保存表格数据到数据库
            db.session.commit()  # commit数据库
            flash('商品已经成功发布')
        return render_template('/addcommodity.html',form=form)

    六.页面

    {% import "bootstrap/wtf.html" as wtf %}
    {% block page_content %}
    <div class="page-header">
        <h1>发布商品</h1>
    </div>
    <div class="col-md-4">
        {{ wtf.quick_form(form) }}
    </div>
    {% endblock %}

    目前还没有实现的功能:

    一. 上传图片功能,

    虽然有办法实现,但是不知道页面和流程怎么设计

    二.  图片更名

    有方法实现,问题同上

    具体的代码:

    app.py
    from flask import Flask
    from flask import flash, render_template
    from flask_sqlalchemy import SQLAlchemy
    from flask_bootstrap import Bootstrap
    from forms import AddCommodity
    from sqlalchemy import func
    import os
    from werkzeug import secure_filename
    from werkzeug.utils import secure_filename
    
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:111111@127.0.0.1:3306/commodity?charset=utf8'
    app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
    app.config['SECRET_KEY'] = 'xcax0cx86x04x98@x02bx1b7x8cx88]x1bxd7"+xe6px@xc3#\'
    bootstrap = Bootstrap(app)
    db = SQLAlchemy(app)
    
    
    @app.route('/', methods=['GET', 'POST'])  # 路由设置
    def hello_world():
        form = AddCommodity()
        if form.validate_on_submit():  # 当表单内容提交
            new_id = db.session.query(func.count(Commpdity.commodityID)).scalar() + 1
            path = '/home/static/commodityImg/' + str(new_id)
            os.makedirs(path)
            filename = form.commodityPic.data.filename
            form.commodityPic.data.save(path + filename)
            commodity = Commpdity(                     # 数据库内容提交
                commodityID=new_id,
                commodityName=form.commodityName.data,
                commodityPic=form.commodityPic.data,
                briefInfo=form.briefInfo.data,
                detailedInfo=form.detailedInfo.data,
                price=form.price.data,
                like=form.like.data,
                sex=form.sex.data
            )
            db.session.add(commodity)  # 保存表格数据到数据库
            db.session.commit()  # commit数据库
            flash('商品已经成功发布')
        return render_template('/addcommodity.html',form=form)
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    
    class Commpdity(db.Model):
        __tablename__ = 'commodity'
        commodityID = db.Column(db.Integer, primary_key=True)
        commodityName = db.Column(db.Text)
        commodityPic = db.Column(db.Text)
        briefInfo = db.Column(db.Text)
        detailedInfo = db.Column(db.Integer)
        price = db.Column(db.Float)
        like = db.Column(db.Integer)
        sex = db.Column(db.Text)

    forms.py
    from wtforms import StringField, IntegerField, SubmitField, FloatField
    from wtforms.validators import DataRequired, Length, Regexp
    from flask_wtf import FlaskForm
    from flask_wtf.file import FileField
    
    
    class AddCommodity(FlaskForm):
        commodityName = StringField('商品名称', validators=[DataRequired(message=u'商品名不能为空'), Length(1, 60),
                Regexp('^[A-Za-z][A-Za-z0-9/ ]*$', 0, '商品名称只允许使用汉字,英文,数字,空格和右斜杠')])  # 商品名称 文字
        commodityPic = FileField(u'商品主图')  # 商品主图 图片文件
        briefInfo = StringField(u'商品卖点', validators=[DataRequired(message=u'商品卖点不能为空'), Length(1, 60),
                Regexp('^[A-Za-z][A-Za-z0-9/ ]*$', 0, '商品卖点只允许使用汉字,英文,数字,空格和右斜杠')])   # 商品卖点 文字
        detailedInfo = FileField(u'上传商品详情',)  # 详细介绍 图片文件
        price = FloatField(u'商品价格', validators=[DataRequired(message=u'商品价格不能为空')])  # 价格 浮点类型
        like = IntegerField(u'点赞次数', validators=[DataRequired(message=u'点赞次数不能为空')])  # 点赞
        sex = IntegerField(u'面向人群', validators=[DataRequired(message=u'面向人群不能为空')])  # 选择框 男或女
        submit = SubmitField(u'发布商品')
    addcommodity.html
    {% import "bootstrap/wtf.html" as wtf %}
    {% block page_content %}
    <div class="page-header">
        <h1>发布商品</h1>
    </div>
    <div class="col-md-4">
        {{ wtf.quick_form(form) }}
    </div>
    {% endblock %}
  • 相关阅读:
    LeetCode 24. Swap Nodes in Pairs (两两交换链表中的节点)
    LeetCode 1041. Robot Bounded In Circle (困于环中的机器人)
    LeetCode 1037. Valid Boomerang (有效的回旋镖)
    LeetCode 1108. Defanging an IP Address (IP 地址无效化)
    LeetCode 704. Binary Search (二分查找)
    LeetCode 744. Find Smallest Letter Greater Than Target (寻找比目标字母大的最小字母)
    LeetCode 852. Peak Index in a Mountain Array (山脉数组的峰顶索引)
    LeetCode 817. Linked List Components (链表组件)
    LeetCode 1019. Next Greater Node In Linked List (链表中的下一个更大节点)
    29. Divide Two Integers
  • 原文地址:https://www.cnblogs.com/mygzhh/p/9354272.html
Copyright © 2011-2022 走看看