Beginner Concepts
Last Updated: July 2024
This tutorial introduces important concepts for first-time or beginner Tethys developers. The topics covered include:
The App Class
Model View Controller
Map Layout
App Navigation
1. App Class
The app class, located in app.py
is the primary configuration file for Tethys apps. All app classes inherit from the TethysAppBase
class.
Open
app.py
in your favorite Python IDE or text editor.Change the theme color of your app by changing the value of the
color
property of theDamInventory
class. Use a site like color-hex to find an appropriate hexadecimal RGB color.You can also change the icon of your app. Find a new image online (square images work best) and save it in the
public/images/
directory of your app. Then change the value of theicon
property of theDamInventory
class to match the name of the image.
Tip
For more details about the app class, see the App Base Class API.
Warning
DO NOT change the value of the index
, package
, or root_url
properties of your app class unless you know what you are doing. Doing so will break your app.
2. App Settings
Other settings for your app can be configured in the app settings. App settings are stored in a database, meaning they can be changed dynamically by the administrator of your portal. Some app settings, like Name and Description, correspond with properties in the app.py
script.
To access the app settings, click on the Settings button (gear icon) at the top right-hand corner of your app.
Change the Name and Description of your app by changing their respective values on the app settings page. Press the
Save
button, located at the bottom of the app settings page. Then navigate back to your app to see the changes.
You can also create custom settings for your app that can be configured on the app settings page:
Open the
app.py
and add thecustom_settings()
method to theDamInventory
class. Don't forget to importCustomSetting
:from tethys_sdk.app_settings import CustomSetting ... class App(TethysAppBase): """ Tethys app class for Dam Inventory. """ ... def custom_settings(self): """ Example custom_settings method. """ custom_settings = ( CustomSetting( name='max_dams', type=CustomSetting.TYPE_INTEGER, description='Maximum number of dams that can be created in the app.', required=False ), ) return custom_settings
Warning
Ellipsis in code blocks in Tethys tutorials indicate code that is not shown for brevity. When there are ellipsis in the code, DO NOT COPY AND PASTE THE BLOCK VERBATIM.
Save changes to
app.py
.The development server should automatically restart when it detects changes to files. However if it does not restart, you can manually restart it by pressing
CTRL-C
to stop the server followed by thetethys manage start
command to start it again.Navigate to the settings page of your app and scroll down to the Custom Settings section and you should see an entry for the
max_dams
settings. Enter a value and save changes to the setting. You will learn how to use this custom setting in the app later on in the tutorial.
Tip
For more information about app settings, see the App Settings API.
3. Map Layout
The MapLayout
provides a drop-in full-screen map view for Tethys Apps. In this tutorial, we will use the MapLayout
to display a map of all of the dams in the dam inventory. For a detailed explanation of the MapLayout
see the Map Layout and checkout the Map Layout Tutorial.
Replace the
home
controller incontrollers.py
with aMapLayout
controller class by replacing the contents ofcontrollers.py
with the following code:
from tethys_sdk.layouts import MapLayout
from tethys_sdk.routing import controller
from .app import App
@controller(name="home")
class HomeMap(MapLayout):
app = App
base_template = f'{App.package}/base.html'
map_title = 'Dam Inventory'
map_subtitle = 'Tutorial'
basemaps = ['OpenStreetMap', 'ESRI']
The properties of the MapLayout
class are used to configure the map. Here is a brief explanation of some of those used in the example above:
map_title
: The title of the map that appears in the top left corner of the page.sub_title
: The subtitle of the map that appears below the title.basemaps
: A list of basemaps that are enabled on this map view. The user can switch between them using the basemap control on the map.
The Map Layout documentation provides detailed information about the properties of the MapLayout
class.
Save your changes to
controllers.py
and refresh the page to view the map.
4. Model View Controller
Tethys apps are developed using the Model View Controller (MVC) software architecture pattern. Model refers to the data model and associated code, View refers to the representations of the data, and Controller refers of the code that coordinates data from the Model for rendering in the View. In Tethys apps, the Model is usually an SQL database or files and the code for accessing them, the Views are most often the templates or HTML files, and Controllers are implemented as Python functions or classes.
Tip
For more information about the MVC pattern, see Key Concepts.
5. Create a New Page
Creating a new page in your app consists of three steps: (1) create a new template, (2) add a new controller function to controllers.py
, and (3) define the routing using the controller
decorator.
Create a new file
/templates/dam_inventory/add_dam.html
and add the following contents:{% extends "dam_inventory/base.html" %}
This is the simplest template you can create in a Tethys app, which amounts to a blank Tethys app page. You must extend the
base.html
for the page to inherit the default layout of the app.Create a new controller function called
add_dam
at the bottom of thecontrollers.py
:@controller(url='dams/add') def add_dam(request): """ Controller for the Add Dam page. """ context = {} return App.render(request, 'add_dam.html', context)
This is the most basic controller function you can write: a function that accepts an argument called
request
and a return value that is the result of therender
function. Therender
function renders the Django template into valid HTML using therequest
andcontext
provided.The
controller
decorator creates a route that maps a URL to this controller function. Theurl
argument is used to provide a custom URL for a controller. The default URL that would have been generated without the use of theurl
argument would have been derived from the name of the function:'add-dam'
. URLs are defined relative to the root URL of the app. The full URL for theadd_dam
controller as shown above is'/apps/dam-inventory/dams/add/'
. Also note that the name of the route created by thecontroller
decorator is, by default, the same as the function name (add_dam
). Knowing the name of the route will be important when we need to reference it in a template.At this point you should be able to access the new page by entering its URL into the address bar of your browser (http://localhost:8000/apps/dam-inventory/dams/add/). It is not a very exciting page, because it is blank.
Tip
New Page Pattern: Adding new pages is an exercise of the Model View Controller pattern. Generally, the steps are:
Modify the model if necessary to provide the data for the new page
Create a new HTML template
Create a new controller function
6. View for the New Page
Views for Tethys apps are constructed using the standard web programming tools: HTML, JavaScript, and CSS. Additionally, HTML templates can use the Django Template Language, because Tethys Platform is build on Django. This allows you to code logic into your HTML documents, using template tags, making the web pages of your app dynamic and reusable.
Modify the
template/dam_inventory/add_dam.html
with a title in the app content area and addAdd
andCancel
buttons to the app actions area:{% extends tethys_app.package|add:"/base.html" %} {% load tethys %} {% block app_content %} <h1>Add Dam</h1> {% endblock %} {% block app_actions %} {% gizmo cancel_button %} {% gizmo add_button %} {% endblock %}
Tip
Django Template Language: If you are familiar with HTML, the contents of this file may seem strange. That's because the file is actually a Django template, which contains special syntax (i.e.: {% ... %}
and {{ ... }}
to make the template dynamic. Django templates can contain variables, filters, and tags.
Variables. Variables are denoted by double curly brace syntax like this: {{ variable }}
. Template variables are replaced by the value of the variable. Dot notation can be used to access attributes of an object, keys of dictionaries, and items in lists or tuples: {{ my_object.attribute }}
, {{ my_dict.key }}
, and {{ my_list.3 }}
.
Filters. Variables can be modified by filters which look like this: {{ variable|filter:argument }}
. Filters modify the value of the variable output such as formatting dates, formatting numbers, changing the letter case, or concatenating multiple variables.
Tags. Tags use curly-brace-percent-sign syntax like this: {% tag %}
. Tags perform many different functions including creating text, controlling flow, or loading external information to be used in the app. Some commonly used tags include for
, if
, block
, and extends
.
Blocks. The block tags in the Tethys templates are used to override the content in the different areas of the app base template. For example, any HTML written inside the app_content
block will render in the app content area of the app.
For a better explanation of the Django Template Language and the blocks available in Tethys apps see the App Templating API.
Tip
Gizmos: The add_dam.html
template used the gizmo
Tethys template tag to insert a buttons using one line of code: {% gizmo add_button %}
. Gizmo tags require one argument, an object that defines the options for the gizmo. These gizmo options must be defined in the controller for that view. In the example above we define the options objects for the two gizmos on the home.html
template and pass them to the template through the context dictionary.
For more details on the Button Gizmo see: Button and Button Group For more information about Gizmos in general see the Template Gizmos API.
7. Controller for the New Page
Basic controllers consist of a Python function that takes a request
object as an argument. But as you saw with the MapLayout
controller, they can also be classes. The request
object contains all the information about the incoming request. Each controller function is also associated with one view or template via the render
call. Any variable assigned to the context
variable in a controller becomes a variable that can be used in the template.
Define the options for the
Add
andCancel
button gizmos in theadd_dam
controller incontrollers.py
. Add the variables to the context so they are available to the template:from tethys_sdk.gizmos import Button ... @controller(url='dams/add') def add_dam(request): """ Controller for the Add Dam page. """ add_button = Button( display_text='Add', name='add-button', icon='plus-square', style='success' ) cancel_button = Button( display_text='Cancel', name='cancel-button', href=App.reverse('home') ) context = { 'add_button': add_button, 'cancel_button': cancel_button, } return App.render(request, 'add_dam.html', context)
Save your changes to
controllers.py
andadd_dam.html
and refresh the page to view the updated page.
8. Link to New Page
Finally, you can also link to the page from another page using a button. Add custom header buttons for the Map and Add Dam pages to make it easier to navigate between the two pages.
Open the
/template/dam_inventory/base.html
and add the followingblock
:{% block header_buttons %} {% url tethys_app|url:'home' as home_url %} {% url tethys_app|url:'add_dam' as add_dam_url %} <div class="header-button glyphicon-button"> <a href="{{ home_url }}" title="Map"><i class="bi bi-map"></i></a> </div> <div class="header-button glyphicon-button"> <a href="{{ add_dam_url }}" title="Add Dam"><i class="bi bi-plus-circle"></i></a> </div> {% endblock %}
Tip
Bootstrap: Tethys Platform provides a library called Bootstrap that is used to create layouts and style the app. The glyphicon-button
class used above is a custom class that is used to style the buttons in the header of the app. The bi bi-map
and bi bi-plus-circle
classes are used to add icons to the buttons. To see more icons available via Bootstrap, visit the Bootstrap Icons.
10. Solution
This concludes the Beginner Tutorial. You can view the solution on GitHub at https://github.com/tethysplatform/tethysapp-dam_inventory or clone it as follows:
git clone https://github.com/tethysplatform/tethysapp-dam_inventory.git cd tethysapp-dam_inventory git checkout -b beginner-solution beginner-4.3