Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework: Correct way to serialize ListFields

Based on the DRF documentation I have a created a list of email_id stored in my model in the following way Models.py

class UserData(models.Model):
  emails = models.CharField(max_length=100,blank=False)

In my serializers.py file

class UserSerializer(serializers.ModelSerializer):
    emails = serializers.ListField(child = serializers.EmailField())

While posting the data, the drf page shows the data in the expected format, i.e

"emails": [
        "[email protected]"
    ],

But, if I query the same data using python or any rest client. I get the data in the following format

data = json.load(urllib2.urlopen("http://localhost:8000/blah/id"))
In [46]: d['emails']
Out[46]: 
[u'[',
 u'u',
 u"'",
 u'b',
 u'a',
 u'l',
 u'@',
 u'b',
 u'a',
 u'l',
 u'.',
 u'c',
 u'o',
 u'm',
 u"'",
 u']']

Ideally, it should have been

d['emails'] = ['[email protected]'] 

I am not sure, what exactly is wrong in here. Any suggestions ?

like image 575
Rahul Avatar asked Jan 06 '16 01:01

Rahul


1 Answers

Your model only has one email field. It does not support storing multiple email in the database. What you need is something like this:

class UserEmail(models.Model)
    user = models.ForeignKey('User', related_name='emails')
    email = models.EmailField(unique=True)

    # You can also store some other useful things here...
    activated = models.BooleanField(default=False)  # For example


class User(models.Model):
    ...


class EmailSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ['id', 'email']


class UserSerializer(serializers.ModelSerializer):
    emails = EmailSerializer(many=True)

However, this will result in a slightly different data structure:

[{
    'someUserField': 'foobar',
    'emails': [
        {'id': 1, 'email': '[email protected]'},
        {'id': 2, 'email': '[email protected]'},
    ]
}, {
    ...
}]

If you don't want this data structure, you could create a custom field

Or... if you're using postgresql you should be able to do this:

from django.contrib.postgres.fields import ArrayField

class UserData(models.Model):
    emails = ArrayField(models.EmailField(), blank=True)
like image 91
demux Avatar answered Nov 20 '22 08:11

demux