Anvil’s Server Modules are a full server-side Python environment.
Sometimes, you want to write code that always executes exactly as it is written (for example, checking a password before changing a file), or code that contains some secret information (for example, your secret authentication keys for a third-party API).
You can write this code in a server module, and it will never be seen by your app’s users (even if they’re experts and poking around inside their own browser). You can call functions in your server modules from your client side code.
To make a server function available from your client code, decorate it as
import anvil.server @anvil.server.callable def guess(number): CORRECT_NUMBER = 127 if number < CORRECT_NUMBER: return "Too low!" elif number > CORRECT_NUMBER: return "Too high!" else: return "Correct!"
From ordinary client-side code (for example, the event handler in a Form), you can call your server-side
function_name is the function name as a string.
# In client code (eg a form): import anvil.server def do_guess(n): result = anvil.server.call("guess", n) print("You guessed: " + n) print("The server said: " + result) return result
anvil.server.call(name, more_arguments…). Any extra arguments are passed
through to the server function. This includes keyword arguments.
You can call server functions from other server functions, as well as from client-side code and uplink functions.
anvil.server.call() is available everywhere.)
The arguments and return values of
@anvil.server.callable functions must be very simple. They may only be strings, numbers, lists,
None, Media objects, or rows from a data table.
They may not be circular (for example, a dict may not contain itself).
anvil.server.call in client code displays a spinner. To call server functions without displaying a spinner, enclose your code in a
with anvil.server.no_loading_indicator: block:
def do_guess_silently(n): with anvil.server.no_loading_indicator: anvil.server.call("guess", n)
You can also call a server function without displaying a spinner by using
anvil.server.call_s instead of
def do_guess_silently(n): anvil.server.call_s("guess", n)
Customise Server Function name
You can customise the name of your callable function by passing a parameter to
this example, the function
foo must be called with
import anvil.server @anvil.server.callable("my_func") def foo(): return 42
Persistent Server Modules
By default, all variables are wiped clean after each server function call returns, except for
This can be avoided by enabling the Persistent Server option, available on our Business plan and above.
Datetime object timezones
datetime.datetime objects with timezones as they pass across interfaces.
This creates a timezone-aware
datetime object, so you don’t lose track of what timezone a
datetime object was created in:
- Any timezone-aware
datetimeobject retains its timezone when transferred in any direction between client, server and Data Tables.
- Any naïve
datetimeobject that is transferred between client and server gets automatically ‘stamped’ with the timezone of the place where it was created before it is transferred. This means that
datetimeobjects generated on the client are automatically ‘stamped’ with the timezone of the browser, while those generated on the server are ‘stamped’ with the timezone of the server, which is always guaranteed to be UTC.
These simple rules mean that you can always compare
datetime objects, no matter where they were created and no matter how much you’ve moved them around or stored them in data tables.
You can explicitly create timezone-aware
datetime objects if you wish, using helper classes from the
import anvil.tz naive_local = datetime.now() # 2019-08-09 10:10:00.406000 aware_local = datetime.now(anvil.tz.tzlocal()) # 'stamped' with the timezone of the browser # 2019-08-09 10:10:00.418000+01:00 naive_utc = datetime.utcnow() # 2019-08-09 09:10:00.426000 aware_utc = datetime.now(anvil.tz.tzutc()) # note: NOT datetime.utcnow() # 'stamped' with the UTC timezone (timezone of the server) # 2019-08-09 09:10:00.433000+00:00 aware_custom = datetime(2017,11,16,23,45,15,0, anvil.tz.tzoffset(hours=3)) # 'stamped' with the UTC+3 timezone # 2017-11-16 23:45:15+03:00
Server function timeout
Server functions run synchronously and should return fairly quickly. By default, the timeout is set to 30 seconds, after which a running function will be stopped. For longer-running jobs, you should use Background Tasks.