Game Python Postgres and Player Registration

Introduction

In this part, we continue building a game with Python and Postgres with Player Registration as part 9 of a multi-part series of lessons where the final result is a graphical top-down-view videogame, where the purpose is to consume powerups while avoiding “intelligent” moving enemy monsters. We chose to use the Arcade library for Python due to its game-related features. We chose Postgres for reading and writing screen and object (player, enemies, obstacles, and power-ups) data, and loading and saving games in progress. In this lesson we will use Postgres again to give users an opportunity to register, creating their username, password, and user id. In future articles we will add player login, multi-player, and a screen editor.

Prerequisites

See part 1 through 8, where we learned how to draw a screen, create tables in Postgres for storing and reading screen data and screen objects as Sprites, reading keys to control player movement, added random movements to the monsters, collision detection, intelligent player tracking for the monsters, sound effects, saving the game, and loading saved games from Postgres. You can start here: Build game with Python and draw a screen.

We are going to depart from the structure of parts in this series in order to create a new application for registration that you can later tie to the main game we created so far.

Overview

We’ll start by building an HTML form where the user can type in their user name (email address) and password. Then we will write a Python application to use the Request and Render_template functions to send the user to that dyanmic HTML form and retrieve data the user/player submitted. Finally, we will hash the password (for security) and add it to a row in our PostgreSQL database.

Let’s now go over the basics of how the “request” and “render_template” functions work. For example, build an HTML form for the player to enter an email and password, receive (get) the data they submitted, hash the password, and then insert it into a table.

Python request from form

The first function we will study is the “request” function, which is used to pull data that was submitted either by form “post” or by a querystring “get”.

Python Request Syntax

1
2
value = request.args.get(field, default val) # querystring, which is GET in HTML.
value = request.form.get(field, default val) # post, which is POST in HTML forms.

Analysis

  • field: This determines the field name; how it was named in your querystring or on the form.
  • default val: If no data was sent by the user for that field, this is the value that will go into your variable. For strings, we might put an empty string here, like “”.

Python Request Examples

Some examples of how the syntax above could look in real world use. We’ll leave out “get” as it has no relevance to our current project:

1
2
t_player_email = request.form.get("t_player_email", "")
t_player_password = request.form.get("t_player_password", "")

Analysis

  • t_player_email: This gets the value the user put into the HTML field called “t_player_email” and places that value in the local Python text variable also named “t_player_email”.

Flask render template

Flask’s Render_Template() function displays an HTML page for the user, which can be filled with dynamic content we control with parameters in the function. Note: Please don’t confuse it with the redirect function, which sends the user away without waiting for a return.

Render Template Example

1
2
3
from flask import Flask
from flask import render_template
return render_template("templates/register.html", t_msg = "A message to display on the page")

Analysis

  • t_msg: The contents of “t_msg” will travel, along with the player, to register.html, an html template we’ll create below, that is able to receive and use t_msg. Note: instead of “t_msg”, you can call your variable whatever you want and even send more parameters.

Hash in Python

A Hash, known also as a checksum, is a string type value which is the result of calculation of a Hash Algorithm. The algorithm we’ll use here is called SHA3-512. One use of Hashing is to determine the integrity of different kinds of data; in this case, a password. The determination of integrity comes in the next part of this series where someone attempts to sign in and we compare a hash of what they typed with the hash stored in Postgres.

Syntax of HASHLIB

1
2
    t_after_hash = hashlib.sha3_512(t_input.encode())
    t_player_password = t_after_hash.hexdigest()

Flask HTML template

Below is the near minimum of what we need for a registration screen. This will render nearly identical on all web browsers. Name this file “register.html” and save it in a folder called “templates”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<html>
    <head>
        <link rel="shortcut icon" href="favicon.ico">
        <title>Flask Hash Password for Postgres</title>
    </head>
<body>
<!-- The "t_msg" below is part of why we call this page a template -->
<!-- It is a benefit of this page being "dynamic" because the server can -->
<!-- fill in at the spot where you see {{t_msg}} with data you sent when we used -->
<!-- render_template("register.html", t_msg = "A message to go in the h1 tag") -->
<h1>{{t_msg}}</h1>
<!-- div to encapsulate the input form -->
<div>
    <!-- Set up form and the file to process user input -->
    <!-- method=post sends the data as a post instead of a get. -->
    <form id='frmTest' name='frmTest' action='' method='post' onsubmit='return true;'>

    <!-- Input box for the player to enter their email address -->
    <!-- Input tag has a 'name' parameter of 't_player_email'. -->
    <!-- So our request function back in Python can use this -->
    <!--   to get data from this field. -->
    <div class="form-row">
    User Name: <input type="text"  name="t_player_email">
    </div>

    <div class="form-row">
    Password: <input type="text"  name="t_player_password">
    </div>

    <!-- button for the player to submit the form -->
    <div>
      <input type="submit" name="btn_submit_add_player" value='Register'>
    </div>

    <!-- Close form -->
    </form>
<!-- Close the container div -->
</div>
<!-- Close the body of the HTML document -->
</body>
</html>

Request with Flask

Let’s begin by using Python’s render_template() function to send the user to the HTML page we built above and then retrieve the data submitted by the user using the request() function.

1
2
3
4
5
@app.route("/register", methods=["POST","GET"])
def register():
    return RENDER_TEMPLATE("register.html", t_msg = "Register Here")
    t_player_email = REQUEST.form.get("t_player_email", "")
    t_player_password = REQUEST.form.get("t_player_password", "")

Hash user input

Now we’ll do the actual hashing of the user’s input.

1
2
    t_value_hashed = hashlib.sha3_512(t_player_password.encode())
    t_player_password = t_value_hashed.hexdigest()

Analysis

  • We start with the value a new player put into “t_player_password”, use the hashlib function to hash it, and store the resulting hashed value in a variable we called “t_value_hashed”.
  • We then use the hexdigest function to convert the bytes returned by hashlib() into hex type data.

Insert with Psycopg2

1
2
3
4
5
6
7
8
9
10
11
s = ""
s += "INSERT INTO tbl_players "
s += "("
s += " t_player_email"
s += ",t_player_password"
s += ") VALUES ("
s += " '(%t_player_email)'"
s += ",'(%t_player_password)'"
s += ")"
try:
    db_cursor.execute(s, [t_player_email, t_player_password])

Analysis: Here we are using SQL to build a parameterized query, where the two parameters are t_player_email and t_player_password, both to be INSERTed into our tbl_players in Postgres.

Full Source Code in Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from flask import Flask
from flask import render_template
from flask import request
import hashlib
import psycopg2

app = Flask(__name__)
@app.route("/", methods=["POST","GET"])

t_host = "database host address"
t_port = "5432"
t_dbname = "database name"
t_user = "database user name"
t_pw = "password"
db_conn = psycopg2.connect(host=t_host, port=t_port, dbname=t_dbname, user=t_user, password=t_pw)
db_cursor = db_conn.cursor()

def register():
    return render_template("register.html", t_msg = "Register to get save game capability")
    t_player_email = request.form.get("t_player_email", "")
    t_player_password = request.form.get("t_player_password", "")

    # Check for user name field is empty
    if t_player_email == "":
        t_msg = "Empty field: Fill in an email address."
        # Send user back to the dynamic html page (template), with a message
        return render_template("register.html", t_msg = t_msg)

    if t_player_password == "":
        t_msg = "Please fill in a password"
        return render_template("register.html", t_msg = t_msg)

    # Hash the password they entered into an encrypted hex text
    t_value_hashed = hashlib.sha256(t_player_password.encode())
    t_player_password = t_value_hashed.hexdigest()

    s = ""
    s += "INSERT INTO tbl_players "
    s += "("
    s += " t_player_email"
    s += ",t_player_password"
    s += ") VALUES ("
    s += " '(%t_player_email)'"
    s += ",'(%t_player_password)'"
    s += ")"
    try:
        db_cursor.execute(s, [t_player_email, t_player_password])
        db_conn.commit()
    except psycopg2.Error as e:
        t_msg = "SQL error: " + e + "/n SQL: " + s
        return render_template("register.html", t_msg = t_msg)
    db_cursor.close()

Conclusion

In this part, we continued creating a game with Python and Postgres with User Registration as part 9 of a multi-part series of lessons where the final result is a graphical top-down-view videogame, where the purpose is to consume powerups while avoiding enemies. We imported the Arcade framework for Python due to its many useful game-related features. We chose Postgres for reading and writing screen, player, enemies, obstacles, sounds, and power-up data, and loading and saving games in progress. In this lesson we used render_template, HTML, and Postgres to give players an opportunity to register, using their email address and password, giving them a user id. In future articles we will add player login, multi-player, and a screen editor.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.