skip to Main Content

I have this database setup:

class Profile(AbstractBaseUser, PermissionsMixin):
    email = models.CharField(max_length=30, null=True, unique=True)
    date_created = models.DateTimeField(auto_now=True) ...
   
class SubProfile(models.Model):
    profile = models.OneToOneField(Profile, on_delete=models.CASCADE)
    display_name = models.CharField(max_length=25) ...
   
class SubProfilePost(models.Model):
    profile = models.ForeignKey(Profile, related_name='sub_profile_postings', on_delete=models.CASCADE)
    title = models.CharField(max_length=20, null=False)
    looking_for_date = models.DateTimeField(null=False)

How do I now fetch the SubProfiles, and prefetch the related SubProfilePosts?

I have tried doing this:

subprofile_queryset = SubProfile.objects 
    select_related('profile') 
    prefetch_related(
    Prefetch('profile__sub_profile_postings', queryset=SubProfilePost.objects.only('id', 'looking_for_date')))

When I run the queryset through my serializers:

serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

The data does not contain SubProfilePost(s).
If I directly access the obj.profile.sub_profile_postings.all() I can see the data.

I might be misunderstanding how prefetching works, or whether the data is annotated to the queryset when prefetching etc.

Can someone more experienced enlighten me if there is something wrong with my setup, or am I misunderstanding the whole concept.

Here are my serializers:

class ProfileSerializer(ModelSerializer):
    class Meta:
        model = Profile
        fields = '__all__'
        extra_kwargs = {
            'password': {'write_only': True, 'required': False},
        }
  

class SubProfilePostSerializer(ModelSerializer):
    profile = ProfileSerializer()
    
    class Meta:
        model = SubProfilePost
        fields = '__all__'
  
  
class SubProfileSerializer(ModelSerializer):
    sub_profile_postings = SubProfilePostSerializer(many=True, read_only=True)
    
    class Meta:
        model = SubProfile
        fields = [
            'id',
            'profile',
            'display_name',
            'sub_profile_postings', # Prefetched field
        ] 

2

Answers


  1. Implemented with SerializerMethodField.

    I tried to express it as Queryset as much as possible, but I couldn’t resolve it where multiple values could be returned to the subquery.

    class SubProfileSerializer(ModelSerializer):
      
      sub_profile_postings = serializers.SerializerMethodField()
      
      def get_sub_profile_postings(self, obj):
        posts = SubProfilePost.objects.filter(profile=obj.profile)
        serializer = SubProfilePostSerializer(posts, many=True)
        return serializer.data
        
      class Meta:
          model = SubProfile
          fields = [
              'id',
              'profile',
              'display_name',
              'sub_profile_postings', # Prefetched field
          ] 
    

    enter image description here

    Login or Signup to reply.
  2. Try this

    class ProfileSerializer(ModelSerializer):
        sub_profile_postings = SubProfilePostSerializer(many=True, read_only=True)
    
        class Meta:
            model = Profile
            fields = '__all__'
            extra_kwargs = {
                'password': {'write_only': True, 'required': False},
            }
      
    
    class SubProfilePostSerializer(ModelSerializer):
        
        class Meta:
            model = SubProfilePost
            fields = '__all__'
      
      
    class SubProfileSerializer(ModelSerializer):
        profile = ProfileSerializer()
        
        class Meta:
            model = SubProfile
            fields = [
                'id',
                'profile',
                'display_name',
                'sub_profile_postings', # Prefetched field
            ]
    

    Should return something like this, just a rough sample.

    {
        "id": 23
        "profile": {
            "id":23224,
            "sub_profile_postings": [{}, {}]
        }
    }
    
    

    or add a getter in the SubProfileSerializer() to filter all the SubProfilePost based on profile.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search