ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

医药信息管理系统实战:Django+MySQL源码与数据库设计详解

医药信息管理系统实战:Django+MySQL源码与数据库设计详解 医药信息管理系统这个标题我见得多了但真正能把“源码数据库文档”三件套做完整、做扎实的项目确实不多。这两年带过不少毕业设计和企业小团队大家一提到医药信息管理第一反应都是“不就是增删改查嘛”可真做起来药品批次、库存流水、供应商对账、处方关联、权限隔离哪一块都能把人绕晕。这篇博文我就以一个完整落地项目的视角从需求拆解、技术选型、数据库设计、核心功能实现到部署上线、问题排查把整个基于Python Django的药店医药信息管理系统讲透。先说清楚这个系统能干什么。它面向的是小型连锁药店、单体药店的日常运营场景具备药品基础信息维护、分类管理、供应商和厂商档案、采购入库、销售出库、库存实时盘点、效期预警、药品下架、操作员权限管理、数据统计报表等完整能力。后端采用Python 3 Django框架数据库用MySQL前端使用Bootstrap进行界面构建整套系统封装了登陆认证、自动生成编号、低库存与过期提醒等机制配合详细的操作文档不管是课程设计、毕业设计还是企业内部信息化的起步原型都能直接复制运行和使用。适合谁来参考如果你是学生想找一个结构清晰、能写出设计文档的课设/毕设项目这篇内容可以帮你理清从ER图到代码的实现链路如果你是刚转行做Django开发的工程师这套系统的模块划分和业务建模思路对理解真实业务系统怎么落地很有帮助就算你只是想给自己药店做个简单的进销存工具这里的表结构设计和部分代码照搬过去改改就能用。1. 项目定位与整体需求拆解1.1 医药信息管理系统到底解决什么问题药店的日常管理远比想象中琐碎。看起来只是卖药背后牵扯到几件麻烦事药品的批号效期要盯着过期药必须及时下架库存台账要准确进货出货每一笔都不能乱供应商的货款要核对卖了什么、还剩多少要一清二楚还有员工的操作权限不能说随便一个收银员都能改药品进价。这些需求用Excel表格不是不能做但一旦数据量上来、多人同时操作版本错乱、公式覆盖、数据丢失的问题就层出不穷。我当时在项目初期和药店运营人员做过一次详细访谈他们反馈最频繁的场景就三个一是每天下班要对一遍当天的销售明细和库存变化二是每周要查一遍近效期药品清单三是月底要按供应商汇总采购金额。这三个困扰本质上指向的就是系统的三大核心——销售台账、效期预警、供应商往来管理。所以在这套Django系统里我并没有刻意堆砌功能模块而是紧紧咬住这几个核心业务痛点做深让系统在真实场景里“用得上”而不只是“能演示”。1.2 功能范围与模块划分基于上面的业务痛点我把系统拆成了六个逻辑模块。每个模块之间保持低耦合通过清晰的接口和数据库外键关联这样后期维护、加功能都方便用户认证与权限模块登录、退出、修改密码支持两种角色管理员、操作员。管理员可以管理用户操作员只能处理日常业务两种角色对应的菜单和数据权限都有区分。药品信息管理模块药品的基础档案包括名称、通用名、剂型、规格、生产厂家、批准文号、储存条件、销售价格、入库价格、药品分类等信息。支持药品的启用/停用状态切换停用的药品在前台销售中不可选择。库存管理模块记录每个药品品类的当前库存数量同时联动药品批次和效期支持盘点、库存调整操作每项操作都会生成流水。供应商管理模块维护供应商档案记录采购订单管理应付账款信息支持按时间区间和药品维度查看采购汇总。销售管理模块前台收银场景支持选择药品、录入数量、自动计算总价、打印小票销售完成后自动扣减库存并生成销售明细。数据统计模块按日/月维度展示销售总额、利润估算、药品销量排行以表格和图表形式呈现。这个模块划分是从业务中长出来的而不是照着某个“系统设计模板”硬分出来的。实际开发中也是这么迭代推进的先做药品管理和库存再做采购和销售最后才是统计和权限。这样的顺序每一步都有前面的数据做支撑不容易返工。2. 技术选型为什么是Django为什么用MySQL2.1 后端框架的选择逻辑选Django不是因为Python近两年热门而是这个项目的业务属性决定的。医药信息管理系统是一个典型的“数据密集事务性强”的Web应用对数据一致性、操作审计要求比较高页面数量不少但交互复杂度其实一般。Django这种“全家桶”风格框架自带ORM、表单处理、模板引擎、Admin后台、认证系统正好匹配这一类项目的开发节奏。对比一下其他方案就更清楚了。如果是Flask轻量是真的轻但用户认证、数据库迁移、表单校验都得自己组装这个项目光基础组件就要多写几百行代码。如果是FastAPI异步性能和API文档确实好但这套系统以服务端渲染的传统页面为主前端需要大量模板页面FastAPI在这方面的生态反而不如Django顺手。用Spring Boot当然也行但Java的工程化成本对一个小型医药管理系统来说显然偏重开发效率会肉眼可见地低一截。从团队协作和后期维护的角度看Django的MTV架构很清楚models.py里放数据模型、views.py里写业务逻辑、templates里放页面新同事接手项目半天就能定位到想改的代码。这在毕业设计、课程设计的场景里尤其重要——答辩的时候老师问到你某个功能在哪里实现的你能直接指出文件比什么都更有说服力。2.2 ORM不用手写SQL但心里要有SQLDjango的ORM非常成熟对MySQL、PostgreSQL、SQLite都支持得很好。这个项目我用的是MySQL原因很简单一方面MySQL在药品进销存这类场景下足够可靠另一方面考虑到这是一个需要提交数据库设计文档的项目MySQL的ER图工具和导出脚本都特别成熟写文档的时候很方便。用ORM的过程中我最大的体会是——不要迷信ORM也不要排斥原生SQL。ORM能解决90%的常规读写需求比如查询某个分类下的所有药品代码写起来非常直观# models.py 药品模型省略部分字段 class Medicine(models.Model): name models.CharField(通用名, max_length128) trade_name models.CharField(商品名, max_length128, blankTrue) category models.ForeignKey(MedicineCategory, on_deletemodels.PROTECT, verbose_name药品分类) specification models.CharField(规格, max_length64) unit models.CharField(单位, max_length16, default盒) manufacture models.CharField(生产厂家, max_length128) approval_number models.CharField(批准文号, max_length64, uniqueTrue) purchase_price models.DecimalField(入库价, max_digits10, decimal_places2) sale_price models.DecimalField(销售价, max_digits10, decimal_places2) is_active models.BooleanField(是否启用, defaultTrue) created_at models.DateTimeField(创建时间, auto_now_addTrue) def __str__(self): return f{self.name} {self.specification} class Meta: db_table medicine verbose_name 药品 ordering [-created_at]这里的on_deletemodels.PROTECT是一个值得细说的细节。当药品分类下还有药品档案时PROTECT策略会阻止你直接删除分类这在医药系统里是必须的——你删掉了一个分类下面关联的药品和历史流水就会变成无源之水报表对账的时候直接乱套。实际项目中我吃过这个亏最初图省事用的CASCADE结果测试时删了一个分类连带几十条库存流水全没了吓得赶紧改了约束。2.3 目录结构和环境隔离一个清晰的项目目录是“源码文档”交付质量的直接体现。我见过太多Django项目views.py里硬塞了两千行代码models.py把所有表都堆一个文件美其名曰“快速开发”后期加一个字段都要翻半天代码。这个项目我在初始化时就做了一个合理的分层apps/目录下按业务域拆分子应用auth_user用户认证、medicine药品档案、stock库存、supplier供应商、sale销售、report统计。每个子应用内部又按Django惯例拆分为models.py、views.py、urls.py、admin.py同时增加一个services.py放业务操作类逻辑避免views里写太多业务代码。templates/目录按子应用再建子目录避免模板重名混乱。static/目录集中存放CSS、JS和图片静态文件在开发环境和生产环境通过配置切换。另外我用了虚拟环境来管理本项目依赖这是几乎每个Django项目都应该做但很多人会忽略的步骤。用venv创建独立环境后再通过pip freeze requirements.txt导出依赖列表别人克隆代码后直接pip install -r requirements.txt就能把环境拉起来省掉了大量“在我电脑上是好的”这类扯皮问题。实际交付文档时我还会额外附一页环境说明写清楚Python版本、MySQL版本、Django版本、关键第三方库版本。3. 数据库设计的核心实现3.1 实体关系拆解与数据表规划医药信息管理系统的数据库设计我从一开始就按照“主数据—业务单据—流水台账”三层结构来规划。这个思路可以避免一个典型设计失误把所有信息都塞在几张宽表里导致字段冗余、更新异常。主数据层用户表、角色表、药品分类表、药品档案表、供应商表。这些表存储的是基础档案变化频率低是整个系统的数据根基。业务单据层采购订单表、采购入库单表、销售订单表、销售明细表。这些表记录一次完整的业务事件比如一次采购、一次销售。流水台账层库存流水表、效期批次表、操作日志表。这些表面向高频写入场景记录每一个影响库存或涉及关键操作的变化细节。这样的分层在后续写统计SQL和查询语句时尤其好使。比如想统计某段时间内每个药品的销量直接查销售明细表做分组求和想定位一笔库存异常是哪次操作引起的从库存流水表按时间倒序查就行不用在一堆业务表里翻来翻去。3.2 关键表结构与字段设计要点拿库存和销售这两块核心表做个详细拆解。药品批号和效期管理是医药系统区别于普通商品进销存的灵魂。同一支药品不同批号、不同效期价格可能都不一样近效期的要先卖。我在表设计上使用了单独的medicine_batch表CREATE TABLE medicine_batch ( id int NOT NULL AUTO_INCREMENT, medicine_id int NOT NULL COMMENT 药品档案ID, batch_no varchar(64) NOT NULL COMMENT 生产批号, expire_date date NOT NULL COMMENT 有效期至, quantity int NOT NULL DEFAULT 0 COMMENT 当前批次剩余数量, purchase_price decimal(10,2) NOT NULL COMMENT 批次入库价, sale_price decimal(10,2) NOT NULL, created_at datetime NOT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT药品批次效期表;销售明细表则必须记录销售当天的快照信息包括药品名称、规格、单价、数量、批号以及关联的销售单号和操作员。这里有一个很重要的原则业务单据上要冗余一份药品名称和价格快照而不是只存medicine_id后去关联主表。为什么因为药品档案将来可能调价、改名称如果销售明细完全依赖关联查询历史报表的数据就会跟着当前档案变动这就是日常说的“历史单据被篡改”的隐患。库存流水表字段也很关键包括药品ID、批次ID、变动类型入库/销售出库/盘点调整/报损、变动前数量、变动后数量、关联业务单号、操作人、备注。我额外加了一个唯一索引(batch_id, change_type, order_no)来防止同一条业务数据被重复执行导致库存不准确——这一个细节在彻底联调时帮了大忙接口反复调用时不会产生重复流水。3.3 数据安全与合规细节医药行业的数据不容忽视的两个关键词是“可追溯”和“权限隔离”。可追溯靠的就是上面的流水表完整记录所有操作任何一笔库存变动都能查出来是谁、在什么时间、基于哪个单据操作的。权限隔离则靠Django自带的用户认证加上自定义的中间件对不同角色请求的URL做访问控制。数据库字符集统一使用utf8mb4这个一定要强调因为药品名称里经常出现特殊符号、生僻字utf8mb4才能完整支持。所有金额字段使用DecimalField对应MySQL的decimal类型绝对不要用float存金额——浮点数在累计统计时会出现0.10.2不等于0.3这类精度问题对医药进销存这种对账敏感的系统来说是不可接受的。3.4 数据字典与状态字段设计业务系统中状态字段是最容易被忽略、但又最影响扩展性的。采购订单我用状态字段status区分“待审核、已入库、已取消”销售订单用status区分“已完成、已退货”用户表里用is_active和role区分权限范围。在建表时我给每个状态字段都加注释并且约定编码值从0开始递增方便后期加状态不影响历史数据。数据字典我建议单独建一张表统一维护比如药品单位盒、瓶、袋、支、剂型片剂、胶囊、口服液、储存条件常温、阴凉、冷藏。虽然Django里用choices也能写死在代码中但把字典放在数据库里以后从管理后台就能维护不用改代码重新部署对业务人员更友好。这个项目中选择的组合方案是代码里用choices保证表单校验数据库里建字典表供维护和报表展示用。4. 核心功能模块实现与代码逻辑4.1 用户登录与权限控制Django自带的django.contrib.auth提供了完整的用户认证基础包括User模型、Session管理、密码哈希。实际项目中我把它和多用户角色结合起来使用。扩展用户信息的标准做法是通过OneToOneField关联到Django的User模型而不是直接修改源码里的User表。# users/models.py from django.contrib.auth.models import User class Profile(models.Model): user models.OneToOneField(User, on_deletemodels.CASCADE, related_nameprofile) role models.CharField(角色, max_length16, choices((admin, 管理员), (operator, 操作员)), defaultoperator) phone models.CharField(联系电话, max_length20, blankTrue) is_delete models.BooleanField(删除标记, defaultFalse) class Meta: db_table user_profile权限控制层面我没有选择最复杂的Django自带Permission框架而是通过一个自定义中间件在请求进入View之前先校验当前用户角色和请求路径的访问关系。原因很简单这个系统的角色只有两种用中间件控制反而最直观、最容易解释。管理员能访问/admin/和/report/目录下的所有页面操作员只能在/sale/和/stock/list/等业务页面内操作无法打开用户管理相关地址。登录视图做了一个增强处理记录登录IP、登录时间和登录失败次数。连续失败5次锁定登录15分钟。虽然是个小功能但放在部署到公网的演示环境中很能增强安全性说服力。这些记录都写入操作日志表operation_log后台可按时间查询也算是对医药信息系统审计要求的一个呼应。4.2 药品档案与库存初始化药品的增删改查是系统的基础功能这里有两个关键点批准文号的唯一性校验和药品停用时的关联检查。approval_number models.CharField(批准文号, max_length64, uniqueTrue)这一行用数据库级别的唯一约束保证了同一批准文号不会被重复录入。药品停用操作则要检查当前库存是否为0如果仍有库存则不允许直接停用必须进入盘点模块将库存清零后才能操作这样避免了账面库存与在售状态矛盾。药品录入界面我用Django ModelForm做表单校验并集成了Bootstrap的样式。Bootstrap最大的价值在于不费什么力气就能得到一套还算体面的界面。页面包括药品列表页搜索、分页、状态筛选、新增/编辑页表单校验、详情页展示基础信息、库存、历史流水。列表页的搜索和筛选直接用Django ORM的Q对象组合条件代码量很小但用户体感很好# medicine/views.py def medicine_list(request): keyword request.GET.get(keyword, ).strip() category_id request.GET.get(category, ).strip() medicines Medicine.objects.select_related(category).all() if keyword: medicines medicines.filter(Q(name__icontainskeyword) | Q(trade_name__icontainskeyword) | Q(approval_number__icontainskeyword)) if category_id: medicines medicines.filter(category_idcategory_id) # 分页处理 paginator Paginator(medicines, 10) page_obj paginator.get_page(request.GET.get(page)) return render(request, medicine/list.html, {page_obj: page_obj})4.3 采购入库与库存流水联动采购入库是库存增加的唯一入口除盘点调整外。整个流程设计为创建采购订单→审核→执行入库。入库操作时根据采购明细里的药品、批号、有效期生成批次记录同时增加药品主库存写入库存流水。这里我用事务包装确保“主库存增加、批次记录新增、流水生成”这三步要么全部成功要么全部回滚from django.db import transaction transaction.atomic def purchase_inbound(request, order_id): order PurchaseOrder.objects.select_related(supplier).get(idorder_id) order_items order.items.all() for item in order_items: # 更新药品总库存 medicine item.medicine medicine.stock_quantity item.quantity medicine.save() # 新增或更新批次记录 MedicineBatch.objects.create( medicinemedicine, batch_noitem.batch_no, expire_dateitem.expire_date, quantityitem.quantity, purchase_priceitem.purchase_price, sale_priceitem.sale_price, ) # 写库存流水 StockLog.objects.create(...) order.status 已入库 order.save()这一段的业务逻辑是整个系统最核心的地方也是写文档时需要重点解释的部分。学生在答辩时如果能讲清楚“为什么要用事务、为什么批次要单独建表”基本上也就掌握了这套系统的设计精髓。实际操作中一定要记得在采购入库表单里加有效期校验有效期必须晚于入库当天否则不能入库这个校验在ModelForm的clean方法里实现。4.4 销售出库与扣减批次库存销售模块我采用的是“先选药品自动核价提交后台事务内完成扣减”的处理方式。前端页面通过JavaScript实现的药品选择框使用jQuery发起AJAX请求根据药品ID实时获取库存量和销售价格将所选药品加入临时购物车列表提交时一次性发送全部销售明细。后端处理销售单的核心逻辑和购入类似也是放在一个事务里生成销售主记录含总金额、操作员、销售时间生成销售明细记录按批号的效期顺序先近效期扣减对应批次的库存同时扣减药品总库存写库存流水。这里扣减批次库存的顺序我特意按expire_date升序排列模拟FIFO原则transaction.atomic def sale_confirm(request): if request.method POST: items_data json.loads(request.POST.get(items)) sale_order SaleOrder.objects.create( order_nogenerate_order_no(), total_amountsum(item[amount] for item in items_data), operatorrequest.user, status已完成 ) for item in items_data: batches MedicineBatch.objects.filter( medicine_iditem[medicine_id], quantity__gt0 ).order_by(expire_date) need_qty int(item[quantity]) for batch in batches: if need_qty 0: break deduct_qty min(batch.quantity, need_qty) batch.quantity - deduct_qty batch.save() need_qty - deduct_qty # 写库存流水和销售明细这段代码注意一个细节查询批次时使用了quantity__gt0和order_by(expire_date)从数据库层面就过滤掉了无库存批次并保证了扣减顺序。这种写法比先查所有批次再在Python里排队更高效也更不容易出错。4.5 效期预警与低库存提醒药品近效期预警是药店运营人员最关心的功能。我把它做成了一个独立页面和一组后台定时任务。页面上默认展示3个月之内到期的批次按到期日近到远排列高亮显示非常紧急的批次。后台定时的实现有两种方案一是写Django management command用crontab每天凌晨跑一次生成预警二是直接在页面上每次打开时动态计算。这个项目我选用后者因为数据量不大、查询有索引实时计算完全是够用的。打开预警页面时ORM自带的条件查询直接生成SQL执行效率可接受from datetime import datetime, timedelta def expire_warning(request): today datetime.now().date() deadline today timedelta(days90) warning_list MedicineBatch.objects.filter( expire_date__ltedeadline, quantity__gt0 ).select_related(medicine).order_by(expire_date) ...低库存提醒则是在药品主表上加了一个stock_threshold字段当当前库存小于等于该阈值时在列表页显示“库存预警”标签dashboard首页显示汇总数据。给每个药品单独设置阈值比统一一个固定值更符合实际——一盒便宜的维生素C和一种稀缺血友药安全库存线显然不一样。5. 实操过程从零搭建到运行调试5.1 环境准备与项目初始化如果你是第一次跑这套系统建议严格按照下面的顺序来。稍微图省事跳步骤后面排查起来反而会花掉更多时间。第一步安装Python和MySQL。Python版本我用的是3.10Django版本4.2 LTS这两个版本目前搭配最稳。MySQL建议直接用8.0版本字符集设置utf8mb4。安装完Python后务必在命令行确认一下python --versionWindows系统下有时会不小心装成系统自带的老版本。第二步创建虚拟环境并安装依赖python -m venv venv source venv/bin/activate # Windows用 venv\Scripts\activate pip install -r requirements.txt第三步在MySQL中创建独立数据库。建议这个项目使用独立数据库用户并赋予该用户只在项目库上的权限避免误操作其他库。创建命令大致是CREATE DATABASE pharma_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER pharma_userlocalhost IDENTIFIED BY 你的密码; GRANT ALL PRIVILEGES ON pharma_db.* TO pharma_userlocalhost; FLUSH PRIVILEGES;第四步修改项目的settings.py中的数据库配置把HOST、PORT、NAME、USER、PASSWORD对应替换。5.2 模型迁移与初始化数据数据库配置好以后执行命令生成并应用表结构python manage.py makemigrations python manage.py migrate迁移完成后需要创建系统管理员账号直接用Django自带的createsuperuser工具python manage.py createsuperuser值得一提的是我把药品分类、基础单位、系统配置这些初始数据写成了fixture文件放在fixtures/目录下。这样别人拿到源码后一条命令python manage.py loaddata initial_data.json就能把基础数据灌进去不需要手工一条条录入。交付时的体验很不一样用户拿到手直接有数据可看而不是面对一堆空白页面发呆。5.3 本地运行与调试技巧一切就绪后运行python manage.py runserver 0.0.0.0:8000启动开发服务器浏览器访问http://127.0.0.1:8000就能看到登录页面。开发调试阶段建议打开settings.py里的这两个配置DEBUG True ALLOWED_HOSTS [*] # 仅限本地开发如果想在手机上调试后台用runserver 0.0.0.0:8000后手机和电脑连同一个局域网访问http://电脑IP:8000即可。5.4 部署到服务器的关键点部署环节如果是小型项目或课程演示最省事的方案是宝塔面板 Nginx Gunicorn。大致步骤是把项目上传到服务器创建虚拟环境安装依赖配置MySQL数据库然后使用Gunicorn启动Django应用Nginx反向代理并托管静态文件。Gunicorn的启动命令参考如下gunicorn pharma_project.wsgi:application --bind 0.0.0.0:8000 --workers 3这里有个关键部署模式下必须把DEBUG设置成False并通过python manage.py collectstatic收集静态文件再由Nginx透过/static/路径去访问。如果漏了这一步页面样式会全部丢失。部署环境中数据库配置和密钥等敏感信息我建议用环境变量或.env文件来管理不要把真实密码直接写在settings.py里再提交到代码仓库。6. 常见问题排查与避坑实录6.1 数据库连接失败与编码问题最容易碰到的问题是数据库连接失败。启动后页面报OperationalError: (2003, Cant connect to MySQL server...)十有八九是以下三种情况MySQL服务没启动、数据库连接配置里的密码不对、MySQL绑定地址只允许本地连接。排查时先在本机命令行用mysql -u pharma_user -p验证能登录再检查settings.py的HOST是不是填了127.0.0.1而不是localhost有些MySQL版本对这两个地址处理方式不太一样。另一个高频问题是中文乱码。如果建库时忘记指定字符集默认可能是latin1存中文就会变成问号。解决办法是在MySQL配置文件的[mysqld]段中加入character-set-server utf8mb4重启MySQL服务。已经建好的库可以用ALTER DATABASE pharma_db CHARACTER SET utf8mb4;修改。6.2 虚拟环境与依赖管理“我代码明明没问题为什么运行报ModuleNotFoundError”——这种情况几乎都是没激活虚拟环境造成的。Windows系统命令行输入python时需要确认当前环境的路径是不是显示为venv目录。如果系统里有多个Python版本更要注意pip安装的包到底属于哪个版本。还有一点requirements.txt里我习惯于把所有依赖库和版本号固定下来。有时候Django版本不同ORM的写法有细微差异别人克隆代码后即使装了依赖跑不起来也常见。比如Django 3.x和4.x在urls.py里的path写法和Field.choices的相关用法就略有不同锁死版本能省掉一大半环境兼容问题。6.3 静态文件加载异常开发环境页面样式丢失常见原因是没有在settings.py里配置STATICFILES_DIRS。Django默认只会在每个app的static/目录下查找静态文件。我把项目级公共CSS、JS放在了根目录的static/下所以必须在settings.py里显式声明STATIC_URL /static/ STATICFILES_DIRS [BASE_DIR / static]部署环境页面样式丢失则几乎都是因为忘了执行collectstatic或者Nginx的静态文件指向路径不对。6.4 销售扣减库存时批次不足销售提交时如果每个批次扣减完还不够系统会怎么处理这是我在设计时认真想过的一个坑。处理方式是在事务里先检查总批次可用量不足时直接抛出一个明确的中文业务异常并且不执行任何写库操作提示“库存不足剩余xx盒”。这样做的关键是要和JavaScript前端的数量校验保持一致但后端不能依赖前端——因为接口可以被直接调用前端校验只是体验问题后端校验才是正确性问题。另一个隐藏问题是并发场景。两个收银员同时卖同一个药品理论上可能扣超库存。要彻底解决需要在扣减批次记录时使用select_for_update()这就是行级锁防止并发扣减导致库存变成负数。课堂设计和一般演示环境用不到但如果要做成真正商用的系统这行代码是必须加上的。6.5 数据库表字段增加后迁移失败开发过程中经常要加字段。我吃过一个亏在一个已有数据的表上新增一个带非空约束、无默认值的字段导致migrate直接失败。解决办法是先允许为空或给默认值迁移完成后再在应用代码层约束。在models.py里这么写remark models.CharField(备注, max_length255, default, blankTrue)另外不要把迁移文件随便删掉。Django的迁移之间存在依赖链删掉历史迁移记录再migrate数据库可能已经应用过旧迁移新旧任务串不起来会报InconsistentMigrationHistory。只要代码还能跑迁移文件就让它留着这才是正确的版本管理姿势。7. 项目交付源码、数据库脚本、文档如何配合使用7.1 源码目录与文档结构一份合格的“源码数据库文档”项目不只是把代码压缩包丢给用户那么简单。我在交付时习惯用如下的结构整理code/完整的Django项目源码包含虚拟环境不打包进来使用requirements.txt声明依赖。docs/项目使用说明、部署手册、系统设计文档。database/初始化SQL脚本、示例数据脚本。README.md最外层的导读文件写清楚项目是什么、怎么跑起来、目录怎么组织。系统设计文档是这套交付物中容易被忽略但价值很高的部分我建议包含需求分析、功能清单、系统架构图、数据库ER图、核心流程说明、接口说明、测试用例。这样别人拿到这个项目既有可以直接运行的代码又能从文档中完整理解设计思路不管是二次开发还是答辩汇报都有了充分素材。7.2 初始化数据库的两种方法拿到项目后初始化数据库我会提供两种方式用户根据熟练程度选择。方法一是通过Django的migrate命令自动建表再执行loaddata灌入基础数据。适合有一定Django基础、打算继续二次开发的人。方法二是直接运行database/init.sql脚本适合只需要用现成系统、不想关心Django迁移机制的人。脚本里包含了建库、建表、插入基础分类数据和默认管理员账号的全部SQL。无论用哪种方式跑完后系统都应该能正常访问。7.3 接口与二次开发建议虽然这个系统以服务端渲染为主但我还是在部分模块中预留了JSON接口比如获取药品信息、提交销售单。使用AJAX实现局部刷新用户操作时不用整页跳转体验会流畅很多。后续如果要扩展成前后端分离架构或者写一个小程序、App端这些接口可以直接作为雏形继续演进。二次开发方向上我认为最值得考虑的几个扩展点包括加入更细粒度的采购入库审核流、对接GSP温湿度监控记录、扩展批号追溯码查询、增加库存月度盘点单。这些方向都牢牢围绕医药行业的核心合规需求做进去之后系统的商用价值会明显提升。个人实操中还有一个体会是这套系统开发的业务逻辑很多思路可以平移。库存账、批次账、流水账这个“三账联动”的设计放到食品行业、保健品、化妆品进销存里同样成立。如果在通用进销存业务上再叠加效期管理功能这个项目的适用面会一下子大很多。最终交付时我会把数据模型设计文档重点讲透因为这也是最能体现一个开发者对业务理解程度的部分。
返回列表