Create a CRUD Restful Service API using Flask + MySQL

  1. SETTING UP ENVIRONMENT on Ubuntu20:
    (base) ubuntu@ubunu2004:~$ mkdir flaskdbexample
    (base) ubuntu@ubunu2004:~$ cd flaskdbexample
    (base) ubuntu@ubunu2004:~/flaskdbexample$ sudo apt install python3-virtualenv
    (base) ubuntu@ubunu2004:~/flaskdbexample$ virtualenv venv
    created virtual environment CPython3.8.2.final.0-64 in 805ms

(base) ubuntu@ubunu2004:~/flaskdbexample/venv/bin$ source ./activate
(venv) (base) ubuntu@ubunu2004:~$ cd flaskdbexample/
(venv) (base) ubuntu@ubunu2004:~/flaskdbexample$ pip install flask flask-sqlalchemy
(venv) (base) ubuntu@ubunu2004:~/flaskdbexample$ pip install pymysql
(venv) (base) ubuntu@ubunu2004:~/flaskdbexample$ pip install marshmallow_sqlalchemy

  1. Complete Code
    (venv) (base) ubuntu@ubunu2004:~/flaskdbexample$ vi app.py
from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
from marshmallow_sqlalchemy import ModelSchema
from marshmallow import fields
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://monty:password@192.168.0.43/EmployeeDB'
db = SQLAlchemy(app)
###Models####
class Product(db.Model):
__tablename__ = "products"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(20))
productDescription = db.Column(db.String(100))
productBrand = db.Column(db.String(20))
price = db.Column(db.Integer)
def create(self):
db.session.add(self)
db.session.commit()
return self
def __init__(self,title,productDescription,productBrand,price):
self.title = title
self.productDescription = productDescription
self.productBrand = productBrand
self.price = price
def __repr__(self):
return '' % self.id
db.create_all()
class ProductSchema(ModelSchema):
class Meta(ModelSchema.Meta):
model = Product
sqla_session = db.session
id = fields.Number(dump_only=True)
title = fields.String(required=True)
productDescription = fields.String(required=True)
productBrand = fields.String(required=True)
price = fields.Number(required=True)
@app.route('/products', methods = ['GET'])
def index():
get_products = Product.query.all()
product_schema = ProductSchema(many=True)
products = product_schema.dump(get_products)
return make_response(jsonify({"product": products}))
@app.route('/products/<id>', methods = ['GET'])
def get_product_by_id(id):
get_product = Product.query.get(id)
product_schema = ProductSchema()
product = product_schema.dump(get_product)
return make_response(jsonify({"product": product}))
@app.route('/products/<id>', methods = ['PUT'])
def update_product_by_id(id):
data = request.get_json()
get_product = Product.query.get(id)
if data.get('title'):
get_product.title = data['title']
if data.get('productDescription'):
get_product.productDescription = data['productDescription']
if data.get('productBrand'):
get_product.productBrand = data['productBrand']
if data.get('price'):
get_product.price= data['price']
db.session.add(get_product)
db.session.commit()
product_schema = ProductSchema(only=['id', 'title', 'productDescription','productBrand','price'])
product = product_schema.dump(get_product)
return make_response(jsonify({"product": product}))
@app.route('/products/<id>', methods = ['DELETE'])
def delete_product_by_id(id):
get_product = Product.query.get(id)
db.session.delete(get_product)
db.session.commit()
return make_response("",204)
@app.route('/products', methods = ['POST'])
def create_product():
data = request.get_json()
product_schema = ProductSchema()
product = product_schema.load(data)
result = product_schema.dump(product.create())
return make_response(jsonify({"product": result}),200)
if __name__ == "__main__":
app.run(debug=True)
from flask import Flask, request, jsonify, make_response from flask_sqlalchemy import SQLAlchemy from marshmallow_sqlalchemy import ModelSchema from marshmallow import fields app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://monty:password@192.168.0.43/EmployeeDB' db = SQLAlchemy(app) ###Models#### class Product(db.Model): __tablename__ = "products" id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(20)) productDescription = db.Column(db.String(100)) productBrand = db.Column(db.String(20)) price = db.Column(db.Integer) def create(self): db.session.add(self) db.session.commit() return self def __init__(self,title,productDescription,productBrand,price): self.title = title self.productDescription = productDescription self.productBrand = productBrand self.price = price def __repr__(self): return '' % self.id db.create_all() class ProductSchema(ModelSchema): class Meta(ModelSchema.Meta): model = Product sqla_session = db.session id = fields.Number(dump_only=True) title = fields.String(required=True) productDescription = fields.String(required=True) productBrand = fields.String(required=True) price = fields.Number(required=True) @app.route('/products', methods = ['GET']) def index(): get_products = Product.query.all() product_schema = ProductSchema(many=True) products = product_schema.dump(get_products) return make_response(jsonify({"product": products})) @app.route('/products/<id>', methods = ['GET']) def get_product_by_id(id): get_product = Product.query.get(id) product_schema = ProductSchema() product = product_schema.dump(get_product) return make_response(jsonify({"product": product})) @app.route('/products/<id>', methods = ['PUT']) def update_product_by_id(id): data = request.get_json() get_product = Product.query.get(id) if data.get('title'): get_product.title = data['title'] if data.get('productDescription'): get_product.productDescription = data['productDescription'] if data.get('productBrand'): get_product.productBrand = data['productBrand'] if data.get('price'): get_product.price= data['price'] db.session.add(get_product) db.session.commit() product_schema = ProductSchema(only=['id', 'title', 'productDescription','productBrand','price']) product = product_schema.dump(get_product) return make_response(jsonify({"product": product})) @app.route('/products/<id>', methods = ['DELETE']) def delete_product_by_id(id): get_product = Product.query.get(id) db.session.delete(get_product) db.session.commit() return make_response("",204) @app.route('/products', methods = ['POST']) def create_product(): data = request.get_json() product_schema = ProductSchema() product = product_schema.load(data) result = product_schema.dump(product.create()) return make_response(jsonify({"product": result}),200) if __name__ == "__main__": app.run(debug=True)
from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
from marshmallow_sqlalchemy import ModelSchema
from marshmallow import fields
app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://monty:password@192.168.0.43/EmployeeDB'
db = SQLAlchemy(app)

###Models####
class Product(db.Model):
    __tablename__ = "products"
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(20))
    productDescription = db.Column(db.String(100))
    productBrand = db.Column(db.String(20))
    price = db.Column(db.Integer)

    def create(self):
      db.session.add(self)
      db.session.commit()
      return self
    def __init__(self,title,productDescription,productBrand,price):
        self.title = title
        self.productDescription = productDescription
        self.productBrand = productBrand
        self.price = price
    def __repr__(self):
        return '' % self.id
db.create_all()
class ProductSchema(ModelSchema):
    class Meta(ModelSchema.Meta):
        model = Product
        sqla_session = db.session
    id = fields.Number(dump_only=True)
    title = fields.String(required=True)
    productDescription = fields.String(required=True)
    productBrand = fields.String(required=True)
    price = fields.Number(required=True)

@app.route('/products', methods = ['GET'])
def index():
    get_products = Product.query.all()
    product_schema = ProductSchema(many=True)
    products = product_schema.dump(get_products)
    return make_response(jsonify({"product": products}))
@app.route('/products/<id>', methods = ['GET'])
def get_product_by_id(id):
    get_product = Product.query.get(id)
    product_schema = ProductSchema()
    product = product_schema.dump(get_product)
    return make_response(jsonify({"product": product}))
@app.route('/products/<id>', methods = ['PUT'])
def update_product_by_id(id):
    data = request.get_json()
    get_product = Product.query.get(id)
    if data.get('title'):
        get_product.title = data['title']
    if data.get('productDescription'):
        get_product.productDescription = data['productDescription']
    if data.get('productBrand'):
        get_product.productBrand = data['productBrand']
    if data.get('price'):
        get_product.price= data['price']    
    db.session.add(get_product)
    db.session.commit()
    product_schema = ProductSchema(only=['id', 'title', 'productDescription','productBrand','price'])
    product = product_schema.dump(get_product)
    return make_response(jsonify({"product": product}))
@app.route('/products/<id>', methods = ['DELETE'])
def delete_product_by_id(id):
    get_product = Product.query.get(id)
    db.session.delete(get_product)
    db.session.commit()
    return make_response("",204)
@app.route('/products', methods = ['POST'])
def create_product():
    data = request.get_json()
    product_schema = ProductSchema()
    product = product_schema.load(data)
    result = product_schema.dump(product.create())
    return make_response(jsonify({"product": result}),200)
if __name__ == "__main__":
    app.run(debug=True)

3. testing the API
(venv) (base) ubuntu@ubunu2004:~/flaskdbexample$ flask run –host=0.0.0.0
A. POST data to http://ubunu2004:5000/products
{
“title” : “Python coding”,
“productDescription” : “ebook”,
“productBrand” : “SUN”,
“price” : “5000”
}

B. GET data

simple flask web app to INSERT record into MySQL

1. install flask and flask-mysqldb
pip install flask
pip install flask_mysqldb
2. mkdir flask_mysql and subfolder templates
we only need two files:
app.py and templates/index.html
3. make app works without DB:
index.html

<HTML>
<BODY bgcolor="cyan">
<form method="POST" action="">
    <center>
    <H1>Enter your details </H1> <br>
    First Name <input type = "text" name= "fname" /> <br>
    Last Name <input type = "text" name = "lname" /> <br>
    <input type = "submit">
    </center>
</form>
</BODY>
</HTML>

app.py

from flask import Flask, render_template
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
    return render_template('index.html')
if __name__ == '__main__':
    app.run()

4. test app.py, you will get the web page as below:

5. then we can create table in MySQL:
CREATE TABLE MyUsers ( firstname VARCHAR(30) NOT NULL, lastname VARCHAR(30) NOT NULL);
update app.py:

from flask import Flask, render_template, request
from flask_mysqldb import MySQL
app = Flask(__name__)
app.config['MYSQL_HOST'] = '192.168.0.43'
app.config['MYSQL_USER'] = 'monty'
app.config['MYSQL_PASSWORD'] = 'somIUpass#98'
app.config['MYSQL_DB'] = 'EmployeeDB'
mysql = MySQL(app)
@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == "POST":
        details = request.form
        firstName = details['fname']
        lastName = details['lname']
        cur = mysql.connection.cursor()
        cur.execute("INSERT INTO MyUsers(firstName, lastName) VALUES (%s, %s)", (firstName, lastName))
        mysql.connection.commit()
        cur.close()
        return 'success'
    return render_template('index.html')
if __name__ == '__main__':
    app.run()

6. run it again, you can submit info into DB on http://127.0.0.1:5000/

python code debug

  1. python pdb debug
    we have sample code read_redis.py:
    import json
    import redis
    client = redis.Redis()
    data = client.lpop(‘info’)
    run it with command: python -i read_redis.py.
    once you got "exception occurred", start pdb debuggin as below:
>>> import pdb
>>> pdb.pm()
> c:\python\lib\site-packages\redis\connection.py(563)connect()
-> raise ConnectionError(self._error_message(e))
(Pdb) data
*** NameError: name 'data' is not defined
  1. VS CODE debug
    you can press F5 to start debugging python in VS CODE as below:

Bash String Manipulation

1. Identify String Length inside Bash Shell Script
${#string}
2. Extract a Substring from a Variable inside Bash Shell Script
${string:position:length}
3. Shortest Substring Match
Following syntax deletes the shortest match of $substring from front of $string
${string#substring}
Following syntax deletes the shortest match of $substring from back of $string
${string%substring}
Following sample shell script explains the above two shortest substring match concepts.
$ cat shortest.sh
filename="bash.string.txt"
echo ${filename#.}
echo ${filename%.
}
$ ./shortest.sh
After deletion of shortest match from front: string.txt
After deletion of shortest match from back: bash.string
4. Longest Substring Match
Following syntax deletes the longest match of $substring from front of $string
${string##substring}
Following syntax deletes the longest match of $substring from back of $string
${string%%substring}
Following sample shell script explains the above two longest substring match concepts.
$ cat longest.sh
filename="bash.string.txt"
echo "After deletion of longest match from front:" ${filename##.}
echo "After deletion of longest match from back:" ${filename%%.
}
$ ./longest.sh
After deletion of longest match from front: txt
After deletion of longest match from back: bash
5. Find and Replace String Values inside Bash Shell Script
Replace only first match
${string/pattern/replacement}
It matches the pattern in the variable $string, and replace only the first match of the pattern with the replacement.
$ cat firstmatch.sh
filename="bash.string.txt"
echo "After Replacement:" ${filename/str./operations.}
$ ./firstmatch.sh
After Replacement: bash.operations.txt
Replace all the matches
${string//pattern/replacement}
It replaces all the matches of pattern with replacement.
$ cat allmatch.sh
filename="Path of the bash is /bin/bash"
echo "After Replacement:" ${filename//bash/sh}
$ ./allmatch.sh
After Replacement: Path of the sh is /bin/sh
Replace beginning and end
${string/#pattern/replacement}
Following syntax replaces with the replacement string, only when the pattern matches beginning of the $string.
${string/%pattern/replacement}
Following syntax replaces with the replacement string, only when the pattern matches at the end of the given $string.
$ cat posmatch.sh
filename="/root/admin/monitoring/process.sh"
echo "Replaced at the beginning:" ${filename/#\/root/\/tmp}
echo "Replaced at the end": ${filename/%.
/.ksh}
$ ./posmatch.sh
Replaced at the beginning: /tmp/admin/monitoring/process.sh
Replaced at the end: /root/admin/monitoring/process.ksh
6. Check if Two Strings are Equal
VAR1="Linuxize"
VAR2="Linuxize"
if [ "$VAR1" = "$VAR2" ]; then
echo "Strings are equal."
else
echo "Strings are not equal."
fi
7. Check if a String Contains a Substring
VAR=’GNU/Linux is an operating system’
if [[ $VAR == "Linux" ]]; then
echo "It’s there."
fi
Copy
8. Check if a String is Empty
VAR=”
if [[ -z $VAR ]]; then
echo "String is empty."
fi

Bash scripting Tutorial

Writing Readable Bash Scripts

#!/bin/bash
set -u
set -e
set -o pipefail
function is-even {
if [[ $(($1 % 2)) -gt 0 ]]
then return 1
else return 0
fi
}
function epoch {
date +"%s"
}
if is-even $(epoch)
then echo "Even epoch"
else echo "Odd epoch"
fi
===============================================
set -u will cause the script to fail if you’re trying to reference a variable that hasn’t been set. The default behavior will just evaluate the variable to the empty string.
set -e will cause the script to exit immediately if a command fails. The default behavior is to simply continue executing the remaining commands in the script.
set -o pipefail will cause a pipeline to fail if any of the commands in the pipeline failed. The default behavior is to only use the exit status of the last command.
#!/bin/bash set -u set -e set -o pipefail function is-even { if [[ $(($1 % 2)) -gt 0 ]] then return 1 else return 0 fi } function epoch { date +"%s" } if is-even $(epoch) then echo "Even epoch" else echo "Odd epoch" fi =============================================== set -u will cause the script to fail if you’re trying to reference a variable that hasn’t been set. The default behavior will just evaluate the variable to the empty string. set -e will cause the script to exit immediately if a command fails. The default behavior is to simply continue executing the remaining commands in the script. set -o pipefail will cause a pipeline to fail if any of the commands in the pipeline failed. The default behavior is to only use the exit status of the last command.
#!/bin/bash

set -u
set -e
set -o pipefail

function is-even {
    if [[ $(($1 % 2)) -gt 0 ]]
    then return 1
    else return 0
    fi
}

function epoch {
    date +"%s"
}

if is-even $(epoch)
then echo "Even epoch"
else echo "Odd epoch"
fi

===============================================
set -u will cause the script to fail if you’re trying to reference a variable that hasn’t been set. The default behavior will just evaluate the variable to the empty string.

set -e will cause the script to exit immediately if a command fails. The default behavior is to simply continue executing the remaining commands in the script.

set -o pipefail will cause a pipeline to fail if any of the commands in the pipeline failed. The default behavior is to only use the exit status of the last command.

Passing arguments to the bash script

#!/bin/bash
# use predefined variables to access passed arguments
#echo arguments to the shell
echo $1 $2 $3 ' -> echo $1 $2 $3'
# We can also store arguments from bash command line in special array
args=("$@")
#echo arguments to the shell
echo ${args[0]} ${args[1]} ${args[2]} ' -> args=("$@"); echo ${args[0]} ${args[1]} ${args[2]}'
#use $@ to print out all arguments at once
echo $@ ' -> echo $@'
# use $# variable to print out
# number of arguments passed to the bash script
echo Number of arguments passed: $# ' -> echo Number of arguments passed: $#'
#!/bin/bash # use predefined variables to access passed arguments #echo arguments to the shell echo $1 $2 $3 ' -> echo $1 $2 $3' # We can also store arguments from bash command line in special array args=("$@") #echo arguments to the shell echo ${args[0]} ${args[1]} ${args[2]} ' -> args=("$@"); echo ${args[0]} ${args[1]} ${args[2]}' #use $@ to print out all arguments at once echo $@ ' -> echo $@' # use $# variable to print out # number of arguments passed to the bash script echo Number of arguments passed: $# ' -> echo Number of arguments passed: $#'
#!/bin/bash
# use predefined variables to access passed arguments
#echo arguments to the shell
echo $1 $2 $3 ' -> echo $1 $2 $3'

# We can also store arguments from bash command line in special array
args=("$@")
#echo arguments to the shell
echo ${args[0]} ${args[1]} ${args[2]} ' -> args=("$@"); echo ${args[0]} ${args[1]} ${args[2]}'

#use $@ to print out all arguments at once
echo $@ ' -> echo $@'

# use $# variable to print out
# number of arguments passed to the bash script
echo Number of arguments passed: $# ' -> echo Number of arguments passed: $#' 

Reading User Input

#!/bin/bash
echo -e "Hi, please type the word: \c "
read word
echo "The word you entered is: $word"
echo -e "Can you please enter two words? "
read word1 word2
echo "Here is your input: \"$word1\" \"$word2\""
echo -e "How do you feel about bash scripting? "
# read command now stores a reply into the default build-in variable $REPLY
read
echo "You said $REPLY, I'm glad to hear that! "
echo -e "What are your favorite colours ? "
# -a makes read command to read into an array
read -a colours
echo "My favorite colours are also ${colours[0]}, ${colours[1]} and ${colours[2]}:-)"
#!/bin/bash echo -e "Hi, please type the word: \c " read word echo "The word you entered is: $word" echo -e "Can you please enter two words? " read word1 word2 echo "Here is your input: \"$word1\" \"$word2\"" echo -e "How do you feel about bash scripting? " # read command now stores a reply into the default build-in variable $REPLY read echo "You said $REPLY, I'm glad to hear that! " echo -e "What are your favorite colours ? " # -a makes read command to read into an array read -a colours echo "My favorite colours are also ${colours[0]}, ${colours[1]} and ${colours[2]}:-)"
#!/bin/bash
 
echo -e "Hi, please type the word: \c "
read  word
echo "The word you entered is: $word"
echo -e "Can you please enter two words? "
read word1 word2
echo "Here is your input: \"$word1\" \"$word2\""
echo -e "How do you feel about bash scripting? "
# read command now stores a reply into the default build-in variable $REPLY
read
echo "You said $REPLY, I'm glad to hear that! "
echo -e "What are your favorite colours ? "
# -a makes read command to read into an array
read -a colours
echo "My favorite colours are also ${colours[0]}, ${colours[1]} and ${colours[2]}:-)" 

Declare simple bash array

#!/bin/bash
#Declare array with 4 elements
ARRAY=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux )
# get number of elements in the array
ELEMENTS=${#ARRAY[@]}
# echo each element in array
# for loop
for (( i=0;i<$ELEMENTS;i++)); do
echo ${ARRAY[${i}]}
done
#!/bin/bash #Declare array with 4 elements ARRAY=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux ) # get number of elements in the array ELEMENTS=${#ARRAY[@]} # echo each element in array # for loop for (( i=0;i<$ELEMENTS;i++)); do echo ${ARRAY[${i}]} done
#!/bin/bash
#Declare array with 4 elements
ARRAY=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux )
# get number of elements in the array
ELEMENTS=${#ARRAY[@]}

# echo each element in array 
# for loop
for (( i=0;i<$ELEMENTS;i++)); do
    echo ${ARRAY[${i}]}
done 

Read file into bash array

#!/bin/bash
# Declare array
declare -a ARRAY
# Link filedescriptor 10 with stdin
exec 10<&0
# stdin replaced with a file supplied as a first argument
exec < $1
let count=0
while read LINE; do
ARRAY[$count]=$LINE
((count++))
done
echo Number of elements: ${#ARRAY[@]}
# echo array's content
echo ${ARRAY[@]}
# restore stdin from filedescriptor 10
# and close filedescriptor 10
exec 0<&10 10<&-
#!/bin/bash # Declare array declare -a ARRAY # Link filedescriptor 10 with stdin exec 10<&0 # stdin replaced with a file supplied as a first argument exec < $1 let count=0 while read LINE; do ARRAY[$count]=$LINE ((count++)) done echo Number of elements: ${#ARRAY[@]} # echo array's content echo ${ARRAY[@]} # restore stdin from filedescriptor 10 # and close filedescriptor 10 exec 0<&10 10<&-
#!/bin/bash
# Declare array
declare -a ARRAY
# Link filedescriptor 10 with stdin
exec 10<&0
# stdin replaced with a file supplied as a first argument
exec < $1
let count=0

while read LINE; do

    ARRAY[$count]=$LINE
    ((count++))
done

echo Number of elements: ${#ARRAY[@]}
# echo array's content
echo ${ARRAY[@]}
# restore stdin from filedescriptor 10
# and close filedescriptor 10
exec 0<&10 10<&-

Bash if / else / fi statements

1. Simple Bash if/else statement
#!/bin/bash
directory="./BashScripting"
# bash check if directory exists
if [ -d $directory ]; then
echo "Directory exists"
else
echo "Directory does not exists"
fi
2. Nested if/else
#!/bin/bash
# Declare variable choice and assign value 4
choice=4
# Print to stdout
echo "1. Bash"
echo "2. Scripting"
echo "3. Tutorial"
echo -n "Please choose a word [1,2 or 3]? "
# Loop while the variable choice is equal 4
# bash while loop
while [ $choice -eq 4 ]; do
# read user input
read choice
# bash nested if/else
if [ $choice -eq 1 ] ; then
echo "You have chosen word: Bash"
else
if [ $choice -eq 2 ] ; then
echo "You have chosen word: Scripting"
else
if [ $choice -eq 3 ] ; then
echo "You have chosen word: Tutorial"
else
echo "Please make a choice between 1-3 !"
echo "1. Bash"
echo "2. Scripting"
echo "3. Tutorial"
echo -n "Please choose a word [1,2 or 3]? "
choice=4
fi
fi
fi
done
1. Simple Bash if/else statement #!/bin/bash directory="./BashScripting" # bash check if directory exists if [ -d $directory ]; then echo "Directory exists" else echo "Directory does not exists" fi 2. Nested if/else #!/bin/bash # Declare variable choice and assign value 4 choice=4 # Print to stdout echo "1. Bash" echo "2. Scripting" echo "3. Tutorial" echo -n "Please choose a word [1,2 or 3]? " # Loop while the variable choice is equal 4 # bash while loop while [ $choice -eq 4 ]; do # read user input read choice # bash nested if/else if [ $choice -eq 1 ] ; then echo "You have chosen word: Bash" else if [ $choice -eq 2 ] ; then echo "You have chosen word: Scripting" else if [ $choice -eq 3 ] ; then echo "You have chosen word: Tutorial" else echo "Please make a choice between 1-3 !" echo "1. Bash" echo "2. Scripting" echo "3. Tutorial" echo -n "Please choose a word [1,2 or 3]? " choice=4 fi fi fi done
1. Simple Bash if/else statement
#!/bin/bash
directory="./BashScripting"

# bash check if directory exists
if [ -d $directory ]; then
	echo "Directory exists"
else 
	echo "Directory does not exists"
fi 

2. Nested if/else
#!/bin/bash
 
# Declare variable choice and assign value 4
choice=4
# Print to stdout
 echo "1. Bash"
 echo "2. Scripting"
 echo "3. Tutorial"
 echo -n "Please choose a word [1,2 or 3]? "
# Loop while the variable choice is equal 4
# bash while loop
while [ $choice -eq 4 ]; do
 
# read user input
read choice
# bash nested if/else
if [ $choice -eq 1 ] ; then
 
        echo "You have chosen word: Bash"

else                   

        if [ $choice -eq 2 ] ; then
                 echo "You have chosen word: Scripting"
        else
         
                if [ $choice -eq 3 ] ; then
                        echo "You have chosen word: Tutorial"
                else
                        echo "Please make a choice between 1-3 !"
                        echo "1. Bash"
                        echo "2. Scripting"
                        echo "3. Tutorial"
                        echo -n "Please choose a word [1,2 or 3]? "
                        choice=4
                fi   
        fi
fi
done 

Bash Comparisons

1. Arithmetic Comparisons
-lt <
-gt >
-le <=
-ge >=
-eq ==
-ne !=
#!/bin/bash
# declare integers
NUM1=2
NUM2=2
if [ $NUM1 -eq $NUM2 ]; then
echo "Both Values are equal"
else
echo "Values are NOT equal"
fi
2. String Comparisons
= equal
!= not equal
< less then
> greater then
-n s1 string s1 is not empty
-z s1 string s1 is empty
#!/bin/bash
#Declare string S1
S1="Bash"
#Declare string S2
S2="Scripting"
if [ $S1 = $S2 ]; then
echo "Both Strings are equal"
else
echo "Strings are NOT equal"
fi
1. Arithmetic Comparisons -lt < -gt > -le <= -ge >= -eq == -ne != #!/bin/bash # declare integers NUM1=2 NUM2=2 if [ $NUM1 -eq $NUM2 ]; then echo "Both Values are equal" else echo "Values are NOT equal" fi 2. String Comparisons = equal != not equal < less then > greater then -n s1 string s1 is not empty -z s1 string s1 is empty #!/bin/bash #Declare string S1 S1="Bash" #Declare string S2 S2="Scripting" if [ $S1 = $S2 ]; then echo "Both Strings are equal" else echo "Strings are NOT equal" fi
1. Arithmetic Comparisons
-lt	<
-gt	>
-le	<=
-ge	>=
-eq	==
-ne	!=
#!/bin/bash
# declare integers
NUM1=2
NUM2=2
if [ $NUM1 -eq $NUM2 ]; then
	echo "Both Values are equal"
else 
	echo "Values are NOT equal"
fi 

2. String Comparisons
=	equal
!=	not equal
<	less then
>	greater then
-n s1	string s1 is not empty
-z s1	string s1 is empty
#!/bin/bash
#Declare string S1
S1="Bash"
#Declare string S2
S2="Scripting"
if [ $S1 = $S2 ]; then
	echo "Both Strings are equal"
else 
	echo "Strings are NOT equal"
fi 

Bash File Testing

-b filename Block special file
-c filename Special character file
-d directoryname Check for directory existence
-e filename Check for file existence
-f filename Check for regular file existence not a directory
-G filename Check if file exists and is owned by effective group ID.
-g filename true if file exists and is set-group-id.
-k filename Sticky bit
-L filename Symbolic link
-O filename True if file exists and is owned by the effective user id.
-r filename Check if file is a readable
-S filename Check if file is socket
-s filename Check if file is nonzero size
-u filename Check if file set-ser-id bit is set
-w filename Check if file is writable
-x filename Check if file is executable
#!/bin/bash
file="./file"
if [ -e $file ]; then
echo "File exists"
else
echo "File does not exists"
fi
#!/bin/bash
while [ ! -e myfile ]; do
# Sleep until file does exists/is created
sleep 1
done
-b filename Block special file -c filename Special character file -d directoryname Check for directory existence -e filename Check for file existence -f filename Check for regular file existence not a directory -G filename Check if file exists and is owned by effective group ID. -g filename true if file exists and is set-group-id. -k filename Sticky bit -L filename Symbolic link -O filename True if file exists and is owned by the effective user id. -r filename Check if file is a readable -S filename Check if file is socket -s filename Check if file is nonzero size -u filename Check if file set-ser-id bit is set -w filename Check if file is writable -x filename Check if file is executable #!/bin/bash file="./file" if [ -e $file ]; then echo "File exists" else echo "File does not exists" fi #!/bin/bash while [ ! -e myfile ]; do # Sleep until file does exists/is created sleep 1 done
-b filename	Block special file
-c filename	Special character file
-d directoryname	Check for directory existence
-e filename	Check for file existence
-f filename	Check for regular file existence not a directory
-G filename	Check if file exists and is owned by effective group ID.
-g filename	true if file exists and is set-group-id.
-k filename	Sticky bit
-L filename	Symbolic link
-O filename	True if file exists and is owned by the effective user id.
-r filename	Check if file is a readable
-S filename	Check if file is socket
-s filename	Check if file is nonzero size
-u filename	Check if file set-ser-id bit is set
-w filename	Check if file is writable
-x filename	Check if file is executable
#!/bin/bash
file="./file"
if [ -e $file ]; then
	echo "File exists"
else 
	echo "File does not exists"
fi 

#!/bin/bash
 
while [ ! -e myfile ]; do
# Sleep until file does exists/is created
sleep 1
done 

Bash for/while/until loop

#!/bin/bash
# bash for loop
for f in $( ls /var/ ); do
echo $f
done
#!/bin/bash
COUNT=6
# bash while loop
while [ $COUNT -gt 0 ]; do
echo Value of count is: $COUNT
let COUNT=COUNT-1
done
#!/bin/bash
COUNT=0
# bash until loop
until [ $COUNT -gt 5 ]; do
echo Value of count is: $COUNT
let COUNT=COUNT+1
done
#!/bin/bash # bash for loop for f in $( ls /var/ ); do echo $f done #!/bin/bash COUNT=6 # bash while loop while [ $COUNT -gt 0 ]; do echo Value of count is: $COUNT let COUNT=COUNT-1 done #!/bin/bash COUNT=0 # bash until loop until [ $COUNT -gt 5 ]; do echo Value of count is: $COUNT let COUNT=COUNT+1 done
#!/bin/bash
# bash for loop
for f in $( ls /var/ ); do
	echo $f
done 

#!/bin/bash
COUNT=6
# bash while loop
while [ $COUNT -gt 0 ]; do
	echo Value of count is: $COUNT
	let COUNT=COUNT-1
done 

#!/bin/bash
COUNT=0
# bash until loop
until [ $COUNT -gt 5 ]; do
        echo Value of count is: $COUNT
        let COUNT=COUNT+1
done 

Bash Functions

!/bin/bash
# BASH FUNCTIONS CAN BE DECLARED IN ANY ORDER
function function_B {
echo Function B.
}
function function_A {
echo $1
}
function function_D {
echo Function D.
}
function function_C {
echo $1
}
# FUNCTION CALLS
# Pass parameter to function A
function_A "Function A."
function_B
# Pass parameter to function C
function_C "Function C."
function_D
!/bin/bash # BASH FUNCTIONS CAN BE DECLARED IN ANY ORDER function function_B { echo Function B. } function function_A { echo $1 } function function_D { echo Function D. } function function_C { echo $1 } # FUNCTION CALLS # Pass parameter to function A function_A "Function A." function_B # Pass parameter to function C function_C "Function C." function_D
!/bin/bash
# BASH FUNCTIONS CAN BE DECLARED IN ANY ORDER
function function_B {
        echo Function B.
}
function function_A {
        echo $1
}
function function_D {
        echo Function D.
}
function function_C {
        echo $1
}
# FUNCTION CALLS
# Pass parameter to function A
function_A "Function A."
function_B
# Pass parameter to function C
function_C "Function C."
function_D 

Bash Select

#!/bin/bash
PS3='Choose one word: '
# bash select
select word in "linux" "bash" "scripting" "tutorial"
do
echo "The word you have selected is: $word"
# Break, otherwise endless loop
break
done
exit 0
#!/bin/bash PS3='Choose one word: ' # bash select select word in "linux" "bash" "scripting" "tutorial" do echo "The word you have selected is: $word" # Break, otherwise endless loop break done exit 0
#!/bin/bash
 
PS3='Choose one word: ' 

# bash select
select word in "linux" "bash" "scripting" "tutorial" 
do
  echo "The word you have selected is: $word"
# Break, otherwise endless loop
  break  
done

exit 0 

Case statement conditional

#!/bin/bash
echo "What is your preferred programming / scripting language"
echo "1) bash"
echo "2) perl"
echo "3) phyton"
echo "4) c++"
echo "5) I do not know !"
read case;
#simple case bash structure
# note in this case $case is variable and does not have to
# be named case this is just an example
case $case in
1) echo "You selected bash";;
2) echo "You selected perl";;
3) echo "You selected phyton";;
4) echo "You selected c++";;
5) exit
esac
#!/bin/bash echo "What is your preferred programming / scripting language" echo "1) bash" echo "2) perl" echo "3) phyton" echo "4) c++" echo "5) I do not know !" read case; #simple case bash structure # note in this case $case is variable and does not have to # be named case this is just an example case $case in 1) echo "You selected bash";; 2) echo "You selected perl";; 3) echo "You selected phyton";; 4) echo "You selected c++";; 5) exit esac
#!/bin/bash
echo "What is your preferred programming / scripting language"
echo "1) bash"
echo "2) perl"
echo "3) phyton"
echo "4) c++"
echo "5) I do not know !"
read case;
#simple case bash structure
# note in this case $case is variable and does not have to
# be named case this is just an example
case $case in
    1) echo "You selected bash";;
    2) echo "You selected perl";;
    3) echo "You selected phyton";;
    4) echo "You selected c++";;
    5) exit
esac 

Bash quotes and quotations
Quotations and quotes are important part of bash and bash scripting. Here are some bash quotes and quotations basics.
Escaping Meta characters
Before we start with quotes and quotations we should know something about escaping meta characters. Escaping will suppress a special meaning of meta characters and therefore meta characters will be read by bash literally. To do this we need to use backslash “\” character. Example:

#!/bin/bash
#Declare bash string variable
BASH_VAR="Bash Script"
# echo variable BASH_VAR
echo $BASH_VAR
#when meta character such us "$" is escaped with "\" it will be read literally
echo $BASH_VAR
# backslash has also special meaning and it can be suppressed with yet another "\"
echo "\"
#!/bin/bash #Declare bash string variable BASH_VAR="Bash Script" # echo variable BASH_VAR echo $BASH_VAR #when meta character such us "$" is escaped with "\" it will be read literally echo $BASH_VAR # backslash has also special meaning and it can be suppressed with yet another "\" echo "\"
#!/bin/bash
 #Declare bash string variable
BASH_VAR="Bash Script"
# echo variable BASH_VAR
echo $BASH_VAR
#when meta character such us "$" is escaped with "\" it will be read literally
echo $BASH_VAR 
# backslash has also special meaning and it can be suppressed with yet another "\"
echo "\" 

Single quotes
Single quotes in bash will suppress special meaning of every meta characters. Therefore meta characters will be read literally. It is not possible to use another single quote within two single quotes not even if the single quote is escaped by backslash.

#!/bin/bash
#Declare bash string variable
BASH_VAR="Bash Script"
# echo variable BASH_VAR
echo $BASH_VAR
# meta characters special meaning in bash is suppressed when using single quotes
echo '$BASH_VAR "$BASH_VAR"'
#!/bin/bash #Declare bash string variable BASH_VAR="Bash Script" # echo variable BASH_VAR echo $BASH_VAR # meta characters special meaning in bash is suppressed when using single quotes echo '$BASH_VAR "$BASH_VAR"'
#!/bin/bash
 
 #Declare bash string variable
 BASH_VAR="Bash Script"
 
 # echo variable BASH_VAR
 echo $BASH_VAR
 
 # meta characters special meaning in bash is suppressed when  using single quotes 
 echo '$BASH_VAR  "$BASH_VAR"' 

Double Quotes
Double quotes in bash will suppress special meaning of every meta characters except “$”, “\” and “`”. Any other meta characters will be read literally. It is also possible to use single quote within double quotes. If we need to use double quotes within double quotes bash can read them literally when escaping them with “\”. Example:

#!/bin/bash
#Declare bash string variable
BASH_VAR="Bash Script"
# echo variable BASH_VAR
echo $BASH_VAR
# meta characters and its special meaning in bash is
# suppressed when using double quotes except "$", "\" and "`"
echo "It's $BASH_VAR and \"$BASH_VAR\" using backticks: `date`"
#!/bin/bash #Declare bash string variable BASH_VAR="Bash Script" # echo variable BASH_VAR echo $BASH_VAR # meta characters and its special meaning in bash is # suppressed when using double quotes except "$", "\" and "`" echo "It's $BASH_VAR and \"$BASH_VAR\" using backticks: `date`"
#!/bin/bash
 
#Declare bash string variable
BASH_VAR="Bash Script"

# echo variable BASH_VAR
echo $BASH_VAR

# meta characters and its special meaning in bash is 
# suppressed when using double quotes except "$", "\" and "`"

echo "It's $BASH_VAR  and \"$BASH_VAR\" using backticks: `date`" 

Arithmetic Operations

echo '### Bash Arithmetic Expansion ###'
# There are two formats for arithmetic expansion: $[ expression ]
# and $(( expression #)) its your choice which you use
echo 4 + 5 = $((4 + 5))
echo 7 - 7 = $[ 7 - 7 ]
echo 4 x 6 = $((3 * 2))
echo 6 / 3 = $((6 / 3))
echo 8 % 7 = $((8 % 7))
echo 2 ^ 8 = $[ 2 ** 8 ]
echo '### Declare ###'
echo -e "Please enter two numbers \c"
# read user input
read num1 num2
declare -i result
result=$num1+$num2
echo "Result is:$result "
# bash convert binary number 10001
result=2#10001
echo $result
# bash convert octal number 16
result=8#16
echo $result
# bash convert hex number 0xE6A
result=16#E6A
echo $result
Round floating point number:
#!/bin/bash
# get floating point number
floating_point_number=3.3446
echo $floating_point_number
# round floating point number with bash
for bash_rounded_number in $(printf %.0f $floating_point_number); do
echo "Rounded number with bash:" $bash_rounded_number
done
echo '### Bash Arithmetic Expansion ###' # There are two formats for arithmetic expansion: $[ expression ] # and $(( expression #)) its your choice which you use echo 4 + 5 = $((4 + 5)) echo 7 - 7 = $[ 7 - 7 ] echo 4 x 6 = $((3 * 2)) echo 6 / 3 = $((6 / 3)) echo 8 % 7 = $((8 % 7)) echo 2 ^ 8 = $[ 2 ** 8 ] echo '### Declare ###' echo -e "Please enter two numbers \c" # read user input read num1 num2 declare -i result result=$num1+$num2 echo "Result is:$result " # bash convert binary number 10001 result=2#10001 echo $result # bash convert octal number 16 result=8#16 echo $result # bash convert hex number 0xE6A result=16#E6A echo $result Round floating point number: #!/bin/bash # get floating point number floating_point_number=3.3446 echo $floating_point_number # round floating point number with bash for bash_rounded_number in $(printf %.0f $floating_point_number); do echo "Rounded number with bash:" $bash_rounded_number done
echo '### Bash Arithmetic Expansion ###'
# There are two formats for arithmetic expansion: $[ expression ] 
# and $(( expression #)) its your choice which you use

echo 4 + 5 = $((4 + 5))
echo 7 - 7 = $[ 7 - 7 ]
echo 4 x 6 = $((3 * 2))
echo 6 / 3 = $((6 / 3))
echo 8 % 7 = $((8 % 7))
echo 2 ^ 8 = $[ 2 ** 8 ]


echo '### Declare ###'

echo -e "Please enter two numbers \c"
# read user input
read num1 num2
declare -i result
result=$num1+$num2
echo "Result is:$result "

# bash convert binary number 10001
result=2#10001
echo $result

# bash convert octal number 16
result=8#16
echo $result

# bash convert hex number 0xE6A
result=16#E6A
echo $result 

Round floating point number:
#!/bin/bash
# get floating point number
floating_point_number=3.3446
echo $floating_point_number
# round floating point number with bash
for bash_rounded_number in $(printf %.0f $floating_point_number); do
echo "Rounded number with bash:" $bash_rounded_number
done 

bash script search string and delete the line above

we search a string "test" in file.txt file, then delete its line above.
hans@testvm:~ $ cat ./del_line_above.sh
#!/bin/bash
line_number="$(grep -n 'test' file.txt| cut -d: -f1)"
line_number_above="$((line_number - 1))"
sed "${line_number_above}d" file.txt
hans@testvm:~ $ cat file.txt
aadsfasfda
line 1
line 2
line 3
line 4
test
java
hans@testvm:~ $ ./del_line_above.sh
aadsfasfda
line 1
line 2
line 3
test
java
we search a string "test" in file.txt file, then delete its line above. hans@testvm:~ $ cat ./del_line_above.sh #!/bin/bash line_number="$(grep -n 'test' file.txt| cut -d: -f1)" line_number_above="$((line_number - 1))" sed "${line_number_above}d" file.txt hans@testvm:~ $ cat file.txt aadsfasfda line 1 line 2 line 3 line 4 test java hans@testvm:~ $ ./del_line_above.sh aadsfasfda line 1 line 2 line 3 test java
we search a string "test" in file.txt file, then delete its line above.
 hans@testvm:~ $ cat ./del_line_above.sh
#!/bin/bash
line_number="$(grep -n 'test' file.txt| cut -d: -f1)"
line_number_above="$((line_number - 1))"
sed "${line_number_above}d" file.txt

 hans@testvm:~ $ cat file.txt
aadsfasfda
line 1
line 2
line 3
line 4
test
java
hans@testvm:~ $ ./del_line_above.sh
aadsfasfda
line 1
line 2
line 3
test
java

Through the forest – Adam’s first poem

Sometimes I sit and wander through the forest ,
Think about humanity and how we’ve grown.
Sit and Learn to our heart desire, but then comes the moan.

Everyone hears, it haunts more then once a life,
A moan of struggles, that echoes through a pipe.

It sends a waves of a hunger for war, forcing everyone to write to their dears.
Then the moan turns into sobbing, representing the world’s tears.

The moan is of pure misery, from the depths of Tautrous herself.
Making people furious and then crumble and melt.
People start as saplings easy to break and bend. They grow, then break in two and snap.

Then I look at the great tree, standing tall and proud.
Looking down at their many branches grown each by themselves.

It only needed a can of water, a trinkle of effort.
To stand as high as the sky, tall and bold.

Looking between the two, sapling and great oak.
One prepared to snap, the other could support a boat.

Makes me wonder, what’s the difference between giants and an elf.
Then I realize that it’s only what people see in them, and what they see in themselves.

TAOBAO login with selenium and pyautogui

there are two challenges during taobao.com login:
1. sometimes the site will ask you pull the slider
resolved with Selenium ActionChains
2. taobao disabled selenium click()
resolved with pyautogui lib:
pip install pyautogui
here is the code for taobao.com login:

from selenium import webdriver
import logging
import time
from selenium.common.exceptions import NoSuchElementException, WebDriverException
from retrying import retry
from selenium.webdriver import ActionChains
import pyautogui
pyautogui.PAUSE = 0.5
logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class taobao():
def __init__(self):
self.browser = webdriver.Chrome("path\to\your\chromedriver.exe")
self.browser.maximize_window()
self.browser.implicitly_wait(5)
self.domain = 'http://www.taobao.com'
self.action_chains = ActionChains(self.browser)
def login(self, username, password):
while True:
self.browser.get(self.domain)
time.sleep(1)
#self.browser.find_element_by_class_name('h').click()
#self.browser.find_element_by_id('fm-login-id').send_keys(username)
#self.browser.find_element_by_id('fm-login-password').send_keys(password)
self.browser.find_element_by_xpath('//*[@id="J_SiteNavLogin"]/div[1]/div[1]/a[1]').click()
self.browser.find_element_by_xpath('//*[@id="fm-login-id"]').send_keys(username)
self.browser.find_element_by_xpath('//*[@id="fm-login-password"]').send_keys(password)
time.sleep(1)
try:
# using Selenium ActionChains for the website SLIDE authentication
slider = self.browser.find_element_by_xpath("//span[contains(@class, 'btn_slide')]")
if slider.is_displayed():
# pull the slider
self.action_chains.drag_and_drop_by_offset(slider, 258, 0).perform()
time.sleep(0.5)
# release the slider
self.action_chains.release().perform()
except (NoSuchElementException, WebDriverException):
logger.info('slider not found')
# using pyautogui click the LOGIN PNG image
#self.browser.find_element_by_class_name('password-login').click()
#self.browser.find_element_by_xpath('//*[@id="login-form"]/div[4]/button').click()
coords = pyautogui.locateOnScreen('1.png')
x, y = pyautogui.center(coords)
pyautogui.leftClick(x, y)
nickname = self.get_nickname()
if nickname:
logger.info('successfully logon, nickname is' + nickname)
break
logger.debug('login failed,please try again after 5 seconds')
time.sleep(5)
def get_nickname(self):
self.browser.get(self.domain)
time.sleep(0.5)
try:
return self.browser.find_element_by_class_name('site-nav-user').text
except NoSuchElementException:
return ''
if __name__ == '__main__':
# Input your TAOBAO username and password
username = 'username'
password = 'password'
tb = taobao()
tb.login(username, password)
from selenium import webdriver import logging import time from selenium.common.exceptions import NoSuchElementException, WebDriverException from retrying import retry from selenium.webdriver import ActionChains import pyautogui pyautogui.PAUSE = 0.5 logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) class taobao(): def __init__(self): self.browser = webdriver.Chrome("path\to\your\chromedriver.exe") self.browser.maximize_window() self.browser.implicitly_wait(5) self.domain = 'http://www.taobao.com' self.action_chains = ActionChains(self.browser) def login(self, username, password): while True: self.browser.get(self.domain) time.sleep(1) #self.browser.find_element_by_class_name('h').click() #self.browser.find_element_by_id('fm-login-id').send_keys(username) #self.browser.find_element_by_id('fm-login-password').send_keys(password) self.browser.find_element_by_xpath('//*[@id="J_SiteNavLogin"]/div[1]/div[1]/a[1]').click() self.browser.find_element_by_xpath('//*[@id="fm-login-id"]').send_keys(username) self.browser.find_element_by_xpath('//*[@id="fm-login-password"]').send_keys(password) time.sleep(1) try: # using Selenium ActionChains for the website SLIDE authentication slider = self.browser.find_element_by_xpath("//span[contains(@class, 'btn_slide')]") if slider.is_displayed(): # pull the slider self.action_chains.drag_and_drop_by_offset(slider, 258, 0).perform() time.sleep(0.5) # release the slider self.action_chains.release().perform() except (NoSuchElementException, WebDriverException): logger.info('slider not found') # using pyautogui click the LOGIN PNG image #self.browser.find_element_by_class_name('password-login').click() #self.browser.find_element_by_xpath('//*[@id="login-form"]/div[4]/button').click() coords = pyautogui.locateOnScreen('1.png') x, y = pyautogui.center(coords) pyautogui.leftClick(x, y) nickname = self.get_nickname() if nickname: logger.info('successfully logon, nickname is' + nickname) break logger.debug('login failed,please try again after 5 seconds') time.sleep(5) def get_nickname(self): self.browser.get(self.domain) time.sleep(0.5) try: return self.browser.find_element_by_class_name('site-nav-user').text except NoSuchElementException: return '' if __name__ == '__main__': # Input your TAOBAO username and password username = 'username' password = 'password' tb = taobao() tb.login(username, password)
from selenium import webdriver
import logging
import time
from selenium.common.exceptions import NoSuchElementException, WebDriverException
from retrying import retry
from selenium.webdriver import ActionChains

import pyautogui
pyautogui.PAUSE = 0.5 

logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class taobao():
    def __init__(self):
        self.browser = webdriver.Chrome("path\to\your\chromedriver.exe")
        self.browser.maximize_window()
        self.browser.implicitly_wait(5)
        self.domain = 'http://www.taobao.com'
        self.action_chains = ActionChains(self.browser)

    def login(self, username, password):
        while True:
            self.browser.get(self.domain)
            time.sleep(1)

            #self.browser.find_element_by_class_name('h').click()
            #self.browser.find_element_by_id('fm-login-id').send_keys(username)
            #self.browser.find_element_by_id('fm-login-password').send_keys(password)
            self.browser.find_element_by_xpath('//*[@id="J_SiteNavLogin"]/div[1]/div[1]/a[1]').click()
            self.browser.find_element_by_xpath('//*[@id="fm-login-id"]').send_keys(username)
            self.browser.find_element_by_xpath('//*[@id="fm-login-password"]').send_keys(password)
            time.sleep(1)

            try:
                # using Selenium ActionChains for the website SLIDE authentication
                slider = self.browser.find_element_by_xpath("//span[contains(@class, 'btn_slide')]")
                if slider.is_displayed():
                    # pull the slider
                    self.action_chains.drag_and_drop_by_offset(slider, 258, 0).perform()
                    time.sleep(0.5)
                    # release the slider
                    self.action_chains.release().perform()
            except (NoSuchElementException, WebDriverException):
                logger.info('slider not found')

            # using pyautogui click the LOGIN PNG image
            #self.browser.find_element_by_class_name('password-login').click()
            #self.browser.find_element_by_xpath('//*[@id="login-form"]/div[4]/button').click()
             coords = pyautogui.locateOnScreen('1.png')
            x, y = pyautogui.center(coords)
            pyautogui.leftClick(x, y)

            nickname = self.get_nickname()
            if nickname:
                logger.info('successfully logon, nickname is' + nickname)
                break
            logger.debug('login failed,please try again after 5 seconds')
            time.sleep(5)

    def get_nickname(self):
        self.browser.get(self.domain)
        time.sleep(0.5)
        try:
            return self.browser.find_element_by_class_name('site-nav-user').text
        except NoSuchElementException:
            return ''


if __name__ == '__main__':
    # Input your TAOBAO username and password
    username = 'username'
    password = 'password'
    tb = taobao()
    tb.login(username, password)

Complete Django/MySQL CRUD Operations

Learned from CodAffection online course, code has been staged on github:
https://github.com/zhuby1973/python/tree/master/employee_project

we need pip install django-crispy-forms for this project.
1. django-admin startproject employee_project
2. python manage.py runserver
3. python manage.py startapp employee_register
edit settings.py, urls.py, views.py and models.py, then run migrate command to create tables:
python manage.py migrate
python manage.py makemigrations employee_register
python manage.py sqlmigrate employee_register 0001
python manage.py sqlmigrate employee_register 0002
python manage.py migrate
python manage.py createsuperuser (create admin user and verify in admin page)
you can verify the tables in MySQL.

# this is employee_register/views.py:
from django.shortcuts import render,redirect
from .forms import EmployeeForm, RegisterForm
from .models import Employee
import os
from django.conf import settings
from django.contrib import messages
#from django.contrib.auth import login, authenticate
#from django.contrib.auth.forms import UserCreationForm
# Create your views here.
def register(request):
registerForm = RegisterForm(request.POST or None)
if request.method == "POST":
if registerForm.is_valid():
registerForm.is_staff = True
registerForm.save()
return render(request, "registration/register.html", {"form": registerForm})
def employee_list(request):
print (settings.BASE_DIR)
context = {'employee_list':Employee.objects.all()}
return render(request,"employee_register/employee_list.html",context)
def employee_form(request, id=0):
if request.method == "GET":
if id == 0:
form = EmployeeForm()
else:
employee = Employee.objects.get(id=id)
form = EmployeeForm(instance=employee)
return render(request,"employee_register/employee_form.html",{'form':form})
else:
if id == 0:
form = EmployeeForm(request.POST or None, request.FILES or None)
else:
employee = Employee.objects.get(id=id)
employee.image.delete()
form = EmployeeForm(request.POST or None, request.FILES or None, instance = employee)
if form.is_valid():
form.save()
if id == 0:
messages.success(request, "Employee Record Added Successfully!")
else:
messages.info(request,"Employee Record Updated Successfully!")
return redirect("/employee/list")
def employee_delete(request,id):
employee = Employee.objects.get(id=id)
employee.delete()
messages.error(request, 'Employee Record Deleted Successfully!')
return redirect('/employee/list')
# this is employee_register/views.py: from django.shortcuts import render,redirect from .forms import EmployeeForm, RegisterForm from .models import Employee import os from django.conf import settings from django.contrib import messages #from django.contrib.auth import login, authenticate #from django.contrib.auth.forms import UserCreationForm # Create your views here. def register(request): registerForm = RegisterForm(request.POST or None) if request.method == "POST": if registerForm.is_valid(): registerForm.is_staff = True registerForm.save() return render(request, "registration/register.html", {"form": registerForm}) def employee_list(request): print (settings.BASE_DIR) context = {'employee_list':Employee.objects.all()} return render(request,"employee_register/employee_list.html",context) def employee_form(request, id=0): if request.method == "GET": if id == 0: form = EmployeeForm() else: employee = Employee.objects.get(id=id) form = EmployeeForm(instance=employee) return render(request,"employee_register/employee_form.html",{'form':form}) else: if id == 0: form = EmployeeForm(request.POST or None, request.FILES or None) else: employee = Employee.objects.get(id=id) employee.image.delete() form = EmployeeForm(request.POST or None, request.FILES or None, instance = employee) if form.is_valid(): form.save() if id == 0: messages.success(request, "Employee Record Added Successfully!") else: messages.info(request,"Employee Record Updated Successfully!") return redirect("/employee/list") def employee_delete(request,id): employee = Employee.objects.get(id=id) employee.delete() messages.error(request, 'Employee Record Deleted Successfully!') return redirect('/employee/list')
# this is employee_register/views.py:
from django.shortcuts import render,redirect
from .forms import EmployeeForm, RegisterForm
from .models import Employee
import os
from django.conf import settings
from django.contrib import messages
#from django.contrib.auth import login, authenticate
#from django.contrib.auth.forms import UserCreationForm

# Create your views here.
def register(request):
    registerForm = RegisterForm(request.POST or None)
    if request.method == "POST":
        if registerForm.is_valid():
            registerForm.is_staff = True
            registerForm.save()

    return render(request, "registration/register.html", {"form": registerForm})

def employee_list(request):
    print (settings.BASE_DIR)
    context = {'employee_list':Employee.objects.all()}
    return render(request,"employee_register/employee_list.html",context)

def employee_form(request, id=0):
    if request.method == "GET":
        if id == 0:
            form = EmployeeForm()
        else:
            employee = Employee.objects.get(id=id)
            form = EmployeeForm(instance=employee)
        return render(request,"employee_register/employee_form.html",{'form':form})
    else:
        if id == 0:
            form = EmployeeForm(request.POST or None, request.FILES or None)
        else:
            employee = Employee.objects.get(id=id)
            employee.image.delete()
            form = EmployeeForm(request.POST or None, request.FILES or None, instance = employee)

        if form.is_valid():
            form.save()
            if id == 0:
                messages.success(request, "Employee Record Added Successfully!")
            else:
                messages.info(request,"Employee Record Updated Successfully!")

        return redirect("/employee/list")


def employee_delete(request,id):
    employee = Employee.objects.get(id=id)
    employee.delete()
    messages.error(request, 'Employee Record Deleted Successfully!')

    return redirect('/employee/list')

create Web Service with FastAPI and uvicorn

  1. pip install fastapi
  2. pip install uvicorn
    code main.py:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class People(BaseModel):
name: str
age: int
address: str = None
@app.post('/insert')
def insert(people: People):
age_after_10_years = people.age + 10
msg = f'Name: {people.name},age after ten years:{age_after_10_years}'
return {'success': True, 'msg': msg}
@app.get('/')
def index():
return {'message': 'Hi, this is your FastApi service!'}
run command: uvicorn main:app --reload, then you can access docs
http://127.0.0.1:8000/docs, you can test POST/GET as below or test it with Postman.
from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class People(BaseModel): name: str age: int address: str = None @app.post('/insert') def insert(people: People): age_after_10_years = people.age + 10 msg = f'Name: {people.name},age after ten years:{age_after_10_years}' return {'success': True, 'msg': msg} @app.get('/') def index(): return {'message': 'Hi, this is your FastApi service!'} run command: uvicorn main:app --reload, then you can access docs http://127.0.0.1:8000/docs, you can test POST/GET as below or test it with Postman.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class People(BaseModel):
    name: str
    age: int
    address: str = None
@app.post('/insert')
def insert(people: People):
    age_after_10_years = people.age + 10
    msg = f'Name: {people.name},age after ten years:{age_after_10_years}'
    return {'success': True, 'msg': msg}
@app.get('/')
def index():
    return {'message': 'Hi, this is your FastApi service!'}

run command: uvicorn main:app --reload, then you can access docs
http://127.0.0.1:8000/docs, you can test POST/GET as below or test it with Postman.