今天给大家分享一个 我最近使用python 框架 fastapi 写的一个web项目 ,叫图书管理系统。项目主要是来巩固 python的编程技术。使用的是前端后 分离开发。
主要实现的功能:
1、用户管理:可以新增、编辑、删除用户信息。
2、图书管理:添加、修改、删除图书,并能够查看图书列表。
3、借阅管理:记录图书借阅、归还情况。
4、数据展示:通过前端页面展示系统中的图书、用户信息,提供了简洁、易用的界面。
使用技术
FastAPI:后端使用FastAPI框架
MySQL 5.7:作为关系型数据库管理系统,MySQL用于存储用户和图书信息,并支持CRUD操作。
Vue 2:前端使用Vue2框架,配合Element UI组件库,提供响应式页面和现代化用户界面。
Element UI:帮助实现简洁且功能丰富的UI设计,极大提高了前端开发效率。
先给大家看一下 页面效果
首页:
代码结构:
菜单个别页面截图:
项目零星代码:
<template>
<div class="home-container">
<el-container>
<el-aside width="200px">
<el-menu
:default-active="$route.path"
class="el-menu-vertical"
background-color="#304156"
text-color="#bfcbd9"
active-text-color="#409EFF"
router
>
<el-menu-item index="/">
<i class="el-icon-s-home"></i>
<span slot="title">首页</span>
</el-menu-item>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-reading"></i>
<span>图书管理</span>
</template>
<el-menu-item index="/category/list">
<i class="el-icon-collection"></i>
<span slot="title">图书分类</span>
</el-menu-item>
<el-menu-item index="/book/list">
<i class="el-icon-notebook-2"></i>
<span slot="title">图书列表</span>
</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-document"></i>
<span>借用归还</span>
</template>
<el-menu-item index="/borrow/list">
<i class="el-icon-document-copy"></i>
<span slot="title">借用列表</span>
</el-menu-item>
<el-menu-item index="/return/list">
<i class="el-icon-document-checked"></i>
<span slot="title">归还列表</span>
</el-menu-item>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-user-solid"></i>
<span>会员管理</span>
</template>
<el-menu-item index="/member/list">
<i class="el-icon-user"></i>
<span slot="title">会员列表</span>
</el-menu-item>
<el-menu-item index="/recharge/list">
<i class="el-icon-money"></i>
<span slot="title">充值记录</span>
</el-menu-item>
</el-submenu>
<el-submenu index="4">
<template slot="title">
<i class="el-icon-user"></i>
<span>系统管理</span>
</template>
<el-menu-item index="/admin/list">
<i class="el-icon-user"></i>
<span slot="title">管理员列表</span>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header>
<div class="header-right">
<el-dropdown trigger="click" @command="handleCommand">
<span class="el-dropdown-link">
{{ userInfo ? userInfo.username : 'admin' }}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</el-header>
<el-main>
<router-view />
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'Home',
computed: {
...mapState('user', ['userInfo'])
},
methods: {
handleCommand(command) {
if (command === 'logout') {
this.$store.dispatch('user/resetToken').then(() => {
this.$router.push('/login')
})
}
}
}
}
</script>
<style lang="scss" scoped>
.home-container {
height: 100vh;
.el-container {
height: 100%;
}
.el-aside {
background-color: #304156;
.el-menu {
border: none;
}
}
.el-header {
background-color: #fff;
box-shadow: 0 1px 4px rgba(0,21,41,.08);
display: flex;
justify-content: flex-end;
align-items: center;
.header-right {
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
}
}
.el-main {
background-color: #f0f2f5;
padding: 0;
}
}
</style>
再分享一段pyhon 后端代码:
from datetime import timedelta
from typing import Optional
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from core.config import settings
from core.security import create_access_token
from core.response import ResponseModel
from core.exceptions import CustomException
from core.deps import get_current_admin
from db.database import get_db
from models.admin import Admin
from schemas.admin import AdminLogin, Token, AdminResponse, AdminCreate, AdminUpdate, AdminListResponse
import hashlib
router = APIRouter()
@router.post("/login")
async def login(login_data: AdminLogin, db: Session = Depends(get_db)):
# 查询管理员
admin = db.query(Admin).filter(Admin.username == login_data.username).first()
if not admin:
raise CustomException(msg="用户名或密码错误")
# MD5加密密码进行比对
md5_password = hashlib.md5(login_data.password.encode()).hexdigest()
if admin.password != md5_password:
raise CustomException(msg="用户名或密码错误")
# 生成访问令牌
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": str(admin.id)},
expires_delta=access_token_expires
)
token = Token(
access_token=access_token,
token_type="bearer"
)
return ResponseModel.success(
data=token.model_dump(),
msg="登录成功"
)
@router.get("/info")
async def get_admin_info(admin: Admin = Depends(get_current_admin)):
return ResponseModel.success(
data=AdminResponse.model_validate(admin),
msg="获取成功"
)
@router.get("/list")
async def get_admin_list(
db: Session = Depends(get_db),
current_admin: Admin = Depends(get_current_admin),
page: int = Query(1, ge=1),
page_size: int = Query(10, ge=1, le=100),
username: Optional[str] = None
):
query = db.query(Admin)
if username:
query = query.filter(Admin.username.like(f"%{username}%"))
total = query.count()
items = [AdminResponse.model_validate(item) for item in query.offset((page - 1) * page_size).limit(page_size).all()]
response = AdminListResponse(total=total, items=items)
return ResponseModel.success(data=response.model_dump())
@router.get("/detail/{admin_id}")
async def get_admin_detail(
admin_id: int,
db: Session = Depends(get_db),
current_admin: Admin = Depends(get_current_admin)
):
admin = db.query(Admin).filter(Admin.id == admin_id).first()
if not admin:
raise CustomException(msg="管理员不存在")
return ResponseModel.success(data=AdminResponse.model_validate(admin))
@router.post("/create")
async def create_admin(
admin_in: AdminCreate,
db: Session = Depends(get_db),
current_admin: Admin = Depends(get_current_admin)
):
# 检查用户名是否已存在
if db.query(Admin).filter(Admin.username == admin_in.username).first():
raise CustomException(msg="用户名已存在")
# MD5加密密码
md5_password = hashlib.md5(admin_in.password.encode()).hexdigest()
admin = Admin(
username=admin_in.username,
password=md5_password,
nickname=admin_in.nickname,
is_super=admin_in.is_super,
created_by=current_admin.username
)
db.add(admin)
db.commit()
db.refresh(admin)
return ResponseModel.success(data=AdminResponse.model_validate(admin))
@router.put("/update/{admin_id}")
async def update_admin(
admin_id: int,
admin_in: AdminUpdate,
db: Session = Depends(get_db),
current_admin: Admin = Depends(get_current_admin)
):
admin = db.query(Admin).filter(Admin.id == admin_id).first()
if not admin:
raise CustomException(msg="管理员不存在")
update_data = admin_in.model_dump()
admin.nickname = update_data['nickname']
db.commit()
db.refresh(admin)
return ResponseModel.success(data=AdminResponse.model_validate(admin))
@router.delete("/delete/{admin_id}")
async def delete_admin(
admin_id: int,
db: Session = Depends(get_db),
current_admin: Admin = Depends(get_current_admin)
):
admin = db.query(Admin).filter(Admin.id == admin_id).first()
if not admin:
raise CustomException(msg="管理员不存在")
# 不允许删除超级管理员
if admin.is_super:
raise CustomException(msg="不能删除超级管理员")
db.delete(admin)
db.commit()
return ResponseModel.success()
项目虽然功能不是很复杂,但是对于刚开始学习编程的小伙伴,有可能也是有难度的,不过如果自己能尝试着 敲一些项目,会对自己的学习到的编程知识有一个更深的体会。对此项目有兴趣的小伙伴可以去看看学习一下。【非开源项目】
https://wwwoop.com/home/Index/projectInfo?goodsId=98&typeParam=1&subKey=-1