Skip to content

Commit

Permalink
Fix get_via_uri not working for alphabetic ids that contain the resou…
Browse files Browse the repository at this point in the history
…rce name (Fixes #1239, Closes #1240)
  • Loading branch information
Pierre-Etienne Mélet authored and SeanHayes committed Feb 22, 2016
1 parent 4cb586c commit b3bf380
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/release_notes/dev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Bugfixes

* Change OAuthAuthentication to use storage method to get user. (Closes #657)
* Fixed UnicodeDecodeError in _handle_500(). (Fixes #1190)
* Fix get_via_uri not working for alphabetic ids that contain the resource name (Fixes #1239, Closes #1240)
13 changes: 9 additions & 4 deletions tastypie/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -842,10 +842,15 @@ def get_via_uri(self, uri, request=None):
if prefix and chomped_uri.startswith(prefix):
chomped_uri = chomped_uri[len(prefix) - 1:]

# We know that we are dealing with a "detail" URI
# Look for the beginning of object key (last meaningful part of the URI)
end_of_resource_name = chomped_uri.rstrip("/").rfind("/")
if end_of_resource_name == -1:
raise NotFound("An incorrect URL was provided '%s' for the '%s' resource." % (uri, self.__class__.__name__))
# We mangle the path a bit further & run URL resolution against *only*
# the current class. This ought to prevent bad URLs from resolving to
# incorrect data.
found_at = chomped_uri.rfind(self._meta.resource_name)
# the current class (but up to detail key). This ought to prevent bad
# URLs from resolving to incorrect data.
found_at = chomped_uri.rfind(self._meta.resource_name, 0, end_of_resource_name)
if found_at == -1:
raise NotFound("An incorrect URL was provided '%s' for the '%s' resource." % (uri, self.__class__.__name__))
chomped_uri = chomped_uri[found_at:]
Expand Down Expand Up @@ -2160,7 +2165,7 @@ def obj_get(self, bundle, **kwargs):
if len(object_list) <= 0:
raise self._meta.object_class.DoesNotExist("Couldn't find an instance of '%s' which matched '%s'." % (self._meta.object_class.__name__, stringified_kwargs))
elif len(object_list) > 1:
raise MultipleObjectsReturned("More than '%s' matched '%s'." % (self._meta.object_class.__name__, stringified_kwargs))
raise MultipleObjectsReturned("More than one '%s' matched '%s'." % (self._meta.object_class.__name__, stringified_kwargs))

bundle.obj = object_list[0]
self.authorized_read_detail(object_list, bundle)
Expand Down
26 changes: 23 additions & 3 deletions tests/core/tests/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -1641,15 +1641,35 @@ def test__get_via_uri__app_name_same_as_resource(self):
note_1 = resource.get_via_uri('/notes/api/v1/notes/1/')
self.assertEqual(note_1.pk, 1)

def test__get_via_uri__identifier_contains_resource_name(self):
class CustomNoteResource(NoteResource):
class Meta(NoteResource.Meta):
detail_uri_name = 'slug'
resource = CustomNoteResource(api_name='v1')
note_1 = Note.objects.first()
note_1.slug = 'notes1-notes'
note_1.save()
note_1_new = resource.get_via_uri('/notes/api/v1/notes/%s/' % note_1.slug)
self.assertEqual(note_1_new.pk, note_1.pk)

def test__get_via_uri__identifier_same_as_resource_name(self):
class CustomNoteResource(NoteResource):
class Meta(NoteResource.Meta):
detail_uri_name = 'slug'
resource = CustomNoteResource(api_name='v1')
note_1 = Note.objects.first()
note_1.slug = 'notes'
note_1.save()
note_1_new = resource.get_via_uri('/notes/api/v1/notes/%s/' % note_1.slug)
self.assertEqual(note_1_new.pk, note_1.pk)

def test__get_via_uri__uri_has_special_chars(self):
resource = NoteResource(api_name='v1')
# Should work even if app name is the same as resource
note_1 = resource.get_via_uri('/~krichy/api/v1/notes/1/')
self.assertEqual(note_1.pk, 1)

def test__get_via_uri__uri_has_encoded_special_chars(self):
resource = NoteResource(api_name='v1')
# Should work even if app name is the same as resource
note_1 = resource.get_via_uri('/%7ekrichy/api/v1/notes/1/')
self.assertEqual(note_1.pk, 1)

Expand All @@ -1675,7 +1695,7 @@ def test__get_via_uri__different_resource(self):

def test__get_via_uri__list_uri(self):
resource = NoteResource(api_name='v1')
with self.assertRaises(MultipleObjectsReturned):
with self.assertRaises(NotFound):
resource.get_via_uri('/api/v1/notes/')

def test__get_via_uri__with_request(self):
Expand Down

0 comments on commit b3bf380

Please sign in to comment.