mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 18:08:03 +03:00 
			
		
		
		
	Merge pull request #2685 from rbarrois/rbarrois/fix_lookup_url_kwarg
Fix lookup_url_kwarg handling in viewsets (Fixes #2591).
This commit is contained in:
		
						commit
						cc64e30f55
					
				| 
						 | 
					@ -218,14 +218,15 @@ class SimpleRouter(BaseRouter):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        https://github.com/alanjds/drf-nested-routers
 | 
					        https://github.com/alanjds/drf-nested-routers
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        base_regex = '(?P<{lookup_prefix}{lookup_field}>{lookup_value})'
 | 
					        base_regex = '(?P<{lookup_prefix}{lookup_url_kwarg}>{lookup_value})'
 | 
				
			||||||
        # Use `pk` as default field, unset set.  Default regex should not
 | 
					        # Use `pk` as default field, unset set.  Default regex should not
 | 
				
			||||||
        # consume `.json` style suffixes and should break at '/' boundaries.
 | 
					        # consume `.json` style suffixes and should break at '/' boundaries.
 | 
				
			||||||
        lookup_field = getattr(viewset, 'lookup_field', 'pk')
 | 
					        lookup_field = getattr(viewset, 'lookup_field', 'pk')
 | 
				
			||||||
 | 
					        lookup_url_kwarg = getattr(viewset, 'lookup_url_kwarg', None) or lookup_field
 | 
				
			||||||
        lookup_value = getattr(viewset, 'lookup_value_regex', '[^/.]+')
 | 
					        lookup_value = getattr(viewset, 'lookup_value_regex', '[^/.]+')
 | 
				
			||||||
        return base_regex.format(
 | 
					        return base_regex.format(
 | 
				
			||||||
            lookup_prefix=lookup_prefix,
 | 
					            lookup_prefix=lookup_prefix,
 | 
				
			||||||
            lookup_field=lookup_field,
 | 
					            lookup_url_kwarg=lookup_url_kwarg,
 | 
				
			||||||
            lookup_value=lookup_value
 | 
					            lookup_value=lookup_value
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,13 @@ class NoteViewSet(viewsets.ModelViewSet):
 | 
				
			||||||
    lookup_field = 'uuid'
 | 
					    lookup_field = 'uuid'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class KWargedNoteViewSet(viewsets.ModelViewSet):
 | 
				
			||||||
 | 
					    queryset = RouterTestModel.objects.all()
 | 
				
			||||||
 | 
					    serializer_class = NoteSerializer
 | 
				
			||||||
 | 
					    lookup_field = 'text__contains'
 | 
				
			||||||
 | 
					    lookup_url_kwarg = 'text'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MockViewSet(viewsets.ModelViewSet):
 | 
					class MockViewSet(viewsets.ModelViewSet):
 | 
				
			||||||
    queryset = None
 | 
					    queryset = None
 | 
				
			||||||
    serializer_class = None
 | 
					    serializer_class = None
 | 
				
			||||||
| 
						 | 
					@ -40,6 +47,9 @@ class MockViewSet(viewsets.ModelViewSet):
 | 
				
			||||||
notes_router = SimpleRouter()
 | 
					notes_router = SimpleRouter()
 | 
				
			||||||
notes_router.register(r'notes', NoteViewSet)
 | 
					notes_router.register(r'notes', NoteViewSet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					kwarged_notes_router = SimpleRouter()
 | 
				
			||||||
 | 
					kwarged_notes_router.register(r'notes', KWargedNoteViewSet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespaced_router = DefaultRouter()
 | 
					namespaced_router = DefaultRouter()
 | 
				
			||||||
namespaced_router.register(r'example', MockViewSet, base_name='example')
 | 
					namespaced_router.register(r'example', MockViewSet, base_name='example')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +57,7 @@ urlpatterns = [
 | 
				
			||||||
    url(r'^non-namespaced/', include(namespaced_router.urls)),
 | 
					    url(r'^non-namespaced/', include(namespaced_router.urls)),
 | 
				
			||||||
    url(r'^namespaced/', include(namespaced_router.urls, namespace='example')),
 | 
					    url(r'^namespaced/', include(namespaced_router.urls, namespace='example')),
 | 
				
			||||||
    url(r'^example/', include(notes_router.urls)),
 | 
					    url(r'^example/', include(notes_router.urls)),
 | 
				
			||||||
 | 
					    url(r'^example2/', include(kwarged_notes_router.urls)),
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,6 +188,33 @@ class TestLookupValueRegex(TestCase):
 | 
				
			||||||
            self.assertEqual(expected[idx], self.urls[idx].regex.pattern)
 | 
					            self.assertEqual(expected[idx], self.urls[idx].regex.pattern)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestLookupUrlKwargs(TestCase):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Ensure the router honors lookup_url_kwarg.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Setup a deep lookup_field, but map it to a simple URL kwarg.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    urls = 'tests.test_routers'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        RouterTestModel.objects.create(uuid='123', text='foo bar')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_custom_lookup_url_kwarg_route(self):
 | 
				
			||||||
 | 
					        detail_route = kwarged_notes_router.urls[-1]
 | 
				
			||||||
 | 
					        detail_url_pattern = detail_route.regex.pattern
 | 
				
			||||||
 | 
					        self.assertIn('^notes/(?P<text>', detail_url_pattern)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_retrieve_lookup_url_kwarg_detail_view(self):
 | 
				
			||||||
 | 
					        response = self.client.get('/example2/notes/fo/')
 | 
				
			||||||
 | 
					        self.assertEqual(
 | 
				
			||||||
 | 
					            response.data,
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "url": "http://testserver/example/notes/123/",
 | 
				
			||||||
 | 
					                "uuid": "123", "text": "foo bar"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestTrailingSlashIncluded(TestCase):
 | 
					class TestTrailingSlashIncluded(TestCase):
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        class NoteViewSet(viewsets.ModelViewSet):
 | 
					        class NoteViewSet(viewsets.ModelViewSet):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user