diff --git a/airflow/models/dag.py b/airflow/models/dag.py
index ad129edf68072..89b79b98b5390 100644
--- a/airflow/models/dag.py
+++ b/airflow/models/dag.py
@@ -2819,6 +2819,10 @@ def get_last_dagrun(self, session=NEW_SESSION, include_externally_triggered=Fals
             self.dag_id, session=session, include_externally_triggered=include_externally_triggered
         )
 
+    def get_is_paused(self, *, session: Optional[Session] = None) -> bool:
+        """Provide interface compatibility to 'DAG'."""
+        return self.is_paused
+
     @staticmethod
     @provide_session
     def get_paused_dag_ids(dag_ids: List[str], session: Session = NEW_SESSION) -> Set[str]:
diff --git a/airflow/www/app.py b/airflow/www/app.py
index efafcd9ede834..bd7a0e25a79a0 100644
--- a/airflow/www/app.py
+++ b/airflow/www/app.py
@@ -114,7 +114,8 @@ def create_app(config=None, testing=False):
 
     init_robots(flask_app)
 
-    Cache(app=flask_app, config={'CACHE_TYPE': 'filesystem', 'CACHE_DIR': gettempdir()})
+    cache_config = {'CACHE_TYPE': 'flask_caching.backends.filesystem', 'CACHE_DIR': gettempdir()}
+    Cache(app=flask_app, config=cache_config)
 
     init_flash_views(flask_app)
 
diff --git a/airflow/www/templates/airflow/dag.html b/airflow/www/templates/airflow/dag.html
index 1ed60ecf71574..7d0cbb923e30a 100644
--- a/airflow/www/templates/airflow/dag.html
+++ b/airflow/www/templates/airflow/dag.html
@@ -27,6 +27,8 @@
   <link rel="stylesheet" type="text/css" href="{{ url_for_asset('switch.css') }}">
 {% endblock %}
 
+{% set dag_is_paused = dag.get_is_paused() %}
+
 {% block head_meta %}
   {{ super() }}
   <meta name="dag_id" content="{{ dag.dag_id }}">
@@ -36,7 +38,7 @@
   <meta name="extra_links_url" content="{{ url_for('Airflow.extra_links') }}">
   <meta name="paused_url" content="{{ url_for('Airflow.paused') }}">
   <meta name="tree_data" content="{{ url_for('Airflow.tree_data') }}">
-  <meta name="is_paused" content="{{ dag.is_paused }}">
+  <meta name="is_paused" content="{{ dag_is_paused }}">
   {% if dag_model is defined and dag_model.next_dagrun_create_after is defined and dag_model.next_dagrun_create_after is not none %}
     <meta name="next_dagrun_create_after" content="{{ dag_model.next_dagrun_create_after }}">
     <meta name="next_dagrun_data_interval_start" content="{{ dag_model.next_dagrun_data_interval_start }}">
@@ -70,11 +72,11 @@ <h3 class="pull-left">
         {% if appbuilder.sm.can_edit_dag(dag.dag_id) %}
           {% set switch_tooltip = 'Pause/Unpause DAG' %}
         {% else %}
-          {% set switch_tooltip = 'DAG is Paused' if dag.is_paused else 'DAG is Active' %}
+          {% set switch_tooltip = 'DAG is Paused' if dag_is_paused else 'DAG is Active' %}
         {% endif %}
         <label class="switch-label{{' disabled' if not can_edit else ''  }} js-tooltip" title="{{ switch_tooltip }}">
           <input class="switch-input" id="pause_resume" data-dag-id="{{ dag.dag_id }}"
-                 type="checkbox"{{ " checked" if not dag.is_paused else "" }}
+                 type="checkbox"{{ " checked" if not dag_is_paused else "" }}
                  {{ " disabled" if not can_edit else "" }}>
           <span class="switch" aria-hidden="true"></span>
         </label>
diff --git a/airflow/www/templates/airflow/dags.html b/airflow/www/templates/airflow/dags.html
index c38cf5b765c9e..c748d329a2193 100644
--- a/airflow/www/templates/airflow/dags.html
+++ b/airflow/www/templates/airflow/dags.html
@@ -146,16 +146,17 @@ <h2>{{ page_title }}</h2>
               <tr><td colspan="10">No results</td></tr>
             {% endif %}
             {% for dag in dags %}
+            {% set dag_is_paused = dag.get_is_paused() %}
               <tr>
                 <td style="padding-right:0;">
                   {% if dag.can_edit %}
                     {% set switch_tooltip = 'Pause/Unpause DAG' %}
                   {% else %}
-                    {% set switch_tooltip = 'DAG is Paused' if dag.is_paused else 'DAG is Active' %}
+                    {% set switch_tooltip = 'DAG is Paused' if dag_is_paused else 'DAG is Active' %}
                   {% endif %}
                   <label class="switch-label{{' disabled' if not dag.can_edit else ''  }} js-tooltip" title="{{ switch_tooltip }}">
                     <input class="switch-input"  id="toggle-{{ dag.dag_id }}" data-dag-id="{{ dag.dag_id }}" type="checkbox"
-                           {{ " checked" if not dag.is_paused else "" }}
+                           {{ " checked" if not dag_is_paused else "" }}
                            {{ " disabled" if not dag.can_edit else "" }}>
                     <span class="switch" aria-hidden="true"></span>
                   </label>
diff --git a/airflow/www/utils.py b/airflow/www/utils.py
index 4cad9a5b47921..e5d0fb45d007f 100644
--- a/airflow/www/utils.py
+++ b/airflow/www/utils.py
@@ -23,11 +23,12 @@
 
 import markdown
 import sqlalchemy as sqla
-from flask import Markup, Response, request, url_for
+from flask import Response, request, url_for
 from flask.helpers import flash
 from flask_appbuilder.forms import FieldConverter
 from flask_appbuilder.models.sqla import filters as fab_sqlafilters
 from flask_appbuilder.models.sqla.interface import SQLAInterface
+from markupsafe import Markup
 from pendulum.datetime import DateTime
 from pygments import highlight, lexers
 from pygments.formatters import HtmlFormatter
diff --git a/airflow/www/views.py b/airflow/www/views.py
index 8144c9d0481e0..09ec76eb79021 100644
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -25,6 +25,7 @@
 import socket
 import sys
 import traceback
+import warnings
 from collections import defaultdict
 from datetime import timedelta
 from functools import wraps
@@ -38,12 +39,10 @@
 import nvd3
 import sqlalchemy as sqla
 from flask import (
-    Markup,
     Response,
     abort,
     before_render_template,
     current_app,
-    escape,
     flash,
     g,
     jsonify,
@@ -78,6 +77,7 @@
 from flask_appbuilder.widgets import FormWidget
 from flask_babel import lazy_gettext
 from jinja2.utils import htmlsafe_json_dumps, pformat  # type: ignore
+from markupsafe import Markup, escape
 from pendulum.datetime import DateTime
 from pendulum.parsing.exceptions import ParserError
 from pygments import highlight, lexers
@@ -1474,7 +1474,10 @@ def task(self, session):
             ti_attrs: Optional[List[Tuple[str, Any]]] = None
         else:
             ti.refresh_from_task(task)
-            all_ti_attrs = ((name, getattr(ti, name)) for name in dir(ti) if not name.startswith("_"))
+            # Some fields on TI are deprecated, but we don't want those warnings here.
+            with warnings.catch_warnings():
+                warnings.simplefilter("ignore", DeprecationWarning)
+                all_ti_attrs = ((name, getattr(ti, name)) for name in dir(ti) if not name.startswith("_"))
             ti_attrs = sorted((name, attr) for name, attr in all_ti_attrs if not callable(attr))
 
         attr_renderers = wwwutils.get_attr_renderer()
diff --git a/metastore_browser/hive_metastore.py b/metastore_browser/hive_metastore.py
index 3400899dbd7a7..e2fdcd17d41cb 100644
--- a/metastore_browser/hive_metastore.py
+++ b/metastore_browser/hive_metastore.py
@@ -23,8 +23,9 @@
 from typing import List
 
 import pandas as pd
-from flask import Blueprint, Markup, request
+from flask import Blueprint, request
 from flask_appbuilder import BaseView, expose
+from markupsafe import Markup
 
 from airflow.plugins_manager import AirflowPlugin
 from airflow.providers.apache.hive.hooks.hive import HiveCliHook, HiveMetastoreHook
diff --git a/setup.cfg b/setup.cfg
index 1ed8e888734c3..3614322f89d06 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -120,7 +120,10 @@ install_requires =
     iso8601>=0.1.12
     # Logging is broken with itsdangerous > 2
     itsdangerous>=1.1.0, <2.0
-    jinja2>=2.10.1,<4
+    # Jinja2 3.1 will remove the 'autoescape' and 'with' extensions, which would
+    # break Flask 1.x, so we limit this for future compatibility. Remove this
+    # when bumping Flask to >=2.
+    jinja2>=2.10.1,<3.1
     jsonschema~=3.0
     lazy-object-proxy
     lockfile>=0.12.2
diff --git a/tests/www/api/experimental/conftest.py b/tests/www/api/experimental/conftest.py
index 1629d83f3967b..698eaea5204f1 100644
--- a/tests/www/api/experimental/conftest.py
+++ b/tests/www/api/experimental/conftest.py
@@ -21,6 +21,9 @@
 from tests.test_utils.config import conf_vars
 from tests.test_utils.decorators import dont_initialize_flask_app_submodules
 
+# This entire directory is testing deprecated functions.
+pytestmark = pytest.mark.filterwarnings("ignore::DeprecationWarning")
+
 
 @pytest.fixture(scope="session")
 def experiemental_api_app():
diff --git a/tests/www/test_app.py b/tests/www/test_app.py
index 2e2579898da7e..7a06010776f02 100644
--- a/tests/www/test_app.py
+++ b/tests/www/test_app.py
@@ -240,7 +240,9 @@ def test_should_set_permanent_session_timeout(self):
     @conf_vars({('webserver', 'cookie_samesite'): ''})
     @dont_initialize_flask_app_submodules
     def test_correct_default_is_set_for_cookie_samesite(self):
-        app = application.cached_app(testing=True)
+        """An empty 'cookie_samesite' should be corrected to 'Lax' with a deprecation warning."""
+        with pytest.deprecated_call():
+            app = application.cached_app(testing=True)
         assert app.config['SESSION_COOKIE_SAMESITE'] == 'Lax'
 
 
diff --git a/tests/www/views/test_views.py b/tests/www/views/test_views.py
index b98c1bc71253f..86e7ea03f4d0e 100644
--- a/tests/www/views/test_views.py
+++ b/tests/www/views/test_views.py
@@ -228,7 +228,11 @@ def test_mark_task_instance_state(test_app):
         task_1 >> [task_2, task_3, task_4, task_5]
 
     dagrun = dag.create_dagrun(
-        start_date=start_date, execution_date=start_date, state=State.FAILED, run_type=DagRunType.SCHEDULED
+        start_date=start_date,
+        execution_date=start_date,
+        data_interval=(start_date, start_date),
+        state=State.FAILED,
+        run_type=DagRunType.SCHEDULED,
     )
 
     def get_task_instance(session, task):
diff --git a/tests/www/views/test_views_acl.py b/tests/www/views/test_views_acl.py
index 7ff7ac4959905..59cbb3eefc3d6 100644
--- a/tests/www/views/test_views_acl.py
+++ b/tests/www/views/test_views_acl.py
@@ -152,6 +152,7 @@ def init_dagruns(acl_app, reset_dagruns):
     acl_app.dag_bag.get_dag("example_bash_operator").create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=DEFAULT_DATE,
+        data_interval=(DEFAULT_DATE, DEFAULT_DATE),
         start_date=timezone.utcnow(),
         state=State.RUNNING,
     )
@@ -159,6 +160,7 @@ def init_dagruns(acl_app, reset_dagruns):
         run_type=DagRunType.SCHEDULED,
         execution_date=DEFAULT_DATE,
         start_date=timezone.utcnow(),
+        data_interval=(DEFAULT_DATE, DEFAULT_DATE),
         state=State.RUNNING,
     )
     yield
diff --git a/tests/www/views/test_views_blocked.py b/tests/www/views/test_views_blocked.py
index 26ad7bd28db38..8a3823a02da29 100644
--- a/tests/www/views/test_views_blocked.py
+++ b/tests/www/views/test_views_blocked.py
@@ -33,7 +33,7 @@ def running_subdag(admin_client, dag_maker):
     with dag_maker(dag_id="running_dag.subdag") as subdag:
         DummyOperator(task_id="dummy")
 
-    with dag_maker(dag_id="running_dag") as dag:
+    with pytest.deprecated_call(), dag_maker(dag_id="running_dag") as dag:
         SubDagOperator(task_id="subdag", subdag=subdag)
 
     dag_bag = DagBag(include_examples=False, include_smart_sensor=False)
@@ -44,10 +44,12 @@ def running_subdag(admin_client, dag_maker):
         dag_bag.sync_to_db(session=session)
 
         # Simulate triggering the SubDagOperator to run the subdag.
+        logical_date = timezone.datetime(2016, 1, 1)
         subdag.create_dagrun(
             run_id="blocked_run_example_bash_operator",
             state=State.RUNNING,
-            execution_date=timezone.datetime(2016, 1, 1),
+            execution_date=logical_date,
+            data_interval=(logical_date, logical_date),
             start_date=timezone.datetime(2016, 1, 1),
             session=session,
         )
diff --git a/tests/www/views/test_views_dagrun.py b/tests/www/views/test_views_dagrun.py
index 64ecadf4baf1a..8ba5c9b87eb7d 100644
--- a/tests/www/views/test_views_dagrun.py
+++ b/tests/www/views/test_views_dagrun.py
@@ -93,6 +93,7 @@ def running_dag_run(session):
     dr = dag.create_dagrun(
         state="running",
         execution_date=execution_date,
+        data_interval=(execution_date, execution_date),
         run_id="test_dag_runs_action",
         session=session,
     )
diff --git a/tests/www/views/test_views_decorators.py b/tests/www/views/test_views_decorators.py
index 1a1c7955b979c..9b5383f2d654e 100644
--- a/tests/www/views/test_views_decorators.py
+++ b/tests/www/views/test_views_decorators.py
@@ -59,6 +59,7 @@ def dagruns(bash_dag, sub_dag, xcom_dag):
     bash_dagrun = bash_dag.create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=EXAMPLE_DAG_DEFAULT_DATE,
+        data_interval=(EXAMPLE_DAG_DEFAULT_DATE, EXAMPLE_DAG_DEFAULT_DATE),
         start_date=timezone.utcnow(),
         state=State.RUNNING,
     )
@@ -66,6 +67,7 @@ def dagruns(bash_dag, sub_dag, xcom_dag):
     sub_dagrun = sub_dag.create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=EXAMPLE_DAG_DEFAULT_DATE,
+        data_interval=(EXAMPLE_DAG_DEFAULT_DATE, EXAMPLE_DAG_DEFAULT_DATE),
         start_date=timezone.utcnow(),
         state=State.RUNNING,
     )
@@ -73,6 +75,7 @@ def dagruns(bash_dag, sub_dag, xcom_dag):
     xcom_dagrun = xcom_dag.create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=EXAMPLE_DAG_DEFAULT_DATE,
+        data_interval=(EXAMPLE_DAG_DEFAULT_DATE, EXAMPLE_DAG_DEFAULT_DATE),
         start_date=timezone.utcnow(),
         state=State.RUNNING,
     )
diff --git a/tests/www/views/test_views_extra_links.py b/tests/www/views/test_views_extra_links.py
index 72e17eee95900..fef430a815edc 100644
--- a/tests/www/views/test_views_extra_links.py
+++ b/tests/www/views/test_views_extra_links.py
@@ -85,6 +85,7 @@ def _create_dag_run(*, execution_date, session):
         return dag.create_dagrun(
             state=DagRunState.RUNNING,
             execution_date=execution_date,
+            data_interval=(execution_date, execution_date),
             run_type=DagRunType.MANUAL,
             session=session,
         )
diff --git a/tests/www/views/test_views_graph_gantt.py b/tests/www/views/test_views_graph_gantt.py
index 589ff1d5513e0..7aedb2860334f 100644
--- a/tests/www/views/test_views_graph_gantt.py
+++ b/tests/www/views/test_views_graph_gantt.py
@@ -50,6 +50,7 @@ def runs(dag):
         dag.create_dagrun(
             run_id=run_id,
             execution_date=execution_date,
+            data_interval=(execution_date, execution_date),
             state=State.SUCCESS,
             external_trigger=True,
         )
diff --git a/tests/www/views/test_views_home.py b/tests/www/views/test_views_home.py
index 748f5ee6b3e25..9b16acea84fd2 100644
--- a/tests/www/views/test_views_home.py
+++ b/tests/www/views/test_views_home.py
@@ -19,6 +19,7 @@
 from unittest import mock
 
 import flask
+import markupsafe
 import pytest
 
 from airflow.dag_processing.processor import DagFileProcessor
@@ -225,7 +226,7 @@ def test_dashboard_flash_messages_many(user_client):
 
 def test_dashboard_flash_messages_markup(user_client):
     link = '<a href="http://example.com">hello world</a>'
-    user_input = flask.Markup("Hello <em>%s</em>") % ("foo&bar",)
+    user_input = markupsafe.Markup("Hello <em>%s</em>") % ("foo&bar",)
     messages = [
         UIAlert(link, html=True),
         UIAlert(user_input),
diff --git a/tests/www/views/test_views_log.py b/tests/www/views/test_views_log.py
index 2b42033d0dbc3..493e69c8b7e08 100644
--- a/tests/www/views/test_views_log.py
+++ b/tests/www/views/test_views_log.py
@@ -136,6 +136,7 @@ def tis(dags, session):
     dagrun = dag.create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=DEFAULT_DATE,
+        data_interval=(DEFAULT_DATE, DEFAULT_DATE),
         start_date=DEFAULT_DATE,
         state=DagRunState.RUNNING,
         session=session,
@@ -145,6 +146,7 @@ def tis(dags, session):
     dagrun_removed = dag_removed.create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=DEFAULT_DATE,
+        data_interval=(DEFAULT_DATE, DEFAULT_DATE),
         start_date=DEFAULT_DATE,
         state=DagRunState.RUNNING,
         session=session,
diff --git a/tests/www/views/test_views_pool.py b/tests/www/views/test_views_pool.py
index fe003558d6834..9b1c0c1d401d3 100644
--- a/tests/www/views/test_views_pool.py
+++ b/tests/www/views/test_views_pool.py
@@ -16,6 +16,7 @@
 # specific language governing permissions and limitations
 # under the License.
 import flask
+import markupsafe
 import pytest
 
 from airflow.models import Pool
@@ -79,10 +80,10 @@ def test_list(app, admin_client, pool_factory):
     # We should see this link
     with app.test_request_context():
         url = flask.url_for('TaskInstanceModelView.list', _flt_3_pool='test-pool', _flt_3_state='running')
-        used_tag = flask.Markup("<a href='{url}'>{slots}</a>").format(url=url, slots=0)
+        used_tag = markupsafe.Markup("<a href='{url}'>{slots}</a>").format(url=url, slots=0)
 
         url = flask.url_for('TaskInstanceModelView.list', _flt_3_pool='test-pool', _flt_3_state='queued')
-        queued_tag = flask.Markup("<a href='{url}'>{slots}</a>").format(url=url, slots=0)
+        queued_tag = markupsafe.Markup("<a href='{url}'>{slots}</a>").format(url=url, slots=0)
     check_content_in_response(used_tag, resp)
     check_content_in_response(queued_tag, resp)
 
diff --git a/tests/www/views/test_views_tasks.py b/tests/www/views/test_views_tasks.py
index 932ea335b0c53..288d93be6fda2 100644
--- a/tests/www/views/test_views_tasks.py
+++ b/tests/www/views/test_views_tasks.py
@@ -56,18 +56,21 @@ def init_dagruns(app, reset_dagruns):
     app.dag_bag.get_dag("example_bash_operator").create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=DEFAULT_DATE,
+        data_interval=(DEFAULT_DATE, DEFAULT_DATE),
         start_date=timezone.utcnow(),
         state=State.RUNNING,
     )
     app.dag_bag.get_dag("example_subdag_operator").create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=DEFAULT_DATE,
+        data_interval=(DEFAULT_DATE, DEFAULT_DATE),
         start_date=timezone.utcnow(),
         state=State.RUNNING,
     )
     app.dag_bag.get_dag("example_xcom").create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=DEFAULT_DATE,
+        data_interval=(DEFAULT_DATE, DEFAULT_DATE),
         start_date=timezone.utcnow(),
         state=State.RUNNING,
     )
@@ -259,6 +262,7 @@ def test_dag_details_trigger_origin_tree_view(app, admin_client):
     app.dag_bag.get_dag('test_tree_view').create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=DEFAULT_DATE,
+        data_interval=(DEFAULT_DATE, DEFAULT_DATE),
         start_date=timezone.utcnow(),
         state=State.RUNNING,
     )
@@ -274,6 +278,7 @@ def test_dag_details_trigger_origin_graph_view(app, admin_client):
     app.dag_bag.get_dag('test_graph_view').create_dagrun(
         run_type=DagRunType.SCHEDULED,
         execution_date=DEFAULT_DATE,
+        data_interval=(DEFAULT_DATE, DEFAULT_DATE),
         start_date=timezone.utcnow(),
         state=State.RUNNING,
     )
