3π
β
The only thing in DRF, that has an access to request object is the view, so you need to figure out how to pass your request from view to serializer, for example in generic ListView you can use get_serializer
.
Then, when you already have it in your serializer, you can use self.parent
(which is a parent serializer) to capture it from the field itself:
class GiveAbsolute(serializers.Field):
def to_native(self,value):
return reverse('link_to_othermodel',
args=[value],
request=self.parent.request)
class SomethingSerializer(serializers.ModelSerializer):
# field with foreign key
othermodel = GiveAbsolute(source="othermodel.id")
class Meta:
model=Something
fields=("fields1","othermodel")
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(SomethingSerializer, self).__init__(*args, **kwargs)
class SomethingView(generics.ListAPIView):
model = Something
serializer_class = SomethingSerializer
def get_serializer(self, instance=None, data=None,
files=None, many=False, partial=False):
serializer_class = self.get_serializer_class()
context = self.get_serializer_context()
return serializer_class(instance, data=data, files=files, many=many,
partial=partial, context=context, request=self.request)
π€mariodev
8π
From the source
The request object is an entry of the context dictionary. ie.
request = self.context.get(βrequestβ)
In your case, just do:
self.request = self.context.get('request')
then build the url
self.request.build_absolute_uri(reverse('some_url_name'))
π€Kwaw Annor
- [Django]-Can this variable really be "referenced before assignment"
- [Django]-How to modify django-ckeditor inline styles?
4π
Based on the answer of mariodev, here is a reusable solution for Models ; I use it to provide URLs to service (see them as metheds) on django models.
Reusable components
serializers.py
class RequestAwareSerializer(serializers.ModelSerializer):
"""
A serializer which fields can access the request object.
"""
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(RequestAwareSerializer, self).__init__(*args, **kwargs)
class APIMethodField(serializers.Field):
""" To get the absolute URL of a method accessible via the API
"""
def __init__(self, url_action_name, *args, **kwargs):
self._url_name = url_action_name
super(APIMethodField, self).__init__(source='*', *args, **kwargs)
def to_native(self, obj):
"""
@param objid the ID of the object
@param method_url_name, the name of the url, as in urls.py
"""
return reverse_lazy(self._url_name, args=[obj.id],
request=self.parent.request)
views.py
class ChattyModelViewSet(ModelViewSet):
""" ModelViewSet which informs the serializer about the request
(abstract)
"""
def get_serializer(self, instance=None, data=None,
files=None, many=False, partial=False):
serializer_class = self.get_serializer_class()
context = self.get_serializer_context()
return serializer_class(instance, data=data, files=files, many=many,
partial=partial, context=context,
request=self.request)
Example use
urls.py
url(r'^v1/maildomain/(?P<maildomain_id>\d+)/check/$',
views.MailDomainDetail.as_view(), name='maildomain_dns_check')
serializers.py
class MailDomainSerializer(RequestAwareSerializer):
checkdns_url = APIMethodField(url_action_name='maildomain_dns_check')
class Meta:
model = MailDomain()
fields = ('name', 'checkdns_url')
views.py
class MailDomainView(ChattyModelViewSet):
model = MailDomain
serializer_class = MailDomainSerializer
- [Django]-Use context processor only for specific application
- [Django]-Using HttpResponseRedirect, but browser is not showing correct URL
- [Django]-What is the best way to consume a django-piston REST API from a Django view?
- [Django]-How can I tell if a value is a string or a list in Django templates?
Source:stackexchange.com