You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Should you want to 'see' or understand deeply the data generated in your application, there are a handful of libraries that can help. One of them is ChartJS, the focus of this article. [ChartJs](https://www.chartjs.org/docs/latest/) is a free JavaScript library for creating charts in the browser (HTML-based charts). It is very easy to use, though basic understanding of JavaScript is required.
7
+
Should you want to 'see' or understand deeply the data generated in your application, there are a handful of libraries that can help. One of them is ChartJS, the focus of this article. [ChartJs](https://www.chartjs.org/docs/latest/) is a free JavaScript library for creating charts in the browser (HTML-based charts). It is very easy to use, though a basic understanding of JavaScript is required.
8
8
9
9
## What We Will Do?
10
10
11
11
We will build a simple flask application for a class teacher to record the mean scores of all the subjects in a class throughout a 3-term year. Example data we will need may include the following:
12
12
13
-
***Subjects**: Math, English, Science, History, and Computer Science
13
+
***Subjects**: Maths, English, Science, History, and Computer Science
14
14
***Mean Scores**: [70, 80, 90, 100, 95]
15
15
***Term**: [1, 2, 3]
16
16
@@ -26,7 +26,7 @@ The completed application can be found in this [GitHub repository](https://githu
26
26
4.[Enable user login](#enable-user-login)
27
27
5.[Improve user experience](#improve-user-experience)
28
28
6.[Display the mean scores of each subject per term](#display-the-mean-scores-of-each-subject-per-term)
29
-
7.[Show meanscore chart](#show-meanscore-chart)
29
+
7.[Show mean score chart](#show-mean-score-chart)
30
30
31
31
### Create a simple flask app
32
32
@@ -35,9 +35,9 @@ I have already created a simple flask app for you. You can refer to it in [this
35
35
36
36
### Add web forms to the app
37
37
38
-
Flask provides the [wtf](https://flask-wtf.readthedocs.io/en/latest/) library for creating web forms. This library is helps create forms that are used to collect data from a user, in our case, it will be the classroom teacher. To create a form, we will need to:
38
+
Flask provides the [wtf](https://flask-wtf.readthedocs.io/en/latest/) library for creating web forms. This library helps create forms that are used to collect data from a user, in our case, it will be the classroom teacher. To create a form, we will need to:
39
39
40
-
- Create a _forms_ module to define all the forms we will need (login, register and meanscore)
40
+
- Create a _forms_ module to define all the forms we will need (login, register, and mean score)
41
41
- Create templates for each form (login.html, register.html)
42
42
- Create a _views_ module to render our forms
43
43
@@ -78,12 +78,12 @@ class RegistrationForm(FlaskForm):
78
78
submit = SubmitField('Register')
79
79
```
80
80
81
-
Here, we want to capture a teacher's email, username and their password to protect their account. A few arguments are used to validate a teacher's credentials. For example:
81
+
Here, we want to capture a teacher's email, username, and password to protect their account. A few arguments are used to validate a teacher's credentials. For example:
82
82
83
83
-`DataRequred` ensures that the field is not empty.
84
84
-`Length` ensures that the field is at least 1 character long and at most 64 characters long.
85
85
-`Email` ensures that the field has a valid email address.
86
-
-`Regexp` ensures that the field only contains letters, numbers, dots or underscores.
86
+
-`Regexp` ensures that the field only contains letters, numbers, dots, or underscores.
87
87
-`EqualTo` ensures that the password fields match.
88
88
89
89
`Email()` requires that we install `email-validator`, so remember to do so in the terminal (`pip3 install email-validator`).
@@ -106,15 +106,15 @@ This variable will be sourced from the environment. In the event the variable do
106
106
107
107
### Add data to the app
108
108
109
-
Just like web forms, we will also use classes to create a database model to store a user's data. `flask-sqlalchemy`, a flask-friendly wrapper to SQLAlchemy, will translate the classes, objects and methods to tables and SQL. Intentionally, I will use the SQLite database since it does not require a server to run.
109
+
Just like web forms, we will also use classes to create a database model to store a user's data. `flask-sqlalchemy`, a flask-friendly wrapper to SQLAlchemy, will translate the classes, objects, and methods to tables and SQL. Intentionally, I will use the SQLite database since it does not require a server to run.
110
110
111
111
To install Flask-SQLAlchemy, run:
112
112
113
113
```python
114
114
(venv)$ pip3 install flask-sqlalchemy
115
115
```
116
116
117
-
Every time we create a new model, we need apply those changes to our database. Same goes to when we update the structure/schema of our database. This action is called `migrating` the database. Database migrations are easily handled by `flask-migrate`.
117
+
Every time we create a new model, we need to apply those changes to our database. The same goes for when we update the structure/schema of our database. This action is called `migrating` the database. Database migrations are easily handled by `flask-migrate`.
We have created three columns in our table. The columns will store every user's username, email and password. The `password_hash` column will store the hashed version of the user's password. This is an additional security measure to secure users' data in the event the database is compromised.
188
+
We have created three columns in our table. The columns will store every user's username, email, and password. The `password_hash` column will store the hashed version of the user's password. This is an additional security measure to secure users' data in the event the database is compromised.
189
189
190
190
This is a new structure. We need to apply these changes and create a brand new database table. To do so, we will run the commands below:
We store a user's information in a variable called `user`. Of interest her is to note that we do not pass a user's password data into this variable. Instead, we hash the password using the helper function `set_password()` as seen in `models.py`. Thereafter, we add the user to the database.
224
+
We store a user's information in a variable called `user`. Of interest, here is to note that we do not pass a user's password data into this variable. Instead, we hash the password using the helper function `set_password()` as seen in `models.py`. Thereafter, we add the user to the database.
225
225
226
226
### Enable user login
227
227
228
228
After a user has registered, we redirect them to the login page. This is a good way to ensure that the user has successfully registered. To add this functionality, we will need to add some login logic to the `login()` view functions.
229
229
230
-
User login in flask is easily handled by `flask-login` package. We need to first install it and then create an instance of it in the app.
230
+
User login in Flask is easily handled by `flask-login` package. We need to first install it and then create an instance of it in the app.
231
231
232
232
```python
233
233
(venv)$ pip3 install flask-login
@@ -242,7 +242,7 @@ User login in flask is easily handled by `flask-login` package. We need to first
242
242
login = LoginManager()
243
243
```
244
244
245
-
Since our database has no clue about user sessions, we need to modily it slightly.
245
+
Since our database has no clue about user sessions, we need to modify it slightly.
246
246
247
247
`app/models.py: Modify the User table`
248
248
```python
@@ -320,7 +320,7 @@ We will then update our _base.html_ template to include a conditional statement
320
320
321
321
A quick reload will reveal the state of a user. If the user is logged in, then the link will change to _logout_. Upon logout, the user will be redirected to the login page.
Every time a new user tries to user an already existing email address or username, we will raise a validation error and provide useful information as to why the registration process does not work.
381
+
Every time a new user tries to use an already existing email address or username, we will raise a validation error and provide useful information as to why the registration process does not work.
We will show this form in the index page. So, let us update the index template to include this form.
419
+
We will show this form on the index page. So, let us update the index template to include this form.
420
420
421
421
`app/templates/index.html: Display Mean Score Per Term Form`
422
422
@@ -439,7 +439,7 @@ We will show this form in the index page. So, let us update the index template t
439
439
440
440
We need to update the `index()` view function to accommodate this form.
441
441
442
-
`app/routes.py: Handling the meanscore form`
442
+
`app/routes.py: Handling the mean score form`
443
443
444
444
```python
445
445
from app.forms import MeanScore
@@ -454,7 +454,7 @@ def index():
454
454
return render_template('index.html', form=form)
455
455
```
456
456
457
-
The form should be on display in the index template after refreshing the page. To story the data, we need to create a MeanScore model. This model will store the following data: term, math, english, science, ict, and history.
457
+
The form should be on display in the index template after refreshing the page. To store the data, we need to create a MeanScore model. This model will store the following data: term, math, english, science, ict, and history.
The _User_ and the _Meanscore_ tables are related by the _user_id_ column. This means that each user will have a list of meanscores. To apply the changes we need to once again run the commands below:
478
+
The _User_ and the _Meanscore_ tables are related by the _user_id_ column. This means that each user will have a list of mean scores. To apply the changes we need to once again run the commands below:
479
479
480
480
```python
481
-
(venv)$ flask db migrate -m 'meanscore table'
481
+
(venv)$ flask db migrate -m 'mean score table'
482
482
(venv)$ flask db upgrade
483
483
```
484
484
485
-
Finally, we need to add a bit of logic on the form to ensure that the data is processed and stored in the new database.
485
+
Finally, we need to add a bit of logic to the form to ensure that the data is processed and stored in the new database.
486
486
487
487
`app/routes.py: Meanscore Form Logic`
488
488
@@ -538,9 +538,9 @@ To display the results, we will need to update the index template.
538
538
539
539
Every time new data is entered, the output will be updated.
540
540
541
-
### Show meanscore chart
541
+
### Show mean score chart
542
542
543
-
A [quick overview of ChartJS](https://www.chartjs.org/docs/latest/) reveals that in order for us to use this library, we need to get the latest version. We will add the line below in our base template to get started.
543
+
A [quick overview of ChartJS](https://www.chartjs.org/docs/latest/) reveals that for us to use this library, we need to get the latest version. We will add the line below in our base template to get started.
544
544
545
545
`app/templates/base.html: Add ChartJS`
546
546
@@ -611,11 +611,11 @@ A simple chart can be created as follows:
611
611
</script>
612
612
```
613
613
614
-
The most important elements for our chart will be the label, and the datasets. The label will be the lesson meanscores in any given term, and the datasets will be the actual mean scores. You can get the graph as a bar chart, a line chart, a pie chart, or a radar chart. We will stick with the basic line chart.
614
+
The most important elements for our chart will be the label and the datasets. The label will be the lesson mean scores in any given term, and the datasets will be the actual mean scores. You can get the graph as a bar chart, a line chart, a pie chart, or a radar chart. We will stick with the basic line chart.
615
615
616
-
As you can see, the values needed for the chart are primarily sourced from a list. We need to figure out a logic to get the data from the database and dislplay it in a simple list. This changes will be applied to the `index()` view function.
616
+
As you can see, the values needed for the chart are primarily sourced from a list. We need to figure out the logic to get the data from the database and display it in a simple list. These changes will be applied to the `index()` view function.
617
617
618
-
`app/routes.py: List meanscores`
618
+
`app/routes.py: List mean scores`
619
619
620
620
```python
621
621
@app.route('/', methods=['GET', 'POST'])
@@ -647,7 +647,7 @@ def index():
647
647
history=history)
648
648
```
649
649
650
-
Here, I have looped through the results stored in the database as filled by a particular teacher. The `teacher.meanscores.all()` method returns a list of all the meanscores for a particular teacher. The result is subsequrently appended to relevant lists. This lists will then be used in the index template to display the results.
650
+
Here, I have looped through the results stored in the database as filled by a particular teacher. The `teacher.meanscores.all()` method returns a list of all the mean scores for a particular teacher. The result is subsequently appended to relevant lists. These lists will then be used in the index template to display the results.
651
651
652
652
`app/templates/index.html: Display Mean Score Per Term`
653
653
@@ -725,7 +725,7 @@ Here, I have looped through the results stored in the database as filled by a pa
725
725
{% endblock %}
726
726
```
727
727
728
-
Notice how I once again loop through individual meanscore lists to retrieve the data we want. Intentionally, we use several dictionaries in our dataset list to display all the meanscores in one graph. Background color and border color are used to differentiate the different datasets.
728
+
Notice how I once again loop through individual mean score lists to retrieve the data we want. Intentionally, we use several dictionaries in our dataset list to display all the mean scores in one graph. Background color and border color are used to differentiate the different datasets.
0 commit comments