Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ORM dealing with MySQL BIT(1) field

Tags:

mysql

orm

django

In a Django application, I'm trying to access an existing MySQL database created with Hibernate (a Java ORM). I reverse engineered the model using:

$ manage.py inspectdb > models.py

This created a nice models file from the Database and many things were quite fine. But I can't find how to properly access boolean fields, which were mapped by Hibernate as columns of type BIT(1).

The inspectdb script by default creates these fields in the model as TextField and adds a comment saying that it couldn't reliably obtain the field type. I changed these to BooleanField but and opened my model objects using the admin, but it doesn't work (the model objects always fetch a value of true for these fields). Using IntegerField won't work as well (e.g. in the admin these fields show strange non-ascii characters).

Any hints of doing this without changing the database? (I need the existing Hibernate mappings and Java application to still work with the database).


Further info: I left these fields as BooleanField and used the interactive shell to look at the fetched values. They are returned as '\x00' (when Java/Hibernate value is false) and '\x01' (when true), instead of Python boolean values "True" and "False".

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

Where the model includes:

class AppUser(models.Model):
    account_expired = models.BooleanField()
    account_enabled = models.BooleanField(blank=True)
    # etc...
like image 268
Carles Barrobés Avatar asked Apr 24 '10 20:04

Carles Barrobés


People also ask

What is Primary_key true in Django?

If True , this field is the primary key for the model. If you don't specify primary_key=True for any fields in your model, Django will automatically add an IntegerField to hold the primary key, so you don't need to set primary_key=True on any of your fields unless you want to override the default primary-key behavior.

Is Django ORM good?

Django's ORM saves developers a lot of time because it allows them to write their data model in a single place, making it easier to update, maintain and reuse code. It also allows for the automatic handling of database schemas. Best of all, your Web Programmers don't have to write SQL.

Can you use Django ORM standalone?

Django doesn't have a separate package for it's ORM, but it's still possible to use it on its own.


2 Answers

This is the detailed solution from Dmitry's suggestion:

My derived field class:

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'

Fields in my model:

account_enabled = MySQLBooleanField()
account_expired = MySQLBooleanField()
like image 137
Carles Barrobés Avatar answered Sep 17 '22 19:09

Carles Barrobés


I had to deal the same problem, but rather than subclassing the field, I extended the MySQL backend to understand the Hibernate way. It's only a few lines of code and has the advantage that the DB introspection can be made to work correctly, as well.

See it 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',
})
like image 27
Ben Anhalt Avatar answered Sep 21 '22 19:09

Ben Anhalt