Files
thpeetz-notes/Quellen/IT/Build a CRUD Web App With Python and Flask - Part .md
T

14 KiB
Raw Blame History

title, source
title source
Build a CRUD Web App With Python and Flask - Part Two https://www.digitalocean.com/community/tutorials/build-a-crud-web-app-with-python-and-flask-part-two

This tutorial is out of date and no longer maintained.

Introduction

This is Part Two of a three-part tutorial to build an employee management web app, named Project Dream Team. In Part One of the tutorial, we set up a MySQL database using MySQL-Python and Flask-SQLAlchemy. We created models, migrated the database, and worked on the home and auth blueprints and templates. By the end of Part One, we had a working app that had a homepage, registration page, login page, and dashboard. We could register a new user, log in, and log out.

In Part Two, we will work on:

  1. Creating an admin user and admin dashboard
  2. Creating, listing, editing, and deleting departments
  3. Creating, listing, editing, and deleting roles
  4. Assigning departments and roles to employees

Admin User

Well start by creating an admin user through the command line. Flask provides a handy command, flask shell, that allows us to use an interactive Python shell for use with Flask apps.

Output

>>> from app.models import Employee
>>> from app import db
>>> admin = Employee(email="admin@admin.com",username="admin",password="admin2016",is_admin=True)
>>> db.session.add(admin)
>>> db.session.commit() 

Weve just created a user with a username, admin, and a password, admin2016. Recall that we set the is_admin field to default to False in the Employee model. To create the admin user above, we override the default value of is_admin and set it to True.

Admin Dashboard

Now that we have an admin user, we need to add a view for an admin dashboard. We also need to ensure that once the admin user logs in, they are redirected to the admin dashboard and not the one for non-admin users. We will do this in the home blueprint.

app/home/views.py

app/auth/views.py

Next, well create the admin dashboard template. Create an admin_dashboard.html file in the templates/home directory, and then add the following code to it:

app/templates/home/admin_dashboard.html

Now we need to edit the base template to show a different menu for the admin user.

app/templates/base.html

In the menu above, we make use of the current_user proxy from Flask-Login to check whether the current user is an admin. If they are, we display the admin menu which will allow them to navigate to the Departments, Roles, and Employees pages. Notice that we use # for the links in the admin menu. We will update this after we have created the respective views.

Now run the app and log in as the admin user that we just created. You should see the admin dashboard:

Lets test the error we set in the home/views.py file to prevent non-admin users from accessing the admin dashboard. Log out and then log in as a regular user. In your browsers address bar, manually enter the following URL: http://127.0.0.1:5000/admin/dashboard. You should get a 403 Forbidden error. It looks pretty boring now, but dont worry, well create custom error pages in Part Three!

Departments

Now well start working on the admin blueprint, which has the bulk of the functionality in the application. Well begin by building out CRUD functionality for the departments.

Forms

Well start with the admin/forms.py file, where well create a form to add and edit departments.

app/admin/forms.py

The form is pretty simple and has only two fields, name and department, both of which are required. We enforce this using the DataRequired() validator from WTForms. Note that we will use the same form for adding and editing departments.

Views

Now, lets work on the views:

app/admin/views.py

We begin by creating a function, check_admin, which throws a 403 Forbidden error if a non-admin user attempts to access these views. We will call this function in every admin view.

The list_departments view queries the database for all departments and assigns them to the variable departments, which we will use to list them in the template.

The add_department view creates a new department object using the form data and adds it to the database. If the department name already exists, an error message is displayed. This view redirects to the list_departments. This means that once the admin user creates a new department, they will be redirected to the Departments page.

The edit_department view takes one parameter: id. This is the department ID and will be passed to the view in the template. The view queries the database for a department with the ID specified. If the department doesnt exist, a 404 Not Found error is thrown. If it does, it is updated with the form data.

The delete_department view is similar to the edit_department one, in that it takes a department ID as a parameter and throws an error if the specified department doesnt exist. If it does, it is deleted from the database.

Note that we render the same template for adding and editing individual departments: department.html. This is why we have the add_department variable in the add_department view (where it is set to True), as well as in the edit_department view (where it is set to False). Well use this variable in the department.html template to determine what wording to use for the title and heading.

Templates

Create a templates/admin directory, and in it, add a departments directory. Inside it, add the departments.html and department.html files:

app/templates/admin/departments/departments.html

Weve created a table in the template above, where we will display all the departments with their name, description, and the number of employees. Take note of the count() function, which we use in this case to get the number of employees. Each department listed will have an edit and delete link. Notice how we pass the department.id value to the edit_department and delete_department views in the respective links.

If there are no departments, the page will display “No departments have been added”. There is also a button that can be clicked to add a new department.

Now lets work on the template for adding and editing departments:

app/templates/admin/departments/department.html

Notice that we use the add_department variable which we initialized in the admin/views.py file, to determine whether the page title will be “Add Department” or “Edit Department”.

Add the following lines to your style.css file:

app/static/css/style.css

The .middle, .inner, and .outer classes are to center the content in the middle of the page.

Lastly, lets put the correct link to the Departments page in the admin menu:

Re-start the flask server, and then log back in as the admin user and click on the Departments link. Because we have not added any departments, loading the page will display:

Lets try adding a department:

It worked! We get the success message we configured in the add_department view, and can now see the department displayed.

Now lets edit it:

Notice that the current department name and description are already pre-loaded in the form. Also, take note of the URL, which has the ID of the department we are editing.

Editing the department is successful as well. Clicking the Delete link deletes the department and redirects to the Departments page, where a confirmation message is displayed:

Roles

Now to work on the roles. This will be very similar to the departments code because the functionality for roles and departments is exactly the same.

Forms

Well start by creating the form to add and edit roles. Add the following code to the admin/forms.py file:

app/admin/forms.py

Views

Next, well write the views to add, list, edit, and delete roles. Add the following code to the admin/views.py file:

app/admin/views.py

These list, add, edit, and delete views are similar to the ones for departments that we created earlier.

Templates

Create a roles directory in the templates/admin directory. In it, create the roles.html and role.html files:

app/templates/admin/roles/roles.html

Just like we did for the departments, we have created a table where we will display all the roles with their name, description, and the number of employees. Each role listed will also have an edit and delete link. If there are no roles, a message of the same will be displayed. There is also a button that can be clicked to add a new role.

app/templates/admin/roles/role.html

We use the add_role variable above the same way we used the add_department variable for the department.html template.

Once again, lets update the admin menu with the correct link:

app/templates/base.html

Re-start the server. You should now be able to access the Roles page, and add, edit and delete roles.

Employees

Now to work on listing employees, as well as assigning them departments and roles.

Forms

Well need a form to assign each employee a department and role. Add the following to the admin/forms.py file:

app/admin/forms.py

We have imported a new field type, QuerySelectField, which we use for both the department and role fields. This will query the database for all departments and roles. The admin user will select one department and one role using the form on the front-end.

Views

Add the following code to the admin/views.py file:

app/admin/views.py

The list_employees view queries the database for all employees and assigns them to the variable employees, which we will use to list them in the template.

The assign_employee view takes an employee ID. First, it checks whether the employee is an admin user; if it is, a 403 Forbidden error is thrown. If not, it updates the employee.department and employee.role with the selected data from the form, essentially assigning the employee a new department and role.

Templates

Create a employees directory in the templates/admin directory. In it, create the employees.html and employee.html files:

app/templates/admin/employees/employees.html

The employees.html template shows a table of all employees. The table shows their full name, department, and role, or displays a - in case no department and role has been assigned. Each employee has an assigned link, which the admin user can click to assign them a department and role.

Because the admin user is an employee as well, they will be displayed in the table. However, we have formatted the table such that admin users stand out with a green background and white text.

app/templates/admin/employees/employee.html

We need to update the admin menu once more:

app/templates/base.html

Navigate to the Employees page now. If there are no users other than the admin, this is what you should see:

When there is an employee registered, this is displayed:

Feel free to add a variety of departments and roles so that you can start assigning them to employees.

You can re-assign departments and roles as well.

Conclusion

We now have a completely functional CRUD web app! In Part Two of the tutorial, weve been able to create an admin user and an admin dashboard, as well as customize the menu for different types of users. Weve also built out the core functionality of the app, and can now add, list, edit, and delete departments and roles, as well as assign them to employees. We have also taken security into consideration by protecting certain views from unauthorized access.

In Part Three, we will create custom error pages, write tests, and deploy the app to PythonAnywhere.