重构: 15天课程体系(从零到Django), 每题先学后做30分钟
This commit is contained in:
@@ -1,48 +0,0 @@
|
||||
# Day_5 · 面向对象(二):继承 —— 复刻 models.Model
|
||||
|
||||
> 上一天你写了 User 类,今天更进一步:**继承**。
|
||||
> Django 里 Article 没有写 `__init__`,没有写 `save()`,却能 `.save()`——为什么?
|
||||
> 因为通用能力都在父类 `models.Model` 里,子类只需要写自己的字段。
|
||||
> 今天我们自己写这个父类。
|
||||
|
||||
## 今日知识点 → 以后在 Django 里对应什么
|
||||
|
||||
| 今天练的 | 以后在 Django 里会看到 |
|
||||
| --- | --- |
|
||||
| 基类 + 子类继承 | 所有 Model 继承 `models.Model` |
|
||||
| 方法重写 + `super()` | 自定义 Model 的 `save()` / `delete()` |
|
||||
| `isinstance` / `issubclass` | 判断对象类型、自定义 Manager |
|
||||
|
||||
---
|
||||
|
||||
## 题目(必做):继承 —— 复刻 models.Model
|
||||
|
||||
**要求**:
|
||||
|
||||
1. 定义基类 `BaseModel`:
|
||||
- 类属性 `objects = []`(模拟数据库表)
|
||||
- `save(self)`:把 `self` 追加进 `objects`,并打印 `[DB] 已保存 <类名>: <str(self)>`
|
||||
- `delete(self)`:把 `self` 从 `objects` 中移除,打印 `[DB] 已删除 <str(self)>`
|
||||
- `to_dict(self)`:把实例的所有属性转成字典(提示:`self.__dict__` 是什么?)
|
||||
- `__str__(self)`:默认返回 `<类名#id>`,比如 `<Article#1405...>`
|
||||
2. 定义 `Article(BaseModel)`:`__init__` 接收 `title, content, author` 存成实例属性,
|
||||
再用 `time` 模块记录 `created_at`(形如 `2026-08-18 10:30:00`)
|
||||
3. 定义 `Comment(BaseModel)`:`__init__` 接收 `content, author`
|
||||
4. 全流程走一遍:创建文章和评论 → save → 遍历 `BaseModel.objects` 打印 → `to_dict()` → delete
|
||||
5. 验证继承关系:`print(issubclass(Article, BaseModel))` 应为 `True`,
|
||||
`print(isinstance(a, BaseModel))` 应为 `True`
|
||||
|
||||
**进阶(思考 + 动手)**:如果要求"Article 保存前先打印一行日志",而 `save()` 写在父类里,
|
||||
怎么办?(提示:在子类里**重写** `save()`,先打印,再 `super().save()`。试试看输出顺序。)
|
||||
|
||||
**出题意图**:Django 的 Model 就是"通用逻辑放父类,子类只写自己的字段"。
|
||||
理解了继承 + `super()`,你就理解了为什么 Django 模型"不写 save 却能保存"。
|
||||
|
||||
---
|
||||
|
||||
## 完成标准
|
||||
|
||||
- [ ] BaseModel + Article + Comment 全流程跑通(save / 遍历 / to_dict / delete)
|
||||
- [ ] 继承验证两行输出均为 `True`(进阶则 +1:重写 save + super)
|
||||
|
||||
完成后打开 `参考解答.py` 对照。建议看完后关掉文件,自己再默写一遍。
|
||||
@@ -1,67 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Day_5 参考解答
|
||||
=============
|
||||
主题:面向对象(二)—— 继承。
|
||||
建议:先自己写,写不出来再看;看完后关掉文件自己默写一遍。
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
class BaseModel:
|
||||
objects = [] # 类属性:模拟数据库表(所有子类共用)
|
||||
|
||||
def save(self):
|
||||
BaseModel.objects.append(self)
|
||||
print(f"[DB] 已保存 {type(self).__name__}: {self}")
|
||||
|
||||
def delete(self):
|
||||
BaseModel.objects.remove(self)
|
||||
print(f"[DB] 已删除 {self}")
|
||||
|
||||
def to_dict(self):
|
||||
return dict(self.__dict__) # 实例的所有属性 => 字典
|
||||
|
||||
def __str__(self):
|
||||
return f"<{type(self).__name__}#{id(self)}>"
|
||||
|
||||
|
||||
class Article(BaseModel):
|
||||
def __init__(self, title, content, author):
|
||||
self.title = title
|
||||
self.content = content
|
||||
self.author = author
|
||||
self.created_at = time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
# 进阶:重写 save,先打日志,再调用父类逻辑
|
||||
def save(self):
|
||||
print(f"[LOG] 正在保存文章《{self.title}》...")
|
||||
super().save() # 父类的 save 负责真正"入库"
|
||||
|
||||
def __str__(self):
|
||||
return f"<Article: {self.title}>"
|
||||
|
||||
|
||||
class Comment(BaseModel):
|
||||
def __init__(self, content, author):
|
||||
self.content = content
|
||||
self.author = author
|
||||
|
||||
def __str__(self):
|
||||
return f"<Comment: {self.content[:10]}...>"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
a1 = Article("Django 入门", "从 Hello World 开始", "zhangsan")
|
||||
a1.save() # 触发重写后的 save(带日志 + super)
|
||||
c1 = Comment("写得太好了!", "lisi")
|
||||
c1.save()
|
||||
|
||||
for obj in BaseModel.objects:
|
||||
print(obj.to_dict())
|
||||
|
||||
print(issubclass(Article, BaseModel)) # True
|
||||
print(isinstance(a1, BaseModel)) # True
|
||||
|
||||
a1.delete()
|
||||
print(len(BaseModel.objects)) # 1(只剩评论)
|
||||
Reference in New Issue
Block a user