【python练习】使用flask+SQLAlchemy完成用户注册、随机注册、登录、数据下载、数据自动上传注册等功能

该博客介绍了如何使用Python的Flask框架构建用户注册、登录接口,以及数据管理功能。包括创建数据库连接、实现注册时的正则验证、登录验证、获取用户列表接口、随机数据生成并导入数据库、数据导出和批量注册。同时,展示了部分可能出现的问题和解决方案。
摘要由CSDN通过智能技术生成

练习目标:

  1. 使用flask完成一个注册接口,数据由用户名+密码组成,要求用户名和密码都是大小写字母和数字的组合。注册后写入本地数据库。
  2. 随机生成一百组数据,写入数据库。
  3. 完成一个登录接口,验证输入的用户名和密码是否准确。
  4. 完成一个get_userlist接口,以指定格式返回用户名和密码。
  5. 将用户名和密码下载到本地。
  6. 清空数据库,读取本地文件,将文件中的数据批量注册到同一数据库中。

拆解:

准备工作:

  • 使用pip安装flask、SQLAlchemy等必要库
  • 数据库-使用navicat连接本机的mysql,创建flask_register数据库,并且新建一个名为register表
  • 本地新建项目,项目中新增config.py,存放数据库连接代码
  • 项目中新增py文件,存放服务端的所有自定义的接口代码(服务端的代码最好写在一起,一定要和客户端分开放)
HOST = 'localhost'
PORT = 3306
USERNAME = 'root'
PASSWORD = '123456' #本机实际的mysql密码
DB = 'flask_register'   #先在mysql中建立好这个名字的数据库

DB_URI = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOST}:{PORT}/{DB}'

配置数据库:

'''配置数据库'''
app = Flask(__name__)
app.config["JSON_AS_ASCII"] = False
app.config['SECRET_KEY'] ='hard to guess'

# 这里登陆的是root用户,要填上自己的密码,MySQL的默认端口是3306,填上之前创建的数据库名
app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://root:123456@127.0.0.1:3306/flask_register'
#设置这一项是每次请求结束后都会自动提交数据库中的变动
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True   #这一句不加会报错
#实例化
db = SQLAlchemy(app)
engine = create_engine(DB_URI)
Base = declarative_base(engine)  # SQLORM基类
session = sessionmaker(engine)()  # 构建session对象

class User_Register(db.Model):
    __tablename__ = 'register'  # 表名
    id = db.Column(Integer, primary_key=True, autoincrement=True)  # 作为主key,且自增1
    username = db.Column(String(20))
    password = db.Column(String(20))
print(type(User_Register))
Base.metadata.create_all()  # 将模型映射到数据库中

此文件需要运行,需在文件末尾增加app.run():

if __name__ == '__main__':
    app.run(port=8080, debug=True)

1、编写注册接口register:

@app.route('/register',methods = ['post'])
def user_register():
    username1 = request.values.get('username')
    password1 = request.values.get('password')
    if username1 and password1:
        import re
        if re.match("^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).*$",username1) == None:
            return jsonify({"code": 202, "msg": "用户名必须是大小写字母+数字,请检查!"})
        elif re.match("^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).*$",password1)==None:
            return jsonify({"code": 203, "msg": "密码必须是大小写字母+数字,请检查!"})
        else:
            user_register = User_Register(username=username1, password=password1)
            session.add(user_register)
            session.commit()
            return jsonify({"code": 200, "msg": "恭喜,注册成功!"})
    else:
        return jsonify({"code": 201, "msg": "用户名/密码,请检查!"})

注意:

1、re.match为正则表达式匹配,匹配成功则返回None,需要import re
2、“^(?😦?=.[A-Z])(?=.[a-z])(?=.[0-9])).$”为字符串必须包含a-z和A-Z以及0-9
3、request.values.get(“username”)表示拿到传过来的字典中username的值,与request.get()方法不同

postman请求及返回:
postman
注意:

post请求不要写在params中,会出现在地址栏,不安全。get请求写在params中。
post请求写在body或者headers里面,注意类型(form或者raw或者json之类)都需要和代码对应。

2、完成一个user_login接口,判断:用户名是否在数据库中;密码是否和用户名匹配:

@app.route('/login',methods = ['post'])
def user_login():
    username1 = request.values.get('username')
    password1 = request.values.get('password')
    if username1:
        username_list = session.query(User_Register.username).all()
        print(username_list)
    
        username_exists = session.query(User_Register.password).filter(User_Register.username == username1).first()
        print(username_exists)
        # 用户名存在,判断密码是否符合
        if username_exists:
            print(username1 + "在用户列表中")
            password_one = session.query(User_Register.password).filter(
                User_Register.username == username1).first()  # result = Test.query.filter(Test.username == 'guest1').first()
            print(password1)
            print(str(username1) + "对应的密码为:" + str(password_one))
            if password1 in password_one:
                return jsonify({"code": 0, "msg": "密码正确,登录成功!"})
            else:
                return jsonify({"code": 205, "msg": "密码错误,请重新输入!"})
        else:
            print(username1 + "不在用户列表中")
            return jsonify({"code": 203, "msg": "用户名未注册,请重新注册"})
    else:
        return jsonify({"code": 201, "msg": "请输入用户名"})

另外一种判断用户名是否存在的写法:

    from sqlalchemy.sql import exists
    username_exists = session.query(
        exists().where(User_Register.username == username1)
    ).scalar()
    if username1 in username_list: 

3、完成一个userlist接口,以指定格式返回用户名和密码:

'''定义userlist接口,返回所有username和password'''
@app.route('/register/userlist',methods = ['get'])
def user_list():
    getdata = session.query(User_Register.username,User_Register.password).all()
    print(getdata)
    return str(getdata)

1、返回多个列,直接加逗号就可以了
2、这里最好处理成json格式,或者其他指定格式,但是我还不会写,格式转换不太会

至此服务端接口全部设置完成。其他客户端的操作不要写在服务端的脚本中了。

4、随机生成一百组数据,并写入到数据库中:

import random
import string
import requests

def auto_register(username_auto,password_auto):
    postdata ={"username":username_auto,"password":password_auto}
    response=requests.post("http://localhost:8080/register",data=postdata)
    print (1)
    print(response.text)
    return response

for i in range(100):
    username_auto = ''.join([random.choice(string.ascii_uppercase +string.ascii_lowercase+ string.digits) for n in range(10)])
    password_auto = ''.join([random.choice(string.ascii_uppercase +string.ascii_lowercase+ string.digits) for n in range(10)])
    print (username_auto,password_auto)
    auto_register(username_auto,password_auto)

注意:

1、命名中的循环有点问题,还不太会写。这个用户名和密码都固定为10位大小写字母和数字了。
2、这里没有去重处理,也还不太会写。
3、response是相应,response.text才是响应获取的内容。
4、response.text 返回的是一个 unicode 型的文本数据,response.content 返回的是 bytes 型的二进制数据。如果想取文本数据可以通过response.text 如果想取图片、文件,则可以通过 response.content。
5、string.ascii_uppercase +string.ascii_lowercase+ string.digits分别表示大写字母、小写字母和数字

5、将userlist接口中的数据下载到本地

'''将userlist接口中的数据下载到本地'''
def user_down():
    response = requests.get("http://localhost:8080/register/userlist")
    with open("XXX本地的绝对路径/user_list.txt","w") as f:
        f.write(str(response.text))
        print(response.text)
user_down()

这里也是还没有进行格式转换

6、清空本地数据库:

'''清空数据库'''
def delete_sql():
    list = session.query(User_Register).all()
    session.delete(list)
    session.commit()

delete_sql()

写是这样写,但是运行后没有作用,最后还是手动清空的。

7、读取本地生成的文件,将文件中记录的用户名和密码批量重新注册在数据库中。

'''读取文件,批量注册'''
def auto_register():
    with open("XXX本地的绝对路径/user_list.txt","r") as f:
        contents=f.read()
        print(contents)
        print(type(contents))
        c=[]
        c=eval(contents)
        print(c)
        print(type(c))
    for i in c:
        username_txt=i[0]
        print(username_txt)
        password_txt=i[1]
        print(password_txt)
        userdata = {"username": username_txt, "password": password_txt}
        response = requests.post("http://localhost:8080/register", data=userdata)
    return response

auto_register()

注意:

1、eval()函数就是把字符串转换成列表/元组/字典,看上去想什么就能转成什么,对应的是str(),把其他的转成字符串。不过eval函数不安全。
2、要把字符串转换成列表才方便取值,不然第一个值是{、(之类的

这样就完成啦。
第一个python小练习,很多东西都不会,还遗留了很多问题,只是勉强完成了需求。先记录在这里,以后再修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值