Django+MySQL药品管理系统实战:从数据库设计到部署上线
2026/9/1 11:25:32 网站建设 项目流程

简介:本资源是一个基于Django框架与MySQL数据库构建的药品管理系统实战项目,面向Python Web开发初学者及医药信息化相关从业者,解决药品库存、供应商、销售记录等核心业务的数字化管理需求。压缩包共118个文件,含39个Python源码(涵盖models、views、urls等Django核心模块)、43个HTML模板(如药品列表、入库出库、供应商管理等页面)、28个pyc编译文件及少量静态资源,整体体积仅148KB,结构清晰,便于快速部署与二次开发。已有2087人学习下载,项目完整实现了药品增删改查、模糊检索、库存实时更新、权限分级控制及表单验证等典型功能,代码注释充分,模板采用Django内置模板语言,配合响应式基础布局,可直接运行并作为课程设计、毕设参考或企业轻量级药管系统原型。 做药品管理系统之前,我建议你先想清楚一件事:这类系统的核心不在“增删改查”,而在“数据一致性和可追溯性”。我最早接手过一个药房管理项目,最初的版本只做了药品入库和出库登记,结果运营三个月后库存对不上、批号追溯查不到源头、近效期药品没人提醒,最后全部推倒重来。所以这篇博文我不打算只教你跑一个 Django 项目,而是把“django+mysql 药品管理系统”从需求拆解到数据库设计、从核心代码到部署上线,完整地过一遍,把我踩过的坑和后来总结出来的方案都写出来。如果你是刚学 Django 的学生,或者正在为公司做内部药品管理系统的开发人员,这篇文章能帮你少走很多弯路。

1. 系统整体设计与技术选型的思考

1.1 先搞清楚药品管理系统到底管什么

药品管理系统不等于“药品列表增删改查”。一个能真正用于药房、药店或医院科室的药品管理系统,至少要覆盖药品基础信息、供应商管理、采购入库、销售出库、库存盘点、近效期预警、批号追溯、用户权限这几大块。

我自己在做需求调研时习惯先画一条“药品生命周期线”:药品从供应商进来,经过验收、入库、上架,到被销售或处方使用,中间还可能发生退货、报损、移库。系统里每一个环节都要留痕,这样才能回答“这个批号的药是谁进的、什么时候用完的、还剩多少”这类问题。

所以第一个建议是:动手写代码之前,先列出核心业务对象和它们之间的关系,不要一上来就建表。药品管理系统最常见的对象有这些:

  • 药品信息(药品名称、通用名、规格、生产厂商、批准文号、剂型、单位、零售价、进货价)
  • 药品库存(关联药品、批号、生产日期、有效期、库存数量、货位)
  • 供应商(名称、联系人、电话、资质证号、地址)
  • 入库单/入库明细(入库单号、供应商、入库时间、经手人、明细行)
  • 出库单/出库明细(出库单号、客户或科室、出库时间、经手人、明细行)
  • 库存流水(每次入库、出库、盘点调整都生成一条流水记录)
  • 预警记录(近效期或低库存触发的提醒)
  • 用户与角色(管理员、采购员、库管员、收银员)

这些对象的关系理顺了,技术实现就是水到渠成的事。

1.2 为什么选 Django + MySQL,而不是其他组合

技术选型上,Django + MySQL 是这类管理系统非常稳的组合。Django 自带强大的 ORM(对象关系映射)、Admin 后台、认证系统、表单处理,而且有完整的迁移机制,开发周期比 Spring Boot 那一套短得多。MySQL 则是久经考验的开源关系型数据库,部署简单、运维资料多、社区成熟,对于药品管理系统这种以事务处理为主、对数据一致性有较高要求的场景非常合适。

有人会问:那为什么不用 PostgreSQL?其实 PostgreSQL 也很好,但选择 MySQL 主要有三个实际原因:

  • 服务器环境大多是 CentOS、Rocky Linux 或 Ubuntu,这些系统上安装 MySQL 非常方便,资料多,出了问题容易搜到答案。
  • 团队或学校课程里普遍熟悉 MySQL,后续维护成本低。
  • 如果以后要部署到云服务器,云厂商的 RDS 默认就是 MySQL,兼容性最好。

Django 这边,无论你用的是 Python 3.8 还是 3.11,Django 4.x LTS 版本对我来说最合适,因为它在 ORM、自动化和安全机制上都比较完善。如果你用的是 MySQL 5.7,建议搭配 django 2.2 到 3.2 这个区间;如果是 MySQL 8.0,直接上 Django 4.x 也没有任何问题,这一点在后面的配置部分我会再展开讲。

2. 数据库设计与 Django 模型实现

2.1 药品信息表和库存表怎么设计才不踩坑

数据库设计是整个系统最核心的部分,比写视图函数重要得多。我先给出药品信息表的设计建议,这是所有功能的基石。

药品信息表(drug_info)应该包含:

class DrugInfo(models.Model): drug_code = models.CharField(max_length=50, unique=True, verbose_name='药品编码') generic_name = models.CharField(max_length=128, verbose_name='通用名') trade_name = models.CharField(max_length=128, blank=True, null=True, verbose_name='商品名') specification = models.CharField(max_length=64, verbose_name='规格') dosage_form = models.CharField(max_length=32, verbose_name='剂型') manufacturer = models.CharField(max_length=128, verbose_name='生产厂商') approval_number = models.CharField(max_length=64, verbose_name='批准文号') unit = models.CharField(max_length=16, verbose_name='单位') reference_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='零售价') purchase_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='进货价') is_active = models.BooleanField(default=True, verbose_name='是否启用') created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'drug_info' verbose_name = '药品信息' verbose_name_plural = '药品信息' indexes = [ models.Index(fields=['generic_name']), models.Index(fields=['drug_code']), ]

这里有几个非常关键的细节:

  • drug_code 必须唯一。这个编码是自己生成的还是国家药品编码都行,但一旦确定,入库出库全部通过它来关联,千万不能允许重复。
  • 价格用 DecimalField,不要用 FloatField。药品价格涉及到金额计算,浮点数会出现 0.1 + 0.2 不等于 0.3 这种问题,而 DecimalField 在 Python 层面通过 decimal 类型保证精确。
  • 通用名和商品名分开存。很多人把药品名称只设计成一个字段,后期在检索和统计的时候会非常痛苦,因为同一通用名的药品可能有多个厂商、多个商品名。

库存表(drug_stock)的设计稍微复杂一些,因为需要支持同一药品不同批号分开管理:

class DrugStock(models.Model): drug = models.ForeignKey(DrugInfo, on_delete=models.PROTECT, verbose_name='药品') batch_no = models.CharField(max_length=64, verbose_name='批号') production_date = models.DateField(verbose_name='生产日期') expiry_date = models.DateField(verbose_name='有效期至') quantity = models.IntegerField(default=0, verbose_name='库存数量') location = models.CharField(max_length=64, blank=True, null=True, verbose_name='货位') updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'drug_stock' verbose_name = '药品库存' verbose_name_plural = '药品库存' constraints = [ models.UniqueConstraint(fields=['drug', 'batch_no'], name='uniq_drug_batch') ]

注意我在外键上用了on_delete=models.PROTECT,意味着有库存记录的药品不允许直接删除。药品不能删,只能停用,这是药品管理系统的硬性规则。因为药品一旦有入库出库记录,删除药品会把历史记录全部搞乱,批号追溯就断了。这里的教训是:凡是涉及财务和溯源的业务,一律逻辑删除,不要物理删除。

2.2 Django 迁移流程与 MySQL 配置细节

模型写好后,接下来就是迁移。迁移之前,先确定 Django 能连上 MySQL。

第一步,安装数据库驱动。Django 连接 MySQL 需要 mysqlclient,但在 Windows 上安装 mysqlclient 经常失败。我推荐两种方案:

  • Linux 环境下先安装依赖再安装:sudo apt install python3-dev default-libmysqlclient-dev build-essential,然后pip install mysqlclient
  • 如果你用的是 Windows,直接装pymysql,然后在项目__init__.py里加两行:
import pymysql pymysql.install_as_MySQLdb()

第二步,修改 settings.py:

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'drug_db', 'USER': 'drug_user', 'PASSWORD': 'your_password', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8mb4', }, } }

注意charset一定要设置成utf8mb4。药品名称里可能出现生僻字或者特殊符号,utf8mb4 才能完整支持;之前用默认字符集导致个别生僻药品名存进去变成了问号,排查了很久。

创建完数据库后执行:

python manage.py makemigrations python manage.py migrate

迁移成功后,可以用python manage.py createsuperuser创建管理员账号。Django 自带的 Admin 后台在这一步就能用了,输入/admin就能通过可视化界面管理用户和权限。很多人不知道的是,Django Admin 不只是给开发者用的,它可以作为药品管理系统的“初级后台”,先让业务方录入基础数据,等前端页面做好后再切换,非常方便。

2.3 Django Admin 的定制技巧

Admin 后台默认展示的是药品对象的__str__返回值,想要体验好,需要做一些定制。在 admin.py 里这样写:

@admin.register(DrugInfo) class DrugInfoAdmin(admin.ModelAdmin): list_display = ('drug_code', 'generic_name', 'trade_name', 'specification', 'manufacturer', 'reference_price', 'is_active') list_filter = ('is_active', 'dosage_form', 'manufacturer') search_fields = ('drug_code', 'generic_name', 'trade_name', 'manufacturer') list_per_page = 20 ordering = ('drug_code',)

这样配置后,后台就能按药品编码、名称搜索,还能按剂型、生产厂商筛选。Admin 的search_fields实际会生成 LIKE 查询,在数据量不大的情况下没有问题;但数据量达到几十万条时,建议换成第三方库 Django Admin 的autocomplete_fields或者直接用下面的搜索接口方案。

3. 核心业务功能的代码实现

3.1 药品入库与出库的事务处理

药品入库和出库操作必须在一个数据库事务里完成,因为这个过程会同时修改“库存表”和“流水表”,任何一步失败都会导致数据不一致。

入库操作的逻辑是:拿到入库单明细,对每一条药品,检查该药品该批号的库存记录是否存在;如果存在,就把数量累加;如果不存在,就新建一条库存记录。同时,向库存流水表(stock_transaction)插入一条“入库”记录。

from django.db import transaction from django.db.models import F from django.utils import timezone def stock_in(request, drug_id, batch_no, production_date, expiry_date, quantity, operator): with transaction.atomic(): drug = DrugInfo.objects.select_for_update().get(id=drug_id) stock, created = DrugStock.objects.select_for_update().get_or_create( drug=drug, batch_no=batch_no, defaults={ 'production_date': production_date, 'expiry_date': expiry_date, 'quantity': 0, } ) stock.quantity = F('quantity') + quantity stock.save(update_fields=['quantity', 'updated_at']) StockTransaction.objects.create( drug=drug, batch_no=batch_no, trans_type='in', quantity=quantity, operator=operator, remark=f'入库单{request_no}' )

这里有两个要点:

  • select_for_update()会锁定对应行,防止并发情况下两个人同时入库导致数量覆盖。这是我在高并发测试中总结出来的,不加锁的话,库存数据在并发场景下会出大问题。
  • 使用F('quantity') + quantity而不是直接读出数量再加上去,是为了把加减操作放到数据库层面执行,避免读改写三步中间插入其他事务。

出库操作类似,但要加一步判断:

if stock.quantity < quantity: raise ValueError('库存不足,无法出库')

这个检查必须在锁内完成。如果不加锁,两个窗口同时出库同一批次的药,很容易出现库存扣成负数的情况。我见过不止一次这种事故,所以这里一定要写清楚。

3.2 药品检索和多条件筛选的 MySQL 查询优化

药品管理系统中,检索是使用频率最高的功能。一个实用的检索接口应该支持按药品编码精确匹配、按通用名模糊匹配、按生产厂商筛选、按有效期范围过滤,还要分页。如果用 Django ORM 写,可以这样组织:

from django.db.models import Q def search_drugs(request): keyword = request.GET.get('keyword', '') manufacturer = request.GET.get('manufacturer', '') expiry_start = request.GET.get('expiry_start', '') expiry_end = request.GET.get('expiry_end', '') queryset = DrugStock.objects.select_related('drug').all() if keyword: queryset = queryset.filter( Q(drug__drug_code__icontains=keyword) | Q(drug__generic_name__icontains=keyword) | Q(drug__trade_name__icontains=keyword) ) if manufacturer: queryset = queryset.filter(drug__manufacturer__icontains=manufacturer) if expiry_start: queryset = queryset.filter(expiry_date__gte=expiry_start) if expiry_end: queryset = queryset.filter(expiry_date__lte=expiry_end) queryset = queryset.order_by('expiry_date') paginator = Paginator(queryset, 20) page = paginator.get_page(request.GET.get('page')) return page

当数据量变大时,icontains会转换成LIKE '%keyword%',这种写法无法用普通索引加速。如果系统里药品数据达到十万条以上,建议做三个优化:

  • drug_code建唯一索引,精确查询走索引,速度几乎无感知。
  • 模糊搜索建议增加全文索引(MySQL 的 FULLTEXT),或者引入 Elasticsearch,不过对于大多数中小型药品管理系统来说还到不了这一步。
  • expiry_date建普通索引,因为近效期筛选expiry_date__lte=xxx能用到索引。

还有一个非常实用的 MySQL 小技巧:分页优化。当页数很大的时候,LIMIT 100000, 20会越来越慢,因为 MySQL 要扫描前面十万行。改成“先取起始位置的主键,再关联查询”可以显著提升性能:

SELECT * FROM drug_stock WHERE id > (SELECT id FROM drug_stock ORDER BY id LIMIT 100000, 1) ORDER BY id LIMIT 20;

在 Django ORM 里,这个需求可以直接用Paginator解决,但业务方反馈“翻到第几千页很慢”的时候,再用上面这条 SQL 优化。

3.3 近效期预警与低库存提醒

药品管理的灵魂功能之一就是近效期预警。药品一旦过期,不但不能出售,处理起来还涉及报损、销毁记录。预警逻辑很简单:从当前日期开始,算到有效期剩余天数,小于设定阈值就提醒。

我通常会在模型层加一个属性,用来判断是否近效期:

def is_near_expiry(self, threshold_days=90): from datetime import timedelta return self.expiry_date <= timezone.now().date() + timedelta(days=threshold_days)

然后通过 Django 的管理命令(management command)定期扫描,生成预警记录:

class Command(BaseCommand): def handle(self, *args, **options): threshold_days = 90 near_expiry_stocks = DrugStock.objects.filter( expiry_date__lte=timezone.now().date() + timedelta(days=threshold_days), quantity__gt=0 ).select_related('drug') for stock in near_expiry_stocks: DrugWarning.objects.update_or_create( drug=stock.drug, batch_no=stock.batch_no, defaults={'warning_type': 'near_expiry', 'warning_date': timezone.now().date()} )

定时任务建议用系统 crontab 每天执行一次:

0 9 * * * cd /path/to/project && /usr/bin/python3 manage.py check_warning

低库存预警逻辑类似,把库存数量与设定的最低库存阈值比较即可。这里的核心思路是:预警要落到独立的表里,而不是每次打开页面现算。因为现算每次都要全表扫描,定时任务在后台跑算了存起来,前端展示效率高得多。

3.4 用户权限设计和操作日志记录

药品管理系统通常涉及多个角色:管理员、采购员、库管员、收银员。不同角色能看到的功能和能执行的操作应当严格区分。Django 自带的认证系统提供了 Group 和 Permission,可以直接复用。

在初始化时创建三个分组:

  • 管理员组:拥有所有权限
  • 采购员组:能够添加和修改药品信息,能够做入库操作,但不可以出库
  • 库管员组:能够查看库存、做盘点调整、处理近效期药品

实现方式是在 view 上加装饰器:

from django.contrib.auth.decorators import login_required, permission_required @login_required @permission_required('drug.add_druginfo', raise_exception=True) def drug_create(request): ...

权限控制之外,操作日志是药品管理系统必不可少的一环。每一次入库、出库、盘点、价格修改都必须记录操作人、操作时间、操作前后的值。Django 的django-auditlog第三方库可以很方便地记录模型变更,但更轻量、更可控的方法是自定义日志表:

class OperationLog(models.Model): user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name='操作人') action = models.CharField(max_length=64, verbose_name='操作类型') target_type = models.CharField(max_length=64, verbose_name='对象类型') target_id = models.CharField(max_length=64, verbose_name='对象ID') detail = models.TextField(blank=True, null=True, verbose_name='操作详情') created_at = models.DateTimeField(auto_now_add=True, verbose_name='操作时间')

在关键视图函数里手动写一行OperationLog.objects.create(...)就行。虽然比中间件多一点代码,但胜在可控性强,想查什么都有清晰的结构。

4. 部署上线与高发问题排查

4.1 从开发环境到生产环境的关键改动

开发环境里 Django 默认的python manage.py runserver只适合本地调试,生产环境必须要搭 WSGI 服务器和 Web 服务中间层。常见的部署方案是 Nginx + Gunicorn + Django + MySQL。

先把 Django 项目的 settings.py 改好:

DEBUG = False ALLOWED_HOSTS = ['your-domain.com', 'your-server-ip'] STATIC_ROOT = '/var/www/drug_system/static' # 数据库连接池建议开启 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'drug_db', 'USER': 'drug_user', 'PASSWORD': 'your_password', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8mb4', 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", }, } }

ALLOWED_HOSTS必须在生产环境显式配置,不然 Django 会拒绝所有非本地请求,直接返回 400。STATIC_ROOT配置好后,执行:

python manage.py collectstatic

把所有静态文件收集到指定目录,交给 Nginx 处理。

Gunicorn 启动命令写成这样比较稳妥:

gunicorn drug_system.wsgi:application --bind 127.0.0.1:8000 --workers 3

workers 数量一般设为 CPU 核数的 2 到 4 倍,我常用的公式是:workers = CPU核心数 * 2 + 1。如果服务器是 2 核,就开 5 个 worker;再高反而因为上下文切换导致性能下降。

Nginx 的配置片段供参考:

server { listen 80; server_name your-domain.com; location /static/ { alias /var/www/drug_system/static/; } location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }

4.2 MySQL 连接数、时区、字符集这些隐藏坑

部署过程中最容易踩的是 MySQL 侧的配置问题。

第一个坑是数据库连接数不够。Django 每个请求都会占用一个数据库连接,Gunicorn 起了 5 个 worker,每个 worker 可能有多个线程,加在一起连接数轻松超过 151(MySQL 默认最大连接数)。解决办法是修改 MySQL 配置:

[mysqld] max_connections = 500

然后在 Django 里也加连接复用参数:

'OPTIONS': { 'charset': 'utf8mb4', 'connect_timeout': 5, }

第二个坑是时区问题。Django settings.py 里的TIME_ZONE建议设置为'Asia/Shanghai',同时把USE_TZ设为True。这里有一件很微妙的事:当USE_TZ=True时,Django 写入 MySQL 的数据是按 UTC 时间存储的,取出来再转本地时间。如果业务方直接查看数据库,可能会觉得时间少了 8 小时。解决方法有两条路:

  • 保持USE_TZ=True,所有时间展示交给 Django 模板自动转换。
  • 或者干脆USE_TZ=False,让 Django 直接存本地时间,但这样会失去时区支持,不推荐在正规项目中使用。

第三个坑是 MySQL 8.0 的认证方式问题。MySQL 8.0 默认使用caching_sha2_password认证,而较旧版本的 mysqlclient 可能不支持,导致连接时报Authentication plugin 'caching_sha2_password' cannot be loaded。解决办法是创建用户时指定mysql_native_password

CREATE USER 'drug_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password'; GRANT ALL PRIVILEGES ON drug_db.* TO 'drug_user'@'%'; FLUSH PRIVILEGES;

4.3 常见问题速查表

根据我接触过的和网上大量同类项目的反馈,这里整理一份高频问题排查表,基本覆盖了“django+mysql 药品管理系统”开发中 70% 的报错场景:

问题现象原因解决办法
启动时ModuleNotFoundError: No module named 'MySQLdb'没有安装 mysqlclient 或 pymysql按上文方法安装驱动,或使用 pymysql 注册
访问页面报 500,日志提示table doesn't exist忘记执行迁移python manage.py migrate
connect timeout连接数据库失败MySQL 服务未启动或 host/port 配置错误systemctl status mysql检查服务状态,确认连接参数
中文数据存入数据库变成?数据库/表字符集不是 utf8mb4修改库表字符集:ALTER TABLE drug_info CONVERT TO CHARACTER SET utf8mb4
接口报DataError: Out of range value字段长度不够或者数据超出范围检查模型字段 max_length/max_digits,调整迁移
库存数量并发扣成负数没有使用数据库锁或事务给库存操作加上select_for_update+transaction.atomic
创建外键时报 1215字段类型或字符集不一致确保关联字段类型和字符集一致,比如都是int或都是utf8mb4
权限判断总是 403raise_exception=True但没有登录登录后访问,或取消异常抛出改为重定向登录页

从我的经验来看,超过一半的部署问题不是 Django 代码的问题,而是 MySQL 服务和配置的问题。遇到报错先看 MySQL 错误日志,一般能直接定位。

4.4 一个反向教训:不要一上来就写前端页面

最后想分享一个很多人会犯的方向性错误:一开始就把精力放在写漂亮的 HTML 页面和复杂的 JavaScript 交互上,结果后端的业务逻辑一塌糊涂。

我现在的开发习惯是:先用 Django Admin 把基础数据管理跑通,让用户真实录入几个星期的数据,看业务流程有没有问题;确认之后,再逐步用 Bootstrap、Vue 等替换成正式界面。这样做的原因是,管理系统的核心价值在于数据和逻辑的正确性,页面的美观程度永远是次要的。把库存、流水、预警这些骨骼搭结实了,外面穿什么衣服都很容易。

这也让我养成了一个习惯:在开发任何管理系统之前,先做一个小范围的“可用性确认”。拿一两天时间,把最小核心闭环跑通,也就是药品信息维护、入库、出库、库存查询这四个功能串成一个完整的流程,然后找实际使用者试用。这个闭环如果不顺,后面的功能做得再多也是白搭。药品管理系统的痛点从来不在技术难度,而在于需求是不是真的理清楚了。很多项目翻车,都是因为开发者在“做功能”而不是“解决问题”。你把核心业务先跑通了,后面加角色权限、加报表、加消息提醒,都是水到渠成的事。

5. 扩展想法:这个系统还能怎么延伸

药品管理系统做完基础版本之后,可以往几个方向扩展,这也是实际业务中很有价值的模块。

第一是处方关联。如果这个系统用在诊所或医院科室,出库记录应当关联到处方单上。设计处方主表和处方明细表,然后把出库明细与处方明细关联起来,这样既能追溯“这批药是谁开的处方”,也能统计科室用药情况。

第二是报表统计。基于库存流水表,可以按天、按周、按月统计药品入库量、出库量、销售额和毛利。Django ORM 里用annotateTruncMonth就能方便地生成月度统计:

from django.db.models.functions import TruncMonth from django.db.models import Sum monthly_sales = StockTransaction.objects.filter( trans_type='out' ).annotate( month=TruncMonth('created_at') ).values('month').annotate( total_quantity=Sum('quantity'), total_amount=Sum('amount') ).order_by('month')

第三是引入扫码枪或二维码。药品入库前打印二维码标签,出库时扫码枪扫一下,系统自动找到对应批号的库存记录并扣减,效率和准确率都远高于手工选择。Django 视图里接收扫码枪输入,本质上就是接收一个字符串参数,把药品编码带进来就行,实现成本不高却极其提升使用体验。

第四是数据库的定期备份。MySQL 定时任务生产环境必须做:

mysqldump -u drug_user -p drug_db --single-transaction --routines > /backup/drug_db_$(date +%Y%m%d).sql

--single-transaction参数在 InnoDB 引擎下可以在不锁表的情况下完成备份,很关键。恢复时使用mysql -u drug_user -p drug_db < backup.sql即可。

我个人的经验是,只要基础核心模块的数据模型设计得足够稳,这些扩展功能都只是“往上添砖”的事。真正难的是刚开始那一步,把数据的流向、约束、权限想明白。如果你正在做类似的药品管理系统,照着这篇文章的思路去梳理一遍你的表结构和业务闭环,会比直接搜索“django 药品管理系统源码”然后复制粘贴有价值得多。源码只能给你一个参考,而理清业务逻辑之后写出来的系统,才是真正能上线长期使用的系统。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询