上一篇Django 2.1.7 模型 - 条件查询 F对象 Q对象 聚合查询讲述了关于Django模型的F对象、Q对象、聚合查询等功能。
但是没有讲到两张表的关联查询的实现,这个在模型里面该怎么处理呢?
参考文献
https://docs.djangoproject.com/zh-hans/2.1/ref/models/relations/https://docs.djangoproject.com/zh-hans/2.1/topics/db/managers/
模型类关系
在进行关联查询之前,首先要了解一下模型之间的关联关系,以及相应的操作。
关系字段类型
关系型数据库的关系包括三种类型:
- ForeignKey:一对多,将字段定义在多的一端中。
- ManyToManyField:多对多,将字段定义在任意一端中。
- OneToOneField:一对一,将字段定义在任意一端中。
- 可以维护递归的关联关系,使用'self'指定。
一对多关系
想在前面篇章中,写到的服务器信息表以及中间件表,就是一对多的关系。
一台服务器对应多个中间件,相应的数据模型如下:
class ServerInfo(models.Model):
server_hostname = models.CharField(max_length=20, default=None)
server_intranet_ip = models.CharField(max_length=20, default=None)
server_internet_ip = models.CharField(max_length=20, default=None)
server_shelves_date = models.DateField(auto_now_add=True) # 数据加入时间
update_time = models.DateTimeField(auto_now=True) # 数据更新时间
is_delete = models.BooleanField(default=False) # 逻辑删除
class MiddlewareInfo(models.Model):
name = models.CharField(max_length=20)
port = models.IntegerField()
server = models.ForeignKey('ServerInfo',on_delete=models.CASCADE, default=None)
shelves_date = models.DateTimeField(auto_now_add=True) # 数据加入时间
update_time = models.DateTimeField(auto_now=True) # 数据更新时间
is_delete = models.BooleanField(default=False) # 逻辑删除
可以从上面的模型看出,一对多的关系构建的关键就是MiddlewareInfo(中间件-多类)设置外键连接ServerInfo(服务器信息 - 一类)。
server = models.ForeignKey('ServerInfo',on_delete=models.CASCADE, default=None)
。
但是在实际使用的过程中,使用外键的话,在做一些数据处理的时候很不方便。也可以不设置一个外键,直接就单纯一个int字段来记录ServerInfo类的id也是可以的。
多对多关系
在前面篇章中,并没有设计关于多对多的关联模型,那么现在可以设计一个。
在前面已有服务器类的前提下,可以设计一个服务器用途类。
定义一个服务器用途类的话,那么一台服务器可能有多种用途,同时一种用途类型下,可能有多台服务器对应。
这种就是多对多的关系。
class ServerUsedType(models.Model):
used_type = models.CharField(max_length=20,default=None)
class ServerInfo(models.Model):
server_hostname = models.CharField(max_length=20, default=None)
server_intranet_ip = models.CharField(max_length=20, default=None)
server_internet_ip = models.CharField(max_length=20, default=None)
server_shelves_date = models.DateField(auto_now_add=True) # 数据加入时间
update_time = models.DateTimeField(auto_now=True) # 数据更新时间
is_delete = models.BooleanField(default=False) # 逻辑删除
server_used_type_id = models.ManyToManyField(ServerUsedType) # 通过ManyToManyField建立多对多的关系
那么这种模型多对多关系的字段通过数据迁移,会生成什么样的字段呢?
执行数据迁移,如下:
python3 manage.py makemigrations
python3 manage.py migrate
从mysql日志查看关键执行日志如下:
2019-06-14T16:54:06.348996Z 21 Query CREATE TABLE `assetinfo_serverinfo_server_used_type_id` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `serverinfo_id` integer NOT NULL, `serverusedtype_id` integer NOT NULL)
2019-06-14T16:54:06.394877Z 21 Query ALTER TABLE `assetinfo_serverinfo_server_used_type_id` ADD CONSTRAINT `assetinfo_serverinfo_serverinfo_id_b297c62e_fk_assetinfo` FOREIGN KEY (`serverinfo_id`) REFERENCES `assetinfo_serverinfo` (`id`)
2019-06-14T16:54:06.441100Z 21 Query ALTER TABLE `assetinfo_serverinfo_server_used_type_id` ADD CONSTRAINT `assetinfo_serverinfo_serverusedtype_id_5551cbd5_fk_assetinfo` FOREIGN KEY (`serverusedtype_id`) REFERENCES `assetinfo_serverusedtype` (`id`)
2019-06-14T16:54:06.489104Z 21 Query ALTER TABLE `assetinfo_serverinfo_server_used_type_id` ADD CONSTRAINT `assetinfo_serverinfo_ser_serverinfo_id_serverused_c12509b8_uniq` UNIQUE (`serverinfo_id`, `serverusedtype_id`)
查看mysql迁移数据之后,生成了两个表,如下:
mysql> show tables;
+------------------------------------------+
| Tables_in_assetinfo |
+------------------------------------------+
| assetinfo_middlewareinfo |
| assetinfo_scriptinfo |
| assetinfo_serverinfo |
| assetinfo_serverinfo_server_used_type_id |
| assetinfo_serverusedtype |
可以看到为了实现多对多的关系,django自动创建了一张中间表assetinfo_serverinfo_server_used_type_id,通过中间表绑定assetinfo_serverinfo和assetinfo_serverusedtype表的关系。
查看这三张表的表结构如下:
mysql> desc assetinfo_serverinfo;
+---------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| server_hostname | varchar(20) | NO | | NULL | |
| server_intranet_ip | varchar(20) | NO | | NULL | |
| server_internet_ip | varchar(20) | NO | | NULL | |
| server_shelves_date | date | NO | | NULL | |
| is_delete | tinyint(1) | NO | | NULL | |
| update_time | datetime(6) | NO | | NULL | |
+---------------------+-------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
mysql> desc assetinfo_serverinfo_server_used_type_id;
+-------------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| serverinfo_id | int(11) | NO | MUL | NULL | |
| serverusedtype_id | int(11) | NO | MUL | NULL | |
+-------------------+---------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> desc assetinfo_serverusedtype;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| used_type | varchar(20) | NO | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql>
在知道Django模型如何实现多对多的关联之后,下面来看看怎么关联查询。
关联查询
Django中也能实现类似于join查询。
通过对象执行关联查询
首先写一个一对多的关联查询SQL,如下:
select s.server_hostname,m.name,s.id,m.server_id from assetinfo_serverinfo as s left join assetinfo_middlewareinfo as m on s.id = m.server_id where s.id = 1;
mysql> select s.server_hostname,m.name,s.id,m.server_id from assetinfo_serverinfo as s left join assetinfo_middlewareinfo as m on s.id = m.server_id where s.id = 1;
+-----------------+-----------+----+-----------+
| server_hostname | name | id | server_id |
+-----------------+-----------+----+-----------+
| 测试服务器 | memcached | 1 | 1 |
| 测试服务器 | redis | 1 | 1 |
| 测试服务器 | test | 1 | 1 |
| 测试服务器 | test | 1 | 1 |
| 测试服务器 | test | 1 | 1 |
| 测试服务器 | test | 1 | 1 |
| 测试服务器 | test | 1 | 1 |
| 测试服务器 | test | 1 | 1 |
| 测试服务器 | test | 1 | 1 |
| 测试服务器 | mongodb | 1 | 1 |
| 测试服务器 | test | 1 | 1 |
| 测试服务器 | test | 1 | 1 |
+-----------------+-----------+----+-----------+
12 rows in set (0.00 sec)
mysql>
那么模型类该怎么实现这个查询呢?
由一到多的访问语法:一对应的模型类对象.多对应的模型类名小写_set
In [1]: from assetinfo.models import ServerInfo,MiddlewareInfo
# 设置查询 id = 1 的 服务器信息
In [2]: s = ServerInfo.objects.get(id=1)
# 关联查询相关的中间件信息
In [3]: s.middlewareinfo_set.all()
Out[3]: <QuerySet [<MiddlewareInfo: MiddlewareInfo object (1)>, <MiddlewareInfo: MiddlewareInfo object (2)>, <MiddlewareInfo: MiddlewareInfo object (5)>, <MiddlewareInfo: Middlewar
eInfo object (6)>, <MiddlewareInfo: MiddlewareInfo object (7)>, <MiddlewareInfo: MiddlewareInfo object (8)>, <MiddlewareInfo: MiddlewareInfo object (9)>, <MiddlewareInfo: Middlewar
eInfo object (10)>, <MiddlewareInfo: MiddlewareInfo object (11)>, <MiddlewareInfo: MiddlewareInfo object (14)>, <MiddlewareInfo: MiddlewareInfo object (15)>, <MiddlewareInfo: Middl
ewareInfo object (16)>]>
In [4]:
对应的SQL如下:
SELECT
assetinfo_middlewareinfo.
id,
assetinfo_middlewareinfo.
name,
assetinfo_middlewareinfo.
port,
assetinfo_middlewareinfo.
server_id,
assetinfo_middlewareinfo.
shelves_date,
assetinfo_middlewareinfo.
update_time,
assetinfo_middlewareinfo.
is_deleteFROM
assetinfo_middlewareinfoWHERE
assetinfo_middlewareinfo.
server_id= 1 LIMIT 21;
mysql> SELECT `assetinfo_middlewareinfo`.`id`, `assetinfo_middlewareinfo`.`name`, `assetinfo_middlewareinfo`.`port`, `assetinfo_middlewareinfo`.`server_id`, `assetinfo_middlewareinfo`.`shelves_date`, `assetinfo_middlewareinfo`.`update_time`, `assetinfo_middlewareinfo`.`is_delete` FROM `assetinfo_middlewareinfo` WHERE `assetinfo_middlewareinfo`.`server_id` = 1 LIMIT 21;
+----+-----------+-------+-----------+----------------------------+----------------------------+-----------+
| id | name | port | server_id | shelves_date | update_time | is_delete |
+----+-----------+-------+-----------+----------------------------+----------------------------+-----------+
| 1 | memcached | 11211 | 1 | 2019-06-10 14:56:46.150556 | 2019-06-10 17:37:51.365155 | 1 |
| 2 | redis | 6379 | 1 | 2019-06-10 14:56:46.150556 | 2019-06-10 17:38:20.712862 | 1 |
| 5 | test | 123 | 1 | 2019-06-10 17:05:16.632773 | 2019-06-10 17:05:16.632773 | 1 |
| 6 | test | 123 | 1 | 2019-06-10 17:06:20.120658 | 2019-06-10 17:06:20.121656 | 1 |
| 7 | test | 123 | 1 | 2019-06-10 17:06:43.193412 | 2019-06-10 17:06:43.193412 | 1 |
| 8 | test | 123 | 1 | 2019-06-10 17:07:03.747395 | 2019-06-10 17:07:03.747395 | 1 |
| 9 | test | 123 | 1 | 2019-06-10 17:08:43.372097 | 2019-06-10 17:08:43.372097 | 1 |
| 10 | test | 123 | 1 | 2019-06-10 17:09:37.877019 | 2019-06-10 17:09:37.877019 | 1 |
| 11 | test | 123 | 1 | 2019-06-10 17:11:45.403627 | 2019-06-10 17:11:45.403627 | 1 |
| 14 | mongodb | 3306 | 1 | 2019-06-11 14:01:24.003175 | 2019-06-11 14:06:14.525648 | 1 |
| 15 | test | 123 | 1 | 2019-06-11 14:04:10.576241 | 2019-06-11 14:04:10.576241 | 0 |
| 16 | test | 3306 | 1 | 2019-06-11 14:06:05.608006 | 2019-06-11 14:06:05.608006 | 0 |
+----+-----------+-------+-----------+----------------------------+----------------------------+-----------+
12 rows in set (0.00 sec)
mysql>
可以结果看出,其实Django模型的关联查询,也只是查询多类一方的单独数据而已。
上面是一到多的查询方式,下面再来一个多到一的查询方式,如下:
查看中间件信息id = 1 对应的 服务器信息
# 首先查询中间件的数据
In [4]: m = MiddlewareInfo.objects.get(id=1)
# 根据中间件的查询结果,再进行服务器信息查询
In [13]: s = ServerInfo.objects.filter(id = m.server_id )
# 打印查询出来的服务器名称
In [14]: for item in s:
...: print(item.server_hostname)
...:
测试服务器
上面查询主键编号的时候都是使用id,还可以使用pk来进行查询,如下:
In [15]: ServerInfo.objects.get(pk=1)
Out[15]: <ServerInfo: ServerInfo object (1)>
In [16]: ServerInfo.objects.get(id=1)
Out[16]: <ServerInfo: ServerInfo object (1)>
In [17]:
这两个查询的结果是一样的。
上面就是使用对象来实现的关联查询。那么有没有更加一句话能搞定的关联查询呢?
通过模型类执行关联查询
由多模型类条件查询一模型类数据:
语法如下:
关联模型类名小写__属性名__条件运算符=值
如果没有"__运算符"部分,表示等于,结果和sql中的inner join相同。
例:查询服务器信息,要求服务器中中间件的name包含'redis'。
In [17]: result = ServerInfo.objects.filter(middlewareinfo__name__contains='redis')
In [18]: print(result)
<QuerySet [<ServerInfo: ServerInfo object (1)>]>
对应的SQL如下:
mysql> SELECT `assetinfo_serverinfo`.`id`, `assetinfo_serverinfo`.`server_hostname`, `assetinfo_serverinfo`.`server_intranet_ip`, `assetinfo_serverinfo`.`server_internet_ip`, `assetinfo_serverinfo`.`server_shelves_date`, `assetinfo_serverinfo`.`update_time`, `assetinfo_serverinfo`.`is_delete` FROM `assetinfo_serverinfo` INNER JOIN `assetinfo_middlewareinfo` ON (`assetinfo_serverinfo`.`id` = `assetinfo_middlewareinfo`.`server_id`) WHERE `assetinfo_middlewareinfo`.`name` LIKE BINARY '%redis%' LIMIT 21
-> ;
+----+-----------------+--------------------+--------------------+---------------------+----------------------------+-----------+
| id | server_hostname | server_intranet_ip | server_internet_ip | server_shelves_date | update_time | is_delete |
+----+-----------------+--------------------+--------------------+---------------------+----------------------------+-----------+
| 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 2019-06-10 14:56:46.425830 | 0 |
+----+-----------------+--------------------+--------------------+---------------------+----------------------------+-----------+
1 row in set (0.00 sec)
mysql>
由一模型类条件查询多模型类数据: 语法如下:
一模型类关联属性名__一模型类属性名__条件运算符=值
例:查询服务器为“测试服务器”的所有中间件信息。
mysql> select * from assetinfo_middlewareinfo as m join assetinfo_serverinfo as s on m.server_id = s.id where s.server_hostname = '测试服务器';
+----+-----------+-------+-----------+-----------+----------------------------+----------------------------+----+-----------------+--------------------+--------------------+---------------------+-----------+----------------------------+
| id | name | port | server_id | is_delete | shelves_date | update_time | id | server_hostname | server_intranet_ip | server_internet_ip | server_shelves_date | is_delete | update_time |
+----+-----------+-------+-----------+-----------+----------------------------+----------------------------+----+-----------------+--------------------+--------------------+---------------------+-----------+----------------------------+
| 1 | memcached | 11211 | 1 | 1 | 2019-06-10 14:56:46.150556 | 2019-06-10 17:37:51.365155 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 2 | redis | 6379 | 1 | 1 | 2019-06-10 14:56:46.150556 | 2019-06-10 17:38:20.712862 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 5 | test | 123 | 1 | 1 | 2019-06-10 17:05:16.632773 | 2019-06-10 17:05:16.632773 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 6 | test | 123 | 1 | 1 | 2019-06-10 17:06:20.120658 | 2019-06-10 17:06:20.121656 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 7 | test | 123 | 1 | 1 | 2019-06-10 17:06:43.193412 | 2019-06-10 17:06:43.193412 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 8 | test | 123 | 1 | 1 | 2019-06-10 17:07:03.747395 | 2019-06-10 17:07:03.747395 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 9 | test | 123 | 1 | 1 | 2019-06-10 17:08:43.372097 | 2019-06-10 17:08:43.372097 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 10 | test | 123 | 1 | 1 | 2019-06-10 17:09:37.877019 | 2019-06-10 17:09:37.877019 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 11 | test | 123 | 1 | 1 | 2019-06-10 17:11:45.403627 | 2019-06-10 17:11:45.403627 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 14 | mongodb | 3306 | 1 | 1 | 2019-06-11 14:01:24.003175 | 2019-06-11 14:06:14.525648 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 15 | test | 123 | 1 | 0 | 2019-06-11 14:04:10.576241 | 2019-06-11 14:04:10.576241 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
| 16 | test | 3306 | 1 | 0 | 2019-06-11 14:06:05.608006 | 2019-06-11 14:06:05.608006 | 1 | 测试服务器 | 172.16.5.1 | 223.5.5.5 | 2019-06-10 | 0 | 2019-06-10 14:56:46.425830 |
+----+-----------+-------+-----------+-----------+----------------------------+----------------------------+----+-----------------+--------------------+--------------------+---------------------+-----------+----------------------------+
12 rows in set (0.00 sec)
mysql>
那么模型该怎么写呢?
In [1]: from assetinfo.models import ServerInfo,MiddlewareInfo
In [2]: MiddlewareInfo.objects.filter(server_id__server_hostname='测试服务器')
Out[2]: <QuerySet [<MiddlewareInfo: MiddlewareInfo object (1)>, <MiddlewareInfo: MiddlewareInfo object (2)>, <MiddlewareInfo: MiddlewareInfo object (5)>
, <MiddlewareInfo: MiddlewareInfo object (6)>, <MiddlewareInfo: MiddlewareInfo object (7)>, <MiddlewareInfo: MiddlewareInfo object (8)>, <MiddlewareInfo
: MiddlewareInfo object (9)>, <MiddlewareInfo: MiddlewareInfo object (10)>, <MiddlewareInfo: MiddlewareInfo object (11)>, <MiddlewareInfo: MiddlewareInf
o object (14)>, <MiddlewareInfo: MiddlewareInfo object (15)>, <MiddlewareInfo: MiddlewareInfo object (16)>]>
In [3]:
对应执行的SQL如下:
mysql> SELECT `assetinfo_middlewareinfo`.`id`, `assetinfo_middlewareinfo`.`name`, `assetinfo_middlewareinfo`.`port`, `assetinfo_middlewareinfo`.`server_id`, `assetinfo_middlewareinfo`.`shelves_date`, `assetinfo_middlewareinfo`.`update_time`, `assetinfo_middlewareinfo`.`is_delete` FROM `assetinfo_middlewareinfo` INNER JOIN `assetinfo_serverinfo` ON (`assetinfo_middlewareinfo`.`server_id` = `assetinfo_serverinfo`.`id`) WHERE `assetinfo_serverinfo`.`server_hostname` = '测试服务器' LIMIT 21
-> ;
+----+-----------+-------+-----------+----------------------------+----------------------------+-----------+
| id | name | port | server_id | shelves_date | update_time | is_delete |
+----+-----------+-------+-----------+----------------------------+----------------------------+-----------+
| 1 | memcached | 11211 | 1 | 2019-06-10 14:56:46.150556 | 2019-06-10 17:37:51.365155 | 1 |
| 2 | redis | 6379 | 1 | 2019-06-10 14:56:46.150556 | 2019-06-10 17:38:20.712862 | 1 |
| 5 | test | 123 | 1 | 2019-06-10 17:05:16.632773 | 2019-06-10 17:05:16.632773 | 1 |
| 6 | test | 123 | 1 | 2019-06-10 17:06:20.120658 | 2019-06-10 17:06:20.121656 | 1 |
| 7 | test | 123 | 1 | 2019-06-10 17:06:43.193412 | 2019-06-10 17:06:43.193412 | 1 |
| 8 | test | 123 | 1 | 2019-06-10 17:07:03.747395 | 2019-06-10 17:07:03.747395 | 1 |
| 9 | test | 123 | 1 | 2019-06-10 17:08:43.372097 | 2019-06-10 17:08:43.372097 | 1 |
| 10 | test | 123 | 1 | 2019-06-10 17:09:37.877019 | 2019-06-10 17:09:37.877019 | 1 |
| 11 | test | 123 | 1 | 2019-06-10 17:11:45.403627 | 2019-06-10 17:11:45.403627 | 1 |
| 14 | mongodb | 3306 | 1 | 2019-06-11 14:01:24.003175 | 2019-06-11 14:06:14.525648 | 1 |
| 15 | test | 123 | 1 | 2019-06-11 14:04:10.576241 | 2019-06-11 14:04:10.576241 | 0 |
| 16 | test | 3306 | 1 | 2019-06-11 14:06:05.608006 | 2019-06-11 14:06:05.608006 | 0 |
+----+-----------+-------+-----------+----------------------------+----------------------------+-----------+
12 rows in set (0.00 sec)
mysql>
自关联
对于地区信息、分类信息等数据,表结构非常类似,每个表的数据量十分有限,为了充分利用数据表的大量数据存储功能,可以设计成一张表,内部的关系字段指向本表的主键,这就是自关联的表结构。
示例数据如下:
创建表的SQL:
CREATE TABLE `AREA` (
`ID` int(11) NOT NULL,
`PARENT_ID` int(11) NOT NULL DEFAULT '0' COMMENT '父级ID',
`NAME` varchar(50) NOT NULL COMMENT '名称',
`SHORT_NAME` varchar(50) NOT NULL COMMENT '简称',
`LONGITUDE` float NOT NULL DEFAULT '0' COMMENT '经度',
`LATITUDE` float NOT NULL DEFAULT '0' COMMENT '纬度',
`LEVEL` int(1) NOT NULL COMMENT '等级(1省/直辖市,2地级市,3区县,4镇/街道)',
`SORT` int(3) NOT NULL DEFAULT '1' COMMENT '排序',
`STATUS` int(1) NOT NULL DEFAULT '0' COMMENT '状态(0禁用/1启用)',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
那么为了更好实验,先来写上这个表结构的模型类,如下:
# 全国区域信息
class AREA(models.Model):
ID = models.AutoField(primary_key=True,db_column='ID',auto_created=True, serialize=False, verbose_name='ID')
PARENT_ID = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True,db_column='PARENT_ID') # 父级id
NAME = models.CharField(max_length=50,default=None,db_column='NAME') # 名称
SHORT_NAME = models.CharField(max_length=50,default=None) # 简称
LONGITUDE = models.FloatField(default=0) # 经度
LATITUDE = models.FloatField(default=0) # 纬度
LEVEL = models.IntegerField(default=1)# 等级
SORT = models.IntegerField(default=1) # 排序
STATUS = models.IntegerField(default=1) # 状态
class Meta:
db_table = 'AREA' # 设置表名为 AREA
执行数据迁移:
python3 manage.py makemigrations
python3 manage.py migrate
到mysql中查看创建的表结构,如下:
mysql> desc AREA;
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | NO | | NULL | |
| SHORT_NAME | varchar(50) | NO | | NULL | |
| LONGITUDE | double | NO | | NULL | |
| LATITUDE | double | NO | | NULL | |
| LEVEL | int(11) | NO | | NULL | |
| SORT | int(11) | NO | | NULL | |
| STATUS | int(11) | NO | | NULL | |
| PARENT_ID | int(11) | YES | MUL | NULL | |
+------------+-------------+------+-----+---------+----------------+
9 rows in set (0.00 sec)
mysql>
导入几条数据,如下:
In [1]: from assetinfo.models import AREA
In [2]: area1 = AREA()
In [3]: area2 = AREA()
In [4]: area1.NAME = '广东省'
In [6]: area1.SHORT_NAME = '广东'
In [7]: area1.save()
In [8]: area2.NAME = '深圳市'
In [9]: area2.SHORT_NAME = '深圳'
In [10]: area2.PARENT_ID = area1
In [11]: area2.save()
In [13]: area3.NAME = '广州市'
In [14]: area3.SHORT_NAME = '广州'
In [15]: area3.PARENT_ID = area1
In [16]: area3.save()
到mysql中查询数据如下:
mysql> select * from AREA;
+----+------------+-----------+----------+-------+------+--------+-----------+-----------+
| ID | SHORT_NAME | LONGITUDE | LATITUDE | LEVEL | SORT | STATUS | PARENT_ID | NAME |
+----+------------+-----------+----------+-------+------+--------+-----------+-----------+
| 1 | 广东 | 0 | 0 | 1 | 1 | 1 | NULL | 广东省 |
| 2 | 深圳 | 0 | 0 | 1 | 1 | 1 | 1 | 深圳市 |
| 3 | 广州 | 0 | 0 | 1 | 1 | 1 | 1 | 广州市 |
+----+------------+-----------+----------+-------+------+--------+-----------+-----------+
3 rows in set (0.00 sec)
mysql>