登录
首页 >  数据库 >  MySQL

在Django中使用MySQL的枚举(ENUM)类型而非用VARCHAR模拟

来源:SegmentFault

时间:2023-01-12 20:41:28 436浏览 收藏

在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是数据库学习者,那么本文《在Django中使用MySQL的枚举(ENUM)类型而非用VARCHAR模拟》就很适合你!本篇内容主要包括在Django中使用MySQL的枚举(ENUM)类型而非用VARCHAR模拟,希望对大家的知识积累有所帮助,助力实战开发!

Django 3.0 开始已经默认支持枚举类型了,使用的方法是通过给模型的内部增加一个元组或内部类代表枚举的选项。参考官方文档和我在文章最下方的代码。在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.db import models
import django_mysql.models
 
class User0(models.Model):
    username = models.CharField(max_length=20, verbose_name='用户名')
    STATUS_LIST = (
        ('A', '正常'),
        ('B', '封禁中'),
        ('C', '已注销'),
    )
    status = django_mysql.models.EnumField(choices=STATUS_LIST)
 
    def __str__(self):
        return self.username

在迁移后,查看数据库的类型,是真正的MySQL

1
2
3
4
5
6
7
+----------+-------------------+-
| Field    | Type              |
+----------+-------------------+-
| id       | int               |
| username | varchar(20)       |
| status   | enum('A','B','C') |
+----------+-------------------+-

访问Django的管理页面,可以在前端看到可读形式的选项

image

数据库内查表可见已经存入数据了

1
2
3
4
5
+----+----------+--------+
| id | username | status |
+----+----------+--------+
| 1  | yizdu   | B      |
+----+----------+--------+

若在代码层面尝试存入非法数据

1
2
3
4
5
6
7
In [6]: from temp_test.models import *
 
In [7]: u0=User0()
 
In [8]: u0.status='X'
 
In [9]: u0.save()

将会引发MySQL的数据错误

1
2
python manage.py makemigrations
python manage.py migrate --fake

随后取消注释,用django-mysql的方式实现功能,执行以下命令重新迁移

1
2
python manage.py makemigrations
python manage.py migrate

其他枚举方式实现参考

在Django的默认枚举实现中,官方文档推荐采用第二种。如果需要在多个模型里使用相同的枚举字段,可以将元组常数放到全局,或将内部类转为和模型同级的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from django.db import models
 
#通过创建一个枚举元组常量
class User1(models.Model):
    username = models.CharField(max_length=20, verbose_name='用户名')
    STATUS_LIST = (
        ('A', '正常'),
        ('B', '封禁中'),
        ('C', '已注销'),
    )
    status = models.CharField(
        max_length=1, verbose_name='状态', choices=STATUS_LIST)
 
    def __str__(self):
        return self.username
 
#通过创建一个内部类
class User2(models.Model):
    username = models.CharField(max_length=20, verbose_name='用户名')
 
    class StatusList(models.TextChoices):
        ACTIVITY = 'A', '正常'
        BANNED = 'B', '封禁中'
        CLOSE = 'C', '已注销'
 
    status = models.CharField(
        max_length=1, verbose_name='状态', choices=StatusList.choices)
 
    def __str__(self):
        return self.username

正常使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
In [1]: from temp_test.models import *
 
In [2]: u1=User1()
 
In [3]: u1.username='yizdu'
 
In [4]: u1.status='A'
 
In [5]: u1.save()
 
In [6]: u2=User2()
 
In [8]: u2.username='yizdu'
 
In [9]: u2.status=User2.StatusList.ACTIVITY
 
In [10]: u2.save()

数据库内

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql > SELECT * FROM temp_test_user1;
+----+----------+--------+
| id | username | status |
+----+----------+--------+
| 2  | yizdu   | A      |
+----+----------+--------+
2 rows in set
Time: 0.022s
mysql > SELECT * FROM temp_test_user2;
+----+----------+--------+
| id | username | status |
+----+----------+--------+
| 1  | yizdu   | A      |
+----+----------+--------+

查看表中数据类型,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# DESC temp_test_user1;
+----------+-------------+
| Field    | Type        |
+----------+-------------+
| id       | int         |
| username | varchar(20) |
| status   | varchar(1)  |
+----------+-------------+
# DESC temp_test_user2;
+----------+-------------+
| Field    | Type        |
+----------+-------------+
| id       | int         |
| username | varchar(20) |
| status   | varchar(1)  |
+----------+-------------+

尝试存入枚举选项之外的数据,不会有任何报错。数据当然也会被存入数据库中

1
2
3
4
5
6
7
In [14]: u1.status='X'
 
In [15]: u1.save()
 
In [16]: u2.status='X'
 
In [17]: u2.save()

修改后,Django后台管理页面会这样显示,不要在意用户名和上面的不一样,图片是以前的。

image

理论要掌握,实操不能落!以上关于《在Django中使用MySQL的枚举(ENUM)类型而非用VARCHAR模拟》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>
评论列表