.. _migrate_3_to_4:
*********************************
Migrating Apps from Tethys 3 to 4
*********************************
**Last Updated:** December 2022
This guide describes how to migrate Tethys 3 apps to work in Tethys 4. There are several "breaking" changes that were introduced in Tethys 4 that may cause apps developed in Tethys 3 to not load or function properly. Use the tips below to help you make the changes necessary for the app to function properly in Tethys 4.
.. note::
To migrate an app developed for Tethys 2 to Tethys 4, you will need to first complete the steps found in the :ref:`migrate_2_to_3` guide.
Index Controller
================
The ``index`` property of the :term:`app class` is used to tell Tethys which controller should be used for the home page of the app. In Tethys 4, the app namespace portion (the part before the ``:``) should be dropped.
For example, a Tethys app with an ``index`` property looking like this:
.. code-block:: python
:emphasize-lines: 2
class MyFirstApp(TethysAppBase):
index = "my_first_app:home"
should be changed to this:
.. code-block:: python
:emphasize-lines: 2
class MyFirstApp(TethysAppBase):
index = "home"
Controller Decorators
=====================
The ``url_maps()`` method is being deprecated in favor of the simpler ``controller`` decorator method introduced in Tethys 4. The ``url_maps`` method is temporarily available in Tethys 4 to allow for easier app migration, but **support for the ``url_maps`` method will be dropped in Tethys 4.1.0**.
It is strongly recommended to migrate apps to use the new ``controller`` decorator approach and remove the ``url_maps()`` method from the :file:`app.py`. If you still wish to declare ``UrlMaps`` in the :file:`app.py`, use the new ``register_url_maps()`` method and then remove the ``url_maps()`` method (see: :ref:`register-url-maps-method`). The console will display warnings for apps still using the ``url_maps`` method in Tethys 4 to encourage migration to one of the new methods described above as soon as possible. **Don't wait for Tethys 4.1 to migrate**.
Use the following tips to help you migrate:
1. Review the :ref:`routing_api` documentation to become familiar with the ``controller`` decorator.
2. If your app has a lot of controllers, use the ``url_maps()`` in :file:`app.py` to make a list of them. There should be one controller function or class for each ``UrlMap`` listed.
3. Add the ``controller`` decorator to each controller function or class in your app.
4. If the default URL or name generated by the ``controller`` decorator don't match what is set in the ``UrlMap``, override it by setting the ``url`` and ``name`` arguments of the controller decorator.
5. If your controller uses any other decorators, remove them and use the appropriate arguments in the ``controller`` decorator instead.
6. Remove the ``url_maps()`` method from the :file:`app.py`.
.. note::
Tethys 4 also introduces the ``consumer`` and ``handler`` decorators that function equivalently for consumers and handler functions. See the :ref:`routing_api` documentation for more details.
Search Path
-----------
Tethys will only search for the ``controller``, ``consumer``, and ``handler`` decorators in modules named ``controllers.py`` or ``consumers.py`` or any module located in packages named ``controllers`` and ``consumers``. If your app has controllers located in modules with different names than these defaults, the **recommended migration** is to move the modules into a package named either ``controllers`` or ``consumers``.
However, you may also use the ``controller_modules`` property of the :term:`app class` to define addtiional search locations. For example:
.. code-block:: python
class MyFirstApp(TethysAppBase):
...
controller_modules = [
'custom_controllers', # For a module named custom_controller.py in the same directory as app.py
'rest', # For a package named "rest" in the same directory as app.py containing modules with controllers
]
Workspaces
==========
It is recommended that you use the ``app_workspace`` and ``user_workspace`` arguments of the ``controller`` decorator to acquire workspaces in Tethys 4.
For example, the following controllers:
.. code-block:: python
from tethys_sdk.workspaces import app_workspace
from .app import App
def controller_a(request):
"""Gets user workspace from old app class method."""
user_workspace = App.get_user_workspace(request.user)
uw_path = user_workspace.path
...
@app_workspace
def controller_b(request, app_workspace):
"""Gets app workspace from the app_workspace decorator."""
aw_path = app_workspace.path
...
should be refactored to use the ``controller`` decorator as follows:
.. code-block:: python
from tethys_sdk.routing import controller
@controller(user_workspace=True)
def controller_a(request, user_workspace):
"""Gets user workspace from the controller decorator."""
uw_path = user_workspace.path
...
@controller(app_workspace=True)
def controller_b(request, app_workspace):
"""Gets app workspace from the controller decorator."""
aw_path = app_workspace.path
...
.. note::
In rare cases when the ``controller`` decorator cannot be used to acquire workspaces, you may use the ``get_app_workspace()`` and ``get_user_workspace()`` methods of the app class. These methods are no longer deprecated. However, they will raise an exception if the quotas feature is enabled and the user or app workspace is out of storage space. The ``controller`` decorator automatically handles these exceptions, but when using the ``get_app_workspace()`` and ``get_user_workspace()`` directly, you will need to handle those exceptions.
Templates
=========
In Tethys 4, the ``staticfiles`` template library needs to be changed to ``static``:
For example, the following ``load`` statement:
.. code-block:: html+django
{% load staticfiles %}
needs to be changed to this:
.. code-block:: html+django
{% load static %}
Theme and Styles
================
The frontend CSS framework, Bootstrap, was upgraded from version 3 to version 5 in Tethys Platform 4. As a result, any Boostrap components that are used in templates will need to be updated to use the `Bootstrap 5