Yathartha Joshi
Yathartha Joshi

Reputation: 776

Displaying two related models in a single get() request

I have two models that are related to each other with user_id, now I want to have a get request in which I will have fields from both the tables. How to make this possible? I guess it would be possible with foreign key, but how do I implement it.

Two models look like:

model1

class Account(AbstractBaseUser):
    fullname = models.CharField(max_length=100, blank=True)
    username = models.CharField(unique=True, max_length=50)
    email = models.EmailField(unique=True)
    phonenumber = models.IntegerField(null=True)
    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    is_admin = models.BooleanField(default=False)
    objects = AccountManager()
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

models2

class Profile(models.Model):
    User = get_user_model()
    branch = models.CharField(max_length=20, null=True)
    year = models.IntegerField(null=True)
    image = models.ImageField(upload_to="accounts/images/", null=True, blank=True)
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        primary_key=False,
        null=True
    )

I want to display particular user details based on who is logged in at the moment.

My get request looks something like this:

def get(self, request, format=None):
        current_user = request.user
        acc = Account.objects.filter(pk=current_user.pk)
        serializer = AccountSerializer(acc, many=True)
        return Response(serializer.data)

But this will show only data as of Account model, I want data of Profile model too. How do I do it?

Update

serializers

class AccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True)
    token = serializers.CharField(max_length=500, read_only=True)

    class Meta:
        model = Account
        fields = (
        'id', 'email', 'username', 'date_created', 'date_modified',
        'fullname', 'password','phonenumber' ,'token' )
        read_only_fields = ('date_created', 'date_modified')

    def create(self, validated_data):
        return Account.objects.create_user(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.username = validated_data.get('username',
        instance.username)
        instance.fullname = validated_data.get('fullname',
        instance.fullname)
        password = validated_data.get('password', None)
        instance.save()
        return instance

Update2

After having a get requst I want something like:

{
   "username": "Steve"
   "fullname": "Steve Smith"
   "phonenumber": "1234567890"
   "email": "[email protected]"
   "profile":[ {
    "branch": "CS"
    "year": 4
    "image": path/to/folder
   }]
}

Upvotes: 0

Views: 68

Answers (2)

Ykh
Ykh

Reputation: 7717

class ProfileSerializer(ModelSerializer):
    user = AccountSerializer(read_only=True)

    class Meta:
        model = Profile
        fields = '__all__'


def get(self, request, format=None):
        try:
            profile= Profile.objects.get(user=request.user)
        except Profile.DoseNotExist:
            return Response('404')
        serializer = ProfileSerializer(profile)
        return Response(serializer.data)

this will return data like:

{
   "your profile fields": "xxx"
   ...
   "user": {
    "your user fields": "xxx"
    ...
   }
}

if you want your user info include profile info:

class AccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True)
    token = serializers.CharField(max_length=500, read_only=True)
    profile = serializers.SerializerMethodField()

    class Meta:
        model = Account
        fields = (
        'id', 'email', 'username', 'date_created', 'date_modified',
        'fullname', 'password','phonenumber' ,'token' )
        read_only_fields = ('date_created', 'date_modified')

    def create(self, validated_data):
        ...

    def update(self, instance, validated_data):
        ...

    def get_profile(self, instance):
        try:
            profile= Profile.objects.get(user=instance)
            return ProfileSerializer(profile).data
        except Profile.DoseNotExist:
                return ''

or:

class AccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True)
    token = serializers.CharField(max_length=500, read_only=True)
    profile = serializers.ProfileSerializer(read_only=True)

    class Meta:
        model = Account
        fields = (
        'id', 'email', 'username', 'date_created', 'date_modified',
        'fullname', 'password','phonenumber' ,'token' )
        read_only_fields = ('date_created', 'date_modified')

    def create(self, validated_data):
        ...

    def update(self, instance, validated_data):
        ...

this will return:

{
   "username": "Steve"
   "fullname": "Steve Smith"
   "phonenumber": "1234567890"
   "email": "[email protected]"
   "profile":{
    "branch": "CS"
    "year": 4
    "image": path/to/folder
   }
}

as your profile is onetoone to user,so profile is JsonObject not JsonArray

Upvotes: 1

zaidfazil
zaidfazil

Reputation: 9235

Configure your AccountSerializer somewhat like this,

class ProfileSerializer(serializers.ModelSerializer):        
    class Meta:
        model = Profile
        fields = [f.name for f in model._meta.fields]

class AccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True)
    token = serializers.CharField(max_length=500, read_only=True)
    profile = ProfileSerializer()
    class Meta:
        model = Account
        fields = [f.name for f in model._meta.fields]

You may also override your create and update methods of your serializer accordingly.

Upvotes: 0

Related Questions