第一站练习答案
参考实现
python
# tickets/views.py
import django
from django.http import JsonResponse
from django.views.decorators.http import require_GET
@require_GET
def health(request):
return JsonResponse(
{"status": "ok", "service": "ticket-desk", "django": django.get_version()}
)python
# tickets/tests.py
from django.test import TestCase
from django.urls import reverse
class HealthTests(TestCase):
def test_health_contract(self):
response = self.client.get(reverse("health"))
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()["status"], "ok")
self.assertEqual(response.json()["service"], "ticket-desk")
def test_health_rejects_post(self):
self.assertEqual(self.client.post(reverse("health")).status_code, 405)运行:
bash
python manage.py test tickets.tests.HealthTests为什么不返回 settings
settings 可能包含数据库地址、密钥、内部主机名和功能开关。健康接口只公开调用方需要的稳定合同;详细依赖状态放到受保护的内部就绪端点或监控系统。
专题二核对
ALLOWED_HOSTS = [host for host in os.environ["DJANGO_ALLOWED_HOSTS"].split(",") if host],随后在生产配置中为空就抛出ImproperlyConfigured。- 一次性导入放到
tickets/management/commands/import_tickets.py,在handle()内执行并让重复运行可识别。 - 用
CaptureQueriesContext(connection)包住importlib.import_module("tickets.apps"),断言查询数为零;不要在AppConfig.ready()做查询。
深水边界
测试客户端绕过真实网络服务器,因此它证明 Django 合同,不证明代理、TLS 或进程信号。第十站还会补生产探测。
开放练习(不提供答案)
让 /ready/ 检查一次数据库连接,同时设置严格超时并避免在数据库故障时阻塞所有探针。记录 /health/ 与 /ready/ 的不同责任。
加码题解:请求链路与配置边界
python
def parse_hosts(raw):
hosts = [part.strip() for part in raw.split(',') if part.strip()]
if not hosts:
raise RuntimeError('production hosts required')
return hosts关键推理
启动时把字符串环境变量转换成稳定列表,并在生产配置缺失时 fail fast。
可替代方案
大型部署可从 secret manager 注入并在 management command 中运行 check --deploy。
典型错误
在 AppConfig.ready 中访问数据库或启动线程,导致测试和迁移出现隐藏副作用。
复盘时请把状态码/事务/权限/资源清理中的至少一项写成自动化测试,而不是只截图成功页面。