中心线

一个热爱“自由”的笔记博客

分享一个用SQLALchemy 实现的命令行版博客程序

| 0 comments

本文分享的是一个我用SQLALchemy 实现的一个命令行版博客程序,实现了简单的创建用户,创建文章,各种查询显示和删除功能。涉及的技术有SQLALchemy的外键关系,一对多、一对一。另外该程序也用到了基本的SQLALchemy的常用查询功能。该程序是我另一篇文章
SQLAlchemy 实例代码,Python命令行实现增删改查功能 的完善版,虽然该程序不够完善但是可以作为简单的入门例子倒是不错的。

代码共有差不多300行,下面分享出来。

先看交互图片:


代码一 models.py


'''SQLAlchemy 外键关系一对多示例
我的博客地址:https://www.z10.xin
'''
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import (Column, String, Text, Integer, BIGINT, ForeignKey,
    DateTime) 
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, relationship, backref

import settings


engine = create_engine(settings.URI_1)
ModelBase = declarative_base()
Session = sessionmaker(bind=engine)


class ModelsMixin(object):
    id = Column(BIGINT, primary_key=True, autoincrement=True)


class User(ModelBase, ModelsMixin):
    __tablename__ = 'users'

    username = Column(String(64), nullable=False, index=True)
    password = Column(String(64), nullable=False)
    email = Column(String(64), nullable=False, index=True)
    articles = relationship('Article', backref='author')
    userinfo = relationship('UserInfo', backref='user', uselist=False)      # uselist=False 把一对多关系,变为一对一

    def __repr__(self):
        return "{}{}".format(self.__class__.__name__, self.username)


class UserInfo(ModelBase, ModelsMixin):
    __tablename__ = 'userinfos'

    name = Column(String(64), nullable=True, index=True)
    qq = Column(String(11), nullable=True)
    phone = Column(String(11), nullable=True)
    user_id = Column(BIGINT, ForeignKey('users.id'))


class Article(ModelBase, ModelsMixin):
    __tablename__ = 'articles'

    title = Column(String(255), nullable=False, unique=True, index=True,
                   default="这是默认的文章标题")
    content = Column(Text, nullable=True)
    user_id = Column(BIGINT, ForeignKey('users.id'))
    
    def __repr__(self):
        return "{}{}".format(self.__class__.__name__, self.title)

if __name__ == '__main__':
    ModelBase.metadata.create_all(engine)

代码二 settings.py


URI_1 = 'postgresql+psycopg2://u_zsf:iiii@localhost:5432/testdb3'

该文件只有这一行,咳咳!

代码三 main.py


"""
使用 SQLAlchemy 创建简单博客程序,实现使用终端命令行进行交互。
数据表:
    1. User
        @username
        @password
        @email
        @articles
        @userinfo
    2. UserInfo
        @name
        @qq
        @phone
        @user_id
    3. Article
        @title
        @content
        @user_id
UserInfo 表是User表的外键,一对一关系。
Article 表是User表的外键,一对多关系
>>>程序主要功能
    1. 创建用户
    2. 给用户添加附加信息
    3. 给指定用户添加文章
    4. 删除用户
    5. 查询单个用户
    6. 查询所有用户
    7. 模糊查询用户
    8. 查询用户文章
>>>程序分为3个文件
    1. models.py
    2. main.py
    3. settings.py
models.py 是表结构文件,执行:python models.py 给数据库创建表,命令执行了文件最底部的代码
文件底部:
    if __name__ == '__main__':
        ModelBase.metadata.create_all(engine)

main.py 文件是我们实现的与数据库交互查询的内容,所有交互功能都在这个文件里边。
>>>运行该程序
    1. 修改setting.py 文件中的 数据库地址 ,按需修改成你的地址即可
        URI_1 = 'postgresql+psycopg2://u_zsf:iiii@localhost:5432/testdb3'
    2. 执行 python models.py
    3. 执行 python main.py 进行与数据库交互

我的博客:https://www.z10.xin
"""
from models import User, UserInfo, Article, Session, ModelBase
from widget import messageLine
session = Session()     # 创建会话实例


# 创建用户
def createUser():
    # 创建用户
    username = input('请输入您的用户名:\n>>>')
    password = input('请输入您的密码:\n>>>')
    email = input('请输入您的Email:\n>>>')
    yesNo = input('是否确认所填用户信息无误Y/n:\n>>>')
    if yesNo in ('Y', 'y'):
        user = User(username=username, password=password, email=email)
        session.add(user)
        session.commit()
        messageLine('用户创建成功!')
    else:
        messageLine('您一取消创建用户!')
    print('\n\n')

# 删除一个用户
def deleteUser():
    username = input('请输入要删除的用户名:\n>>>')
    yesNo = input('是否确定删除:Y/n\n>>>')
    if yesNo in ('Y', 'y'):
        user = session.query(User).filter_by(username=username).first()
        session.delete(user)
        session.commit()
    elif yesNo in ('N', 'n'):
        print("删除操作已取消!")
    print('\n\n')

# 获取一个用户
def getUser():
    # 查询单个用户
        username = input('请输入要查询的用户名:\n>>>')
        user = session.query(User).filter_by(username=username).first()
        if user.userinfo:
            print(
                "username: {username}\n"
                "password: {password}\n"
                "email: {email}\n"
                "附加信息:\n\t"
                "昵称: {name}\n\t"
                "QQ: {qq}\n\t"
                "手机: {phone}\t".format(
                    username=user.username,
                    password=user.password,
                    email=user.email,
                    name=user.userinfo.name,
                    qq=user.userinfo.qq,
                    phone=user.userinfo.phone
                )
            )
        else:
            print(
                    "username: {username}\n"
                    "password: {password}\n"
                    "email: {email}\n"
                    "附加信息: 空".format(
                        username=user.username,
                        password=user.password,
                        email=user.email,
                    )
                )
        messageLine('查询结束!')
        print('\n\n')

# 获取全部用户
def getAllUser():
    users = session.query(User).filter()
    for user in users:
        if user.userinfo:
            print(
                "username: {username}\n"
                "password: {password}\n"
                "email: {email}\n"
                "附加信息:\n\t"
                "昵称: {name}\n\t"
                "QQ: {qq}\n\t"
                "手机: {phone}".format(
                    username=user.username,
                    password=user.password,
                    email=user.email,
                    name=user.userinfo.name,
                    qq = user.userinfo.qq,
                    phone = user.userinfo.phone
                )
            )
            messageLine(user.userinfo.name)
        else:
            print(
                "username: {username}\n"
                "password: {password}\n"
                "email: {email}\n"
                "附加信息: 空".format(
                    username=user.username,
                    password=user.password,
                    email=user.email,
                )
            )
            messageLine('-')

    messageLine('所有用户信息已打印输出完毕!')
    print('\n\n')

# 按用户名模糊查询
def getInUser():
    # 按用户名模糊搜索
    username = input('输入用户名的部分即可:\n>>>')
    messageLine('-')
    users = session.query(User).filter(User.username.like("%{}%".format(username))).all()
    for user in users:
        if user.userinfo:
            print(
                "username: {username}\n"
                "password: {password}\n"
                "email: {email}\n"
                "附加信息:\n\t"
                "昵称: {name}\n\t"
                "QQ: {qq}\n\t"
                "手机: {phone}".format(
                    username=user.username,
                    password=user.password,
                    email=user.email,
                    name=user.userinfo.name,
                    qq = user.userinfo.qq,
                    phone = user.userinfo.phone
                )
            )
            messageLine(user.userinfo.name)
        else:
            print(
                "username: {username}\n"
                "password: {password}\n"
                "email: {email}\n"
                "附加信息: 空".format(
                    username=user.username,
                    password=user.password,
                    email=user.email,
                )
            )
            messageLine('-')
    messageLine('包含: {} 的所有用户信息已打印输出完毕!'.format(username))

    if len(users) == 0:
        messageLine('用户不存在,_^_^_')
    
    print('\n\n')

# 给用户添加附加信息
def addUserInfo():
    # 给用户添加附加信息
    username = input('请输入要添加附加信息的用户名:\n>>>')
    name = input('请输入一个昵称:\n>>>')
    qq = input('请输入您的QQ号:\n>>>')
    phone = input('请输入您的手机号:\n>>>')
    yesNo = input('信息添加完毕,是否添加到数据库Y/n\n>>>')
    if yesNo in ('y', 'Y'):
        user = session.query(User).filter_by(username=username).first()
        userinfo = UserInfo(name=name, qq=qq, phone=phone, user=user)
        session.add(userinfo)
        session.commit()
        messageLine('{username} 的附加信息已经更新成功!'.format(username=username))
        messageLine('--')
    elif yesNo in ('n', 'N'):
        messageLine('您已取消添加附加信息!')
    print('\n\n')

# 创建文章
def createArticle():
    username = input('请选择使用哪个用户来创建文章,输入用户名: ')
    user = session.query(User).filter(User.username==username).first()
    title = input('文章标题:\n>>>')
    content = input('文章内容:\n>>>')
    yesNo = input('是否保存文章:Y/n\n>>>')
    if yesNo in ('y', 'Y'):
        article = Article(title=title, content=content, user_id=user.id)
        session.add(article)
        session.commit()
        messageLine('文章:{} 已经创建成功!'.format(title))
    elif yesNo in ('n', 'N'):
        messageLine('您已取消文章创建!')

# 查询文章
def getArticle():
    username = input('文章用户名:\n>>>')
    user = session.query(User).filter(User.username==username).first()
    articles = session.query(Article).filter(Article.user_id==user.id).all()
    article_len = len(articles)
    for article in articles:
        print(
            "文章标题: {}\n"
            "文章内容: {}".format(
                article.title,
                article.content)
        )
    messageLine('以上是:{} 的所有文章。共 {} 篇'.format(username, article_len))

# 循环交互
while True:
    tAoption = input(
        "请选择操作:\n"
        "{'cu': 创建用户, 'SD': 查询单个用户, 'GA': 查询所有用户,"
        "'AI': 添加用户附加信息,}\n{'du': 删除用户, 'su': 按用户名模糊查询,"
        "' ca': 创建文章, 'car': 查询用户文章, Q': 退出}\n>>>")
    messageLine('-')
    if tAoption in ('cu', 'CU', 'cU', 'Cu'):
        # 创建用户
        createUser()
    elif tAoption in ('sd', 'SD', 'Sd', 'sD'):
        getUser()
    elif tAoption in ('ai', 'AI', 'aI', 'Ai'):
        addUserInfo()
    elif tAoption in ('ga', 'GA', 'Ga', 'gA'):
        getAllUser()
    elif tAoption in ('su', 'SU'):
        getInUser()
    elif tAoption in ('du', 'DU', 'dU', 'Du'):
        deleteUser()
    elif tAoption in ('ca', 'CA', 'cA', 'Ca'):
        createArticle()
    elif tAoption in ('car', 'CAR'):
        getArticle()
    if tAoption in ('q', 'Q'):
        messageLine('程序已退出!')
        break

第四个文件 widget.py


该文件差点忘了都,值显现了一个功能,就是打印分割线。

def messageLine(message):
    messageLineWidth = 120
    messageLength = int(len(message))
    befor = (messageLineWidth - messageLength) // 2
    lineFlag = befor * '-'
    print('{0}{1}{0}'.format(lineFlag, message))

除非注明,否则均为中心线原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.z10.xin/archives/310

发表评论

Required fields are marked *.