I\'ve defined a simple Django app that includes the following model:
class Project(models.Model):
name = models.CharField(max_length=200)
thumbnail =
check this!
class FileFieldWithLinkRepresentation(serializers.FileField):
def to_representation(self, value):
return create_link(value.url, self.context['request'])
and create_link
method:
def create_link(path: str, request: Request):
domain = request.META['HTTP_HOST']
if not path.startswith('/', 0, 1):
path = '/' + path
return request.scheme + "://" + domain + path
you can use FileFieldWithLinkRepresentation
in every class that needs hyperlink
representation of a FileField
.
I found it annoying to write the same code for a serialized method field.
If you have set correctly the MEDIA_ROOT
to your S3 bucket URL, you can add a field to the serializer like:
class ProjectSerializer(serializers.ModelSerializer):
logo_url = serializers.URLField(read_only=True, source='logo.url')
class Meta:
model = Project
logo is an ImageField in the model. it must not be nullable in order to avoid errors like ValueError: The 'img' attribute has no file associated with it.
I only use .build_absolute_uri
in a serializer methodfield to return absolute urls that use other views in my API. for example, in my project there is an URL /webviews/projects/<pk>
that shows, a title and a button that collects some user input (i.e. not exactly what you would do with suffixes, as it's not a plain representation of the resource but includes some logic instead). the end point /projects/<pk>/
contains a field "webview_url" ponting there, which is generated with SerializerMethodField. it's not media.
Try SerializerMethodField
Example (untested):
class MySerializer(serializers.ModelSerializer):
thumbnail_url = serializers.SerializerMethodField('get_thumbnail_url')
def get_thumbnail_url(self, obj):
return self.context['request'].build_absolute_uri(obj.thumbnail_url)
The request must available to the serializer, so it can build the full absolute URL for you. One way is to explicitly pass it in when the serializer is created, similar to this:
serializer = MySerializer(account, context={'request': request})
Just pass the context and pass request object. if you are using @api_view
serializer = CustomerSerializer(customer, context={"request": request})
For ViewSet user get_serializer_context method
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.all()
serializer_class = ProjectSerializer
def get_serializer_context(self):
return {'request': self.request}
Just pass this "context={'request': request}"
argument where you call your model serializer class to serialize the object. You can follow the below snippet to get the complete URL field.
serialized_object = serializers.MySerializer(data, many=true, context={'request': request})