Support for Django 1.8 ArrayField

1,661 views
Skip to first unread message

Kevin Foster

unread,
Nov 13, 2014, 12:24:12 PM11/13/14
to django-res...@googlegroups.com
Hi everyone,

I'm a little overwhelmed trying to figure out how to get the ArrayField object working with Django Rest Framework.  ArrayField is being added to django.contrib.postgres in Django 1.8. Here's the docs for it: https://docs.djangoproject.com/en/dev/ref/contrib/postgres/fields/

To get it working, I believe I need to write my own custom field serializer for the ArrayField object.  I want to confirm this first, because I do notice that there is a ListField object in the latest github code (although not the latest release so I assume this is something for v 3.0?), and I was wondering if I could use that or if I should use it as a base to write the custom field serializer for ArrayField.

class Template(TimeStampedModel):
    name = models.CharField(_('name'), max_length=128, blank=True)
    field_names = ArrayField(models.CharField(max_length=32), blank=True)


Assuming I need to write my own serializer field, I realize I need to override from_native and to_native. The question is what format does each need to deliver its information in... Is the following correct?

from_native: Needs to convert a list of primitive datatypes (in my case CharField) to a list of native values (ie strings)
to_native:  Needs to convert a list of strings to a list of CharFields

Thank you for your guidance.

Kev

Carlton Gibson

unread,
Nov 18, 2014, 11:24:51 AM11/18/14
to django-res...@googlegroups.com
Hi Kev,

> On 13 Nov 2014, at 18:24, Kevin Foster <kevin.gra...@gmail.com> wrote:
> I'm a little overwhelmed trying to figure out how to get the ArrayField object working with Django Rest Framework. ArrayField is being added to django.contrib.postgres in Django 1.8. Here's the docs for it: https://docs.djangoproject.com/en/dev/ref/contrib/postgres/fields/

I’ve been playing with this myself. There may be specific issues that come up but, at least for simple cases like that from the docs:

tags = ArrayField(models.CharField(max_length=200), blank=True)

… it should Just Work™.

By default DRF 3.0 will map the above field to a `ModelField`:

tags = ModelField(model_field=<django.contrib.postgres.fields.array.ArrayField: tags>, required=False)

This will just pass whatever data it’s given through to the ArrayField’s `to_python` — which will just set it as the value.


So assuming your data looks something like:

{

“tags”: [“fruit”, “veggies”, “nuts”],

}

... you’ll end up with the dict you need being set on the model instance.

(I could imagine a set of validators being a worthwhile investment.)

All I can say at this point is, give it a run. If there are particular areas where you get stuck come back to the list. (If there’s a clear case that you think should be handled but isn’t perhaps the issue tracker.)

Kind Regards,

Carlton




Tom Christie

unread,
Nov 18, 2014, 11:52:19 AM11/18/14
to django-res...@googlegroups.com
> I want to confirm this first, because I do notice that there is a ListField object in the latest github code (although not the latest release so I assume this is something for v 3.0?)

Yup. ListField is 3.0 (master) and is useful for these sorts of situations.
As Carlton notes you'll probably be fine with the default `ModelField`, but if you did need to deal with it more explicitly then you can do something like this...

    my_field = serializers.ListField(child=serializers.CharField(max_length=32, allow_blank=True))

Alternatively, declare a new serializer class like so...

    class ArrayField(serializers.ListField):
        child=serializers.CharField(max_length=32, allow_blank=True)

Which you can then reuse throughout your codebase...

    my_field = ArrayField()

Hope that helps, some!

  Tom

Kevin Foster

unread,
Nov 18, 2014, 5:55:30 PM11/18/14
to django-res...@googlegroups.com
Thanks guys for the detailed responses. You'll definitely help get me there. A bit more info... I am on version 2.4.3 right now.. As I stand right now in version 2.4.3 it does appear to be working almost as I'd expect! The only thing I don't like is when I use a serializer to return a record in JSON format, it returns as a string, not as a list... eg:

{u'name': 'Temp A', u'field_names': u'["Name", "address", "phone", "postal", "fax", "facebook"]'}

Is it possible that the upgrade to version 3.0 and using one of your suggestions could return the results as list instead of a string representing a list?

Kev

Kevin Foster

unread,
Nov 20, 2014, 3:20:34 PM11/20/14
to django-res...@googlegroups.com
Just wanted to say thanks guys, everything that you suggested worked perfectly. Here's some info on what I found in case anyone else has questions on this.

Using the default 'ModelField' approach suggested by Carlton works, however when the JSON serialization will result in a string of a list (ie 'field_names': u'["Name", "address", "phone", "postal", "fax", "facebook"]')

The approach described by Tom...

class TemplateSerializer(serializers.ModelSerializer):
    field_names = serializers.ListField(child=serializers.CharField(max_length=32, allow_blank=True))

    class Meta:
        model = Template
        fields = ('id',  'name', 'field_names')

....Gave me the results that I wanted, the ArrayField was updated properly, and the JSON representation that I was returned gave me an actual list (not a string of a list).

K

Tom Christie

unread,
Nov 20, 2014, 3:39:25 PM11/20/14
to django-res...@googlegroups.com
Nice! Cool to see some new 3.0 features proving their worth, then!

Tom Christie

unread,
Nov 21, 2014, 7:30:09 AM11/21/14
to django-res...@googlegroups.com
Note to say that I've created tickets for nicely supporting 1.8's ArrayField and HStoreField...

and

You can subscribe these tickets if you're interested in following updates on this functionality.
Reply all
Reply to author
Forward
0 new messages