代码之家  ›  专栏  ›  技术社区  ›  Carles Barrobés

django orm处理mysql位(1)字段

  •  7
  • Carles Barrobés  · 技术社区  · 15 年前

    在Django应用程序中,我试图访问用Hibernate(Java ORM)创建的现有MySQL数据库。我使用以下方法对模型进行了逆向工程:

    $ manage.py inspectdb > models.py
    

    这从数据库中创建了一个很好的模型文件,很多东西都很好。但是我找不到如何正确访问布尔字段,这些字段被hibernate映射为bit(1)类型的列。

    默认情况下,inspectdb脚本在模型中将这些字段创建为textfield,并添加一条注释,指出它无法可靠地获取字段类型。我将它们改为booleanfield,但是使用admin打开了我的模型对象,但是它不起作用(模型对象总是为这些字段获取true值)。使用integerfield也不起作用(例如,在管理中,这些字段显示奇怪的非ascii字符)。

    有没有在不更改数据库的情况下这样做的提示?(我需要现有的Hibernate映射和Java应用程序仍然与数据库一起工作)。


    进一步信息:我将这些字段保留为booleanfield,并使用交互式shell查看获取的值。它们返回为“\x00”(当java/Hibernate值为false)和“\x01”(true)时,而不是Python布尔值“true”和“false”。

    >>> u = AppUser.objects.all()[0]
    >>> u.account_expired
    '\x00'
    >>> u.account_enabled
    '\x01'
    

    模型包括:

    class AppUser(models.Model):
        account_expired = models.BooleanField()
        account_enabled = models.BooleanField(blank=True)
        # etc...
    
    6 回复  |  直到 6 年前
        1
  •  2
  •   Dmitry Shevchenko    15 年前

    我想唯一的方法是对booleanfield进行子类化,并重写为python/get-prep-value函数,这样该字段就可以与django和 你的数据库。

        2
  •  10
  •   Carles Barrobés    15 年前

    这是dmitry建议的详细解决方案:

    我的派生字段类:

    class MySQLBooleanField(models.BooleanField):
        __metaclass__ = models.SubfieldBase
    
        def to_python(self, value):
            if isinstance(value, bool):
                return value
            return bytearray(value)[0]
    
        def get_db_prep_value(self, value):
            return '\x01' if value else '\x00'
    

    模型中的字段:

    account_enabled = MySQLBooleanField()
    account_expired = MySQLBooleanField()
    
        3
  •  2
  •   Jossef Harush Kadouri    11 年前

    我不得不处理同样的问题,但我没有对该字段进行子类化,而是扩展了mysql后端以理解hibernate方式。它只需要几行代码,而且它的优点是可以使db内省正常工作。

    看到它 here.

    hibernateboolsbackend/backends/mysql/base.py

    # We want to import everything since we are basically subclassing the module.
    from django.db.backends.mysql.base import *
    
    django_conversions.update({
            FIELD_TYPE.BIT: lambda x: x != '\x00',
    })
    
    DatabaseIntrospection.data_types_reverse.update({
            FIELD_TYPE.BIT: 'BooleanField',
    })
    
        4
  •  1
  •   Adam Johnson Bud P. Bruegger    9 年前

    这个 Django MySQL 包提供 布尔油田 调用的子类 Bit1BooleanField 解决了这个问题:

    from django.db import Model
    from django_mysql.models import Bit1BooleanField
    
    class AppUser(Model):
        bit1bool = Bit1BooleanField()
    

    比自己滚动更容易,并在几个django和python版本上进行了测试。

        5
  •  0
  •   reiven    10 年前

    要使它在django 1.7.1上工作,我必须更改“to_python”函数,因为它无法从数据库正确读取数据:

    def to_python(self, value):
        if value in (True, False): return value
        if value in ('t', 'True', '1', '\x01'): return True
        if value in ('f', 'False', '0', '\x00'): return False
    
        6
  •  0
  •   Subhabrata Bari    6 年前

    Python布尔类型是整数的一个子类,而Java则是BITE类型。 因此,在db for python中,布尔字段数据类型应为tinyint,而不是位类型。

    由于上述原因,应用程序意外返回 \x00 \x01 价值。

    如果我们在django模型中添加一个布尔字段并运行迁移,然后迁移,它将添加tinyint类型的列,而不是bit类型的列。

    因此,将列类型更新为tinyint应该可以解决这个问题。