Django ORM:BooleanField可以关联数据库中的char列吗?

1 投票
2 回答
901 浏览
提问于 2025-04-17 09:17

我接手了一个旧系统的数据库,这个数据库有很多问题。其中有一张表的某一列本来应该是布尔值(也就是只有真和假),结果却是一个字符型(varchar(1)),用'N'或'0'来表示假,用'Y'或'1'来表示真。代码的不同部分在写的时候用的约定不一样,但在读取的时候似乎都能识别这两种方式。

我正在把这个系统从Java重写成Python+Django,等我把这个新系统做好后,才能关闭旧系统,并“清理”数据库里的混乱。

我想在模型类中让这个字段看起来像布尔值,这样等数据库修正后,我只需要把代码中的这个字段改成普通的BooleanField就可以了。有没有简单的方法可以做到这一点?

2 个回答

3

我的情况有点类似,不过旧的数据一直用Y和N来表示真和假,但我还遇到一个问题,就是有些字段可以是空值(Null)。所以我这里有一些自定义的字段类型。我觉得这些例子更完整,能更好地展示在这种情况下你可以做些什么。而且我还继承了BooleanField类型,我觉得这样在表单中显示和编辑这些字段会更好。

from django.db import models

class YNBooleanField(models.BooleanField):

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 1
        super(YNBooleanField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        if value in ('Y', 'y'):
            return True
        elif value in ('N', 'n'):
            return False
        else:
            raise ValueError

    def get_prep_value(self, value):
        if value:
            return 'Y'
        else:
            return 'N'

class NullYNBooleanField(models.NullBooleanField):

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 1
        super(NullYNBooleanField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        if value is None:
            return None
        elif value in ('Y', 'y'):
            return True
        elif value in ('N', 'n'):
            return False
        else:
            raise ValueError

    def get_prep_value(self, value):
        if value is None:
            return None
        elif value:
            return 'Y'
        else:
            return 'N'
5

你可以通过创建自己的字段类来实现你想要的功能,方法是继承 django.db.models.Field,并实现 to_python 方法,比如:

from django.db import models

class MyField(models.CharField):

     def to_python(self, value):
         if value in ('Y', '1'):
             return True
         if value in ('N', '0'):
             return False
         raise ValueError

希望这能给你一些启发 :)

撰写回答