Custom field implementing Boolean Field is having response value as None instead of False

66 views
Skip to first unread message

Priyanka Thakur

unread,
Jun 16, 2017, 10:33:22 AM6/16/17
to Django users
Hi,

I am doing migration from Django 1.7 to 1.10 version and has a custom django field.

Below is the custom class for the field:

----

from django.db import models



class HibernateBooleanField(models.BooleanField):

    def from_db_value(self, value, expression, connection, context):

        return self.to_python(value)


    def get_internal_type(self):

        return "HibernateBooleanField"


    def db_type(self, connection):

        return 'bit(1)'


    def to_python(self, value):

        if value in (True, False):

            return value

        if value in ('t', 'True', 'true', '1', '\x01'): return True

        if value in ('f', 'False', 'false', '0', '\x00', None): return False


    def get_db_prep_value(self, value, connection, prepared=False):

        return 0x01 if value else 0x00


    def get_db_prep_save(self, value, connection):

        return 0x01 if value else 0x00


    def get_prep_value(self, value):

        return self.to_python(value)

---


I have defined a field in the model as:



class MetaMetadata(models.Model):

    is_folder = HibernateBooleanField()



When I invoke a POST request on API in my test case , I get the value for this field as "None" in response. 


The API is :


response = self._client.post('/xyz/api/metametadatas/',
{'edit_view': "TestEditView",
'grid_view': "TestGridView",
'name': "Test Metametadata",
'sort_key': 9000,
'parentid': 0,
'version':0,
'id': 100}, format='json')


Please explain , what is it that I'm doing wrong. Why isn't to_python method getting invoked ? Am I missing something?

Regards,
Priyanka


Melvyn Sopacua

unread,
Jun 16, 2017, 11:18:02 AM6/16/17
to django...@googlegroups.com

On Friday 16 June 2017 07:33:22 Priyanka Thakur wrote:

> Hi,

>

> I am doing migration from Django 1.7 to 1.10 version and has a custom

> django field.

>

> Below is the custom class for the field:

>

> ----

>

> from django.db import models

>

>

>

> class HibernateBooleanField(models.BooleanField):

>

> def from_db_value(self, value, expression, connection, context):

>

> return self.to_python(value)

>

>

> def get_internal_type(self):

>

> return "HibernateBooleanField"

>

>

> def db_type(self, connection):

>

> return 'bit(1)'

>

>

> def to_python(self, value):

>

> if value in (True, False):

>

> return value

>

> if value in ('t', 'True', 'true', '1', '\x01'): return True

>

> if value in ('f', 'False', 'false', '0', '\x00', None): return

> False

 

and if value is something else, nothing (aka None) is returned. You have no else clause here.

 

--

Melvyn Sopacua

Priyanka Thakur

unread,
Jun 19, 2017, 4:59:02 AM6/19/17
to Django users
Hi Melvyn,

I am checking for None in the last if condition in to_python method :

--copy--

> if value in ('f', 'False', 'false', '0', '\x00', None): return

> False

--copy--


Thanks for checking and replying !!


Regards,

Priyanka

m712 - Developer

unread,
Jun 19, 2017, 6:35:06 AM6/19/17
to Priyanka Thakur, Django users

Melvyn was not saying whether you were checking for None. If `value` is i.e. "some string" your to_python method will return `None`. You should do something like this:

```
    if value in ('t', ...): return True
    elif value in ('f', ...): return False
    else: return bool(value) # You can change this
```

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/c89377a1-78cb-4b76-9518-39cd5181dcb8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Priyanka Thakur

unread,
Jun 19, 2017, 7:00:42 AM6/19/17
to Django users, priyan...@gmail.com, com...@getbackinthe.kitchen
Oh, ok got the point !!

Thanks !!

Regards,
Priyanka

Melvyn Sopacua

unread,
Jun 19, 2017, 1:21:44 PM6/19/17
to django...@googlegroups.com

On Monday 19 June 2017 04:00:42 Priyanka Thakur wrote:

> On Monday, 19 June 2017 16:05:06 UTC+5:30, m712 - Developer wrote:

> > Melvyn was not saying whether you were checking for None. If `value`

> > is i.e. "some string" your to_python method will return `None`. You

> > should do something like this:

> >

> > ```

> >

> > if value in ('t', ...): return True

> > elif value in ('f', ...): return False

> > else: return bool(value) # You can change this

> >

> > ```

 

That's correct for to_python. But personally, I would raise an exception in from_db_value, since that indicates data corruption.

 

In your case, there are only a handful of allowed values that should come from the database. Anything else, will indicate somebody messing with your data or upgrades of one of the libraries in between Django and the database changed it's output format. Both of which will require attention.

 

This is one advantage of from_db_value and to_python separation.

 

--

Melvyn Sopacua

Priyanka Thakur

unread,
Jun 20, 2017, 1:51:20 AM6/20/17
to Django users
Hi Melvyn,

Finally i had breakthrough and saw the root cause.

The issue is that i haven't defined any default value for this Custom field in the model class.

As per Django 1.10 documentation, the default value of Boolean Field is None if "default" value is not defined. Hence "None" value.

Though surprising thing is , that when data is getting inserted , it's invoking proper custom field methods and inserting the value "0", but once the object is saved i.e. serializer.save () , the instance returned is containing the value "None" which it is getting from "to_representation " method.


Regards,
Priyanka
Reply all
Reply to author
Forward
0 new messages