User Server Module¶
Backend databases¶
The User table that we have been dealing with is actually inside a database. At the moment the database has only one table, but eventually we will add extra tables to it. There are four basic operations that databases need to do - create, read, update and delete, referred to as CRUD. We have already been using a read operation, the built in get_user()
.
CRUD
CRUD stands for Create, Read, Update, and Delete. These are the four basic operations that are fundamental to database management:
Create: These operations add new records to a database.
Read: These operations retrieve data from the database.
Update: These operations modify existing records in the database.
Delete: These operations remove records from the database.
All database operations occur server-side (backend). Server-side code provides methods that can be called by the client-side (frontend). When the client-side calls the methods, the server executes the server-side code and then sends the results back to the client-side.
To provide additional, custom methods we will need to create our first server-side code. We will call this module user-service
as it will provide CRUD operations to user data.
Code¶
To start we will need to create a Server Module.
Go to the file submenu
Click on Add Server Module
Then name the new server module
user_service
Making a callable method¶
If you look at the comment in the user_service
it tells you how to create callable function for your server code. Making a function callable allows it to be used in the client-side code.
To make a function callable, you need to add @anvil.server.callable
above it. This is called a decorator. Decorators are a bit beyond the scope of this course, and this is the only place that you will use them, so for our purposes, just use it as is.
Decorators
Python decorators can change how other functions work. When you use a decorator, you attach it to another function to change its behavior. This lets you add extra features to your function without changing its main code.
More information can be found at Free Code Camps - Python Decorators Explained For Beginners
Create the update user function¶
So to create a function for our website to use we must:
create a function that accepts a first name and last name
get’s the current user
updates the current user’s first name and last name with the values provided
then add the
@anvil.server.callable
decorator above the function
Remove all the comments within user_services
, then add the code below:
7@anvil.server.callable
8def update_user(first_name, last_name):
9 user = anvil.users.get_user()
10
11 user["first_name"] = first_name
12 user["last_name"] = last_name
Code explaination
line 7:
@anvil.server.callable
→ the decorator that allows the client-side code to call this function
line 8:
def update_user
→ names the functionupdate_user
(first_name, last_name)
→ requires the valuesfirst_name
andlast_name
to be passed when called
line 9:
anvil.users.get_user()
→ get the details of the current user. Note these details are stored in a dictionaryuser =
→ stores the dictionary of the current user details in a variable called user
line 11:
user["first_name"] = first_name
→ change the first_name value of the user to the first_name passed to the function.
line 12:
user["last_name"] = last_name
→ change the last_name value of the user to the last_name passed to the function.
Call the update user function¶
Now that we have the a server-side function we need to call it, so return to the code of SetDetailsComponent.
Replace line 30 with the highlighted text.
17 def button_save_click(self, **event_args):
18
19 if self.text_box_first_name.text == "":
20 self.label_error.text = "First name cannot be blank"
21 self.label_error.visible = True
22 return
23
24 if self.text_box_last_name.text == "":
25 self.label_error.text = "Last name cannot be blank"
26 self.label_error.visible = True
27 return
28
29 self.label_error.visible = False
30 anvil.server.call("update_user",
31 self.text_box_first_name.text,
32 self.text_box_last_name.text)
Code explaination
Note: lines 30 - 32 are one statement, it has just been spread over three lines to make it easier to read (you can split arguements after a ,
).
line 30:
anvil.server.call
→ this is how you call functions that have the@anvil.server.callable
decorator"update_user"
→ when usinganvil.server.call
the first argument passed is the name of the function you want to call.self.text_box_first_name.text
→ the text of the first name text box that will passed asfirst_name
to theupdate_user
function.self.text_box_last_name.text
→ the text of the last name text box that will passed aslast_name
to theupdate_user
function.
Testing¶
Time to test if this all works.
Go to the User table and delete your users
Launch your website
Register a new user
Enter a first name and last name
Click on Save Details
Stop your website
Go to the User table and check that your new user has the correct
first_name
andlast_name
.
Final code state¶
By the end of this tutorial your code should be the same as below:
Final SetDetailsForm¶
1from ._anvil_designer import SetDetailsComponentTemplate
2from anvil import *
3import anvil.server
4import anvil.tables as tables
5import anvil.tables.query as q
6from anvil.tables import app_tables
7import anvil.users
8
9
10class SetDetailsComponent(SetDetailsComponentTemplate):
11 def __init__(self, **properties):
12 # Set Form properties and Data Bindings.
13 self.init_components(**properties)
14
15 # Any code you write here will run before the form opens.
16
17 def button_save_click(self, **event_args):
18
19 if self.text_box_first_name.text == "":
20 self.label_error.text = "First name cannot be blank"
21 self.label_error.visible = True
22 return
23
24 if self.text_box_last_name.text == "":
25 self.label_error.text = "Last name cannot be blank"
26 self.label_error.visible = True
27 return
28
29 self.label_error.visible = False
30 anvil.server.call("update_user",
31 self.text_box_first_name.text,
32 self.text_box_last_name.text)
Final user_service¶
1import anvil.users
2import anvil.tables as tables
3import anvil.tables.query as q
4from anvil.tables import app_tables
5import anvil.server
6
7@anvil.server.callable
8def update_user(first_name, last_name):
9 user = anvil.users.get_user()
10
11 user["first_name"] = first_name
12 user["last_name"] = last_name