Platforms, Python Practice Projects, and Picking up Flask: A blog story
Tags: python, flask, python3, backend
Published: 2019-03-15 17:53:32

---
title: Platforms, Python Practice Projects, and Picking up Flask: A blog story 
published: true
description: My raw, unfiltered notes from a recent dive into Python Flask
tags: python, flask, python3, backend
---

# Platforms, Python Practice Projects, and Picking up Flask: A blog story 

### Warning: raw language used. I have a filthy mouth sometimes. Don't read if you don't like seeing adult language used. I am raw and unfiltered here just like I am in real life! 
### Note to anyone interested in metrics: sh\*t appears 7 times, f\*ck appears twice.

I'm primarily a coder. I have been paid to dev stuff like an iOS app. I have also been paid to fix bugs in big, corporate iOS applications. I've further been paid to write Python scripts and perform pentests on iOS, Android, and Web applications.

There's a world of difference between my skillset and the skillsets of "actual developers". 

Actual devs build things. I'm just good at code. I've built things, but not on the regular; nor with the knowledge of actual devs so much as a Computer Science graduate with no strong direction and simply trying to get back onto his financial feet so he can move the fuck out of his grandma's home and live a much happier life.

I tend to pick up what is needed and/or asked of me. I've become aware of the wide range of tools and roles that a "dev" can occupy. There is a lot out there, and I'll be damned if I am expected to learn garbage toolchains like "React.js" that are completely antithetical to my entire approach of keeping shit minimal.

Recently, I applied to get onto a certain website's platform, and after a casual chat with an engineer, I was asked to build a "small" (to me, it was not small at the time) backend project. You're given some REST endpoints, details on how it should work (though, not enough details), and some sample input/output to drive things. You're given hints about object design. It is up to you to decide how to build it.

So, because I love Python, and wanted to keep things "flexible", I opted to learn something called "Flask".

Below is the largely disorganized personal notes from the project. This is actually how I work when building and learning things. It will come off as a bit "scatterbrained" because this is how I reflect on myself while working. I kinda "chat" back-and-forth with myself via a markdown blog. I don't really "talk" a whole lot to myself, except through text and handwriting. 

For this project, I went in *blog heavy*.

I have changed the names of REST endpoints and removed URLs that hint at the project. I think it would be very "wrong" to expect me NOT to share my research and newly-learned tools and skills with the rest of the world, so I can't be expected of that, so I have done due diligence to hide any "meaningful" details.

I look forward to making future blog posts and to growing my skills as a Python user...programmer, developer, and hacker, and to building things for others so that I can get paid and move into a better environment so that I can be happy and content...well, more so :) 

-----

# xxxxx - Development blog

```
Refresh JWT

POST /some-token-endpoint/refresh
-----
User login

POST /some-token-endpoint
-----
Log out current user

DELETE /some-token-endpoint
-----
Get current user's info

GET /myinfo
-----
Create idea

POST /getideas
-----
Delete idea

DELETE /getideas/:id
-----
Get a page of ideas (1 page = 10 ideas)

GET /getideas
-----
Update idea

PUT /getideas/:id
-----
User Signup

POST /getusers
```

-----

This seems easy enough, just getting started is the hard part.
We can use flask to define each of the API endpoints.
We don't list it in the API, but there is implied a login page at `/`.

Current day and time: **Sat Feb 23 2019 22:55**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **12m30s**
Total time spent: **12m30s**

-----

On each new update/entry to this blog, 
we will prepend with the current day/time, 
delivery date, and current and total time spent

-----

### Useful links for this project

- **deleted to protect project**
- **deleted to protect project**
- [https://jwt.io/introduction/](https://jwt.io/introduction/)
- [https://tools.ietf.org/html/rfc7519](https://tools.ietf.org/html/rfc7519)

-----

Current day and time: **Mon Feb 25 2019 01:33**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **1hr20m**
Total time spent: **1hr32m**

Initial pages created.

```
/
/user_registration
/getusers
/some-token-endpoint
```

Todo soon:

1. Handle user registration
    - database initial creation
    - database update
2. Handle user login
3. Handle user logout

-----

Continuing...

Somehow, my flask isn't linked up to Python anymore, and I have too many versions installed, so I am going to take time to clean up my Python installs by removing the existing ones, and then installing from scratch via brew.

-----

Current day and time: **Mon Feb 25 2019 23:46**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **44m01s**
Total time spent: **1hr44m33m**

I fixed the Flask setup...ate up a bit of time...Python3 as well.

I moved some of the code around, but haven't made much progress.

-----

I need to do some research on how to handle user registration and how to store the data in the database.

We will spend time on that now.

- [https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-ii-templates](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-ii-templates)

So, a good idea is templates.

We should do that now.

-----

Ok, we have managed to transition over to a template page system smoothly and it feels natural to create and manage pages this way.

We still need to create the initial user table and decide on how we are going to store ideas for each user.

```
user table:
user_id - email - password_hash

```

The `user_id` could link to other table content so that we could stash ideas possibly in a blob object or something?

I am not sure what the "best" way to do this is, so I will have to look into that.

Current day and time: **Tue Feb 26 2019 00:14**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **24m08s**
Total time spent: **2hr08m41m**

-----

Installed `flask-wtf`.

Moved stuff around to be more 'proper'.

App structure:

```
xxxxx/
	config.py
	xxxxx.py
	run.sh

	app/
		__init__.py
		routes.py

		templates/
			index.html
			user_registration.html
			users.html
```

Everything still builds and runs fine.

We still need to do user registration, but we are following the tutorial.

Gotta read before we dive in.

Time check.

Current day and time: **Thu Feb 28 2019 02:21**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **28m11s**
Total time spent: **2hr36m52m**

-----

Went a little deeper into building forms.

Actual LoginForm() object.

Current day and time: **Thu Feb 28 2019 02:48**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **25m47s**
Total time spent: **3hr01m39m**

-----

We've progressed a little bit but are now on implementing error messages when the user enters invalid form data.

`LoginForm()` and `RegistrationForm()`.

Taking a break to sleep.

Current day and time: **Thu Feb 28 2019 03:28**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **39m12s**
Total time spent: **3hr40m51m**

-----

```
My xxxxx:

______________________________
usermode: 10
trial: 10
continental: 10
averaje: 10

OK Cancel
```

-----

I FINALLY progressed through the database section of the tutorial:

- [https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database)

I created a `User` and `Idea` 'model' which is basically the table definition.

To fix the db when we change shit:

```
flask db migrate
flask db upgrade 
```

When you make changes, you can comment

```
flask db migrate -m "your comment"
```

-----

Now that we've done that we are ready to start working with logins:

- [https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins)

We have been working hard, and so we should take a break.

Current day and time: **Thu Feb 28 2019 22:06**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **1hr42m57s**
Total time spent: **4hr23m48s**

-----

Current diff:

fixed a bunch of shit as im working through the login tutorial, something broke but it turned out to be these two imports causing errors on the next line down in another file when I try to import something from `__init__.py`.

Current day and time: **Fri Mar 1 2019 02:46**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **1hr29m23s**
Total time spent: **5hr53m11s**

We still need to check out the shell and login from that level.

Ugh shit is broken :( 

YES

WE HAVE LIFTOFF!!!

I have tested the login form and it is working as expected.

This is kind of exciting again!

We can take a break. Need to clear head and prepare for next steps.

Current day and time: **Fri Mar 1 2019 03:29**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **40m48s**
Total time spent: **5hr04m36s**

-----

Next steps:

- User registration *easy*
- Implement the ideas thingy
	- Add an idea
	- Delete an idea
	- Display ideas

-----

Alright
Time to grind this shit out!
User Registration!
We have it working.
You can create a new user immediately and login with them immediately.
The idea list is all that remains.
Let us checkpoint and continue.

Current day and time: **Fri Mar 1 2019 23:36**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **22m48s**
Total time spent: **5hr28m04s**

-----

- Implement the ideas thingy
	- Add an idea
	- Delete an idea
	- Display ideas

-----

On a successful user registration, we should take the user to the "My Ideas" page.

I'm thinking I only actually need to implement the endpoints and not the pages themselves `-_-` whoops!

Ok...

Lets re-arrange stuff.

I'm doing user-registration first.

If I can test this in curl...first I need to fix curl...brew curl...

Ok...

-----

Progress report:

I've got `POST /getusers` reflecting our input data.

We need it to compute a `jwt` token and a `refresh_token` and return it as json.

```
{
	"jwt" : "...",
	"refresh_token" : "..."
}
```

Looks like we can use `Flask-JWT` for that.

https://pythonhosted.org/Flask-JWT/

I've got it installed and kind of rigged into `routes.py` but I am erroring when attempting to authenticate at `/auth`...

```
./run.sh           
 * Serving Flask app "xxxxx.py"
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
[2019-03-02 02:56:46,265] ERROR in app: Exception on /auth [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python3.7/site-packages/flask_jwt/__init__.py", line 115, in _default_auth_request_handler
    username = data.get(current_app.config.get('JWT_AUTH_USERNAME_KEY'), None)
AttributeError: 'NoneType' object has no attribute 'get'
127.0.0.1 - - [02/Mar/2019 02:56:46] "POST /auth HTTP/1.1" 500 -
```

This looks like a possible bug in Flask_JWT but I cannot be 100% sure here...

Because this whole thing is taking me so long, I've asked them for another 4 days to work on it. If I grind hard, I can make it in 4 days.

Thing is, this part is representing a roadblock at the moment...

Even if I were to backtrack/start-from-scratch, re-build everything in bare-minimum Flask, when I get to this part, I will still have to solve how to generate the JWT...

Flask_JWT was supposed to have solved this for me, but even using it is a little challenging...

I am taking a lot of new information in, and this requires some mental background processing on my part.

So, to recap:

```
/getusers is reflecting our json post data now
/auth is crashing for Flask_JWT
```

Current day and time: **Sat Mar 2 2019 03:03**
Delivery date: **Sat Mar 2 2019 06:35 AM**
Current time spent: **1hr50m01s**
Total time spent: **7hr18m05s**

-----

# Wednesday, March 6th, 2019

Updating stats:

Current day and time: **Wed Mar 6 2019 14:29**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr0m0s**
Total time spent: **7hr18m05s**

We have been granted the extension.

Check this out:

We need to restart this from scratch, we overbuilt.

```
User Signup: POST /getusers
Refresh JWT: POST /some-token-endpoint/refresh
User login: POST /some-token-endpoint
Log out: DELETE /some-token-endpoint
Get current user's info: GET /myinfo
Create idea: POST /getideas
Delete idea: DELETE /getideas/:id
Get a page of ideas (1 page = 10 ideas): GET /getideas
Update idea: PUT /getideas/:id
```

For each method available:

1. User signup
2. Refresh JWT
3. User login
4. User logout
5. Get current user's info
6. Create an idea
7. Delete an idea
8. Get a page of ideas
9. Update an idea

We will need to re-create the database.

```
class User:
	name
	email
	password_hash

class Idea:
	user_id 
	text
	usermode
	trial
	continental
	averaje

UserTable
IdeaTable
```

-----

First commit. Hello world.

Current day and time: **Wed Mar 6 2019 14:49**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr8m12s**
Total time spent: **7hr26m17s**

-----

We'll need to create the database and tables again next.

Done.

Current day and time: **Wed Mar 6 2019 15:19**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr23m49s**
Total time spent: **7hr50m06s**

-----

Next up, actually implementing each functionality.
We should logically start with *user registration*.

**User registration**

1. Parse out the inputs
2. Verify inputs
3. Pass verified-inputs to new User object
4. commit User to db
5. Construct JWT and return required tokens

Verifying inputs.

Current day and time: **Wed Mar 6 2019 23:05**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr28m0s**
Total time spent: **8hr18m06s**

-----

First I heard of `flask_jwt`.

- [https://pythonhosted.org/Flask-JWT/](https://pythonhosted.org/Flask-JWT/)

Then I heard of `flask_jwt_extended`.

- [https://flask-jwt-extended.readthedocs.io/en/latest/installation.html](https://flask-jwt-extended.readthedocs.io/en/latest/installation.html)

Then I heard of `flask_jwt_auth`

- [https://realpython.com/token-based-authentication-with-flask/](https://realpython.com/token-based-authentication-with-flask/)

All of these tutorials are massive pains!

-----

OH SHIT
IT FUCKING WORKS
WE ARE GENERATING JWTs!!!

The magic sauce is 

```
retval = {
	'access_token' : create_access_token(identity=u.id),
	'refresh_token' : create_refresh_token(identity=u.id)
}
```

We are actually getting both a JWT and a refresh_token back.

My main question is still how the `refresh_token` works in the first place, that isn't explained in the JWT intro, but I'm still expected to know what that is and how it works when I submit it...

Oh right, there's some decorator like `@refresh_token_required` or something.

This comes from the library `flask_jwt_extended ` so thank you for being my savior here.

We still have all of the other APIs to implement, but `registerUser` is officially DONE!

-----

For each method available:

**1. User signup - DONE**
2. Refresh JWT
3. User login
4. User logout
5. Get current user's info
6. Create an idea
7. Delete an idea
8. Get a page of ideas
9. Update an idea

Current day and time: **Thu Mar 7 2019 23:30**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **1hr31m02s**
Total time spent: **9hr49m08s**

-----

Note to self:

The reason we had so much trouble getting SECRET_KEY in there was that we configure our app from an object defined, called Config. To solve the problem, we had to move SECRET_KEY and JWT_SECRET_KEY into the class definition.

-----

Lets do login.
That should be easy.

```
Mar 8 1:57am: TIL Flask routes expect to return Responses or strings, tuples, etc, but not Dicts!
```

Looks like login is done.

We could spend a few minutes to clean up debugging messages.

**1. User signup - DONE**
**2. User login - DONE**
3. Refresh JWT
4. User logout
5. Get current user's info
6. Create an idea
7. Delete an idea
8. Get a page of ideas
9. Update an idea

Current day and time: **Thu Mar 8 2019 02:13**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr55m11s**
Total time spent: **10hr44m19s**

-----

Refresh token:

```
POST /some-token-endpoint/refresh 
```

```
{'jwt': '', 'refresh_token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTIwMzA5OTcsIm5iZiI6MTU1MjAzMDk5NywianRpIjoiYjBjOGNhNDMtZmQzYi00OWI5LWFjM2YtZmU4ZWU0YjljY2UyIiwiZXhwIjoxNTUyMDMxNTk3LCJpZGVudGl0eSI6MSwidHlwZSI6InJlZnJlc2gifQ.9Akh0uY4ou8DBarkp2lDqS38dlIebqnwk0ss3J5B05s'}
```

```
JWT="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTIwMzA5OTcsIm5iZiI6MTU1MjAzMDk5NywianRpIjoiMWQ5NmU4MGQtOWQyZi00Mjg2LWEyMzItNGYxNDY5NjI5MGYyIiwiZXhwIjoxNTUyMDMxODk3LCJpZGVudGl0eSI6MSwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.HyMCR5mFdcoUi7VUjA3LeiTDGn8Ccsy08Y9Bbc0LL9M"
REFRESH_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTIwMzA5OTcsIm5iZiI6MTU1MjAzMDk5NywianRpIjoiYjBjOGNhNDMtZmQzYi00OWI5LWFjM2YtZmU4ZWU0YjljY2UyIiwiZXhwIjoxNTUyMDMxNTk3LCJpZGVudGl0eSI6MSwidHlwZSI6InJlZnJlc2gifQ.9Akh0uY4ou8DBarkp2lDqS38dlIebqnwk0ss3J5B05s"
./curl_refresh.sh "$JWT" "$REFRESH_TOKEN"

```

Looks like we are successfully returning new JWTs!!!

-----

Note to self to save selves from future trouble: 

```
JWT_HEADER_NAME 
JWT_HEADER_TYPE
```

Lots of Config options in flask-jwt-extended

-----

**1. User signup - DONE**
**2. User login - DONE**
**3. Refresh JWT**
4. User logout
5. Get current user's info
6. Create an idea
7. Delete an idea
8. Get a page of ideas
9. Update an idea

Current day and time: **Fri Mar 9 2019 02:51**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr35m23s**
Total time spent: **11hr19m42s**

-----

Logout

- [https://flask-jwt-extended.readthedocs.io/en/latest/blacklist_and_token_revoking.html](https://flask-jwt-extended.readthedocs.io/en/latest/blacklist_and_token_revoking.html)

Seems like we did it.

-----

**1. User signup - DONE**
**2. User login - DONE**
**3. Refresh JWT**
**4. User logout**
5. Get current user's info
6. Create an idea
7. Delete an idea
8. Get a page of ideas
9. Update an idea

Current day and time: **Fri Mar 8 2019 04:56**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr20m08s**
Total time spent: **11hr39m50s**

-----

Get current user's info
This was super-easy.
We still have to do something about that gravatar url thing.
We can come back to that.

**1. User signup - DONE**
**2. User login - DONE**
**3. Refresh JWT**
**4. User logout**
**5. Get current user's info**
6. Create an idea
7. Delete an idea
8. Get a page of ideas
9. Update an idea

Current day and time: **Fri Mar 8 2019 05:10**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr10m44s**
Total time spent: **11hr50m34s**

-----

Create an idea

So far so good...

**1. User signup - DONE**
**2. User login - DONE**
**3. Refresh JWT**
**4. User logout**
**5. Get current user's info**
**6. Create an idea**
7. Delete an idea
8. Get a page of ideas
9. Update an idea

Current day and time: **Fri Mar 8 2019 06:08**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr51m00s**
Total time spent: **12hr41m34s**

-----

Delete an idea

- Verify the idea id is valid & exists
- Remove the idea from the db

Crap...

How do I make dynamic routes that have IDs in them in Flask???

- [https://stackoverflow.com/questions/15117416/capture-arbitrary-path-in-flask-route](https://stackoverflow.com/questions/15117416/capture-arbitrary-path-in-flask-route)

Looking good.

I'm fucking hungry.

**1. User signup - DONE**
**2. User login - DONE**
**3. Refresh JWT**
**4. User logout**
**5. Get current user's info**
**6. Create an idea**
**7. Delete an idea**
8. Get a page of ideas
9. Update an idea

Current day and time: **Fri Mar 8 2019 06:25**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr15m00s**
Total time spent: **12hr56m34s**

-----

We took a couple days off but

# Get a page of ideas

first, log in, then pass the JWT to /getideas

```
{'jwt': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTIyMzkzMDMsIm5iZiI6MTU1MjIzOTMwMywianRpIjoiYzc3NGIyZWUtZTVmZi00ZTUzLWI2ZjktYjAyNDkxZWI1ZDI4IiwiZXhwIjoxNTUyMjQwMjAzLCJpZGVudGl0eSI6MSwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.NJDvj57c_hxqoqt5N_0zPYFHqxJOOjhMdAaQ_jIIcR4', 'refresh_token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTIyMzkzMDMsIm5iZiI6MTU1MjIzOTMwMywianRpIjoiNzc5ZDYzZTctZjM0Ni00MjQ1LWFlMTEtODkwMDM0OGQ3OWYyIiwiZXhwIjoxNTUyMjM5OTAzLCJpZGVudGl0eSI6MSwidHlwZSI6InJlZnJlc2gifQ.xX9a60sgVZ01OHjFwSPFF8EV-E_oS1YBfLiglGECYL4'}
```

We are trying to get our Ideas back as json.

```
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Idea is not JSON serializable
```

So, how do we make an object in Python JSON serializable?

- [https://stackoverflow.com/questions/21411497/flask-jsonify-a-list-of-objects](https://stackoverflow.com/questions/21411497/flask-jsonify-a-list-of-objects)

One workaround I got working is to call .serialize() once it is defined.

```
retval = jsonify([idea.serialize() for idea in idea_page.items])
```

I think that completes that!

**1. User signup - DONE**
**2. User login - DONE**
**3. Refresh JWT**
**4. User logout**
**5. Get current user's info**
**6. Create an idea**
**7. Delete an idea**
**8. Get a page of ideas**
9. Update an idea

Current day and time: **Sun Mar 10 2019 13:54**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr20m00s**
Total time spent: **13hr16m34s**

-----

# Update an idea

DONE!!!

Current day and time: **Sun Mar 10 2019 14:53**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr17m30s**
Total time spent: **13hr34m04s**

-----

Ok, that seems to be everything.

We did omit the gravatar url thing.

We don't have enough time to submit now, BUT we are mostly done.

# What you need to do:

1. Create a private Github or Bitbucket repository for your final code submission
2. Add our Github or Bitbucket account to your repository
3. Deploy your code to an online version
4. Email us with the following information:
	- Email subject:
	- Small Back End Project: xxxxx
	- Your name
	- Your repository link
	- An API server link where we can access and test

-----

# Gravatar URL

```
https://en.gravatar.com/site/implement/images/
```

1. Calculate email hash
2. URL = https://www.gravatar.com/avatar/HASH

```
https://en.gravatar.com/site/implement/hash/
```

```
echo md5( strtolower( trim( "MyEmailAddress@example.com " ) ) );
```

Lets convert that to Python.

```
python3

import hashlib
email = 'youremail@example.com'
a = hashlib.md5(email.lower().encode())
a.hexdigest()
```

That gets what we want.

```
gravURL = 'https://www.gravatar.com/avatar/' + str(a.hexdigest())
```

We need this to happen at user registration.

This is in `routes.py`.

In order to do this, we need to update the `User` definition in the `models.py` file.

Or, could we return it calculated every time?

Maybe we can avoid updating the model.

Note to self: check the type before enforcing cast. Actually use your brain when writing code. I know we need to get shit done.

I anticipated this by having the field in `getCurrentUserInfo`.

Problem solved.

Submission time.

-----

1. Create private github

sidenote: green tea time

done

-----

2. Deploy our code to an online version

- [http://flask.pocoo.org/docs/1.0/deploying/](http://flask.pocoo.org/docs/1.0/deploying/)

We are gonna try out the `localtunnel` method, it seems the least hassle. I don't feel like learning Heroku or whatever tonight.

Modern localtunnel:

- [https://localtunnel.github.io/www/](https://localtunnel.github.io/www/)

Command is `lt` now.

Crap...just realized that I am going to have to install a lot of dependencies `-_-;...`

```
sudo apt install python3-flask -y 
python3-flask-sqlalchemy
python3-flask-migrate
python3-flask-jwt-extended

sudo apt install python3-pip
pip install setuptools
pip install flask-jwt-extended
```

Ok, got it running on my server.

Looks like we have to do this instead:

- [http://flask.pocoo.org/docs/1.0/deploying/mod_wsgi/](http://flask.pocoo.org/docs/1.0/deploying/mod_wsgi/)

-----

I am very tired.
We will do this in the morning on a brand-new server.

Current day and time: **Wed Mar 13 2019 4:39**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **1hr40m41s**
Total time spent: **15hr14m04s**

-----

Back at it at night lol. ffff

Spinning up a server to host this thing on.

Goin apache mod_wsgi route.

First things first secure the server.

Done.

Next, install dependencies.

```
sudo apt-get install python3-pip \
python3-flask \
python3-flask-sqlalchemy \
python3-flask-migrate -y

pip3 install setuptools
pip3 install flask-jwt-extended
```

Done.

Now, all that is left is to move the app code into an appropriate directory and begin the wsgi setup.

Current day and time: **Wed Mar 13 2019 22:31**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **0hr20m00s**
Total time spent: **15hr34m04s**

-----

This is way too hard...
I've gone thru all the steps but keep encountering 500 errors when I try to serve it up.
I'm throwing in the towel. 
Wait...
ITS SERVING!!!
WE DID IT!!!

- [https://www.bogotobogo.com/python/Flask/Python_Flask_HelloWorld_App_with_Apache_WSGI_Ubuntu14.php](https://www.bogotobogo.com/python/Flask/Python_Flask_HelloWorld_App_with_Apache_WSGI_Ubuntu14.php)
- [https://stackoverflow.com/questions/19344252/how-to-install-configure-mod-wsgi-for-py3](https://stackoverflow.com/questions/19344252/how-to-install-configure-mod-wsgi-for-py3)
- [https://www.linode.com/docs/websites/hosting-a-website-ubuntu-18-04/](https://www.linode.com/docs/websites/hosting-a-website-ubuntu-18-04/)
- [https://modwsgi.readthedocs.io/en/develop/installation.html](https://modwsgi.readthedocs.io/en/develop/installation.html)
- [http://flask.pocoo.org/docs/1.0/deploying/mod_wsgi/](http://flask.pocoo.org/docs/1.0/deploying/mod_wsgi/)

-----

FINALLY SUBMITTED EVERYTHING

FINAL TIME LOG!!!

Current day and time: **Thu Mar 14 2019 2:59**
Delivery date: **Fri Mar 8 2019 11:59 PM**
Current time spent: **1hr02m00s**
Total time spent: **16hr36m04s**

Over the course of like 2-3 weeks, managed to squeeze out 16 hours worth of extra "time" that was spent learning the "Flask" framework in a real crashcourse-like manner.

However.

I am now capable of developing and deploying web apps via Flask and mod_wsgi with JWT token login.

There's a lot to do in formatting this blog of materials, because it is really chaotic/scatterbrained, but I think a lot of people will find this useful and entertaining.

-----

**All URLs in this blog**

- [https://jwt.io/introduction/](https://jwt.io/introduction/)
- [https://tools.ietf.org/html/rfc7519](https://tools.ietf.org/html/rfc7519)
- [https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-ii-templates](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-ii-templates)
- [https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database)
- [https://pythonhosted.org/Flask-JWT/](https://pythonhosted.org/Flask-JWT/)
- [https://flask-jwt-extended.readthedocs.io/en/latest/installation.html](https://flask-jwt-extended.readthedocs.io/en/latest/installation.html)
- [https://realpython.com/token-based-authentication-with-flask/](https://realpython.com/token-based-authentication-with-flask/)
- [https://flask-jwt-extended.readthedocs.io/en/latest/blacklist_and_token_revoking.html](https://flask-jwt-extended.readthedocs.io/en/latest/blacklist_and_token_revoking.html)
- [https://stackoverflow.com/questions/15117416/capture-arbitrary-path-in-flask-route](https://stackoverflow.com/questions/15117416/capture-arbitrary-path-in-flask-route)
- [https://stackoverflow.com/questions/21411497/flask-jsonify-a-list-of-objects](https://stackoverflow.com/questions/21411497/flask-jsonify-a-list-of-objects)
- [http://flask.pocoo.org/docs/1.0/deploying/](http://flask.pocoo.org/docs/1.0/deploying/)
- [https://localtunnel.github.io/www/](https://localtunnel.github.io/www/)
- [http://flask.pocoo.org/docs/1.0/deploying/mod_wsgi/](http://flask.pocoo.org/docs/1.0/deploying/mod_wsgi/)
- [https://www.bogotobogo.com/python/Flask/Python_Flask_HelloWorld_App_with_Apache_WSGI_Ubuntu14.php](https://www.bogotobogo.com/python/Flask/Python_Flask_HelloWorld_App_with_Apache_WSGI_Ubuntu14.php)
- [https://stackoverflow.com/questions/19344252/how-to-install-configure-mod-wsgi-for-py3](https://stackoverflow.com/questions/19344252/how-to-install-configure-mod-wsgi-for-py3)
- [https://www.linode.com/docs/websites/hosting-a-website-ubuntu-18-04/](https://www.linode.com/docs/websites/hosting-a-website-ubuntu-18-04/)
- [https://modwsgi.readthedocs.io/en/develop/installation.html](https://modwsgi.readthedocs.io/en/develop/installation.html)
- [http://flask.pocoo.org/docs/1.0/deploying/mod_wsgi/](http://flask.pocoo.org/docs/1.0/deploying/mod_wsgi/)

-----

# [If you need a Computer Science tutor, code reviewer, or just someone to pair program with, hit me up](https://codementor.io/mikebell66)