ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

从零搭建 tarot_juicer:Python 版本锁定与 Django 部署避坑指南

从零搭建 tarot_juicer:Python 版本锁定与 Django 部署避坑指南

简介:这是一套基于Django框架搭建的随机塔罗牌生成器网站源码,面向Python Web初学者与Django爱好者,适合作为课程设计、练手项目或CMS二次开发参考。项目以22张塔罗牌大阿卡纳为核心,用户点击“随机”按钮即可动态展示牌面图片、密钥名称、占星与炼金术属性、希伯来字母及象征意义,并融入伽利略、圣保罗等历史与流行文化人物解读,兼具趣味性与知识性。压缩包共281个文件,约10.62MB,包含53个py业务逻辑脚本、25个html模板、10个css样式表,以及95张jpg、27个gif、18个png等图片素材,另有js、字体、sqlite数据库备份与说明文档,结构完整可直接运行。目前已有1964人学习下载。通过该资源可掌握Django视图与模板渲染、静态资源组织、多应用拆分(生成器、登陆、论文)等实战思路,并借鉴其门户页与关于页的CMS设计,快速搭建属于自己的动态内容站点。

1. 从零搭一套 tarot_juicer:为什么我建议你先锁 Python 版本再动手

上周帮一个做内容站的朋友部署 tarot_juicer,一个随机塔罗牌生成器加基础 Django CMS 的小项目。他本地跑得好好的,一到服务器就报TemplateDoesNotExist,折腾到凌晨两点才发现是 Python 3.12 下 Django 版本没对齐,模板路径解析行为变了。这种坑不是代码问题,是环境问题。tarot_juicer 这类项目结构不复杂,但依赖链上 Django、Pillow、数据库驱动、静态文件处理一个都不能少,装不好就是白屏、500、静态资源 404 三连。这篇记录我完整走一遍的安装过程,从版本选择到跑通验证,适合刚接触 Django 部署的开发者,也适合想快速复现一个可运行塔罗牌站点的熟手。

2. 环境准备:Python、Django 与数据库的版本取舍

2.1 为什么选 Python 3.10 + Django 4.2 LTS

tarot_juicer 的核心逻辑是随机抽牌加 CMS 内容管理,不涉及重型计算,但对模板渲染和 ORM 稳定性要求高。我一般会选 Django 4.2 LTS,支持周期到 2026 年,和 Python 3.10 搭配是当前最稳的组合。Python 3.12 虽然新,但部分第三方包还没跟上,尤其是图像处理和数据库驱动。如果你用的是 Python 3.11,Django 4.2 也能跑,但 3.10 的兼容性验证最充分。

# 确认当前 Python 版本,低于 3.10 建议先升级 python3 --version # 创建独立虚拟环境,避免污染系统包 python3 -m venv venv_tarot # 激活虚拟环境 source venv_tarot/bin/activate # 升级 pip 和 setuptools,老版本装包容易出玄学问题 pip install --upgrade pip setuptools wheel

虚拟环境这步别省。我见过太多人直接pip install django装到系统 Python 里,后面和系统包管理器打架,修都修不回来。激活后命令行前面会有(venv_tarot)提示,确认在环境里再继续。

2.2 数据库选型:SQLite 够用,PostgreSQL 更稳

tarot_juicer 的 CMS 部分需要存文章、牌面数据、用户会话。开发阶段 SQLite 完全够,零配置,文件即数据库。但如果要上线给多人访问,PostgreSQL 更合适,并发写入和全文检索都强不少。我这次先用 SQLite 跑通,再给 PostgreSQL 的切换方案。

# 安装项目核心依赖,版本号写死避免自动升级翻车 pip install django==4.2.11 pip install pillow==10.2.0 pip install python-decouple==3.8 # 如果要用 PostgreSQL,额外装驱动 pip install psycopg2-binary==2.9.9

Pillow 是处理塔罗牌图片的,Django 的 ImageField 依赖它。python-decouple 用来管理敏感配置,把 SECRET_KEY 和数据库密码从代码里拆出去。版本号我习惯写死,pip install django不带版本号,哪天自动升到 5.x 可能直接跑不起来。

2.3 目录结构与静态文件路径规划

tarot_juicer 的目录结构直接影响后面模板和静态文件能不能找到。我一般按下面这样组织:

tarot_juicer/ ├── manage.py ├── tarot_juicer/ │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── cards/ │ ├── models.py │ ├── views.py │ └── templates/cards/ ├── cms/ │ ├── models.py │ └── templates/cms/ ├── static/ │ ├── css/ │ └── images/ ├── media/ └── requirements.txt

static放 CSS、JS 和牌面缩略图,media放用户上传或 CMS 后台上传的图片。这两个目录在 settings 里要分开配,混在一起后面 collectstatic 会出问题。requirements.txt 用pip freeze > requirements.txt生成,部署到另一台机器时pip install -r requirements.txt就能复现环境。

3. 安装与配置:从 pip 依赖到 settings.py 关键项

3.1 创建项目骨架并接入 cards 与 cms 应用

假设你已经拿到 tarot_juicer 的源码包,解压后进入项目根目录。如果没有现成源码,用 Django 命令起骨架再往里填。

# 在项目根目录创建 Django 项目,注意结尾的点和项目名 django-admin startproject tarot_juicer . # 创建两个核心应用 python manage.py startapp cards python manage.py startapp cms

结尾那个点很关键,少了它会在当前目录下再套一层同名目录。创建完应用后,去tarot_juicer/settings.py里注册:

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'cards', # 塔罗牌抽牌逻辑 'cms', # 内容管理模块 ]

注册顺序有讲究,自定义应用放最后,确保 Django 内置的 auth、contenttypes 先加载。cards 负责随机抽牌和牌面展示,cms 负责文章和页面管理,两个应用通过外键关联。

3.2 settings.py 里必须改的五个配置项

settings.py 是安装过程中最容易埋雷的地方。下面这五个配置项不改,后面要么报错要么静态资源全丢。

import os from decouple import config # 1. SECRET_KEY 从环境变量读取,别硬编码在代码里 SECRET_KEY = config('SECRET_KEY', default='django-insecure-change-me-in-production') # 2. DEBUG 开发时 True,上线必须 False DEBUG = config('DEBUG', default=True, cast=bool) # 3. ALLOWED_HOSTS 上线后填域名或服务器 IP ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='localhost,127.0.0.1').split(',') # 4. 模板路径,确保能找到 cards 和 cms 下的模板 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, # 这行必须 True,否则应用内模板找不到 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] # 5. 静态文件和媒体文件路径 STATIC_URL = '/static/' STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # collectstatic 输出目录 MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

APP_DIRS设为 True 后,Django 会自动去每个应用的templates目录下找模板。如果你把模板放在项目根目录的templates里,就得靠DIRS指定。两种方式都行,但别混着用,容易找不到。STATIC_ROOT和STATICFILES_DIRS不能是同一个目录,这是 Django 的硬性规定,踩过一次就记住了。

3.3 数据库迁移与超级用户创建

配置改完,接下来初始化数据库。Django 的迁移机制会把模型定义同步到数据库表结构。

# 生成迁移文件,检测 models.py 的变化 python manage.py makemigrations cards cms # 执行迁移,真正建表 python manage.py migrate # 创建后台管理账号,按提示输入用户名密码 python manage.py createsuperuser

makemigrations只生成迁移脚本,不碰数据库。migrate才真正执行。如果 models.py 里定义了塔罗牌的字段比如牌名、正逆位含义、图片,迁移后数据库里就有对应的表。超级用户用来登录/admin/后台,CMS 的内容录入全靠它。

如果迁移时报No changes detected,检查两点:应用是否在 INSTALLED_APPS 里注册,models.py 里是否有继承models.Model的类。常见做法是先python manage.py makemigrations不带应用名,让 Django 自己扫描。

3.4 静态文件收集与 CSS 加载验证

tarot_juicer 的牌面展示和 CMS 页面都依赖 CSS。开发模式下 Django 会自动找静态文件,但上线后需要 collectstatic 把散落的静态文件汇总到一个目录,交给 Nginx 或 WhiteNoise 托管。

# 收集所有静态文件到 STATIC_ROOT python manage.py collectstatic --noinput # 启动开发服务器验证 python manage.py runserver 0.0.0.0:8000

--noinput跳过覆盖确认,适合脚本化部署。启动后访问http://127.0.0.1:8000/static/css/下的具体文件,比如style.css,能返回内容说明静态配置正确。如果 404,检查STATICFILES_DIRS路径是否写对,以及文件是否真的在那个目录里。

提示:开发阶段DEBUG=True时 Django 会自动托管静态文件,不需要 collectstatic。但DEBUG=False后必须 collectstatic,否则所有 CSS 和图片都会 404。

4. 避坑与排查:五个让我熬夜的典型问题

4.1 TemplateDoesNotExist:模板路径的三种死法

现象:访问抽牌页面报TemplateDoesNotExist at /cards/draw/,提示找不到cards/draw.html。

原因:一是APP_DIRS设成了 False;二是模板目录名写错,Django 要求必须是templates而不是template;三是应用没注册到 INSTALLED_APPS,Django 不会去它的目录下找。

解决:确认APP_DIRS: True,检查目录名拼写,确认应用已注册。如果模板放在项目根目录,确保DIRS里路径正确。我一般会在 settings 里加一行打印TEMPLATES[0]['DIRS']来确认实际路径。

4.2 静态文件 404:collectstatic 后仍然加载失败

现象:DEBUG=False后页面样式全丢,控制台报 CSS 文件 404。

原因:STATIC_ROOT目录没被 Web 服务器指向,或者STATICFILES_DIRS和STATIC_ROOT设成了同一个路径导致 collectstatic 拒绝执行。

解决:确保STATIC_ROOT是独立目录,collectstatic 后把该目录配到 Nginx 的 location。用 WhiteNoise 的话,在 MIDDLEWARE 里加whitenoise.middleware.WhiteNoiseMiddleware并设STATICFILES_STORAGE。

4.3 数据库迁移冲突:多应用依赖顺序问题

现象:migrate时报InconsistentMigrationHistory,说某个迁移已经应用但依赖的迁移没应用。

原因:cards 和 cms 之间有外键依赖,如果先迁移了 cms 再迁移 cards,或者手动改过迁移文件,就会乱序。

解决:开发阶段直接删掉db.sqlite3和各个应用下的migrations目录(保留__init__.py),重新makemigrations和migrate。生产环境不能这么干,得用--fake参数手动标记迁移状态。

4.4 Pillow 安装失败:缺少系统级图像库

现象:pip install pillow报错,提示找不到jpeg或zlib头文件。

原因:Pillow 编译时需要系统级的图像处理库,纯净的 Linux 环境默认没有。

解决:Ubuntu/Debian 下先apt install libjpeg-dev zlib1g-dev libwebp-dev,CentOS 下yum install libjpeg-turbo-devel zlib-devel。装完再 pip install。如果不想编译,用pip install pillow --only-binary :all:装预编译轮子。

4.5 时区与语言:中文后台显示英文、时间差 8 小时

现象:admin 后台全是英文,抽牌记录的时间比北京时间少 8 小时。

原因:settings 里LANGUAGE_CODE和TIME_ZONE没改,默认是en-us和UTC。

解决:

LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_TZ = True

USE_TZ=True时数据库存 UTC 时间,Django 在模板里自动转成 TIME_ZONE 指定的时区。如果不想自动转换,设USE_TZ=False,但跨时区部署会乱。

5. 验证跑通:抽牌接口、后台 CMS 与静态资源三件套

装完不算完,得验证三个核心链路都通。我一般按下面顺序走一遍,任何一步卡住就回到对应章节排查。

第一步:抽牌接口返回正常

访问/cards/draw/,页面应该随机展示一张塔罗牌,包含牌名、正逆位和图片。如果图片裂了,检查MEDIA_URL和MEDIA_ROOT配置,开发模式下还需要在urls.py里加:

from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # ... 其他路由 ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

这段只在DEBUG=True时生效,上线后由 Nginx 托管 media 目录。

第二步:后台 CMS 能录入内容

访问/admin/,用超级用户登录。在 cards 应用下应该能看到塔罗牌模型,在 cms 下能看到文章模型。新增一条牌面数据,填好牌名和含义,保存后回到抽牌页面刷新,看新牌是否出现在随机池里。这一步验证了 ORM、admin 注册和模板渲染整条链路。

第三步:静态资源全部 200

打开浏览器开发者工具,切到 Network 面板,刷新页面。CSS、JS、图片的请求应该全是 200。如果有 404,看请求路径和STATIC_URL是否匹配。我习惯用curl -I http://127.0.0.1:8000/static/css/style.css快速确认。

验证清单表格

检查项预期结果失败时看哪里
抽牌页面随机展示牌面cards/views.py 和模板路径
后台登录能进 admin 并增删数据createsuperuser 和 INSTALLED_APPS
静态 CSS返回 200 且样式生效STATIC_URL 和 collectstatic
媒体图片牌面图片正常显示MEDIA_URL 和 urls.py
数据库数据能存能读migrate 状态和数据库连接

最后说个习惯。从那以后我每次部署 Django 项目,都强制走一遍python manage.py check --deploy,它会提示 SECRET_KEY 强度、DEBUG 状态、ALLOWED_HOSTS 等安全隐患。装 tarot_juicer 这类项目,环境对了就成功一半,剩下的一半靠验证清单兜底。希望帮到你。

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进