diff --git a/django_rest/test_app/templates/test_app/index.html b/django_rest/test_app/templates/test_app/index.html
index 28dadb391a5dda6f34f48cea4e3bc24f2ac565c5..f48926e765fa28215bf09a3a868fb909654a647e 100644
--- a/django_rest/test_app/templates/test_app/index.html
+++ b/django_rest/test_app/templates/test_app/index.html
@@ -7,6 +7,13 @@
 
 {% block content %}
   <p>Test Page Content</p>
+
+  {% if is_class_view %}
+    <p><a href="{% url 'test_app:index' %}">Render page from Function view</a></p>
+  {% else %}
+    <p><a href="{% url 'test_app:index_as_class' %}">Render page from Class view</a></p>
+  {% endif %}
+
   <ul>
     <li>
       <p>Standard Views:</p>
diff --git a/django_rest/test_app/urls.py b/django_rest/test_app/urls.py
index 71407c25b6a367c9c9e8ceb055d70d71a242cf9d..b35cd39f368f149ba1322791a74b9f33d4fa8bbc 100644
--- a/django_rest/test_app/urls.py
+++ b/django_rest/test_app/urls.py
@@ -25,6 +25,8 @@ urlpatterns = [
     # Test REST API views.
     path('api/api-token-auth', rest_views.obtain_auth_token, name='api_token_auth'),
 
+    # Test app root, but as a class.
+    path('as_class', views.ExampleClassView.as_view(), name='index_as_class'),
     # App root.
     path('', views.index, name='index')
 ]
diff --git a/django_rest/test_app/views.py b/django_rest/test_app/views.py
index dd06e3c8f09ecd126094cfbed749b5897dfbfa34..1da95a16904a7220aea60a84fe937cae2f6ea997 100644
--- a/django_rest/test_app/views.py
+++ b/django_rest/test_app/views.py
@@ -12,9 +12,10 @@ import requests
 from django.contrib.auth import get_user_model
 from django.contrib.auth.decorators import login_required, permission_required
 from django.contrib.auth.models import Group
-from django.http import HttpResponse, JsonResponse, QueryDict
+from django.http import JsonResponse, QueryDict
 from django.views.decorators.csrf import csrf_exempt
 from django.views.decorators.http import require_http_methods
+from django.views.generic import TemplateView
 from django.shortcuts import redirect, render, reverse
 from rest_framework import permissions, viewsets
 
@@ -38,6 +39,122 @@ def index(request):
     """Test app index page."""
     return render(request, 'test_app/index.html')
 
+
+class ExampleClassView(TemplateView):
+    """A basic Class Django view,
+    with some of the more common built-in methods and documentation of what they do.
+
+    Note: Some of these methods won't do anything with TemplateView. For example,
+          the form valid/invalid methods require a class that will POST form data.
+          Such as CreateView or UpdateView.
+    """
+
+    # Magic DjangoView args. Often times, can just define these and skip most method calls.
+
+    # Template to render.
+    template_name = 'test_app/index.html'
+
+    # Url to use if redirecting.
+    # If args/kwargs are needed, then probably need to use get_redirect_url() instead.
+    url = None
+
+    # If using a ModelView (ListView, DetailView, etc), these define what model data to call with.
+    model = None
+    queryset = None     # Can call more complicated query logic in get_queryset().
+
+    # If using a ListView, this determines the number of results to display per page with pagination.
+    paginate_by = 25
+
+    # Params for views with form logic.
+    form_class = None       # Form class to use.
+    initial = {}            # Initial data to populate into form, if applicable.
+    success_url = None      # If args/kwargs are needed, then probably need to use get_success_url() instead.
+
+    def dispatch(self, request, *args, **kwargs):
+        """Determines initial logic to call on view access.
+        This is one of the first methods called by Django class views.
+        This determines which of [GET(), POST(), etc] base class handling methods are called.
+        If you need redirecting or other logic prior to calling these, do it here.
+
+        If not redirecting outside of this class, then should probably always finish
+        this function by returning a call to the original dispatch method.
+        """
+        return super().dispatch(request, *args, **kwargs)
+
+    def get_context_data(self, **kwargs):
+        """Pulls additional context data to be used in the template."""
+
+        # Get base context object.
+        context = super().get_context_data(**kwargs)
+
+        # Add new value to context.
+        context['is_class_view'] = True
+
+        # Return context.
+        return context
+
+    def get_queryset(self):
+        """If using a view that uses models (DetailView, ListView, etc), then this modifies the default queryset."""
+        queryset = super().get_queryset()
+
+        # Use additional model query logic here.
+
+        # Return our modified queryset.
+        return queryset
+
+    def get_ordering(self):
+        """Return the field or fields to use for ordering the queryset."""
+
+        # Replace this with a return to a single model field or list of model fields to order by.
+        return super().get_ordering()
+
+    def get(self, request, *args, **kwargs):
+        """Handling for GET response type."""
+
+        # Replace this with a response object.
+        return super().get(request, *args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        """Handling for POST response type."""
+
+        # Replace this with either a response object, or a call to
+        # form_valid()/form_invalid() functions. Depending on what you need for class logic.
+        return super().post(request, *args, **kwargs)
+
+    def form_valid(self, form):
+        """When processing a form, this is the logic to run on form validation success."""
+
+        # Call parent logic. Should always include this line, as default views sometimes do additional processing.
+        response = super().form_valid(form)
+
+        # Do some handling with response here.
+
+        # Return some response object for render.
+        return response
+
+    def form_invalid(self, form):
+        """When processing a form, this is the logic to run on form validation failure."""
+
+        # Call parent logic. Should always include this line, as default views sometimes do additional processing.
+        response = super().form_invalid(form)
+
+        # Do some handling with response here.
+
+        # Return some response object for render.
+        return response
+
+    def get_success_url(self):
+        """When processing a form, determines how to get the url for form success redirect."""
+
+        # Replace this with a `reverse()` call to generate the correct URL.
+        return super().get_success_url()
+
+    def get_redirect_url(self, *args, **kwargs):
+        """When handling a redirect view, this determines how to get the url."""
+
+        # Replace this with a `reverse()` call to generate the correct URL.
+        return super().get_redirect_url()
+
 # endregion Index/Root Views
 
 
diff --git a/django_v4/test_app/views.py b/django_v4/test_app/views.py
index bd54c74692ddd08fd0dd41af9f0c87b71202a2ee..39b125f210ebd552f1ed9849efa79246cfd44b20 100644
--- a/django_v4/test_app/views.py
+++ b/django_v4/test_app/views.py
@@ -10,12 +10,12 @@ import requests
 
 # Third-Party Imports.
 from django.contrib.auth.decorators import login_required, permission_required
-from django.http import HttpResponse, JsonResponse, QueryDict
+from django.http import JsonResponse, QueryDict
 from django.views.decorators.csrf import csrf_exempt
 from django.views.decorators.http import require_http_methods
-from django.views.generic import TemplateView, View
+from django.views.generic import TemplateView
 from django.shortcuts import redirect, render, reverse
-from django.views.generic.edit import FormMixin
+
 # Internal Imports.
 from test_app.forms import ApiSendForm
 from test_app.models import ApiRequestJson
@@ -32,34 +32,6 @@ def index(request):
     """Test app index page."""
     return render(request, 'test_app/index.html')
 
-# endregion Index/Root Views
-
-
-# region Login/Permission Test Views
-
-@login_required
-def view_with_login_check(request):
-    """Test view with basic login check."""
-    return render(request, 'test_app/login_check.html')
-
-
-@permission_required('test_app.test_permission')
-def view_with_permission_check(request):
-    """Test view with basic User permission check."""
-    return render(request, 'test_app/permission_check.html')
-
-
-@login_required
-def view_with_group_check(request):
-    """Test view with basic User group check."""
-
-    # Check group.
-    user_groups = request.user.groups.all().values_list('name', flat=True)
-    if 'test_group' not in user_groups and not request.user.is_superuser:
-        return redirect(reverse('login'))
-
-    return render(request, 'test_app/group_check.html')
-
 
 class ExampleClassView(TemplateView):
     """A basic Class Django view,
@@ -176,6 +148,34 @@ class ExampleClassView(TemplateView):
         # Replace this with a `reverse()` call to generate the correct URL.
         return super().get_redirect_url()
 
+# endregion Index/Root Views
+
+
+# region Login/Permission Test Views
+
+@login_required
+def view_with_login_check(request):
+    """Test view with basic login check."""
+    return render(request, 'test_app/login_check.html')
+
+
+@permission_required('test_app.test_permission')
+def view_with_permission_check(request):
+    """Test view with basic User permission check."""
+    return render(request, 'test_app/permission_check.html')
+
+
+@login_required
+def view_with_group_check(request):
+    """Test view with basic User group check."""
+
+    # Check group.
+    user_groups = request.user.groups.all().values_list('name', flat=True)
+    if 'test_group' not in user_groups and not request.user.is_superuser:
+        return redirect(reverse('login'))
+
+    return render(request, 'test_app/group_check.html')
+
 # endregion Login/Permission Test Views