Reputation: 1135
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
Upvotes: 0
Views: 1272
Reputation: 10256
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
Upvotes: 1