# Django 课后练习题

## 1. Python 虚拟环境创建

请根据下列方法选择一种创建 Python 虚拟环境，并按要求安装课程所需包。

在 Python 中，虚拟环境是一种隔离的工作环境，可以防止不同项目的依赖项之间相互干扰。有多种方法可以创建 Python 虚拟环境，以下是其中几种常见的方法：

* **使用 venv 模块创建虚拟环境** ***——推荐使用***

  ```bash
  python -m venv myenv      # 创建虚拟环境
  source myenv/bin/activate  # 激活虚拟环境
  ```
* **使用 virtualenv 创建虚拟环境**

  ```bash
  virtualenv myenv        # 创建虚拟环境
  source myenv/bin/activate  # 激活虚拟环境
  ```
* **使用 conda 创建虚拟环境**

  ```bash
  conda create --name myenv  # 创建虚拟环境
  conda activate myenv        # 激活虚拟环境
  ```

​

以上是三种常见的 Python 虚拟环境创建方法，其中 venv 和 virtualenv 是在命令行中使用的，而 conda 是 Python 第三方库，需要先安装。另外，在 Windows 系统中，需要使用 Scripts 目录下的 activate.bat 文件来激活虚拟环境。

## 2. pip 源设置

请根据需求设置 pip 源

pip 源设置的方法有修改 pip 配置文件和使用代理两种方法。

* 修改 pip 配置文件：在 pip 配置文件中添加相应的源。
* 使用代理：在命令行中使用代理命令进行设置。

临时使用：在 pip install 命令后面加上 -i 参数，指定 pip 源。例如：

```bash
pip install jieba -i https://pypi.tuna.tsinghua.edu.cn/simple
```

永久修改：在 Linux 系统中，修改 \~/.pip/pip.conf 文件（没有就创建一个），指定 pip 源。例如：清华大学源。

请切换 pip 源为国内源，可多次尝试。

国内 pip 源有：

* 清华大学：<https://pypi.tuna.tsinghua.edu.cn/simple；>
* 阿里云：<https://mirrors.aliyun.com/pypi/simple；>
* 中国科学技术大学：<https://pypi.mirrors.ustc.edu.cn/simple；>
* 华中科技大学：<http://pypi.hustunique.com/；>
* 豆瓣源：<http://pypi.douban.com/simple；>
* 腾讯源：<http://mirrors.cloud.tencent.com/pypi/simple；>
* 华为镜像源：<https://repo.huaweicloud.com/repository/pypi/simple。>

## 4. Django 项目搭建

根据下列流程搭建一个学生管理系统。

创建 Django 项目的步骤如下：

1. 安装 Django：首先，确保你的系统上已经安装了Python。然后，通过以下命令安装 Django：

   ```
   pip install django
   ```
2. 创建 Django 项目：使用以下命令创建一个新的 Django 项目：

   ```
   django-admin startproject project_name
   ```

   其中，`project_name` 是你的项目名称。这将在当前目录下创建一个名为 `project_name` 的文件夹，其中包含了一个基本的 Django 项目结构。
3. 配置项目：进入项目文件夹：

   ```bash
   cd project_name
   ```

   然后，编辑`settings.py` 文件，根据你的需求配置项目设置，例如数据库设置、静态文件路径等。
4. 创建应用：使用以下命令创建一个新的 Django 应用：

   ```bash
   # 二者皆可
   python manage.py startapp app_name  

   django-admin startapp app_name
   ```

   其中，`app_name` 是你的应用名称。这将在 `project_name` 文件夹下的 `app` 文件夹中创建一个新的应用。
5. 定义模型：在应用中定义数据库模型。打开`app/models.py`文件，并定义你的模型类。这些模型类将映射到数据库中的表。
6. 创建数据库表：运行以下命令来创建数据库表：

   ```bash
   python manage.py makemigrations app_name
   python manage.py migrate app_name
   ```

   这将根据你在`models.py`文件中定义的模型创建数据库表。
7. 编写视图和模板：在应用中编写视图和模板文件，以实现具体的业务逻辑和页面呈现。
8. 运行项目。运行开发服务器。在终端中输入以下命令来启动开发服务器：

   ```bash
   python manage.py runserver
   ```

## 5. 创建班级和学生表

请按下列方法创建班级、学生表

在Django中创建班级和学生表，需要执行以下步骤：

1. 创建Django应用

   如果还没有创建Django应用，请执行以下命令创建一个新的Django应用：

   ```bash
   python manage.py startapp myapp
   ```

   其中`myapp`是你想要创建的应用名称。
2. 定义班级和学生模型

   在`myapp/models.py`文件中定义班级和学生模型。例如：

   ```python
   from django.db import models

   class Classroom(models.Model):
       name = models.CharField(max_length=100)
       grade = models.IntegerField()

       def __str__(self):
           return self.name

   class Student(models.Model):
       name = models.CharField(max_length=100)
       age = models.IntegerField()
       classroom = models.ForeignKey(Classroom, on_delete=models.CASCADE)

       def __str__(self):
           return self.name
   ```

   这里我们定义了两个模型，`Classroom`和`Student`，并在`Student`模型中通过`ForeignKey`字段关联了`Classroom`模型。
3. 生成迁移脚本

   执行以下命令生成迁移脚本：

   ```bash
   python manage.py makemigrations
   ```

   其中`myapp`是刚刚创建的应用名称。这个命令会在`myapp/migrations/`目录下生成一个迁移脚本文件。
4. 执行迁移命令

   执行以下命令将模型应用到数据库中：

   ```bash
   python manage.py migrate
   ```

   这个命令会将迁移脚本应用到数据库中，创建相应的班级和学生表。如果迁移成功，就可以在Django的admin后台管理页面中看到这两个表，并进行增删改查等操作。

## 6. QuerySet 和 Instance增删改查

请使用QuerySet 和 Instance在班级、学生表上进行增删改查。

在Django中，我们可以使用QuerySet和实例对班级和学生表进行增删改查操作。以下是一些例子：

* **增加（Create）**

创建新的班级和学生实例：

```python
from myapp.models import Classroom, Student

# 创建一个新的班级
new_classroom = Classroom(name='一班', grade=1)
new_classroom.save()

# 创建一个新的学生，并关联到刚刚创建的班级
new_student = Student(name='小明', age=10, classroom=new_classroom)
new_student.save()
```

* **查询（Retrieve）**

使用QuerySet查询班级和学生：

```python
# 获取所有班级
all_classrooms = Classroom.objects.all()

# 获取名称为'一班'的班级
classroom = Classroom.objects.get(name='一班')

# 获取班级为'一班'的所有学生
students = Student.objects.filter(classroom__name='一班')
```

* **更新（Update）**

更新班级或学生的属性：

```python
# 获取名称为'一班'的班级
classroom = Classroom.objects.get(name='一班')

# 更新班级的名称
classroom.name = '二班'
classroom.save()
```

* **删除（Delete）**

删除班级或学生：

```python
# 获取名称为'二班'的班级
classroom = Classroom.objects.get(name='二班')

# 删除该班级
classroom.delete()
```

注意，删除一个班级将会同时删除与之关联的所有学生，因为我们在学生模型中设置了`on_delete=models.CASCADE`。这意味着当一个班级被删除时，与之关联的学生也会被删除。如果你不希望这样，你可以考虑更改`on_delete`参数的设置。例如，设置为`models.SET_NULL`将会在删除班级时将学生的班级设置为NULL。不过，这样你需要确保学生的班级字段允许为NULL。

## 7. 使用serializers 序列化、APIView 创建班级和学生查询

请对创建的班级、学生表进行序列化。

要使用APIView创建班级和学生的查询视图，你需要执行以下步骤：

首先，确保你已经安装了Django REST framework。如果没有安装，可以使用以下命令进行安装：

```python
pip install djangorestframework
```

然后，你可以使用以下代码在Django中创建班级和学生的查询视图：

1. 在`myapp`应用中创建一个名为`views.py`的文件（如果尚未创建）。
2. 在`myapp/models.py`文件中定义班级和学生模型。可参考task5
3. 在`views.py`文件中，导入所需的模块并创建查询视图。例如：

   ```python
   from rest_framework.views import APIView
   from rest_framework.response import Response
   from .models import Classroom, Student

   class ClassroomListView(APIView):
       def get(self, request):
           classrooms = Classroom.objects.all()
           serializer = ClassroomSerializer(classrooms, many=True)
           return Response(serializer.data)

   class StudentListView(APIView):
       def get(self, request):
           students = Student.objects.all()
           serializer = StudentSerializer(students, many=True)
           return Response(serializer.data)
   ```
4. 在上述代码中，我们创建了两个视图，一个用于查询所有班级，另一个用于查询所有学生。这些视图继承了 `APIView`，并使用了Django REST framework 的 `Response` 和序列化器来处理数据。
5. 你还需要创建序列化器，以便将班级和学生实例转换为 JSON 格式。在 `myapp` 应用中创建一个名为 `serializers.py` 的文件，并在其中定义序列化器。例如：

   ```python
   from rest_framework import serializers
   from .models import Classroom, Student

   class ClassroomSerializer(serializers.ModelSerializer):
       class Meta:
           model = Classroom
           fields = ['id', 'name', 'grade']

   class StudentSerializer(serializers.ModelSerializer):
       class Meta:
           model = Student
           fields = ['id', 'name', 'age', 'classroom']
   ```
6. 最后，在你的应用的`urls.py`文件中添加URL配置，以便将视图与URL进行关联。例如：

   ```python
   from django.urls import path
   from .views import ClassroomListView, StudentListView

   urlpatterns = [
       path('classrooms/', ClassroomListView.as_view(), name='classroom-list'),
       path('students/', StudentListView.as_view(), name='student-list'),
   ]
   ```

现在，当你访问`/classrooms/`路径时，你将获得所有班级的列表，当你访问`/students/`路径时，你将获得所有学生的列表。这些视图会以JSON格式返回数据。

## 8. 使用 ModelViewSet 创建班级、学生查询 view

请使用 ModelViewSet 创建班级、学生查询 view。

使用 `ModelViewSet` 可以更方便地创建班级和学生的查询视图。`ModelViewSet` 是 Django REST framework 提供的一个视图集，它提供了默认的 `list()` 和 `retrieve()` 方法，适用于查询操作。

下面是使用 `ModelViewSet` 创建班级和学生查询视图的步骤：

1. 在 `myapp` 应用的 `views.py` 文件中，导入所需的模块并创建 `ModelViewSet` 子类。例如：

   ```python
   from rest_framework.viewsets import ModelViewSet
   from .models import Classroom, Student
   from .serializers import ClassroomSerializer, StudentSerializer

   class ClassroomViewSet(ModelViewSet):
       queryset = Classroom.objects.all()
       serializer_class = ClassroomSerializer

   class StudentViewSet(ModelViewSet):
       queryset = Student.objects.all()
       serializer_class = StudentSerializer
   ```
2. 在上述代码中，我们创建了两个视图集，`ClassroomViewSet` 用于处理班级的查询操作， `StudentViewSet` 用于处理学生的查询操作。我们指定了 `queryset` 属性来定义视图中使用的查询集，以及`serializer_class`属性来定义用于序列化和反序列化数据的序列化器。
3. 在应用的 `urls.py` 文件中，使用路由器（Router）自动生成 URL 配置。这样可以简化 URL 的定义。首先，导入路由器类，然后在 `urls.py` 文件的底部添加以下代码：

   ```python
   from rest_framework.routers import DefaultRouter

   router = DefaultRouter()
   router.register(r'classrooms', ClassroomViewSet)
   router.register(r'students', StudentViewSet)


   urlpatterns += router.urls 
   ```

上述代码使用路由器注册了班级和学生视图集，并将生成的URL模式添加到 `urlpatterns` 列表中。

现在，当你访问 `/classrooms/` 路径时，你会获得所有班级的列表，并且可以通过 `/classrooms/<id>/` 路径访问特定班级的详细信息。类似地，通过访问 `/students/` 路径，你可以获得所有学生的列表，并通过 `/students/<id>/` 路径访问特定学生的详细信息。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://likechen.gitbook.io/sweettalk-django4.2/docs/contents/p13.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
