使用cookiecutter-django时应用外导入config模块及环境变量问题求助
问题概述
使用Cookiecutter-Django框架开发时,遇到两个核心问题:
- 在Django应用外部的
bot/bot.py中尝试导入config模块,抛出ModuleNotFoundError: No module named 'config' - 若改用
os.environ['BOT_TOKEN']读取环境变量,project/app/signals.py中会出现KeyError: 'BOT_TOKEN'
需求是实现:当Django模型对象创建时,通过Telegram Bot发送消息,BOT_TOKEN存储在.envs/.local/.bot文件中。
项目结构
project ┣ .envs ┃ ┗ .local ┃ ┃ ┣ .bot ┃ ┃ ┣ .django ┣ bot ┃ ┣ __init__.py ┃ ┗ bot.py ┣ compose ┃ ┣ local ┃ ┃ ┣ django ┃ ┃ ┃ ┣ Dockerfile ┃ ┃ ┃ ┗ start ┃ ┃ ┗ pytelegrambot ┃ ┃ ┃ ┣ Dockerfile ┃ ┃ ┃ ┗ start ┣ config ┃ ┣ settings ┃ ┃ ┣ __init__.py ┃ ┃ ┣ base.py ┃ ┃ ┣ local.py ┃ ┣ __init__.py ┃ ┣ urls.py ┃ ┗ wsgi.py ┣ project ┃ ┣ app ┃ ┃ ┣ migrations ┃ ┃ ┃ ┗ __init__.py ┃ ┃ ┣ admin.py ┃ ┃ ┣ apps.py ┃ ┃ ┣ signals.py ┃ ┃ ┣ models.py ┃ ┃ ┗ views.py ┣ requirements ┃ ┣ base.txt ┣ README.md ┣ local.yml ┣ manage.py
相关代码
bot.py
import telebot from config.settings.base import env bot = telebot.TeleBot(env('BOT_TOKEN')) def send_welcome(message): print(message) if __name__ == '__main__': bot.infinity_polling()
signals.py
from bot.bot import send_welcome @receiver(post_save, sender=Model) def translate(sender, instance, created, **kwargs): send_wlcome("Hi") # 注意:此处函数名拼写错误,应为send_welcome
解决方案
1. 解决config模块导入问题
由于bot目录不在Python默认搜索路径中,需要将项目根目录添加到Python路径:
- 在
bot.py开头添加路径配置:import sys import os # 获取项目根目录(bot目录的父级目录) project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(project_root) - 或者运行bot时通过环境变量指定路径:
PYTHONPATH=/path/to/project python bot/bot.py
2. 解决环境变量读取问题
Cookiecutter-Django使用python-dotenv加载环境变量文件,需让bot手动加载.envs/.local/.bot:
- 在
bot.py中添加环境变量加载逻辑:from dotenv import load_dotenv # 加载bot专属的环境变量文件 env_file_path = os.path.join(project_root, '.envs', '.local', '.bot') load_dotenv(env_file_path) - 同时修正
signals.py中的函数名错误:把send_wlcome改为send_welcome
3. 最优方案:复用Django环境
让bot初始化时加载Django运行环境,直接复用Django的配置和环境变量加载逻辑:
import os import sys # 添加项目根目录到Python路径 project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(project_root) # 设置Django配置模块并初始化 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") import django django.setup() # 现在可以正常导入config模块和使用env from config.settings.base import env import telebot bot = telebot.TeleBot(env('BOT_TOKEN')) def send_welcome(message): print(message) if __name__ == '__main__': bot.infinity_polling()
此方案下,signals.py在Django上下文运行时,环境变量已被自动加载,只需修正函数名拼写错误即可正常调用send_welcome。
内容的提问来源于stack exchange,提问作者mirodil
相关产品推荐
相关产品推荐

