0

I have the following model skeletons:

class A(models.Model):
    post_id = models.ForeignKey('D')
    user_id = models.ForeignKey('B')

class B(AbstractBaseUser):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=20, unique=True)    
    first_name = models.CharField(max_length=40)
    last_name = models.CharField(max_length=40)
    # `resource_id`
    profile_photo = models.ForeignKey('C', null=True)

class C(models.Model):
    user_id = models.ForeignKey('B')
    name = models.CharField(max_length=60)

I want to write a serializer for A which should return name from model C, which is related to B.

The relation here is like A->B->C Now using A's serializer I want data to be fetched from C

I want to access C via A i.e get profile_photo from B and the get the name of profile_photo from C

I scrolled through RelatedFields as given here Django Rest relations but am not able to achieve what I want.

Is their any way I can achieve it.

Also there are a lot of fields other than mentioned in the model skeleton and I do not want to fetch those.

EDIT: The final result I need is the all the user_id for a particular post_id from A with the name from model C

1 Answer 1

1

You can do this with a ModelSerializer:

Note: I will asumme that 'posts.Post' is model C

class CsSerializer(serializers.ModelSerializer):

    class Meta:
        model = C
        fields = ('name')


class AsSerializer(serializers.ModelSerializer):

    post_id = CsSerializer()

    class Meta:
        model = A
        # exclude = ('field_you_dont_want_1', 'field_you_dont_want_2')
        # fields = ('field_you_want_1', 'field_you_want_2')

Note that in CsSerializer you can return any field you want from model C in this case I'm just returning a name.

If you just need a string, you could use StringRelatedField

class AsSerializer(serializers.ModelSerializer):
    post_id = serializers.StringRelatedField(many=True)

    class Meta:
        model = A

This StringRelatedField will return what C models return in __unicode__ method (__str__ method if python 3.x).

EDIT

Now, from your comment, I know that 'posts.Post' is not C model. So you could use SerializerMethodField:

class AsSerializer(serializers.ModelSerializer):
    c_name = serializers.SerializerMethodField()

    def get_c_name(self, obj):
        return obj.user_id.c_set.values('name')  # this will return a list of dicts with B's related C objects.

    class Meta:
        model = A

EDIT

You can always define class methods in your models:

class B(AbstractBaseUser):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=20, unique=True)    
    first_name = models.CharField(max_length=40)
    last_name = models.CharField(max_length=40)
    # `resource_id`
    profile_photo = models.ForeignKey('C', null=True)

    def get_profile_photo(self):
        return self.profile_photo.name  # This will return 'C' related object's name

So when you have an A's objects:

a_object.user_id.get_profile_photo()

Or if you have an B's object:

b_object.get_profile_photo()

EDIT

You can define a new Serializer for C class:

class CsSerializer(serializers.Serializer):

    class Meta:
        model = C

Then in your AsSerializer

class AsSerializer(serializers.ModelSerializer):
    c_name = serializers.SerializerMethodField()

    def get_c_name(self, obj):
        qs = obj.user_id.c_set.all()
        qs_serialized = CsSerializer(qs, many=True)
        return qs_serialized.data

    class Meta:
        model = A
Sign up to request clarification or add additional context in comments.

4 Comments

Sorry for being unclear, 'posts.Post' is not model C, it is some other model
@ofnowhereland So you want access to C via B?
I want to access C via A i.e get profile_photo from B and the get the name of profile_photo from C
Got it working, but I need to serialize it and queryset may include more than one users , any idea how could that be achieved

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.