aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/api-guide/fields.md2
-rw-r--r--rest_framework/fields.py34
2 files changed, 34 insertions, 2 deletions
diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md
index 411f7944..2a8949a1 100644
--- a/docs/api-guide/fields.md
+++ b/docs/api-guide/fields.md
@@ -280,5 +280,7 @@ This field is always read-only.
* `view_name` - The view name that should be used as the target of the relationship. **required**.
* `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument.
+* `slug_field` - The field on the target that should be used for the lookup. Default is `'slug'`.
+* `slug_url_kwarg` - The named url parameter for the slug field lookup. Default is to use the same value as given for `slug_field`.
[cite]: http://www.python.org/dev/peps/pep-0020/
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index e194690d..1b1f57db 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -599,20 +599,50 @@ class HyperlinkedIdentityField(Field):
"""
Represents the instance, or a property on the instance, using hyperlinking.
"""
+ pk_url_kwarg = 'pk'
+ slug_field = 'slug'
+ slug_url_kwarg = None # Defaults to same as `slug_field` unless overridden
def __init__(self, *args, **kwargs):
# TODO: Make view_name mandatory, and have the
# HyperlinkedModelSerializer set it on-the-fly
self.view_name = kwargs.pop('view_name', None)
self.format = kwargs.pop('format', None)
+
+ self.slug_field = kwargs.pop('slug_field', self.slug_field)
+ default_slug_kwarg = self.slug_url_kwarg or self.slug_field
+ self.slug_url_kwarg = kwargs.pop('slug_url_kwarg', default_slug_kwarg)
+
super(HyperlinkedIdentityField, self).__init__(*args, **kwargs)
def field_to_native(self, obj, field_name):
request = self.context.get('request', None)
format = self.format or self.context.get('format', None)
view_name = self.view_name or self.parent.opts.view_name
- view_kwargs = {'pk': obj.pk}
- return reverse(view_name, kwargs=view_kwargs, request=request, format=format)
+ kwargs = {self.pk_url_kwarg: obj.pk}
+ try:
+ return reverse(view_name, kwargs=kwargs, request=request, format=format)
+ except:
+ pass
+
+ slug = getattr(obj, self.slug_field, None)
+
+ if not slug:
+ raise ValidationError('Could not resolve URL for field using view name "%s"' % view_name)
+
+ kwargs = {self.slug_url_kwarg: slug}
+ try:
+ return reverse(self.view_name, kwargs=kwargs, request=request, format=format)
+ except:
+ pass
+
+ kwargs = {self.pk_url_kwarg: obj.pk, self.slug_url_kwarg: slug}
+ try:
+ return reverse(self.view_name, kwargs=kwargs, request=request, format=format)
+ except:
+ pass
+
+ raise ValidationError('Could not resolve URL for field using view name "%s"', view_name)
##### Typed Fields #####