ARTICLE DETAIL

资讯详情

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

Django发布会签到系统源码拆解:从模型设计到生产部署

Django发布会签到系统源码拆解:从模型设计到生产部署 简介基于Python与Web技术的发布会签到系统源码面向活动组织者及Web开发者提供一套可直接部署或二次开发的签到解决方案。系统后端采用Python与Django框架配合uWSGI配置文件完成服务部署前端使用JavaScript、CSS、HTML构建交互页面并配有SVG、PNG等图标素材。压缩包共134个文件约9.49MB核心文件包括27个JS脚本、26个Python程序、9个CSS样式表、7个HTML页面同时包含db.sqlite3数据库、all.log运行日志、XML配置、字体文件以及文档与测试目录覆盖从界面展示到数据存储的完整链路。前端脚本负责动态交互与页面渲染后端程序处理签到逻辑、用户认证、状态更新与数据库读写模块边界清晰doc目录和readme文件可帮助快速上手整个系统兼顾活动管理需求模块化设计便于按场景定制。已有296人学习适合需要掌握Web签到系统完整设计思路、参考前后端整合方案的初中级开发者。1. 发布会签到系统为什么值得拆一套 Django 源码做过活动运营或技术布道的人都知道发布会签到这件事看起来只是「扫码 → 登记 → 入场」但真正落地时涉及用户认证、签到状态幂等、并发写入、现场网络不稳定、临时换人换场等一堆细节。用 Excel 或第三方表单工具能顶一两次活动规模一上来数据对不上、入场排队、重复签到这些问题就会把现场搞得很狼狈。这套基于 Python 和 Web 技术的发布会签到系统源码就是用来解决这类问题的它以 Django 为后端框架配合 uWSGI 部署配置前端由 JavaScript、CSS、HTML 组成整套项目 132 个文件既有可运行的管理后台也保留了完整的二次开发结构。适合谁来读如果你是做 Python Web 开发、想找一个真实业务场景练手 Django 的开发者或者你在做活动管理系统选型、需要参考签到模块的设计思路这套源码都值得花一个晚上拆一遍。它不只是一个「能跑」的项目更重要的是它的目录结构、信号处理、缓存与数据库交互方式能直接迁移到会议报名、展览入场、培训考勤等场景。接下来我会按「框架结构 → 签到核心流程 → 前端交互 → 部署与排错 → 实用改造」这条线完整拆解并给出可抄作业的代码和命令。2. Django 项目结构与签到系统的数据模型设计2.1 从 manage.py 和 django_uwsgi.ini 看项目骨架这套源码的入口是manage.py这是 Django 项目的标准启动文件所有迁移、创建超级用户、启动开发服务器的操作都通过它完成。和普通 Django 项目略有不同的是项目根目录多了一个django_uwsgi.ini配置文件这说明作者从一开始就考虑了生产环境部署而不是只停留在runserver阶段。先看这个 uWSGI 配置的常见写法一般会包含如下内容[uwsgi] chdir /path/to/project module project_name.wsgi:application master true processes 4 threads 2 socket 127.0.0.1:8001 vacuum true daemonize /var/log/uwsgi/app.log参数含义chdir指定项目所在目录module指向 WSGI 入口processes和threads决定并发处理能力socket用于和 Nginx 通信vacuum会在进程退出时清理 socket 文件。对于签到这种读多写少、单次请求耗时极短的系统4 进程 2 线程已经是比较稳妥的起点如果现场并发超过 500 人同时签到可以适当上调processes但要注意数据库连接数也会随之上升。2.2 基于 db.sqlite3 的数据表划分思路项目中的数据库文件是db.sqlite3说明开发阶段直接用了 SQLite。对于发布会签到场景SQLite 在几百人规模下完全够用而且免去安装数据库服务的麻烦。签到系统的核心数据表一般围绕以下几个模型设计数据模型核心字段作用用户表用户名、密码哈希、手机号认证与权限控制活动表活动名称、时间、地点、最大人数管理发布会场次签到记录表用户 ID、活动 ID、签到时间、设备标识记录签到状态与幂等控制签到配置表签到方式、二维码有效期、开放时间控制签到逻辑参数Python 程序文件中会有对应的模型类定义例如签到记录表中会设置unique_together约束避免同一用户在同一活动中重复签到。这是签到系统最关键的数据层设计之一只有从数据库层面约束唯一性才能防止并发请求下出现重复签到记录。2.3 信号机制与日志、测试目录的工程价值项目中的all.log文本文件不是普通输出日志它由 Django logging 配置生成记录了所有签到请求的 IP、用户、时间和结果。现场排查问题时这个日志的价值甚至高于数据库记录因为数据库只能告诉你结果日志能看到完整的请求链路。建议在 settings.py 中配置两个 handler一个写all.log全量信息一个写error.log只保留 ERROR 以上级别LOGGING { version: 1, handlers: { file: { level: INFO, class: logging.FileHandler, filename: all.log, }, }, loggers: { django: { handlers: [file], level: INFO, }, }, }tests目录的存在说明项目中包含功能验证脚本。签到系统这种偏工具型的 Web 应用测试的重点应该放在签到接口的幂等性上同一用户连续请求三次签到接口只有第一次返回成功后两次返回「已签到」。这个测试用例建议用 Django TestCase 写配合transactionTrue模拟真实数据库事务。3. 签到核心流程实现从请求到数据库写入的完整链路3.1 前端提交到 Django View 的参数流签到系统的前端页面向后端提交的数据通常包含三类签到凭证二维码内容或二维码图片、用户身份标识、活动 ID。前端 JavaScript 脚本首先对表单数据进行预处理然后通过 AJAX 或 Fetch 发送到 Django view。async function submitSignin(activityId, credential) { const formData new FormData(); formData.append(activity_id, activityId); formData.append(credential, credential); formData.append(timestamp, Date.now()); formData.append(sign, generateSign(activityId credential)); const response await fetch(/api/signin/, { method: POST, body: formData, headers: { X-CSRFToken: getCookie(csrftoken) } }); return response.json(); }这里每段代码都有它的职责FormData用于构造 multipart 请求体timestamp是防重放的时间戳sign是前端生成的简单签名防止请求被直接抓包后篡改参数。X-CSRFToken请求头是 Django 的 CSRF 防护机制签到的 POST 请求必须携带这个 token否则会被 Django 中间件拦截返回 403。后端 Django view 接收到请求后会依次校验签名、查询活动状态、验证凭证有效性、写入签到记录并返回结果。29 个 JavaScript 脚本中除了表单校验逻辑之外还有处理二维码扫码结果和轮询签到状态的部分。3.2 Python 后端控制器的关键业务逻辑后端签名校验函数是整个系统的安全边界它负责验证前端请求是否合法防止无关请求刷入数据库。签名算法使用 MD5 加盐的方式虽然强度不高但足以应对发布会签到这种低攻击价值的场景。关键代码示例如下import hashlib from django.http import JsonResponse from django.views.decorators.http import require_POST from django.views.decorators.csrf import csrf_exempt from .models import Activity, SigninRecord def check_sign(params, sign, secretyour-salt-here): raw_string .join([str(params[k]) for k in sorted(params.keys())]) expected hashlib.md5((raw_string secret).encode(utf-8)).hexdigest() return expected sign require_POST csrf_exempt def api_signin(request): activity_id request.POST.get(activity_id) credential request.POST.get(credential) timestamp request.POST.get(timestamp) sign request.POST.get(sign) if not all([activity_id, credential, timestamp, sign]): return JsonResponse({code: 400, msg: 参数不完整}) if not check_sign(request.POST, sign): return JsonResponse({code: 401, msg: 签名校验失败}) try: activity Activity.objects.get(idactivity_id, statusopen) except Activity.DoesNotExist: return JsonResponse({code: 404, msg: 活动不存在或已结束}) record, created SigninRecord.objects.get_or_create( activityactivity, credentialcredential, defaults{signin_time: timezone.now()} ) if created: return JsonResponse({code: 200, msg: 签到成功, signin_time: record.signin_time}) else: return JsonResponse({code: 201, msg: 您已签到请勿重复操作})这段代码的核心在get_or_create这行查询活动、创建签到记录是原子操作两个请求同时到达时Django 的数据库事务保证只有一个能成功插入。这是签到系统最重要的一行——不需要显式加锁仅靠数据库唯一约束和get_or_create就能解决 99% 的重复签到问题。3.3 多场次活动与「未开放/已结束」状态处理发布会签到系统通常不只服务一场活动一个系统可能同时承载「上午主论坛」「下午分论坛」「晚宴」等多个场次。每个场次就是一个独立的Activity前端通过切换活动 ID 来区分。数据库层面要处理的边界情况有两个活动未开始statuspending和活动已结束statusclosed。在查询活动时除了校验状态还需要校验当前时间是否在签到的有效时间窗口内。常见做法是给 Activity 增加sign_start_time和sign_end_time两个字段签到接口中做如下判断from django.utils import timezone now timezone.now() if now activity.sign_start_time or now activity.sign_end_time: return JsonResponse({code: 403, msg: f签到未开始或已结束当前时间 {now:%H:%M:%S}})这样可以避免签到开放前有人提前签到以及结束后补签导致的入场数据混乱。24 个 Python 文件中像这样的判断逻辑散落在不同的 view 和 service 层里拆源码时值得单独拎出来看一遍。4. 前端交互与视觉层实现从 HTML 骨架到动态反馈4.1 7 个 HTML 页面的功能划分项目中的 7 个 HTML 页面对应签到系统的不同用户场景。最常见的划分是登录页、签到首页扫码/手动输入、签到成功页、签到失败页重复签到/凭证无效、活动管理页、记录查询页、系统设置页。部分页面直接继承 Django 的 admin 模板——项目里有login.html、dashboard.css、base.css这些文件说明后端管理界面用了 Django admin 的自定义模板。签到的用户页面讲究「单页单操作」一个页面只做一件事扫码枪扫出凭证后自动提交页面直接展示结果不需要用户跳转。因此签到首页需要常驻显示活动信息、当前签到人数和最近签到记录这部分交互由 JavaScript 脚本每隔 5 秒轮询后端接口实现function loadStats() { fetch(/api/signin/stats/?activity_id${currentActivityId}) .then(response response.json()) .then(data { document.getElementById(total-count).innerText data.total; document.getElementById(recent-list).innerHTML data.recent.map(item li${item.name} ${item.time}/li).join(); }); } setInterval(loadStats, 5000);4.2 CSS 与 SVG、PNG 资源的本地化部署思路项目中的 9 个 CSS 文件并非全部是手写的其中base.css、widgets.css、forms.css、changelists.css这些是 Django admin 自带样式而draw_results.css和自定义样式表才是签到界面自己的视觉定义。19 个 SVG 图形多为图标类资源比 PNG 更适合做界面装饰——矢量图在 Retina 屏上不会模糊而且体积小。需要特别提醒的是如果把签到界面部署在无外网环境必须把前端依赖全部本地化。打开 CSS 文件检查是否有外链字体或 CDN 引用如果有谷歌字体之类的外链现场网络波动会导致样式加载失败。项目中的 3 个 woff 字体文件已经构建了本地字体栈部署时只需要确认 Nginx 静态文件路径配置正确。4.3 扫码签到与手动签到的前端差异处理扫码枪的本质是「键盘输入设备」扫码后会直接把内容输入到当前聚焦的表单元素中并以回车结尾。技术上只需要监听输入框的keypress事件判断回车键触发提交即可。而手动签到需要额外的用户信息补录前端表单会多出手机号、姓名等字段。两种签到方式的交互差异也在 CSS 中体现扫码模式需要大字号、高对比度的输入框和按钮方便现场工作人员快速操作手动模式则需要清晰的表单分组和错误提示区域。draw_results.css这个文件里应该还有签到成功后的大屏动画效果用于发布会现场的实时展示提高参与感。5. 从源码到可运行部署步骤、验证方法与常见坑5.1 本机启动 Django 项目的完整命令序列拿到源码后第一步是在本地把它跑起来。假设 Python 3.8 以上版本已安装依次执行以下命令cd signin_system python -m venv venv source venv/bin/activate pip install django python manage.py migrate python manage.py createsuperuser python manage.py runserver 0.0.0.0:8000命令含义venv创建独立虚拟环境避免依赖冲突migrate根据模型文件生成数据库表结构createsuperuser创建管理员账号runserver启动开发服务器。启动后访问http://localhost:8000/admin/即可进入管理后台。若界面显示但样式错乱执行python manage.py collectstatic收集静态文件后再刷新。5.2 用测试数据和并发脚本验证签到逻辑跑通界面之后必须验证最核心的防重复签到逻辑。可以打开 Django shell 手动创建测试活动和用户然后用并发请求模拟多人同时签到python manage.py shell在 shell 中执行from your_app.models import Activity, SigninRecord from django.contrib.auth.models import User a Activity.objects.create(name发布会主论坛, statusopen) u User.objects.create_user(test001, passwordtest123)创建完成后停掉 shell再用 curl 模拟两次签到请求验证第二次返回已签到curl -X POST http://localhost:8000/api/signin/ \ -d activity_id1credentialTEST001timestamp1700000000signdummy先用真实签名方式请求一次再请求第二次观察返回值。5.3 常见坑位清单CKEditor 上传、时区、静态文件、中文乱码这套源码拆解和部署过程中我遇到过几个有代表性的坑都值得提前避开。第一db.sqlite3里如果已有旧数据直接跑的后果是迁移冲突稳妥方案是备份后删掉重新migrate第二TIME_ZONE如果不设置日志时间会比北京时间差 8 小时现场核对签到时间会出问题第三用 Nginx 部署时collectstatic的目录和 Nginx 的alias必须一一对应第四直接print中文到终端可能出现字符编码报错Python 3 下把环境变量PYTHONIOENCODINGutf-8加上就能解决第五签到数据量超过 1 万条时记得给SigninRecord表的(activity, credential)加复合索引否则查询会明显变慢。6. 把签到系统改造成多活动通用平台的四个扩展点6.1 二维码凭证从「固定字符串」升级为「动态加密串」目前的签到凭证是固定的二维码 ID复制粘贴就能冒用。更稳妥的做法是为每位参会者生成带过期时间的加密凭证二维码内容为base64(activity_id user_id expire_time sign)。前端扫码后直接提交后端解出字段再验签过期则提示重新获取。生成动态凭证可以用 Django 的signing模块它有dumps和loads方法自带时间戳校验from django.core.signing import TimestampSigner signer TimestampSigner(saltsignin-qrcode) token signer.sign(f{activity_id}-{user_id}) # 解析 try: plain signer.unsign(token, max_age300) except Exception: return JsonResponse({code: 403, msg: 二维码已过期})6.2 用 Celery 处理签到大屏的实时数据推送发布会现场的大屏需要实时显示签到人数和区域统计每 5 秒轮询一次接口可以用但更平滑的方案是采用 WebSocket 推送。如果要保持纯 Django 技术栈不引入额外组件可以退一步用 SSEServer-Sent Events实现服务器单向推送后端在签到成功后把最新数据写入内存缓存前端通过 EventSource 订阅变化。如果现场规模进一步扩大甚至可以将签到数据写入 Redis 做计数再异步批量落库。这套源码的 24 个 Python 文件里虽然没包含 Celery 任务定义但目录结构已经预留了包扩展空间加一个tasks.py就能接入。6.3 将 SQLite 迁移至 MySQL 的注意事项原系统使用 SQLite适合开发和单机部署。当活动规模增长到需要多台服务器时需要将数据库切换为 MySQL。迁移时需要注意自增主键、事务行为和时区处理在 settings.py 中修改数据库配置即可DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: signin_db, USER: signin_user, PASSWORD: strong_password, HOST: 127.0.0.1, PORT: 3306, } }6.4 现场一键清场与数据导出活动结束后一键清除所有签到记录的操作需要在管理后台提供入口避免直接在数据库中执行危险操作。随后用 Excel 或 CSV 导出签到名单常用导出命令是import csv from .models import SigninRecord with open(signin_report.csv, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([用户, 签到时间, 活动]) for record in SigninRecord.objects.select_related(user, activity): writer.writerow([record.user.username, record.signin_time, record.activity.name])utf-8-sig编码是为了让导出的 CSV 文件在 Windows 上用 Excel 打开时中文不乱码。项目的 XML 和文本配置文件可以根据实际情况加入导出模板的路径配置方便现场工作人员按活动分场次导出签到名单其他字段也按此逻辑扩展即可。本文还有配套的精品资源点击获取
返回列表