//cmd
(tensor) C:\Users\bob>cd C:\Users\bob\python-machineLearning
(tensor) C:\Users\bob\python-machineLearning>pip install sklearn
Collecting sklearn
Downloading https://files.pythonhosted.org/packages/1e/7a/dbb3be0ce9bd5c8b7e3d87328e79063f8b263b2b1bfa4774cb1147bfcd3f/sklearn-0.0.tar.gz
Requirement already satisfied: scikit-learn in c:\users\bob\anaconda3\lib\site-packages (from sklearn) (0.21.2)
Requirement already satisfied: joblib>=0.11 in c:\users\bob\anaconda3\lib\site-packages (from scikit-learn->sklearn) (0.13.2)
Requirement already satisfied: scipy>=0.17.0 in c:\users\bob\anaconda3\lib\site-packages (from scikit-learn->sklearn) (1.2.1)
Requirement already satisfied: numpy>=1.11.0 in c:\users\bob\anaconda3\lib\site-packages (from scikit-learn->sklearn) (1.16.4)
Building wheels for collected packages: sklearn
Building wheel for sklearn (setup.py) ... done
Stored in directory: C:\Users\bob\AppData\Local\pip\Cache\wheels\76\03\bb\589d421d27431bcd2c6da284d5f2286c8e3b2ea3cf1594c074
Successfully built sklearn
Installing collected packages: sklearn
Successfully installed sklearn-0.0
(tensor) C:\Users\bob\python-machineLearning>pip install pandas
Requirement already satisfied: pandas in c:\users\bob\anaconda3\lib\site-packages (0.24.2)
Requirement already satisfied: python-dateutil>=2.5.0 in c:\users\bob\anaconda3\lib\site-packages (from pandas) (2.8.0)
Requirement already satisfied: numpy>=1.12.0 in c:\users\bob\anaconda3\lib\site-packages (from pandas) (1.16.4)
Requirement already satisfied: pytz>=2011k in c:\users\bob\anaconda3\lib\site-packages (from pandas) (2019.1)
Requirement already satisfied: six>=1.5 in c:\users\bob\appdata\roaming\python\python37\site-packages (from python-dateutil>=2.5.0->pandas) (1.12.0)
(tensor) C:\Users\bob\python-machineLearning>pip install numpy
Requirement already satisfied: numpy in c:\users\bob\anaconda3\lib\site-packages (1.16.4)
-------------------------------------
go to https://archive.ics.uci.edu/ml/datasets/Student+Performance -> click data folder -> student.zip -> extract -> copy student-mat.csv to project directory
#test
import pandas as pd
import numpy as np
import keras
import sklearn
from sklearn import linear_model
from sklearn.utils import shuffle
data = pd.read_csv("student-mat.csv", sep=";")
#print top 5 of original data
print(data.head())
data = data[['G1','G2','G3','studytime','failures','absences']]
#print top 5 of reduced data fields
print(data.head())
-------------------------------------
#logs
G1 - first period grade (numeric: from 0 to 20)
G2 - second period grade (numeric: from 0 to 20)
G3 - final grade (numeric: from 0 to 20, output target)
school sex age address famsize Pstatus ... Walc health absences G1 G2 G3
0 GP F 18 U GT3 A ... 1 3 6 5 6 6
1 GP F 17 U GT3 T ... 1 3 4 5 5 6
2 GP F 15 U LE3 T ... 3 3 10 7 8 10
3 GP F 15 U GT3 T ... 1 5 2 15 14 15
4 GP F 16 U GT3 T ... 2 5 4 6 10 10
[5 rows x 33 columns]
G1 G2 G3 studytime failures absences
0 5 6 6 2 0 6
1 5 5 6 2 0 4
2 7 8 10 2 3 10
3 15 14 15 3 0 2
4 6 10 10 2 0 4
----------------------------------------
#test continue
#'G3' is the column we are predicting using the rest of the columns
predict = 'G3'
#x is the array of columns in data other than column name 'G3'
x = np.array(data.drop([predict],1))
#y is column 'G3'
y = np.array(data[predict])
#x_test, y_test are the real data value
#x_train, y_train are the 10% of the data set used for prediction, prediction will generate a math model, x_test, y_test are used tor testing the accuracy of the model.
x_train, x_text, y_train, y_test = sklearn.model_selection.train_test_split(x,y,test_size=0.1)
#prediction method
linear = linear_model.LinearRegression()
linear.fit(x_train, y_train)
#prediction success rate
acuracy = linear.score(x_text, y_test)
print(acuracy)
#predicted slope and intercept
print("Co: \n", linear.coef_)
print("Intercept: \n", linear.intercept_)
predictions = linear.predict(x_text)
#print real data set with predicted value
for x in range(len(predictions)):
print(predictions[x], x_text[x], y_test[x])
---------------------------------------
#logs
#accuracy
0.8131211978854692
Co:
[ 0.16246545 0.97828472 -0.1944719 -0.26809678 0.03586954]
Intercept:
-1.5963742429164807
#predicted value, variables for predictions, real value
3.6128014305152814 [6 5 2 1 0] 0
7.035051917962379 [9 8 2 1 0] 0
10.249288008311625 [12 10 2 0 14] 11
13.346607601626296 [13 13 2 0 14] 14
6.985943972123177 [9 8 4 0 2] 8
10.031965729151835 [10 10 2 0 17] 10
9.565661730937075 [10 10 2 0 4] 10
12.746005563221631 [14 12 2 0 20] 13
-1.7828092550568728 [5 0 1 3 0] 0
7.01795042719044 [8 8 3 0 2] 10
11.031342787551868 [13 11 2 0 4] 11
8.424911568454709 [9 9 2 0 4] 10
9.74698670281766 [11 10 2 1 12] 10
5.954256371206496 [ 7 6 2 0 26] 6
12.804573674551168 [11 13 1 1 10] 13
8.69112254723661 [9 9 1 0 6] 10
15.360138913766692 [16 15 2 0 2] 15
5.861771966746274 [ 7 6 1 0 18] 6
14.251395206351592 [14 14 1 0 2] 14
9.331457207222437 [ 9 10 2 0 2] 10
8.32116603673902 [10 9 3 0 2] 9
13.934190478733061 [14 14 3 0 4] 14
9.033239773373271 [10 10 4 0 0] 10
7.212422329323918 [8 8 2 0 2] 8
12.183311149567002 [10 13 4 0 6] 13
11.807429434320646 [11 12 1 0 2] 11
13.150377665450387 [14 13 2 0 4] 13
7.335155154808971 [8 8 1 0 0] 11
6.532622843513421 [ 7 8 2 3 10] 10
15.647095220360393 [16 15 2 0 10] 15
7.110434831650663 [ 8 8 4 0 10] 8
9.208724381737385 [ 9 10 3 0 4] 10
9.422183577640226 [10 10 2 0 0] 10
18.78238940121379 [19 18 2 0 2] 18
-0.9216847973657908 [7 0 1 1 0] 0
9.65626033239987 [10 10 2 1 14] 9
7.967787683346893 [10 8 2 0 14] 9
9.291724585641276 [ 8 10 1 0 0] 11
9.331457207222437 [ 9 10 2 0 2] 9
7.465614146807921 [10 8 2 0 0] 9
--------------------------------------
reference:
https://www.youtube.com/watch?v=1BYu65vLKdA
Saturday, 31 August 2019
python machine learning 1
download and install anaconda
https://www.anaconda.com/distribution/
-------------------------------------
//command prompt
Microsoft Windows [Version 10.0.18362.295]
(c) 2019 Microsoft Corporation. All rights reserved.
C:\Users\bob>conda
usage: conda-script.py [-h] [-V] command ...
conda is a tool for managing and deploying applications, environments and packages.
Options:
positional arguments:
command
clean Remove unused packages and caches.
config Modify configuration values in .condarc. This is modeled
after the git config command. Writes to the user .condarc
file (C:\Users\bob\.condarc) by default.
create Create a new conda environment from a list of specified
packages.
help Displays a list of available conda commands and their help
strings.
info Display information about current conda install.
init Initialize conda for shell interaction. [Experimental]
install Installs a list of packages into a specified conda
environment.
list List linked packages in a conda environment.
package Low-level conda package utility. (EXPERIMENTAL)
remove Remove a list of packages from a specified conda environment.
uninstall Alias for conda remove.
run Run an executable in a conda environment. [Experimental]
search Search for packages and display associated information. The
input is a MatchSpec, a query language for conda packages.
See examples below.
update Updates conda packages to the latest compatible version.
upgrade Alias for conda update.
optional arguments:
-h, --help Show this help message and exit.
-V, --version Show the conda version number and exit.
conda commands available from other packages:
build
convert
debug
develop
env
index
inspect
metapackage
render
server
skeleton
verify
C:\Users\bob>python
Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32
Warning:
This Python interpreter is in a conda environment, but the environment has
not been activated. Libraries may fail to load. To activate this environment
please see https://conda.io/activation
Type "help", "copyright", "credits" or "license" for more information.
>>> exit
Use exit() or Ctrl-Z plus Return to exit
>>> exit()
C:\Users\bob>conda create -n tensor
Collecting package metadata (current_repodata.json): done
Solving environment: done
==> WARNING: A newer version of conda exists. <==
current version: 4.7.10
latest version: 4.7.11
Please update conda by running
$ conda update -n base -c defaults conda
## Package Plan ##
environment location: C:\Users\bob\Anaconda3\envs\tensor
Proceed ([y]/n)? y
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
# $ conda activate tensor
#
# To deactivate an active environment, use
#
# $ conda deactivate
C:\Users\bob>conda activate tensor
(tensor) C:\Users\bob>pip install tensorflow
Collecting tensorflow
Downloading https://files.pythonhosted.org/packages/f7/08/25e47a53692c2e0dcd2211a493ddfe9007a5cd92e175d6dffa6169a0b392/tensorflow-1.14.0-cp37-cp37m-win_amd64.whl (68.3MB)
|████████████████████████████████| 68.3MB 2.2MB/s
Collecting google-pasta>=0.1.6 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/d0/33/376510eb8d6246f3c30545f416b2263eee461e40940c2a4413c711bdf62d/google_pasta-0.1.7-py3-none-any.whl (52kB)
|████████████████████████████████| 61kB 1.3MB/s
Collecting keras-preprocessing>=1.0.5 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/28/6a/8c1f62c37212d9fc441a7e26736df51ce6f0e38455816445471f10da4f0a/Keras_Preprocessing-1.1.0-py2.py3-none-any.whl (41kB)
|████████████████████████████████| 51kB 1.1MB/s
Collecting wrapt>=1.11.1 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/23/84/323c2415280bc4fc880ac5050dddfb3c8062c2552b34c2e512eb4aa68f79/wrapt-1.11.2.tar.gz
Collecting astor>=0.6.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/d1/4f/950dfae467b384fc96bc6469de25d832534f6b4441033c39f914efd13418/astor-0.8.0-py2.py3-none-any.whl
Collecting grpcio>=1.8.6 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/32/e7/478737fd426798caad32a2abb7cc63ddb4c12908d9e03471dd3c41992b05/grpcio-1.23.0-cp37-cp37m-win_amd64.whl (1.6MB)
|████████████████████████████████| 1.6MB 6.4MB/s
Requirement already satisfied: six>=1.10.0 in c:\users\bob\appdata\roaming\python\python37\site-packages (from tensorflow) (1.12.0)
Collecting absl-py>=0.7.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/3c/0d/7cbf64cac3f93617a2b6b079c0182e4a83a3e7a8964d3b0cc3d9758ba002/absl-py-0.8.0.tar.gz (102kB)
|████████████████████████████████| 112kB 119kB/s
Collecting protobuf>=3.6.1 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/46/8b/5e77963dac4a944a0c6b198c004fac4c85d7adc54221c288fc6ca9078072/protobuf-3.9.1-cp37-cp37m-win_amd64.whl (1.0MB)
|████████████████████████████████| 1.0MB 1.3MB/s
Collecting tensorflow-estimator<1.15.0rc0,>=1.14.0rc0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/3c/d5/21860a5b11caf0678fbc8319341b0ae21a07156911132e0e71bffed0510d/tensorflow_estimator-1.14.0-py2.py3-none-any.whl (488kB)
|████████████████████████████████| 491kB 6.4MB/s
Collecting tensorboard<1.15.0,>=1.14.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/91/2d/2ed263449a078cd9c8a9ba50ebd50123adf1f8cfbea1492f9084169b89d9/tensorboard-1.14.0-py3-none-any.whl (3.1MB)
|████████████████████████████████| 3.2MB 2.2MB/s
Requirement already satisfied: wheel>=0.26 in c:\users\bob\anaconda3\lib\site-packages (from tensorflow) (0.33.4)
Requirement already satisfied: numpy<2.0,>=1.14.5 in c:\users\bob\anaconda3\lib\site-packages (from tensorflow) (1.16.4)
Collecting gast>=0.2.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/4e/35/11749bf99b2d4e3cceb4d55ca22590b0d7c2c62b9de38ac4a4a7f4687421/gast-0.2.2.tar.gz
Collecting termcolor>=1.1.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/8a/48/a76be51647d0eb9f10e2a4511bf3ffb8cc1e6b14e9e4fab46173aa79f981/termcolor-1.1.0.tar.gz
Collecting keras-applications>=1.0.6 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/71/e3/19762fdfc62877ae9102edf6342d71b28fbfd9dea3d2f96a882ce099b03f/Keras_Applications-1.0.8-py3-none-any.whl (50kB)
|████████████████████████████████| 51kB 3.4MB/s
Requirement already satisfied: setuptools in c:\users\bob\anaconda3\lib\site-packages (from protobuf>=3.6.1->tensorflow) (41.0.1)
Collecting markdown>=2.6.8 (from tensorboard<1.15.0,>=1.14.0->tensorflow)
Downloading https://files.pythonhosted.org/packages/c0/4e/fd492e91abdc2d2fcb70ef453064d980688762079397f779758e055f6575/Markdown-3.1.1-py2.py3-none-any.whl (87kB)
|████████████████████████████████| 92kB 1.5MB/s
Requirement already satisfied: werkzeug>=0.11.15 in c:\users\bob\anaconda3\lib\site-packages (from tensorboard<1.15.0,>=1.14.0->tensorflow) (0.15.4)
Requirement already satisfied: h5py in c:\users\bob\anaconda3\lib\site-packages (from keras-applications>=1.0.6->tensorflow) (2.9.0)
Building wheels for collected packages: wrapt, absl-py, gast, termcolor
Building wheel for wrapt (setup.py) ... done
Stored in directory: C:\Users\bob\AppData\Local\pip\Cache\wheels\d7\de\2e\efa132238792efb6459a96e85916ef8597fcb3d2ae51590dfd
Building wheel for absl-py (setup.py) ... done
Stored in directory: C:\Users\bob\AppData\Local\pip\Cache\wheels\9a\1e\7a\456008eb5e47fd5de792c6139df6d5b3d5f71d51c6a0b94799
Building wheel for gast (setup.py) ... done
Stored in directory: C:\Users\bob\AppData\Local\pip\Cache\wheels\5c\2e\7e\a1d4d4fcebe6c381f378ce7743a3ced3699feb89bcfbdadadd
Building wheel for termcolor (setup.py) ... done
Stored in directory: C:\Users\bob\AppData\Local\pip\Cache\wheels\7c\06\54\bc84598ba1daf8f970247f550b175aaaee85f68b4b0c5ab2c6
Successfully built wrapt absl-py gast termcolor
Installing collected packages: google-pasta, keras-preprocessing, wrapt, astor, grpcio, absl-py, protobuf, tensorflow-estimator, markdown, tensorboard, gast, termcolor, keras-applications, tensorflow
Found existing installation: wrapt 1.10.11
Uninstalling wrapt-1.10.11:
Successfully uninstalled wrapt-1.10.11
Successfully installed absl-py-0.8.0 astor-0.8.0 gast-0.2.2 google-pasta-0.1.7 grpcio-1.23.0 keras-applications-1.0.8 keras-preprocessing-1.1.0 markdown-3.1.1 protobuf-3.9.1 tensorboard-1.14.0 tensorflow-1.14.0 tensorflow-estimator-1.14.0 termcolor-1.1.0 wrapt-1.11.2
(tensor) C:\Users\bob>pip install keras
Collecting keras
Downloading https://files.pythonhosted.org/packages/f8/ba/2d058dcf1b85b9c212cc58264c98a4a7dd92c989b798823cc5690d062bb2/Keras-2.2.5-py2.py3-none-any.whl (336kB)
|████████████████████████████████| 337kB 1.1MB/s
Requirement already satisfied: h5py in c:\users\bob\anaconda3\lib\site-packages (from keras) (2.9.0)
Requirement already satisfied: numpy>=1.9.1 in c:\users\bob\anaconda3\lib\site-packages (from keras) (1.16.4)
Requirement already satisfied: keras-applications>=1.0.8 in c:\users\bob\anaconda3\lib\site-packages (from keras) (1.0.8)
Requirement already satisfied: keras-preprocessing>=1.1.0 in c:\users\bob\anaconda3\lib\site-packages (from keras) (1.1.0)
Requirement already satisfied: pyyaml in c:\users\bob\anaconda3\lib\site-packages (from keras) (5.1.1)
Requirement already satisfied: six>=1.9.0 in c:\users\bob\appdata\roaming\python\python37\site-packages (from keras) (1.12.0)
Requirement already satisfied: scipy>=0.14 in c:\users\bob\anaconda3\lib\site-packages (from keras) (1.2.1)
Installing collected packages: keras
Successfully installed keras-2.2.5
(tensor) C:\Users\bob>
---------------------------------------
#pycharm
create new project -> enter project name -> click file -> settings -> project interpreter -> click gear icon -> add -> conda environment -> existing environment -> click 3 dot icon -> change path to c:/users/(username)/Anaconda3/pythonw.exe -> ok -> apply -> waiting for package update to finish -> create new python file -> type import tensorflow, should have no error -> click add configration (top right)-> click + -> python -> name configuration -> change script path to project path/(name).py -> apply ok
-------------------------------
reference:
https://www.youtube.com/watch?v=ujTCoH21GlA
https://www.anaconda.com/distribution/
-------------------------------------
//command prompt
Microsoft Windows [Version 10.0.18362.295]
(c) 2019 Microsoft Corporation. All rights reserved.
C:\Users\bob>conda
usage: conda-script.py [-h] [-V] command ...
conda is a tool for managing and deploying applications, environments and packages.
Options:
positional arguments:
command
clean Remove unused packages and caches.
config Modify configuration values in .condarc. This is modeled
after the git config command. Writes to the user .condarc
file (C:\Users\bob\.condarc) by default.
create Create a new conda environment from a list of specified
packages.
help Displays a list of available conda commands and their help
strings.
info Display information about current conda install.
init Initialize conda for shell interaction. [Experimental]
install Installs a list of packages into a specified conda
environment.
list List linked packages in a conda environment.
package Low-level conda package utility. (EXPERIMENTAL)
remove Remove a list of packages from a specified conda environment.
uninstall Alias for conda remove.
run Run an executable in a conda environment. [Experimental]
search Search for packages and display associated information. The
input is a MatchSpec, a query language for conda packages.
See examples below.
update Updates conda packages to the latest compatible version.
upgrade Alias for conda update.
optional arguments:
-h, --help Show this help message and exit.
-V, --version Show the conda version number and exit.
conda commands available from other packages:
build
convert
debug
develop
env
index
inspect
metapackage
render
server
skeleton
verify
C:\Users\bob>python
Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32
Warning:
This Python interpreter is in a conda environment, but the environment has
not been activated. Libraries may fail to load. To activate this environment
please see https://conda.io/activation
Type "help", "copyright", "credits" or "license" for more information.
>>> exit
Use exit() or Ctrl-Z plus Return to exit
>>> exit()
C:\Users\bob>conda create -n tensor
Collecting package metadata (current_repodata.json): done
Solving environment: done
==> WARNING: A newer version of conda exists. <==
current version: 4.7.10
latest version: 4.7.11
Please update conda by running
$ conda update -n base -c defaults conda
## Package Plan ##
environment location: C:\Users\bob\Anaconda3\envs\tensor
Proceed ([y]/n)? y
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
# $ conda activate tensor
#
# To deactivate an active environment, use
#
# $ conda deactivate
C:\Users\bob>conda activate tensor
(tensor) C:\Users\bob>pip install tensorflow
Collecting tensorflow
Downloading https://files.pythonhosted.org/packages/f7/08/25e47a53692c2e0dcd2211a493ddfe9007a5cd92e175d6dffa6169a0b392/tensorflow-1.14.0-cp37-cp37m-win_amd64.whl (68.3MB)
|████████████████████████████████| 68.3MB 2.2MB/s
Collecting google-pasta>=0.1.6 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/d0/33/376510eb8d6246f3c30545f416b2263eee461e40940c2a4413c711bdf62d/google_pasta-0.1.7-py3-none-any.whl (52kB)
|████████████████████████████████| 61kB 1.3MB/s
Collecting keras-preprocessing>=1.0.5 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/28/6a/8c1f62c37212d9fc441a7e26736df51ce6f0e38455816445471f10da4f0a/Keras_Preprocessing-1.1.0-py2.py3-none-any.whl (41kB)
|████████████████████████████████| 51kB 1.1MB/s
Collecting wrapt>=1.11.1 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/23/84/323c2415280bc4fc880ac5050dddfb3c8062c2552b34c2e512eb4aa68f79/wrapt-1.11.2.tar.gz
Collecting astor>=0.6.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/d1/4f/950dfae467b384fc96bc6469de25d832534f6b4441033c39f914efd13418/astor-0.8.0-py2.py3-none-any.whl
Collecting grpcio>=1.8.6 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/32/e7/478737fd426798caad32a2abb7cc63ddb4c12908d9e03471dd3c41992b05/grpcio-1.23.0-cp37-cp37m-win_amd64.whl (1.6MB)
|████████████████████████████████| 1.6MB 6.4MB/s
Requirement already satisfied: six>=1.10.0 in c:\users\bob\appdata\roaming\python\python37\site-packages (from tensorflow) (1.12.0)
Collecting absl-py>=0.7.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/3c/0d/7cbf64cac3f93617a2b6b079c0182e4a83a3e7a8964d3b0cc3d9758ba002/absl-py-0.8.0.tar.gz (102kB)
|████████████████████████████████| 112kB 119kB/s
Collecting protobuf>=3.6.1 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/46/8b/5e77963dac4a944a0c6b198c004fac4c85d7adc54221c288fc6ca9078072/protobuf-3.9.1-cp37-cp37m-win_amd64.whl (1.0MB)
|████████████████████████████████| 1.0MB 1.3MB/s
Collecting tensorflow-estimator<1.15.0rc0,>=1.14.0rc0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/3c/d5/21860a5b11caf0678fbc8319341b0ae21a07156911132e0e71bffed0510d/tensorflow_estimator-1.14.0-py2.py3-none-any.whl (488kB)
|████████████████████████████████| 491kB 6.4MB/s
Collecting tensorboard<1.15.0,>=1.14.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/91/2d/2ed263449a078cd9c8a9ba50ebd50123adf1f8cfbea1492f9084169b89d9/tensorboard-1.14.0-py3-none-any.whl (3.1MB)
|████████████████████████████████| 3.2MB 2.2MB/s
Requirement already satisfied: wheel>=0.26 in c:\users\bob\anaconda3\lib\site-packages (from tensorflow) (0.33.4)
Requirement already satisfied: numpy<2.0,>=1.14.5 in c:\users\bob\anaconda3\lib\site-packages (from tensorflow) (1.16.4)
Collecting gast>=0.2.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/4e/35/11749bf99b2d4e3cceb4d55ca22590b0d7c2c62b9de38ac4a4a7f4687421/gast-0.2.2.tar.gz
Collecting termcolor>=1.1.0 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/8a/48/a76be51647d0eb9f10e2a4511bf3ffb8cc1e6b14e9e4fab46173aa79f981/termcolor-1.1.0.tar.gz
Collecting keras-applications>=1.0.6 (from tensorflow)
Downloading https://files.pythonhosted.org/packages/71/e3/19762fdfc62877ae9102edf6342d71b28fbfd9dea3d2f96a882ce099b03f/Keras_Applications-1.0.8-py3-none-any.whl (50kB)
|████████████████████████████████| 51kB 3.4MB/s
Requirement already satisfied: setuptools in c:\users\bob\anaconda3\lib\site-packages (from protobuf>=3.6.1->tensorflow) (41.0.1)
Collecting markdown>=2.6.8 (from tensorboard<1.15.0,>=1.14.0->tensorflow)
Downloading https://files.pythonhosted.org/packages/c0/4e/fd492e91abdc2d2fcb70ef453064d980688762079397f779758e055f6575/Markdown-3.1.1-py2.py3-none-any.whl (87kB)
|████████████████████████████████| 92kB 1.5MB/s
Requirement already satisfied: werkzeug>=0.11.15 in c:\users\bob\anaconda3\lib\site-packages (from tensorboard<1.15.0,>=1.14.0->tensorflow) (0.15.4)
Requirement already satisfied: h5py in c:\users\bob\anaconda3\lib\site-packages (from keras-applications>=1.0.6->tensorflow) (2.9.0)
Building wheels for collected packages: wrapt, absl-py, gast, termcolor
Building wheel for wrapt (setup.py) ... done
Stored in directory: C:\Users\bob\AppData\Local\pip\Cache\wheels\d7\de\2e\efa132238792efb6459a96e85916ef8597fcb3d2ae51590dfd
Building wheel for absl-py (setup.py) ... done
Stored in directory: C:\Users\bob\AppData\Local\pip\Cache\wheels\9a\1e\7a\456008eb5e47fd5de792c6139df6d5b3d5f71d51c6a0b94799
Building wheel for gast (setup.py) ... done
Stored in directory: C:\Users\bob\AppData\Local\pip\Cache\wheels\5c\2e\7e\a1d4d4fcebe6c381f378ce7743a3ced3699feb89bcfbdadadd
Building wheel for termcolor (setup.py) ... done
Stored in directory: C:\Users\bob\AppData\Local\pip\Cache\wheels\7c\06\54\bc84598ba1daf8f970247f550b175aaaee85f68b4b0c5ab2c6
Successfully built wrapt absl-py gast termcolor
Installing collected packages: google-pasta, keras-preprocessing, wrapt, astor, grpcio, absl-py, protobuf, tensorflow-estimator, markdown, tensorboard, gast, termcolor, keras-applications, tensorflow
Found existing installation: wrapt 1.10.11
Uninstalling wrapt-1.10.11:
Successfully uninstalled wrapt-1.10.11
Successfully installed absl-py-0.8.0 astor-0.8.0 gast-0.2.2 google-pasta-0.1.7 grpcio-1.23.0 keras-applications-1.0.8 keras-preprocessing-1.1.0 markdown-3.1.1 protobuf-3.9.1 tensorboard-1.14.0 tensorflow-1.14.0 tensorflow-estimator-1.14.0 termcolor-1.1.0 wrapt-1.11.2
(tensor) C:\Users\bob>pip install keras
Collecting keras
Downloading https://files.pythonhosted.org/packages/f8/ba/2d058dcf1b85b9c212cc58264c98a4a7dd92c989b798823cc5690d062bb2/Keras-2.2.5-py2.py3-none-any.whl (336kB)
|████████████████████████████████| 337kB 1.1MB/s
Requirement already satisfied: h5py in c:\users\bob\anaconda3\lib\site-packages (from keras) (2.9.0)
Requirement already satisfied: numpy>=1.9.1 in c:\users\bob\anaconda3\lib\site-packages (from keras) (1.16.4)
Requirement already satisfied: keras-applications>=1.0.8 in c:\users\bob\anaconda3\lib\site-packages (from keras) (1.0.8)
Requirement already satisfied: keras-preprocessing>=1.1.0 in c:\users\bob\anaconda3\lib\site-packages (from keras) (1.1.0)
Requirement already satisfied: pyyaml in c:\users\bob\anaconda3\lib\site-packages (from keras) (5.1.1)
Requirement already satisfied: six>=1.9.0 in c:\users\bob\appdata\roaming\python\python37\site-packages (from keras) (1.12.0)
Requirement already satisfied: scipy>=0.14 in c:\users\bob\anaconda3\lib\site-packages (from keras) (1.2.1)
Installing collected packages: keras
Successfully installed keras-2.2.5
(tensor) C:\Users\bob>
---------------------------------------
#pycharm
create new project -> enter project name -> click file -> settings -> project interpreter -> click gear icon -> add -> conda environment -> existing environment -> click 3 dot icon -> change path to c:/users/(username)/Anaconda3/pythonw.exe -> ok -> apply -> waiting for package update to finish -> create new python file -> type import tensorflow, should have no error -> click add configration (top right)-> click + -> python -> name configuration -> change script path to project path/(name).py -> apply ok
-------------------------------
reference:
https://www.youtube.com/watch?v=ujTCoH21GlA
Thursday, 29 August 2019
Thursday, 22 August 2019
Wireshark Course: Beginner to Network Admin!
icmp (ping)
decryption: edit -> preference -> protocols -> wpa key -> data readable
export media file: right click on data -> export -> save -> open with vlc
reference:
https://www.youtube.com/watch?v=JnKc6fptviI&t=293s
decryption: edit -> preference -> protocols -> wpa key -> data readable
export media file: right click on data -> export -> save -> open with vlc
reference:
https://www.youtube.com/watch?v=JnKc6fptviI&t=293s
Wednesday, 21 August 2019
Top 10 Wireshark Display Filters
ip.addr == 192.168.0.16
ip.src == 192.168.0.16
ip.dst == 192.168.0.16
dns or http
tcp.port ==80
tcp.srcport == 80
tcp.dstport == 80
tcp.analysis.flags
right click on packet -> follow -> tcp/http stream
tcp contains 163
http.request
http.response == 200
tcp.flags.syn == 1
tcp.flags.reset == 1
reference:
https://www.youtube.com/watch?v=68t07-KOH9Y
ip.src == 192.168.0.16
ip.dst == 192.168.0.16
dns or http
tcp.port ==80
tcp.srcport == 80
tcp.dstport == 80
tcp.analysis.flags
right click on packet -> follow -> tcp/http stream
tcp contains 163
http.request
http.response == 200
tcp.flags.syn == 1
tcp.flags.reset == 1
reference:
https://www.youtube.com/watch?v=68t07-KOH9Y
Tuesday, 20 August 2019
Monday, 19 August 2019
Monday, 12 August 2019
django 67 deploy to heroku
deployed to heroku
https://chuanshuoge-ecommerce.herokuapp.com/
code link
https://github.com/chuanshuoge6/ecommerce
----------------------------------------
create app on heroku
git init
git:remote -a chuanshuoge-ecommerce
------------------------
#power shell
heroku login
heroku buildpacks:set heroku/python
heroku buildpacks:add --index 1 heroku/nodejs
---------------------
copy files from react folder to django folder
------------------------
//package.json add postinstall
{
"name": "python-react",
"version": "0.1.0",
"private": true,
"dependencies": {
"antd": "^3.19.1",
"axios": "^0.19.0",
"bootstrap": "^4.3.1",
"image-to-base64": "^2.0.1",
"querystring": "^0.2.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-icons": "^3.7.0",
"react-redux": "^7.0.3",
"react-router-dom": "^5.0.1",
"react-scripts": "3.0.1",
"react-stripe-checkout": "^2.6.3",
"react-table": "^6.10.0",
"reactstrap": "^8.0.0",
"redux": "^4.0.1",
"redux-logger": "^3.0.6",
"redux-promise-middleware": "^6.1.0",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"postinstall": "npm run build"
},
"engines": {
"node": "10.12.0",
"npm": "6.10.2"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
------------------------------------
//Procfile
release: python manage.py migrate
web: gunicorn reactdjango.wsgi --log-file -
---------------------------------
//create requirement.txt
pip freeze > requirements.txt
-------------------------------
//whitenoise static storage
#power shell
pip install Django whitenoise gunicorn
#django settings
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'build', 'static'),
]
------------------------------
//tell heroku to use react as frontend
#django setting
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'build')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
#django urls
from django.contrib import admin
from django.urls import path, include, re_path
from django.views.generic import TemplateView
urlpatterns = [
path('admin/', admin.site.urls),
path('rest-auth/',include('rest_auth.urls')),
path('api/', include('music.api.urls')),
path('', include('django.contrib.auth.urls')),
re_path('.*', TemplateView.as_view(template_name='index.html'))
]
-------------------------------------------------
//allow heroku
#django settings
ALLOWED_HOSTS = ['chuanshuoge-ecommerce.herokuapp.com', '127.0.0.1']
----------------------------------
change request url to heroku
sample action
import axios from 'axios';
const config = require('../../config');
export function changePassword(token, data) {
return {
type: "change_password",
payload: axios({
method: 'post',
url: config.URL + 'rest-auth/password/change/',
headers: {
Authorization: 'Token ' + token,
},
data: data,
})
}
}
//config
module.exports = {
URL: 'https://chuanshuoge-ecommerce.herokuapp.com/',
//URL: 'http://127.0.0.1:8000/',
}
------------------------------------
#power shell
git add .
git commit -am "make it better"
git push heroku master
--------------------------------
heroku logs
PS C:\Users\bob\django\project2> git push heroku master
Enumerating objects: 21, done.
Counting objects: 100% (21/21), done.
Delta compression using up to 4 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (11/11), 1.47 KiB | 751.00 KiB/s, done.
Total 11 (delta 9), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Node.js app detected
remote:
remote: -----> Creating runtime environment
remote:
remote: NPM_CONFIG_LOGLEVEL=error
remote: NODE_ENV=production
remote: NODE_MODULES_CACHE=true
remote: NODE_VERBOSE=false
remote:
remote: -----> Installing binaries
remote: engines.node (package.json): 10.12.0
remote: engines.npm (package.json): 6.10.2
remote:
remote: Resolving node version 10.12.0...
remote: Downloading and installing node 10.12.0...
remote: Bootstrapping npm 6.10.2 (replacing 6.4.1)...
remote: npm 6.10.2 installed
remote:
remote: -----> Restoring cache
remote: - node_modules
remote:
remote: -----> Installing dependencies
remote: Installing node modules (package.json + package-lock)
remote:
remote: > python-react@0.1.0 postinstall /tmp/build_3d982eb1603cca98d4fb0a55ee743746
remote: > npm run build
remote:
remote:
remote: > python-react@0.1.0 build /tmp/build_3d982eb1603cca98d4fb0a55ee743746
remote: > react-scripts build
remote:
remote: Creating an optimized production build...
remote: Compiled with warnings.
remote:
...warnings
remote:
remote: Search for the keywords to learn more about each warning.
remote: To ignore, add // eslint-disable-next-line to the line before.
remote:
remote: File sizes after gzip:
remote:
remote: 524.18 KB build/static/js/2.17f36e06.chunk.js
remote: 75.89 KB build/static/css/2.cf0cc74f.chunk.css
remote: 9.41 KB build/static/js/main.1191967e.chunk.js
remote: 916 B build/static/css/main.b8ed5430.chunk.css
remote: 762 B build/static/js/runtime~main.a8a9905a.js
remote:
remote: The project was built assuming it is hosted at the server root.
remote: You can control this with the homepage field in your package.json.
remote: For example, add this to build it for GitHub Pages:
remote:
remote: "homepage" : "http://myname.github.io/myapp",
remote:
remote: The build folder is ready to be deployed.
remote: You may serve it with a static server:
remote:
remote: npm install -g serve
remote: serve -s build
remote:
remote: Find out more about deployment here:
remote:
remote: https://bit.ly/CRA-deploy
remote:
remote: audited 904172 packages in 103.782s
remote: found 0 vulnerabilities
remote:
remote:
remote: -----> Build
remote: Running build
remote:
remote: > python-react@0.1.0 build /tmp/build_3d982eb1603cca98d4fb0a55ee743746
remote: > react-scripts build
remote:
remote: Creating an optimized production build...
remote: Compiled with warnings.
remote:
...warnings
remote: Search for the keywords to learn more about each warning.
remote: To ignore, add // eslint-disable-next-line to the line before.
remote:
remote: File sizes after gzip:
remote:
remote: 524.18 KB build/static/js/2.17f36e06.chunk.js
remote: 75.89 KB build/static/css/2.cf0cc74f.chunk.css
remote: 9.41 KB build/static/js/main.1191967e.chunk.js
remote: 916 B build/static/css/main.b8ed5430.chunk.css
remote: 762 B build/static/js/runtime~main.a8a9905a.js
remote:
remote: The project was built assuming it is hosted at the server root.
remote: You can control this with the homepage field in your package.json.
remote: For example, add this to build it for GitHub Pages:
remote:
remote: "homepage" : "http://myname.github.io/myapp",
remote:
remote: The build folder is ready to be deployed.
remote: You may serve it with a static server:
remote:
remote: npm install -g serve
remote: serve -s build
remote:
remote: Find out more about deployment here:
remote:
remote: https://bit.ly/CRA-deploy
remote:
remote:
remote: -----> Pruning devDependencies
remote: audited 904172 packages in 12.523s
remote: found 0 vulnerabilities
remote:
remote:
remote: -----> Caching build
remote: - node_modules
remote:
remote: -----> Build succeeded!
remote: -----> Python app detected
remote: -----> Installing requirements with pip
remote:
remote: -----> $ python manage.py collectstatic --noinput
remote: 163 static files copied to '/tmp/build_3d982eb1603cca98d4fb0a55ee743746/staticfiles', 511 post-processed.
remote:
remote: -----> Discovering process types
remote: Procfile declares types -> release, web
remote:
remote: -----> Compressing...
remote: Done: 179.4M
remote: -----> Launching...
remote: ! Release command declared: this new release will not be available until the command succeeds.
remote: Released v11
remote: https://chuanshuoge-ecommerce.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
remote: Running release command...
remote:
remote: Operations to perform:
remote: Apply all migrations: admin, auth, authtoken, contenttypes, music, sessions
remote: Running migrations:
remote: No migrations to apply.
remote: Waiting for release.... done.
To https://git.heroku.com/chuanshuoge-ecommerce.git
cd76f6b..3a6cdd2 master -> master
--------------------------------------
reference:
https://simpleisbetterthancomplex.com/tutorial/2016/08/09/how-to-deploy-django-applications-on-heroku.html
https://www.codementor.io/jamesezechukwu/how-to-deploy-django-app-on-heroku-dtsee04d4
https://medium.com/@qazi/how-to-deploy-a-django-app-to-heroku-in-2018-the-easy-way-48a528d97f9c
https://devcenter.heroku.com/articles/django-app-configuration
https://chuanshuoge2.blogspot.com/2018/12/deploy-react-and-express-to-heroku.html
https://alphacoder.xyz/deploy-react-django-app-on-heroku/
https://www.youtube.com/watch?v=r0ECufCyyyw
https://librenepal.com/article/django-and-create-react-app-together-on-heroku/
https://support.dnsimple.com/articles/heroku-error-ssl/
https://chuanshuoge-ecommerce.herokuapp.com/
code link
https://github.com/chuanshuoge6/ecommerce
----------------------------------------
create app on heroku
git init
git:remote -a chuanshuoge-ecommerce
------------------------
#power shell
heroku login
heroku buildpacks:set heroku/python
heroku buildpacks:add --index 1 heroku/nodejs
---------------------
copy files from react folder to django folder
------------------------
//package.json add postinstall
{
"name": "python-react",
"version": "0.1.0",
"private": true,
"dependencies": {
"antd": "^3.19.1",
"axios": "^0.19.0",
"bootstrap": "^4.3.1",
"image-to-base64": "^2.0.1",
"querystring": "^0.2.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-icons": "^3.7.0",
"react-redux": "^7.0.3",
"react-router-dom": "^5.0.1",
"react-scripts": "3.0.1",
"react-stripe-checkout": "^2.6.3",
"react-table": "^6.10.0",
"reactstrap": "^8.0.0",
"redux": "^4.0.1",
"redux-logger": "^3.0.6",
"redux-promise-middleware": "^6.1.0",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"postinstall": "npm run build"
},
"engines": {
"node": "10.12.0",
"npm": "6.10.2"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
------------------------------------
//Procfile
release: python manage.py migrate
web: gunicorn reactdjango.wsgi --log-file -
---------------------------------
//create requirement.txt
pip freeze > requirements.txt
-------------------------------
//whitenoise static storage
#power shell
pip install Django whitenoise gunicorn
#django settings
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'build', 'static'),
]
------------------------------
//tell heroku to use react as frontend
#django setting
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'build')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
#django urls
from django.contrib import admin
from django.urls import path, include, re_path
from django.views.generic import TemplateView
urlpatterns = [
path('admin/', admin.site.urls),
path('rest-auth/',include('rest_auth.urls')),
path('api/', include('music.api.urls')),
path('', include('django.contrib.auth.urls')),
re_path('.*', TemplateView.as_view(template_name='index.html'))
]
//allow heroku
#django settings
ALLOWED_HOSTS = ['chuanshuoge-ecommerce.herokuapp.com', '127.0.0.1']
----------------------------------
change request url to heroku
sample action
import axios from 'axios';
const config = require('../../config');
export function changePassword(token, data) {
return {
type: "change_password",
payload: axios({
method: 'post',
url: config.URL + 'rest-auth/password/change/',
headers: {
Authorization: 'Token ' + token,
},
data: data,
})
}
}
//config
module.exports = {
URL: 'https://chuanshuoge-ecommerce.herokuapp.com/',
//URL: 'http://127.0.0.1:8000/',
}
------------------------------------
#power shell
git add .
git commit -am "make it better"
git push heroku master
--------------------------------
heroku logs
PS C:\Users\bob\django\project2> git push heroku master
Enumerating objects: 21, done.
Counting objects: 100% (21/21), done.
Delta compression using up to 4 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (11/11), 1.47 KiB | 751.00 KiB/s, done.
Total 11 (delta 9), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Node.js app detected
remote:
remote: -----> Creating runtime environment
remote:
remote: NPM_CONFIG_LOGLEVEL=error
remote: NODE_ENV=production
remote: NODE_MODULES_CACHE=true
remote: NODE_VERBOSE=false
remote:
remote: -----> Installing binaries
remote: engines.node (package.json): 10.12.0
remote: engines.npm (package.json): 6.10.2
remote:
remote: Resolving node version 10.12.0...
remote: Downloading and installing node 10.12.0...
remote: Bootstrapping npm 6.10.2 (replacing 6.4.1)...
remote: npm 6.10.2 installed
remote:
remote: -----> Restoring cache
remote: - node_modules
remote:
remote: -----> Installing dependencies
remote: Installing node modules (package.json + package-lock)
remote:
remote: > python-react@0.1.0 postinstall /tmp/build_3d982eb1603cca98d4fb0a55ee743746
remote: > npm run build
remote:
remote:
remote: > python-react@0.1.0 build /tmp/build_3d982eb1603cca98d4fb0a55ee743746
remote: > react-scripts build
remote:
remote: Creating an optimized production build...
remote: Compiled with warnings.
remote:
...warnings
remote:
remote: Search for the keywords to learn more about each warning.
remote: To ignore, add // eslint-disable-next-line to the line before.
remote:
remote: File sizes after gzip:
remote:
remote: 524.18 KB build/static/js/2.17f36e06.chunk.js
remote: 75.89 KB build/static/css/2.cf0cc74f.chunk.css
remote: 9.41 KB build/static/js/main.1191967e.chunk.js
remote: 916 B build/static/css/main.b8ed5430.chunk.css
remote: 762 B build/static/js/runtime~main.a8a9905a.js
remote:
remote: The project was built assuming it is hosted at the server root.
remote: You can control this with the homepage field in your package.json.
remote: For example, add this to build it for GitHub Pages:
remote:
remote: "homepage" : "http://myname.github.io/myapp",
remote:
remote: The build folder is ready to be deployed.
remote: You may serve it with a static server:
remote:
remote: npm install -g serve
remote: serve -s build
remote:
remote: Find out more about deployment here:
remote:
remote: https://bit.ly/CRA-deploy
remote:
remote: audited 904172 packages in 103.782s
remote: found 0 vulnerabilities
remote:
remote:
remote: -----> Build
remote: Running build
remote:
remote: > python-react@0.1.0 build /tmp/build_3d982eb1603cca98d4fb0a55ee743746
remote: > react-scripts build
remote:
remote: Creating an optimized production build...
remote: Compiled with warnings.
remote:
...warnings
remote: Search for the keywords to learn more about each warning.
remote: To ignore, add // eslint-disable-next-line to the line before.
remote:
remote: File sizes after gzip:
remote:
remote: 524.18 KB build/static/js/2.17f36e06.chunk.js
remote: 75.89 KB build/static/css/2.cf0cc74f.chunk.css
remote: 9.41 KB build/static/js/main.1191967e.chunk.js
remote: 916 B build/static/css/main.b8ed5430.chunk.css
remote: 762 B build/static/js/runtime~main.a8a9905a.js
remote:
remote: The project was built assuming it is hosted at the server root.
remote: You can control this with the homepage field in your package.json.
remote: For example, add this to build it for GitHub Pages:
remote:
remote: "homepage" : "http://myname.github.io/myapp",
remote:
remote: The build folder is ready to be deployed.
remote: You may serve it with a static server:
remote:
remote: npm install -g serve
remote: serve -s build
remote:
remote: Find out more about deployment here:
remote:
remote: https://bit.ly/CRA-deploy
remote:
remote:
remote: -----> Pruning devDependencies
remote: audited 904172 packages in 12.523s
remote: found 0 vulnerabilities
remote:
remote:
remote: -----> Caching build
remote: - node_modules
remote:
remote: -----> Build succeeded!
remote: -----> Python app detected
remote: -----> Installing requirements with pip
remote:
remote: -----> $ python manage.py collectstatic --noinput
remote: 163 static files copied to '/tmp/build_3d982eb1603cca98d4fb0a55ee743746/staticfiles', 511 post-processed.
remote:
remote: -----> Discovering process types
remote: Procfile declares types -> release, web
remote:
remote: -----> Compressing...
remote: Done: 179.4M
remote: -----> Launching...
remote: ! Release command declared: this new release will not be available until the command succeeds.
remote: Released v11
remote: https://chuanshuoge-ecommerce.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
remote: Running release command...
remote:
remote: Operations to perform:
remote: Apply all migrations: admin, auth, authtoken, contenttypes, music, sessions
remote: Running migrations:
remote: No migrations to apply.
remote: Waiting for release.... done.
To https://git.heroku.com/chuanshuoge-ecommerce.git
cd76f6b..3a6cdd2 master -> master
--------------------------------------
reference:
https://simpleisbetterthancomplex.com/tutorial/2016/08/09/how-to-deploy-django-applications-on-heroku.html
https://www.codementor.io/jamesezechukwu/how-to-deploy-django-app-on-heroku-dtsee04d4
https://medium.com/@qazi/how-to-deploy-a-django-app-to-heroku-in-2018-the-easy-way-48a528d97f9c
https://devcenter.heroku.com/articles/django-app-configuration
https://chuanshuoge2.blogspot.com/2018/12/deploy-react-and-express-to-heroku.html
https://alphacoder.xyz/deploy-react-django-app-on-heroku/
https://www.youtube.com/watch?v=r0ECufCyyyw
https://librenepal.com/article/django-and-create-react-app-together-on-heroku/
https://support.dnsimple.com/articles/heroku-error-ssl/
Sunday, 11 August 2019
django 66 react loading spin
Migrated to cloud, request response time is longer, display loading status with spin
logging in
fetching albums
adding item to cart
added item to cart
updating cart
cart updated
deleting item in cart
item deleted
checking out cart
receipt
fetching order history
order history fetched
fetching order detail
detail fetched
registering user
user registered
changing password
password changed
resetting password
password reset email is sent
password reset email received
chuanshuo updating album
album updated
nick deleting album
permission denied
//react/pages/orderhistoryimport React, { Component } from 'react';
import '../App.css';
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
import { getOrderHistory } from '../redux/actions/getOrderHistory';
import { message, Collapse, Spin } from 'antd';
import OrderCollapse from '../partials/orderCollapse';
class OrderHistory extends Component {
constructor(props) {
super(props);
this.state = {
spin: false,
spinTip: '',
};
}
componentDidMount() {
//start fetching database once logged in
if (this.props.loggedin) {
if (!this.props.gotOrders) {
this.props.dispatch(getOrderHistory(this.props.token));
}
//wait for 10sec, check every 0.1s to see if orders are fetched
let i = 0;
this.setState({ spin: true, spinTip: 'Fetching Orders...' })
const waitOrders = setInterval(() => {
if (this.props.gotOrders) {
clearInterval(waitOrders);
this.setState({ spin: false })
}
if (i == 100) {
message.error('fetching order history timed out.')
clearInterval(waitOrders);
this.setState({ spin: false })
}
i++;
}, 100)
}
}
render() {
if (!this.props.loggedin) {
return <Redirect to='/login' />
}
return (
<div style={{ padding: '10px', marginTop: '10px' }}>
<legend>Order History</legend>
{this.state.spin ? <Spin tip={this.state.spinTip} style={{ width: '100%', textAlign: 'center' }}></Spin> : null}
<hr />
{this.props.gotOrders ?
this.props.orders.sort((a, b) => { return new Date(b.date) - new Date(a.date) })
.map((order, index) => {
return <OrderCollapse header={order.date.toString()} extra={order.total.toString()}
orderid={order.id} key={index} />
})
: null}
</div>
);
}
}
export default connect(
(store) => {
return {
loggedin: store.login.fetched,
token: store.login.token,
gotOrders: store.orderHistory.fetched,
orders: store.orderHistory.orders,
};
}
)(OrderHistory);
------------------------------
//react/pages/resetPassword
import React, { Component } from 'react';
import '../App.css';
import { resetPassword } from '../redux/actions/resetPassword';
import { connect } from 'react-redux';
import { Input, Spin } from 'antd';
import { Button } from 'reactstrap';
import { MdEmail } from "react-icons/md";
class ResetPassword extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
};
}
inputChange = (e, p) => {
this.setState({ [p]: e.target.value });
}
formSubmit = (e) => {
e.preventDefault();
const formData = new FormData();
formData.set('email', this.state.email);
this.props.dispatch(resetPassword(formData));
}
render() {
return (
<form style={{ marginLeft: '10px', width: '300px' }}
onSubmit={(e) => this.formSubmit(e)}>
<legend>Reset Password</legend>
{this.props.sending ? <Spin tip='Reseting Password...' style={{ width: '100%', textAlign: 'center' }}></Spin> : null}
<hr />
<p style={{ color: 'red' }}>{this.props.error}</p>
{this.props.sent ? <p style={{ color: 'green' }}>Password reset email has been sent to {this.state.email}</p> : null}
<Input placeholder="email" required='required' type='email'
prefix={<MdEmail style={{ color: 'rgba(0,0,0,.25)' }} />}
onChange={(e) => this.inputChange(e, 'email')}
style={{ marginTop: '5px' }}
/>
<Button color="success" type='submit' size='sm'
style={{ marginTop: '15px' }}
>Submit</Button>
</form>
);
}
}
export default connect(
(store) => {
return {
sent: store.login.sent,
sending: store.login.sending,
error: store.login.error
};
}
)(ResetPassword);
reference:
https://ant.design/components/spin/
Wednesday, 7 August 2019
django 65 migrate to elephantSQL
register at elephantsql.com for a free postgres database on cloud
----------------------------------------
#update database
#django/settings
DATABASES = {'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'pupssizu',
'USER': 'pupssizu',
'PASSWORD': 'xxxxx',
'HOST': 'raja.db.elephantsql.com',
'PORT': '5432',
}
}
----------------------------
#pgadmin connect cloud database
pgAdmin 4 create server
lots of database on elephantSQL, locate my database
---------------------------
#django/models
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
class Album(models.Model):
artist = models.CharField(max_length=50)
album_title = models.CharField(max_length=50)
genre = models.CharField(max_length=50)
album_logo = models.TextField(default='iVBOR...')
date_posted = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
price = models.DecimalField(decimal_places=2,max_digits=5, default=10)
#form submitted without action redirect to detail
def get_absolute_url(self):
return reverse('music:detail', kwargs={'pk': self.pk})
#query album.objects.get(pk=1)
def __str__(self):
return self.album_title + ' - ' + self.artist
class Song(models.Model):
album = models.ForeignKey(Album, on_delete=models.CASCADE)
file_type = models.CharField(max_length=50)
song_title = models.CharField(max_length=50)
is_favorite = models.BooleanField(default=False)
def __str__(self):
return self.song_title
# form submitted without action redirect to detail
def get_absolute_url(self):
return reverse('music:detail', kwargs={'pk': self.album.id})
class ShoppingItem(models.Model):
shopper = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
album = models.ForeignKey(Album, on_delete=models.CASCADE, blank=True, default=1)
quantity = models.PositiveIntegerField(blank=True, default=0)
def __str__(self):
return 'shopper ' + str(self.shopper) + ' - album ' + str(self.album) + ' - quantity '+str(self.quantity)
class OrderHistory(models.Model):
order = models.CharField(max_length=50)
shopper = models.ForeignKey(User, on_delete=models.CASCADE)
total = models.DecimalField(decimal_places=2,max_digits=7, default=0)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.order)+ ' ' + str(self.shopper) + ' bought ' + str(self.total) + ' on ' + str(self.date)
#powershell python manage.py migrate
------------------------------------
#django create super user#django/models
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
class Album(models.Model):
artist = models.CharField(max_length=50)
album_title = models.CharField(max_length=50)
genre = models.CharField(max_length=50)
album_logo = models.TextField(default='iVBOR...')
date_posted = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
price = models.DecimalField(decimal_places=2,max_digits=5, default=10)
#form submitted without action redirect to detail
def get_absolute_url(self):
return reverse('music:detail', kwargs={'pk': self.pk})
#query album.objects.get(pk=1)
def __str__(self):
return self.album_title + ' - ' + self.artist
class Song(models.Model):
album = models.ForeignKey(Album, on_delete=models.CASCADE)
file_type = models.CharField(max_length=50)
song_title = models.CharField(max_length=50)
is_favorite = models.BooleanField(default=False)
def __str__(self):
return self.song_title
# form submitted without action redirect to detail
def get_absolute_url(self):
return reverse('music:detail', kwargs={'pk': self.album.id})
class ShoppingItem(models.Model):
shopper = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
album = models.ForeignKey(Album, on_delete=models.CASCADE, blank=True, default=1)
quantity = models.PositiveIntegerField(blank=True, default=0)
def __str__(self):
return 'shopper ' + str(self.shopper) + ' - album ' + str(self.album) + ' - quantity '+str(self.quantity)
class OrderHistory(models.Model):
order = models.CharField(max_length=50)
shopper = models.ForeignKey(User, on_delete=models.CASCADE)
total = models.DecimalField(decimal_places=2,max_digits=7, default=0)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.order)+ ' ' + str(self.shopper) + ' bought ' + str(self.total) + ' on ' + str(self.date)
#powershell python manage.py migrate
------------------------------------
https://docs.djangoproject.com/en/1.8/intro/tutorial02/
super user chuanshuo created
-----------------------------#django/admin
from django.contrib import admin
from .models import Album, Song, ShoppingItem, OrderHistory
admin.site.register(Album)
admin.site.register(Song)
admin.site.register(ShoppingItem)
admin.site.register(OrderHistory)
-----------------------------------------
#install django-rest-auth
https://django-rest-auth.readthedocs.io/en/latest/installation.html
# django-rest-auth configuration
#django settings
OLD_PASSWORD_FIELD_ENABLED = True
LOGIN_URL = 'http://localhost:3000/login'
#django urls
path('rest-auth/',include('rest_auth.urls')),
path('', include('django.contrib.auth.urls')),
-----------------------------------
#create registration template
https://chuanshuoge2.blogspot.com/2019/05/django-33-reset-password-by-email.html
https://chuanshuoge2.blogspot.com/2019/07/django-53-react-redux-reset-password-by.html
----------------------------------------------
#email setting
#django settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = 'zchen2014chuanshuo@gmail.com'
EMAIL_HOST_PASSWORD = 'xxxx'
---------------------------------------
#enable cors
#power shell
pip install django-cors-headers
#django setting
INSTALLED_APPS = (
...
'corsheaders',
)
MIDDLEWARE_CLASSES = (
...
'corsheaders.middleware.CorsMiddleware',
)
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
https://chuanshuoge2.blogspot.com/2019/06/django-40-django-react-redux-ftech-token.html
-------------------------------------
#create rest api
#power shell
pip install djangorestframework
pip install django-filter
#django settings
INSTALLED_APPS = [
...
'rest_framework',
]
#django urls
path('api/', include('music.api.urls')),
------------------------------------------
#django rest framework token authentication
#django settings
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework.authtoken',
'django_filters',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES':(
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
}
#powershell
python manage.py migrate
https://chuanshuoge2.blogspot.com/2019/05/django-38-rest-framework-authentication.html
--------------------------
#django/api/urls
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from music.api import apiview
from rest_framework.authtoken import views
app_name = 'musicAPI'
urlpatterns = [
path('album_list/', apiview.AlbumList.as_view(), name='AlbumList'),
path('shoppingItems/', apiview.ShoppingItemsList.as_view(), name='ShoppingItems'),
path('user_list/', apiview.UserList.as_view(), name='UserList'),
path('user_register/', apiview.UserRegister.as_view(), name='UserRegister'),
path('song_list/', apiview.SongList.as_view(), name='SongList'),
path('cart_checkout/', apiview.CartCheckout.as_view(), name='CartCheckout'),
path('order_history/', apiview.OrderHistoryList.as_view(), name='OrderHistory'),
path('album_detail/<int:pk>/', apiview.AlbumDetail.as_view(), name='AlbumDetail'),
path('shoppingItem/<int:pk>/', apiview.ShoppingItemDetail.as_view(), name='ShoppingItemDetail'),
path('orderDetail/<int:pk>/', apiview.OrderHistoryDetail.as_view(), name='OrderDetail'),
path('api-token-auth/', views.obtain_auth_token, name='AuthToken'),
path('update_password/', apiview.UpdatePassword.as_view(), name='UpdatePassword'),
]
urlpatterns = format_suffix_patterns(urlpatterns)
-------------------------------------------
#django/api/serializers
from rest_framework import serializers
from music.models import Album, Song, ShoppingItem, OrderHistory
from django.contrib.auth.models import User
from django.contrib.auth.password_validation import validate_password
class MusicSerializer(serializers.ModelSerializer):
class Meta:
model = Album
fields = '__all__'
def __init__(self, *args, **kwargs):
super(MusicSerializer, self).__init__(*args, **kwargs)
self.fields['album_logo'] = serializers.CharField(required=True)
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email')
class SongSerializer(serializers.ModelSerializer):
class Meta:
model = Song
fields = ('id', 'album', 'file_type', 'song_title', 'is_favorite')
class PasswordSerializer(serializers.Serializer):
old_password = serializers.CharField(required=True)
new_password = serializers.CharField(required=True)
def validate_new_password(self, value):
validate_password(value)
return value
class ShoppingItemsSerializer(serializers.ModelSerializer):
class Meta:
model = ShoppingItem
fields = ('id', 'shopper', 'album', 'quantity')
class OrderHistorySerializer(serializers.ModelSerializer):
class Meta:
model = OrderHistory
fields = ('id', 'order', 'shopper', 'total', 'date')
-----------------------------------------
#django/api/apiview
from music.models import Album, Song, ShoppingItem, OrderHistory
from music.api.serializers import MusicSerializer, UserSerializer, SongSerializer, PasswordSerializer, ShoppingItemsSerializer, OrderHistorySerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.http import Http404
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from rest_framework.decorators import authentication_classes, permission_classes
from django.contrib.auth.password_validation import validate_password
from django.core import exceptions
from django.forms.models import model_to_dict
from django.conf import settings
import stripe
class AlbumList(APIView):
def get(self, request, format=None):
username = request.GET.get('author')
data_length = request.GET.get('data_length')
#filter by author
if username==None:
albums = Album.objects.all()
else:
author_id = get_object_or_404(User, username=username).pk
albums = Album.objects.filter(author=author_id).order_by('-date_posted')
#filter by data length
if data_length!=None:
try:
int(data_length)
except ValueError:
return Response('data length is invvalid', status=status.HTTP_406_NOT_ACCEPTABLE)
else:
albums = albums[:int(data_length)]
serializer = MusicSerializer(albums, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = MusicSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class AlbumDetail(APIView):
def get_object(self, pk):
try:
return Album.objects.get(pk=pk)
except Album.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
album = self.get_object(pk)
serializer = MusicSerializer(album)
return Response(serializer.data)
def put(self, request, pk, format=None):
album = self.get_object(pk)
#only owner can edit
if album.author != request.user:
return Response({"detail": "You do not have permission to perform this action."},
status= status.HTTP_403_FORBIDDEN)
serializer = MusicSerializer(album, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
album = self.get_object(pk)
# only owner can delete
if album.author != request.user:
return Response({"detail": "You do not have permission to perform this action."},
status=status.HTTP_403_FORBIDDEN)
album.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class UserList(APIView):
def get(self, request, format=None):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
@authentication_classes([])
@permission_classes([])
class UserRegister(APIView):
def post(self, request, format=None):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
#email has to be unique
email = request.POST.get('email')
unique_email = User.objects.filter(email=email).count()
if(unique_email > 0):
return Response({'email': 'email already exist'}, status=status.HTTP_406_NOT_ACCEPTABLE)
#validate password
password = request.POST.get('password')
try:
validate_password(password)
except exceptions.ValidationError as e:
return Response(e.messages, status=status.HTTP_406_NOT_ACCEPTABLE)
else:
pass
#register new user
serializer.save()
#set password for new user
username = serializer.data.get('username')
newUser = User.objects.get(username=username)
newUser.set_password(password)
#save password for new user
newUser.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class SongList(APIView):
def get(self, request, format=None):
songs = Song.objects.all()
serializer = SongSerializer(songs, many=True)
return Response(serializer.data)
class UpdatePassword(APIView):
def get_object(self, queryset=None):
return self.request.user
def put(self, request, *args, **kwargs):
currentUser = self.get_object()
serializer = PasswordSerializer(data=request.data)
if serializer.is_valid():
# Check old password
old_password = serializer.data.get("old_password")
if not currentUser.check_password(old_password):
return Response({"old_password": ["Wrong password."]},
status=status.HTTP_400_BAD_REQUEST)
# set_password also hashes the password that the user will get
currentUser.set_password(serializer.data.get("new_password"))
currentUser.save()
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class ShoppingItemsList(APIView):
def get(self, request, format=None):
#for privacy, only return shoppers items
shoppingItems = ShoppingItem.objects.filter(shopper=request.user)
serializer = ShoppingItemsSerializer(shoppingItems, many=True)
return Response(serializer.data)
def post(self, request, format=None):
#customer has item in cart
try:
revisitedItem = ShoppingItem.objects.get(shopper=request.user, album=request.data.get('album'))
revisitedItem.quantity= int(request.data.get('quantity')) + revisitedItem.quantity
serializer = ShoppingItemsSerializer(data=model_to_dict( revisitedItem ))
if serializer.is_valid():
# update database
revisitedItem.save()
return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#customer select new item
except exceptions.ObjectDoesNotExist:
serializer = ShoppingItemsSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class ShoppingItemDetail(APIView):
def get_object(self, pk):
try:
return ShoppingItem.objects.get(pk=pk)
except ShoppingItem.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
shoppingItem = self.get_object(pk)
serializer = ShoppingItemsSerializer(shoppingItem)
return Response(serializer.data)
def put(self, request, pk, format=None):
shoppintItem = self.get_object(pk)
#only owner can edit
if shoppintItem.shopper != request.user:
return Response({"detail": "You do not have permission to perform this action."},
status= status.HTTP_403_FORBIDDEN)
serializer = ShoppingItemsSerializer(shoppintItem, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
shoppingItem = self.get_object(pk)
# only owner can delete
if shoppingItem.shopper != request.user:
return Response({"detail": "You do not have permission to perform this action."},
status=status.HTTP_403_FORBIDDEN)
shoppingItem.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class CartCheckout(APIView):
def post(self, request, format=None):
stripe.api_key = settings.STRIPE_SECRET_KEY
token = request.data.get('token')
cart = request.data.get('cart')
try:
customer=stripe.Customer.create(email=token['email'],source=token['id'])
charge=stripe.Charge.create(
amount=int(cart['price']*100),
currency='cad',
receipt_email= token['email'],
customer=customer.id,
metadata=cart['items'],
)
return Response(charge, status=status.HTTP_202_ACCEPTED)
except Exception as e:
return Response(e, status=status.HTTP_400_BAD_REQUEST)
class OrderHistoryList(APIView):
def get(self, request, format=None):
orders = OrderHistory.objects.filter(shopper=request.user)
serializer = OrderHistorySerializer(orders, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = OrderHistorySerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class OrderHistoryDetail(APIView):
def get_object(self, pk):
try:
return OrderHistory.objects.get(pk=pk)
except OrderHistory.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
stripe.api_key = settings.STRIPE_SECRET_KEY
order = self.get_object(pk)
try:
#order is a model boject, request is a python dictionary
charge=stripe.Charge.retrieve(order.order)
return Response(charge, status=status.HTTP_200_OK)
except Exception as e:
return Response(e, status=status.HTTP_400_BAD_REQUEST)
-------------------------------------------------------
#stripe
#power shell
pip install stripe
#django settings
STRIPE_SECRET_KEY = 'sk_test_xxxxxx'
https://chuanshuoge2.blogspot.com/2019/07/django-62-stripe-checkout.html
Subscribe to:
Posts (Atom)