Search code examples
pythondjangodjango-rest-frameworkdjango-serializer

Access @property method in reverse relation serialization DRF


I have these models:

class Datas(BaseModel):
  path = models.CharField()
  folder = models.ForeignKey(folder, on_delete=models.CASCADE)


class Photos(BaseModel):
  data = models.ForeignKey('Datas', on_delete=models.CASCADE)
  name = models.CharField()

  @property
  def file_path(self):
    return urljoin(self.data.folder.url, quote(self.full_path))

And these serializer for Datas model:

class DatasSerializer(serializers.ModelSerializer):
  path = serializers.CharField()
  file_url = serializers.SerializerMethodField()

  class Meta:
    model = Datas
    fields = (
      'id',
      'path',
      'folder',
      'file_url'
    )

  def get_file_url(self, obj):
    return Photos.file_path

What I want is to retrieve file_path from Photos model. Is it possible to access property method this way in reverse relation?


Solution

  • Due to ForeignKey relationship, you can have multiple Photos object for one Datas model(it should be Data because it is a plural word already). If you want the latest Photo then try like this:

    class DatasSerializer(serializers.ModelSerializer):
      path = serializers.CharField()
      file_url = serializers.SerializerMethodField()
    
      class Meta:
          model = Datas
          fields = (
              'id',
              'path',
              'folder',
              'file_url'
          )
    
        def get_file_url(self, obj):
            return obj.photos_set.last().file_path  # or `first()` to get the first object
    

    If you want all of them then you can try like this:

    class PhotoSerializer(serializers.ModelSerializer):
        file_url = serializers.Field()
        class Meta:
            model = Photos
            fields = ['file_url']
    
    class DatasSerializer(serializers.ModelSerializer):
          path = serializers.CharField()
          photos = PhotoSerializer(read_only=True, many=True, source='photos_set')
          class Meta:
              model = Datas
             fields = ('id', 'path', 'folder', 'photos')
    

    More information can be found in DRF documentation on reverse relations: