Django prefetch_related на отношении ForeignKey

У меня настроена такая база данных:

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)

Как мне теперь получить субпрофили и предварительно получить связанные с ними SubProfilePosts?

Я пробовал делать так:

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

Когда я прогоняю набор queryset через свои сериализаторы:

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

Данные не содержат SubProfilePost(ов). Если я напрямую обращаюсь к obj.profile.sub_profile_postings.all(), я вижу данные.

Возможно, я неправильно понимаю, как работает предварительная выборка, аннотируются ли данные к набору запросов при предварительной выборке и т.д.

Может ли кто-то более опытный просветить меня, если что-то не так с моей установкой, или я неправильно понимаю всю концепцию.

Вот мои сериализаторы:

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
        ] 

Реализовано с помощью SerializerMethodField.

Я попытался выразить его как Queryset, насколько это возможно, но не смог решить проблему, при которой в подзапрос можно было бы вернуть несколько значений.

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

Попробуйте это

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
        ]

Должно получиться что-то вроде этого, просто грубый пример.

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

или добавьте геттер в SubProfileSerializer(), чтобы отфильтровать все SubProfilePost на основе профиля.

Вернуться на верх