Add Day_2: 字典与字符串(URL参数解析)
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# Day_2 · 字典与字符串:先学会"接住"请求
|
||||
|
||||
> 后端程序每天都在处理两样东西:**字典**(各种参数、数据记录)和**字符串**(URL、文本)。
|
||||
> 今天的两道题只用到基础语法,但都是后端最真实的日常。
|
||||
> 做完它们,你就拿到了读懂 Django 的第一把钥匙。
|
||||
|
||||
## 今日知识点 → 以后在 Django 里对应什么
|
||||
|
||||
| 今天练的 | 以后在 Django 里会看到 |
|
||||
| --- | --- |
|
||||
| 列表 + 字典的筛选、排序 | ORM 查询结果(QuerySet)的循环处理 |
|
||||
| 字符串分割与格式化 | URL 路由解析、模板渲染、日志输出 |
|
||||
| 字典的增删改查 | `request.GET` / `request.POST`、JSON 响应 |
|
||||
|
||||
---
|
||||
|
||||
## 题目一(热身):模拟查询结果的处理
|
||||
|
||||
**背景**:ORM 查数据库,拿回来的是"一堆记录",每条记录就是一个字典。
|
||||
以后你天天和这种东西打交道。今天先热身。
|
||||
|
||||
**要求**:造一个用户列表(`list[dict]`,4~5 条),字段:`name`、`age`、`city`。然后:
|
||||
|
||||
1. 筛出**年龄 ≥ 18** 的用户(提示:列表推导式 `[u for u in users if ...]`)
|
||||
2. 按**年龄从大到小**排序(提示:`sorted(users, key=lambda u: u["age"], reverse=True)`)
|
||||
3. 输出 `zhangsan(20岁)` 这种格式的字符串列表(提示:f-string)
|
||||
4. **进阶(加分)**:把上一步的结果用 `", "` 拼成一个字符串输出
|
||||
|
||||
**输入输出示例**
|
||||
|
||||
```
|
||||
users = [
|
||||
{"name": "zhangsan", "age": 20, "city": "青岛"},
|
||||
{"name": "lisi", "age": 17, "city": "济南"},
|
||||
{"name": "wangwu", "age": 22, "city": "北京"},
|
||||
]
|
||||
|
||||
筛选 ≥18: [{'name': 'zhangsan', ...}, {'name': 'wangwu', ...}]
|
||||
按年龄降序: wangwu, zhangsan
|
||||
字符串列表: ['wangwu(22岁)', 'zhangsan(20岁)']
|
||||
进阶拼接: 'wangwu(22岁), zhangsan(20岁)'
|
||||
```
|
||||
|
||||
**出题意图**:`filter` + `order_by` 在 Django 里是 `objects.filter(age__gte=18).order_by("-age")`——今天你用纯 Python 先把同样的思维练熟。
|
||||
|
||||
---
|
||||
|
||||
## 题目二(必做):解析 URL 查询参数
|
||||
|
||||
**背景**:浏览器访问 `https://example.com/register?username=zhangsan&age=20&city=qingdao`,
|
||||
`?` 后面的 `username=zhangsan&age=20&city=qingdao` 叫做**查询参数(query string)**。
|
||||
Django 里 `request.GET` 就是帮你解析好的字典。今天我们手写一个解析器,看清它背后发生了什么。
|
||||
|
||||
**要求**:写函数 `parse_query_string(query)`,输入一行查询参数(不含 `?`),返回一个字典。
|
||||
|
||||
必须处理的边界情况:
|
||||
|
||||
1. 空输入 → 返回空字典 `{}`
|
||||
2. 重复键,如 `name=a&name=b` → 后者覆盖前者:`{'name': 'b'}`
|
||||
3. 参数没有 `=`,如 `flag` → 值为空字符串:`{'flag': ''}`
|
||||
4. 值为空,如 `name=` → `{'name': ''}`
|
||||
|
||||
**输入输出示例**
|
||||
|
||||
```
|
||||
输入: username=zhangsan&age=20&city=qingdao
|
||||
输出: {'username': 'zhangsan', 'age': '20', 'city': 'qingdao'}
|
||||
|
||||
输入: name=a&name=b&flag
|
||||
输出: {'name': 'b', 'flag': ''}
|
||||
|
||||
输入: (空字符串)
|
||||
输出: {}
|
||||
```
|
||||
|
||||
**进阶(加分)**:URL 编码还原——把值中的 `+` 还原为空格,`%20` 也还原为空格。
|
||||
如 `name=Zhang+San` → `{'name': 'Zhang San'}`。
|
||||
|
||||
> 提示:
|
||||
> - 先 `split('&')` 把整体切成若干段,再对每一段 `split('=', 1)`。
|
||||
> 想想为什么 `maxsplit` 要写成 1?(如果值里本身就含 `=` 会怎样?)
|
||||
> - 字典赋值 `d[key] = value` 天然处理了"覆盖"和"空值"两种情况。
|
||||
|
||||
**出题意图**:Django 的 `QueryDict`(`request.GET`)底层干的就是这件事。
|
||||
把它吃透,以后看到 `request.GET.get('page')` 就不再是黑魔法,而是老朋友。
|
||||
|
||||
---
|
||||
|
||||
## 完成标准
|
||||
|
||||
- [ ] 题目一四步全部跑通(含进阶则 +1)
|
||||
- [ ] 题目二 4 个边界情况全部通过(含进阶则 +1)
|
||||
|
||||
完成后打开 `参考解答.py` 对照。建议看完后关掉文件,自己再默写一遍。
|
||||
|
||||
> 写给还没开始的你:这系列是递进关系——
|
||||
> Day_2 字典/字符串 → Day_3 函数/异常 → Day_4~Day_6 面向对象 → 进阶_Django 实战。
|
||||
> 每天只做必做题,也足够支撑你开学后跟上节奏。
|
||||
Reference in New Issue
Block a user