Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Join related models in django rest framework

Trying to create an API method for getting user profile. The problem is that there are two tables related to user: built in django User and SocialAccount from allauth framework. I guess the joining part should be in serializers so after a research I came up with this:

from rest_framework import serializers
from django.contrib.auth.models import User
from allauth.socialaccount.models import SocialAccount


class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('pk', 'first_name', 'last_name')


class SocialSerializer(serializers.ModelSerializer):
    user = UserSerializer(many=False, read_only=True)

    class Meta:
        model = SocialAccount
        fields = ('uid', 'provider', 'user')

It works but it outputs it as nested objects:

{
  "uid": "",
  "provider": "",
  "user": {
    "pk": 5,
    "first_name": "",
    "last_name": ""
  }
}

I would like it to be as one object:

{
  "uid": "",
  "provider": "",
  "pk": 5,
  "first_name": "",
  "last_name": ""
}
like image 692
Simon Moshenko Avatar asked Feb 10 '18 14:02

Simon Moshenko


People also ask

How do I merge two django models?

1 Answer. Show activity on this post. In your models Device and History models are related with a foreign key from History to DeviceModel, this mean when you have a History object you can retrieve the Device model related to it, and viceversa (if you have a Device you can get its History).

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.

What is Slug related field in django?

What is SlugField in Django? It is a way of generating a valid URL, generally using data already obtained. For instance, using the title of an article to generate a URL. Let's assume our blog have a post with the title 'The Django book by Geeksforgeeks' with primary key id= 2.


Video Answer


2 Answers

You can either try to flatten the JSON (see this link) or redefine your serializer as below:

class SocialSerializer(serializers.ModelSerializer):
    pk = serializers.SerializerMethodField()
    first_name = serializers.SerializerMethodField()
    last_name = serializers.SerializerMethodField()

    class Meta:
        model = SocialAccount
        fields = ('uid', 'provider', 'pk', 'first_name', 'last_name')

    def get_pk(self, obj):
        return obj.user.pk

    def get_first_name(self, obj):
        return obj.user.first_name

    def get_last_name(self, obj):
        return obj.user.last_name

These are serializers.SerializermethodField() fields which will look at the get_<field_name> method and call them and use the returned value.

http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

like image 25
Kryštof Řeháček Avatar answered Oct 06 '22 06:10

Kryštof Řeháček


alternatively, try

class SocialSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    class Meta:
        model = SocialAccount
        fields = ('uid', 'provider', 'user')

    def to_representation(self, instance):
        data = super(SocialSerializer, self).to_representation(instance)
        user = data.pop('user')
        for key, val in user.items():
            data.update({key: val})
        return data
like image 69
Kevin L. Avatar answered Oct 06 '22 06:10

Kevin L.