
# P04 Django 构建数据表创建与数据迁移
## **数据表创建**

### **模块功能**

数据表的构建主要是通过 models.py 文件来完成,models.py文件是Django中定义和操作数据库数据模型的核心文件，它直接影响着应用程序与数据库的交互方式。它的作用可以简要概括如下：

1. **定义数据模型**：`models.py` 文件用于定义应用程序中的数据模型。这些模型通常对应数据库中的表，定义了数据的组织方式和结构。

2. **映射数据库表**：通过在`models.py`中创建类（继承自`django.db.models.Model`），可以指定数据库表的名称、字段类型以及字段之间的关系（如一对多、多对多）。

3. **字段和行为**：在模型类中，每个字段都对应数据库中的一个列，你可以指定字段的类型（如整数、字符串、日期等），以及字段的其他属性（如是否可为空、是否是主键等）。

4. **数据验证**：`models.py` 中的模型可以包含数据验证规则，确保输入的数据符合预期的格式和约束。

5. **生成数据库迁移**：当你在`models.py`中对模型进行更改后，可以通过 Django 的迁移系统生成迁移文件，这些文件包含了将数据库结构更新到最新模型定义所需的SQL命令。


今天的例子就是在`apps`应用的 models.py 文件中创建两个表：产品分类表和产品信息表。

### **models.py**

#### 引入模块

引入用到其他app中用到的模块以及将`from django.db import models`换为`from django.db.models import *`,其功能如下：


  1. 引入`Django`的数据库操作模块：`Django`是一个`Web`框架，它的`db.models`模块提供了`ORM`（对象关系映射）功能，让我们可以用Python对象来操作数据库。
  2. 导入所有模型类和工具：使用*通配符导入意味着你将导入models模块中的所有类、函数和变量。这包括Model基类（用于定义数据模型），各种字段类型（如`CharField`, `IntegerField`等），以及查询相关的工具和函数。
  3. 简化代码：通过一次导入所有内容，你可以直接使用`Django ORM`提供的任何功能，而无需每次都写全模块路径，比如django.db.models.CharField可以直接写成`CharField`。
  4. 可能的副作用：尽管这种导入方式方便，但也可能导致命名冲突，特别是当你从其他库也导入相似名称的对象时。因此，通常推荐只导入你需要的具体对象，以保持代码的清晰性和可读性。例如，`from django.db.models import Model, CharField`。

#### 创建模型类

**产品分类表**

```py
from django.db.models import *

class GoodsCategory(Model):

    name = CharField(max_length=64, verbose_name='名称')

    remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')

```

**产品信息表** 

```py   
class Goods(Model):
        
    number = CharField(max_length=32, verbose_name='编号')

    name = CharField(max_length=64, verbose_name='名称')

    barcode = CharField(max_length=32, null=True, blank=True, verbose_name='条码')

    category = ForeignKey('data.GoodsCategory', on_delete=SET_NULL, null=True,related_name='goods_set', verbose_name='产品分类')

    spec = CharField(max_length=64, null=True, blank=True, verbose_name='规格')
            
    shelf_life_days = IntegerField(null=True, verbose_name='保质期天数')

    purchase_price = FloatField(default=0, verbose_name='采购价')

    retail_price = FloatField(default=0, verbose_name='零售价')

    remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')
   
```

## **合并数据库**

这两个命令是 Django 框架中的关键命令，用于进行数据库迁移。当你修改了 Django 模型后，你需要运行这两个命令，以将这些更改应用到数据库中。

`python manage.py makemigrations`

 这个命令用于生成迁移脚本，迁移脚本用于告诉数据库如何根据这些结构变化进行更新。当你更新了模型文件之后，需要运行该命令，Django 会检测模型的改变，然后自动生成相应的迁移脚本，存储在 `migrations/` 目录下。通常来说，你需要针对每个应用运行一次该命令。

`python manage.py migrate`

这个命令用于将迁移脚本应用到数据库中。当你在模型文件中进行更改之后，需要先通过 `makemigrations` 命令生成迁移脚本，然后运行该命令将这些脚本应用到数据库中。对于新的迁移脚本，Django 会逐个执行它们，从而更新数据库结构。对于已经执行过的脚本，Django 会跳过它们，避免重复执行。

这两个命令是 Django 框架中非常重要的命令，在修改数据库相关内容时必须时刻清醒地记住使用它们。

### 课后习题：
[课后练习题](/contents/P13.md#5-创建班级和学生表)