diff --git a/djblets/extensions/hooks.py b/djblets/extensions/hooks.py
index e1d6133921bef4af2568d7e3ba123eccd30a5d9c..b543e886edc719cc9f86c3068e96522140a8dd33 100644
--- a/djblets/extensions/hooks.py
+++ b/djblets/extensions/hooks.py
@@ -27,7 +27,6 @@ from __future__ import unicode_literals
 
 import uuid
 
-from django.core.urlresolvers import NoReverseMatch, reverse
 from django.template.loader import render_to_string
 
 from djblets.util.compat import six
@@ -91,6 +90,26 @@ class ExtensionHookPoint(type):
         cls.hooks.remove(hook)
 
 
+class AppliesToURLMixin(object):
+    """A mixin for hooks to allow restricting to certain URLs.
+
+    This provides an applies_to() function for the hook that can be used
+    by consumers to determine if the hook should apply to the current page.
+    """
+    def __init__(self, extension, apply_to=[], *args, **kwargs):
+        super(AppliesToURLMixin, self).__init__(extension)
+        self.apply_to = apply_to
+
+    def applies_to(self, request):
+        """Returns whether or not this hook applies to the page.
+
+        This will determine whether any of the URL names provided in
+        ``apply_to`` matches the current requested page.
+        """
+        return (not self.apply_to or
+                request.resolver_match.url_name in self.apply_to)
+
+
 @six.add_metaclass(ExtensionHookPoint)
 class URLHook(ExtensionHook):
     """Custom URL hook.
@@ -135,7 +154,7 @@ class SignalHook(ExtensionHook):
 
 
 @six.add_metaclass(ExtensionHookPoint)
-class TemplateHook(ExtensionHook):
+class TemplateHook(AppliesToURLMixin, ExtensionHook):
     """Custom templates hook.
 
     A hook that renders a template at hook points defined in another template.
@@ -143,10 +162,9 @@ class TemplateHook(ExtensionHook):
     _by_name = {}
 
     def __init__(self, extension, name, template_name=None, apply_to=[]):
-        super(TemplateHook, self).__init__(extension)
+        super(TemplateHook, self).__init__(extension, apply_to=apply_to)
         self.name = name
         self.template_name = template_name
-        self.apply_to = apply_to
 
         if not name in self.__class__._by_name:
             self.__class__._by_name[name] = [self]
@@ -172,41 +190,6 @@ class TemplateHook(ExtensionHook):
         finally:
             context.pop()
 
-    def applies_to(self, context):
-        """Returns whether or not this TemplateHook should be applied given the
-        current context.
-        """
-
-        # If apply_to is empty, this means we apply to all - so
-        # return true
-        if not self.apply_to:
-            return True
-
-        # Extensions Middleware stashes the kwargs into the context
-        kwargs = context['request']._djblets_extensions_kwargs
-        current_url = context['request'].path_info
-
-        # For each URL name in apply_to, check to see if the reverse
-        # URL matches the current URL.
-        for applicable in self.apply_to:
-            try:
-                reverse_url = reverse(applicable, args=(), kwargs=kwargs)
-            except NoReverseMatch:
-                # It's possible that the URL we're reversing doesn't take
-                # any arguments.
-                try:
-                    reverse_url = reverse(applicable)
-                except NoReverseMatch:
-                    # No matches here, move along.
-                    continue
-
-            # If we got here, we found a reversal.  Let's compare to the
-            # current URL
-            if reverse_url == current_url:
-                return True
-
-        return False
-
     @classmethod
     def by_name(cls, name):
         return cls._by_name.get(name, [])
diff --git a/djblets/extensions/templatetags/djblets_extensions.py b/djblets/extensions/templatetags/djblets_extensions.py
index 8d5f033b2c2b2a63a5373f9d7a3d41eeb61a6df4..9bc359b16125d596a3f39602a05cca1f0f9d50c9 100644
--- a/djblets/extensions/templatetags/djblets_extensions.py
+++ b/djblets/extensions/templatetags/djblets_extensions.py
@@ -21,12 +21,13 @@ def template_hook_point(context, name):
     Registers a template hook point that TemplateHook instances can
     attach to.
     """
-    s = ""
-    for hook in TemplateHook.by_name(name):
-        if hook.applies_to(context):
-            s += hook.render_to_string(context.get('request', None), context)
+    request = context['request']
 
-    return s
+    return ''.join([
+        hook.render_to_string(request, context)
+        for hook in TemplateHook.by_name(name)
+        if hook.applies_to(request)
+    ])
 
 
 @register.tag
diff --git a/djblets/extensions/tests.py b/djblets/extensions/tests.py
index 12718a11fdd18cc9474b416bb3787cf141404318..d8d80dd6cc40ab37253c9d455d203c8a84ca21d0 100644
--- a/djblets/extensions/tests.py
+++ b/djblets/extensions/tests.py
@@ -720,12 +720,11 @@ class TemplateHookTest(TestCase):
             ]
         )
 
-        self.fake_request = Mock()
-        self.fake_request._djblets_extensions_kwargs = {}
-        self.fake_request.path_info = '/'
-        self.context = {
-            'request': self.fake_request,
-        }
+        self.request = Mock()
+        self.request._djblets_extensions_kwargs = {}
+        self.request.path_info = '/'
+        self.request.resolver_match = Mock()
+        self.request.resolver_match.url_name = 'root'
 
     def test_hook_added_to_class_by_name(self):
         """Testing TemplateHook registration"""
@@ -752,14 +751,17 @@ class TemplateHookTest(TestCase):
 
     def test_applies_to_default(self):
         """Testing TemplateHook.applies_to defaults to everything"""
-        self.assertTrue(self.template_hook_no_applies.applies_to(self.context))
+        self.assertTrue(self.template_hook_no_applies.applies_to(self.request))
         self.assertTrue(self.template_hook_no_applies.applies_to(None))
 
     def test_applies_to(self):
         """Testing TemplateHook.applies_to customization"""
-        self.fake_request.path_info = '/some_other/url'
         self.assertFalse(
-            self.template_hook_with_applies.applies_to(self.context))
+            self.template_hook_with_applies.applies_to(self.request))
+
+        self.request.resolver_match.url_name = 'test-url-name'
+        self.assertTrue(
+            self.template_hook_with_applies.applies_to(self.request))
 
 # A dummy function that acts as a View method
 test_view_method = Mock()
