B-06 Django-第三部分(进阶技巧)-模型(Model)设计-为模型提供初始化的数据

模型(Model)设计-为模型提供初始化的数据

目标

前面已经介绍了如何快速入门,现在开始熟练掌握一些知识

  • 掌握不同方式下,为模型提供初始化的数据
  • 掌握给单表、关系表提供初始化的数据

回顾

a、模型(Model)示例

回顾一下之前练习时,设计的模型类。

# 使用的model
from django.db import models


# Create your models here.
class Grade(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=8, verbose_name="年级名称", unique=True)

    class Meta:
        db_table = 't_grade'

    def __str__(self):
        # 默认显示类的name字段
        return self.name

    @classmethod
    def create(cls, _name):
        if _name is 'admin':
            obj = cls(name=_name)
            return obj
        else:
            print('不合法')


class Teacher(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=10, verbose_name="教师名称")
    # class_id = models.ManyToManyField(to='Class', db_column="class_id", db_table="t_teach2cls")

    class Meta:
        db_table = 't_teacher'  # 定义表名为t_teacher

    def __str__(self):
        # 默认显示类的name字段
        return self.name


class Class(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16, verbose_name="编辑名称", unique=True)
    grade_id = models.ForeignKey(to='Grade', to_field='id', on_delete=models.CASCADE, db_column="grade_id")
    teacher_id = models.ManyToManyField(to='Teacher', db_column="teacher_id", db_table="t_teach2cls")

    class Meta:
        db_table = 't_class'

    def __str__(self):
        # 默认显示类的name字段
        return self.name


class Student(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16, verbose_name="学生名称")
    GENDER_CHOICES = (
        (0, u"女"),
        (1, u"男"),
    )
    gender = models.CharField(max_length=4, verbose_name="性别", choices=GENDER_CHOICES)
    class_id = models.ForeignKey(to='Class', to_field='id', on_delete=models.CASCADE, db_column="class_id")
    course_id = models.ManyToManyField(to='Course', through='Score', through_fields=('student_id', 'course_id'),
                                       db_column="course_id")

    class Meta:
        db_table = 't_student'

    def __str__(self):
        # 默认显示类的name字段
        return self.name


class Course(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16, verbose_name="课程名称", unique=True)
    teacher_id = models.ForeignKey(to='Teacher', to_field='id', on_delete=models.CASCADE, db_column="teacher_id")

    class Meta:
        db_table = 't_course'

    def __str__(self):
        # 默认显示类的name字段
        return self.name


class Score(models.Model):
    id = models.AutoField(primary_key=True)
    student_id = models.ForeignKey(verbose_name='学生', to="Student", to_field='id', on_delete=models.CASCADE,
                                   db_column="student_id")
    course_id = models.ForeignKey(verbose_name='课程', to="Course", to_field='id', on_delete=models.CASCADE,
                                  db_column="course_id")
    score = models.IntegerField(verbose_name="分数", default=0)

    class Meta:
        db_table = 't_score'
        unique_together = [('student_id', 'course_id'), ]

    def __str__(self):
        v = self.student_id.name + "---" + self.course_id.name
        return v

资料

一、为模型提供初始化的数据

第一次配置应用时,用硬编码的数据预备数据库有时很很有用。你能通过迁移和固定内容提供初始数据。

1.1、通过固定内容提供初始数据

你也能通过固定内容提供数据,不过,这些数据不会自动加载,除非你使用 TransactionTestCase.fixtures。
固定内容是一个 Django 知道如何导入数据库的集合。若你已有一些可用数据,最直接的创建固定内容的方式是使用manage.py dumpdata 命令。或者,你可以手写固定内容;固定数据能被写作 JSON,XML 或 YAML (要求已安装 PyYAML)文档。 序列化文档 拥有更多这些支持的 序列化格式 的细节信息。
下面我以JSON文件来演示具体操作步骤

第一步:在对应应用下创建一个文件夹fixtures

如下图所示
在这里插入图片描述

补充说明:

  • Django 从哪里寻找固定内容文件 默认情况下:Django 在每个应用的 fixtures 目录中查找固定内容,故需要在对应应用下创建这个目录。你可以将配置项 FIXTURE_DIRS 设为一个 Django 需要额外寻找的目录列表。
第二步:创建对应JSON文件

如下图所示
在这里插入图片描述

第三步:编写对应JSON文件

编写对应JSON文件,需要更加模型类的关系,存在几种情况

a、模型(Model)为单表关系的JSON文件

回顾中单表模型,Grade、 Teacher对应的JSON文件如下

[{
	"model": "app_b.Grade",
	"pk": 1,
	"fields": {
		"name": "一年级"
	}
}, {
	"model": "app_b.Grade",
	"pk": 2,
	"fields": {
		"name": "二年级"
	}
}, {
	"model": "app_b.Grade",
	"pk": 3,
	"fields": {
		"name": "三年级"
	}
}, {
	"model": "app_b.Grade",
	"pk": 4,
	"fields": {
		"name": "四年级"
	}
}, {
	"model": "app_b.Grade",
	"pk": 5,
	"fields": {
		"name": "五年级"
	}
}, {
	"model": "app_b.Grade",
	"pk": 6,
	"fields": {
		"name": "六年级"
	}
}]
[{
	"model": "app_b.Teacher",
	"pk": 1,
	"fields": {
		"name": "张三"
	}
}, {
	"model": "app_b.Teacher",
	"pk": 2,
	"fields": {
		"name": "李四"
	}
}, {
	"model": "app_b.Teacher",
	"pk": 3,
	"fields": {
		"name": "王五"
	}
}]

代码说明:

  • model:对应模型,一般是应用名称.模型类名称,比如 “app_b.Teacher” ,“app_b.Grade”。
  • pk:表示主键。
  • fields:代表模型类中的字段。
a、模型(Model)为一对多关系的JSON文件

回顾中一对多模型Course, 他有外键 models.ForeignKey 。对应的JSON文件如下

[{
	"model": "app_b.Course",
	"pk": 1,
	"fields": {
		"name": "生物",
        "teacher_id": 1
	}
}, {
	"model": "app_b.Course",
	"pk": 2,
	"fields": {
		"name": "体育",
        "teacher_id": 1
	}
}, {
	"model": "app_b.Course",
	"pk": 3,
	"fields": {
		"name": "物理",
        "teacher_id": 2
	}
}]

代码说明:

  • teacher_id: 这里外键直接用对应表的主键值,比如我这里就是整型
a、模型(Model)为多对多关系的JSON文件

回顾中多对多模型 Class、Student ,他们有多对多字段 models.ManyToManyField 。对应的JSON文件如下两种情况

  • 情况一、多对多没有定义新的模型类,比如Class
[{
	"model": "app_b.Class",
	"pk": 1,
	"fields": {
		"name": "一年一班",
		"grade_id": 1,
		"teacher_id": [1, 2]
	}
}, {
	"model": "app_b.Class",
	"pk": 2,
	"fields": {
		"name": "一年二班",
		"grade_id": 1,
		"teacher_id": [1, 3]
	}
}, {
	"model": "app_b.Class",
	"pk": 3,
	"fields": {
		"name": "二年一班",
		"grade_id": 2
	}
}, {
	"model": "app_b.Class",
	"pk": 4,
	"fields": {
		"name": "二年二班",
		"grade_id": 2
	}
}, {
	"model": "app_b.Class",
	"pk": 5,
	"fields": {
		"name": "三年一班",
		"grade_id": 3
	}
}, {
	"model": "app_b.Class",
	"pk": 6,
	"fields": {
		"name": "三年二班",
		"grade_id": 3
	}
}]

代码说明:

  • teacher_id: 在对应模型类Class中 , teacher_id = models.ManyToManyField(to='Teacher', db_column="teacher_id", db_table="t_teach2cls") 如此定义,没有针对多对多关系,定义新的模型类,故在提供数据的时候,该字段已列表方式赋值。比如 "teacher_id": [1, 2]

  • 情况二、多对多有定义新的模型类,比如 Student,将多对多映射到新的模型类 Score

[{
	"model": "app_b.Score",
	"pk": 1,
	"fields": {
		"student_id": 1,
		"course_id": 1,
		"score": 60
	}
}, {
	"model": "app_b.Score",
	"pk": 2,
	"fields": {
		"student_id": 1,
		"course_id": 2,
		"score": 59
	}
}, {
	"model": "app_b.Score",
	"pk": 3,
	"fields": {
		"student_id": 1,
		"course_id": 3,
		"score": 59
	}
}, {
	"model": "app_b.Score",
	"pk": 4,
	"fields": {
		"student_id": 2,
		"course_id": 1,
		"score": 77
	}
}, {
	"model": "app_b.Score",
	"pk": 5,
	"fields": {
		"student_id": 2,
		"course_id": 2,
		"score": 99
	}
}, {
	"model": "app_b.Score",
	"pk": 6,
	"fields": {
		"student_id": 2,
		"course_id": 3,
		"score": 80
	}
}]
  • model: 由于在模型类 Student 中, course_id = models.ManyToManyField(to='Course', through='Score', through_fields=('student_id', 'course_id'), db_column="course_id") 如此定义,有针对多对多的关系,定义新的模型类Score,故在提供数据的时候,按照模型类Score赋值就行。
第四步:导入对应JSON文件

加载数据非常简单:只需调用 manage.py loaddata , 是你刚创建的固定内容的文件名。每次你运行 loaddata,数据都会从固定内容读出,重新装入数据库。这意味着若你修改了某个固定内容创建的行,随后再次运行 loaddata ,你会丢掉所有的修改。

(LearnDjango) D:\Programma\Python\Python3\LearnDjango\DjangoProjectA>python manage.py loaddata grade.json
Installed 6 object(s) from 1 fixture(s)

导入后效果:
在这里插入图片描述
在这里插入图片描述

1.2、通过SQL语句提供初始数据

为提供初始化的SQL数据django提供了传递数据库任意的SQL的钩子,这些SQL是当你运行syncdb的时候在CREATE TABLE后会被运行的。你可以使用这个钩子去填充默认记录,或者创建SQL函数或者视图函数,触发器等等。

钩子是很简单的:django会在你的app目录下寻找一个名叫 sql/<modelname>.sql 的文件,这个文件的中的modelname是你的模型名字的小写。所以,如果你有一个名叫Person的模型在你的名为myapp的app目录下,你可以在你的myapp目录下的sql/person.sql文件里面添加任意的SQL,下面是一个例子:

INSERT INTO myapp_person (first_name, last_name) VALUES ('John', 'Lennon');
INSERT INTO myapp_person (first_name, last_name) VALUES ('Paul', 'McCartney');

每个sql文件(如果有的话),应该包含有效的往表中插入数据的语句(分号隔开的insert语句)。sql文件可以被manage.py中的sqlcustom,sqlreset,sqlall和reset命令读取。注意的是,如果你有多个sql文件,他们被运行的顺序是无法保证的,你唯一能做的是,保证需要用的的数据表都是事先已经被创建好的
下面是一个例子:值得注意的是,这个初始化仅在第一次运行syncdb时创建
在这里插入图片描述
特定数据库后端的sql数据django提供了特定后端的sql数据的钩子。特定后端的sql会被先运行(后端和ENGINE的值一样才起效)。
举个例子,如果你的app包含sql/person.sql和sql/person.sqlite3.sql两个文件,并且数据库使用sqlite,django会先运行sql/person.sqlite3.sql,然后才运行sql/person.sql。相信这个例子很容易理解,django会先寻找文件<appname>/sql/<modelname>.<backend>.sql文件,<appname>是你的应用目录,<modelname>是你的模型的名字的小写形式,<backend>是你的数据库引擎。
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值