added slug support for HyperlinkedIdentityField

This commit is contained in:
Stephan Groß 2012-11-06 17:02:34 +01:00
parent 4f5a6fca64
commit 2c52a2581f
2 changed files with 34 additions and 2 deletions

View File

@ -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**. * `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. * `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/ [cite]: http://www.python.org/dev/peps/pep-0020/

View File

@ -599,20 +599,50 @@ class HyperlinkedIdentityField(Field):
""" """
Represents the instance, or a property on the instance, using hyperlinking. 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): def __init__(self, *args, **kwargs):
# TODO: Make view_name mandatory, and have the # TODO: Make view_name mandatory, and have the
# HyperlinkedModelSerializer set it on-the-fly # HyperlinkedModelSerializer set it on-the-fly
self.view_name = kwargs.pop('view_name', None) self.view_name = kwargs.pop('view_name', None)
self.format = kwargs.pop('format', 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) super(HyperlinkedIdentityField, self).__init__(*args, **kwargs)
def field_to_native(self, obj, field_name): def field_to_native(self, obj, field_name):
request = self.context.get('request', None) request = self.context.get('request', None)
format = self.format or self.context.get('format', None) format = self.format or self.context.get('format', None)
view_name = self.view_name or self.parent.opts.view_name view_name = self.view_name or self.parent.opts.view_name
view_kwargs = {'pk': obj.pk} kwargs = {self.pk_url_kwarg: obj.pk}
return reverse(view_name, kwargs=view_kwargs, request=request, format=format) 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 ##### ##### Typed Fields #####