Files
DailyChallenge_ProgrammingD…/Day_4/README.md
T

113 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Day_4 · 设计一个真正的 Django 小应用
> 前提:你应该已经跟着教程跑通了 Django 的安装,执行过
> `django-admin startproject mysite` 和 `python manage.py startapp blog`,
> 知道 `settings.py` / `urls.py` / `views.py` / `models.py` 大概长什么样。
> 今天不是"照着教程敲一遍",而是"**先想清楚,再动手设计**"。
> 题目里每一步都问了为什么——能回答上,才算真的懂了。
## 今日目标
做一个**社团招新管理系统**:成员(Member)发布文章(Article),成员可以评论(Comment)。
覆盖:模型设计、ORM 查询、视图、URL 路由、模板、以及"从请求到响应"的完整链路。
## 环境准备
```bash
pip install django
django-admin startproject mysite
cd mysite
python manage.py startapp blog
# 记得把 'blog' 加进 settings.py 的 INSTALLED_APPS
```
---
## 题目一(必做):设计数据模型 models.py
**背景**:一个博客/招新系统,核心数据是"文章",文章有作者,作者是社团成员,文章下面有评论。
**要求**:在 `blog/models.py` 里写出完整代码,包含三个模型:
1. **Member**(成员):昵称 `nickname`、邮箱 `email`(要**唯一**)、
加入时间 `joined_at`(自动记录创建时间)、简介 `bio`(允许为空)
2. **Article**(文章):标题 `title`、正文 `content`、作者 `author`
(外键 → Member,作者被删时文章级联删除)、是否发布 `is_published`(默认 False)、
发布时间 `created_at`(自动记录)、浏览量 `views`(默认 0)
3. **Comment**(评论):正文 `content`、所属文章 `article`
(外键,`related_name="comments"`)、评论者 `commenter`(外键 → Member)
四个要求:
- 三个模型都要有合理的 `__str__`(Article 返回标题,Comment 返回"评论者 + 内容前 20 字",Member 返回昵称)
- 用 `Meta` 设置排序:Article 按 `created_at` 倒序,Comment 按 `id` 正序
- 字段参数用对:`max_length`、`default`、`null=True`/`blank=True` 该加的地方要加
- 思考题写进注释里(各一两句即可)
**思考题(写进注释)**:
1. 为什么外键要用 `on_delete=models.CASCADE`?如果改成 `SET_NULL` 会发生什么、需要什么前提?
2. `related_name="comments"` 是干什么的?(提示:`article.comments.all()` 是什么?)
---
## 题目二(必做):写视图 + ORM 查询 views.py
**要求**:在 `blog/views.py` 里写四个视图函数:
1. **`index(request)`**:查出所有**已发布**的文章(`is_published=True`),按时间倒序,
渲染 `index.html`,把文章列表传进模板
2. **`article_detail(request, pk)`**:用 `get()` 取单篇文章,**不存在时抛 `Http404`**;
浏览量 +1 并保存;渲染 `detail.html`
3. **`add_comment(request, pk)`**:POST 请求时读取 `request.POST` 里的 `content`,
创建一条评论(评论者先用 `Member.objects.first()` 随便取一个,我们还没做登录),
完成后**重定向**回文章详情页;GET 请求也直接重定向回详情页
4. **(进阶)`author_articles(request, nickname)`**:按作者昵称查该作者的全部文章,
并且**用 ORM 统计每篇文章的评论数**(提示:`annotate` + `Count`,配合 `related_name`),
渲染 `author.html`。想不出 `annotate` 就先用 Python 算,但要写一句注释说明两种做法的区别
**思考题(写进注释)**:
- 浏览量 +1 有两种写法:
a) `article.views += 1; article.save()`
b) `Article.objects.filter(pk=pk).update(views=F("views") + 1)`
两个请求同时点击文章时,a 会出什么问题?b 为什么没问题?(提示:并发 / 原子性)
---
## 题目三(必做):URL 路由 + 完整链路说明
**要求**:
1. 写出项目级 `urls.py`(含 `include`)和应用级 `blog/urls.py`,路由表覆盖:
- 列表页 `""` → `index`
- 文章详情 `/article/<int:pk>/` → `article_detail`
- 提交评论 `/article/<int:pk>/comment/` → `add_comment`
- 作者文章页 `/author/<str:nickname>/` → `author_articles`
每个路由都要起 `name`。
2. **写一段话(150 字内)**:用户在浏览器输入 `/article/3/` 回车后,
从"请求到响应"经历了哪些环节?必须提到:URL 匹配、视图函数、
ORM 查询、`render`、模板、`HttpResponse` 这几个词。
3. **(进阶)** 给出 `index.html` 的模板片段:
- 用 `{% for %}` 循环展示文章标题和"查看详情"链接
- 用模板过滤器把 `created_at` 格式化成 `Y-m-d H:i`
- 空列表时显示"暂无文章"
---
## 完成标准
- [ ] 题目一:三个模型写全,思考题有自己的答案(不必和参考一致,能自圆其说就行)
- [ ] 题目二:四个视图能跑通,`python manage.py runserver` 后列表页、详情页、评论、作者页都能访问
- [ ] 题目三:路由表写全 + 链路说明写出来(进阶则 +1)
**验收动作(强烈建议)**:跑起来 `runserver`,在浏览器里真的走一遍
"打开列表页 → 点进文章 → 提交评论 → 回到详情页看到评论"。
能跑通,说明 Day_4 真正过关。
完成后打开 `参考解答.md` 对照。
> 进度提示:Day_4 做完,你就完成了"基础语法 → 面向对象 → 框架实战"的完整闭环。
> 下一步可以自己加功能:分页、搜索、`@login_required`、用 Celery 给文章作者发通知……
> 每加一个功能,都是一次新的练习。