# 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>/` 路径访问特定学生的详细信息。
