From a719c356894405450d64171a785f2ff2ac8d5c18 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 6 Dec 2020 12:11:35 +0200 Subject: [PATCH 01/34] added text-pro-app project --- text-pro-app/README.md | 2 ++ text-pro-app/textpro.py | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 text-pro-app/README.md create mode 100644 text-pro-app/textpro.py diff --git a/text-pro-app/README.md b/text-pro-app/README.md new file mode 100644 index 0000000..4af6d6d --- /dev/null +++ b/text-pro-app/README.md @@ -0,0 +1,2 @@ +# Text Pro Demo App +Description: very basic demo app covering the Python syntax: functions, loops, statements \ No newline at end of file diff --git a/text-pro-app/textpro.py b/text-pro-app/textpro.py new file mode 100644 index 0000000..14a6387 --- /dev/null +++ b/text-pro-app/textpro.py @@ -0,0 +1,42 @@ +# Text Pro Demo App +# Description: very basic demo app covering the Python syntax: functions, loops, statements + +# Author: Valeriy B. +# Language: Python + + +# Question words +def question_words(msg): + questions_list = ["what", "where", "when", "which", "who", "whom", "whose", "why", "how", "is", "are", "will"] + hello_list = ["hello", "hi", "howdy"] + if msg == "hello": + return hello_list + elif msg == "questions": + return questions_list + + +# App logic +def textpro(msg): + + # Result list + result_list = [] + + # Looping while message not equals '!end' + while msg != ("!end"): + + # Typing messages + msg = input("Type something: ") + + # Verifying if first typed word is not in question words list + if msg.split()[0] in question_words("questions"): + result_list.append(msg.capitalize() + "?") + elif msg.split()[0] in question_words("hello"): + result_list.append(msg.capitalize() + "!") + else: + result_list.append(msg.capitalize() + ".") + + # Printing the the list converted into string without the last element + print(" ".join(result_list[:-1])) + + +textpro("") \ No newline at end of file From 453c78b48567692d4f984a899bbade3a00a9a7a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 6 Dec 2020 12:18:17 +0200 Subject: [PATCH 02/34] added Text Pro App to README.md file --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d72aff..d82e6fd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Python Demo Projects * [Movie Collection App](https://github.com/valeriybercha/python-demos/tree/master/movie-collection-app) -* [Tic-Tac-Toe game](https://github.com/valeriybercha/python-demos/tree/master/tic-tac-toe) \ No newline at end of file +* [Tic-Tac-Toe game](https://github.com/valeriybercha/python-demos/tree/master/tic-tac-toe) +* [Text Pro App](https://github.com/valeriybercha/python-demos/tree/master/text-pro-app) \ No newline at end of file From 89221f2b63ead493cd26d317cd053f582b0aba72 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Mon, 4 Jan 2021 15:53:22 +0200 Subject: [PATCH 03/34] added tkinter projects folder --- tkinter/README.md | 13 +++++++++++++ tkinter/first-program.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tkinter/README.md create mode 100644 tkinter/first-program.py diff --git a/tkinter/README.md b/tkinter/README.md new file mode 100644 index 0000000..db661c4 --- /dev/null +++ b/tkinter/README.md @@ -0,0 +1,13 @@ +# Creating GUI applications with Python module tkinter + +Content: + +#### 1. Hello World application with Tkinter module - [first-program.py](#) + +Topics covered: +* module import +* creating the main window +* setting window size +* creating a button +* mainloop + diff --git a/tkinter/first-program.py b/tkinter/first-program.py new file mode 100644 index 0000000..2867595 --- /dev/null +++ b/tkinter/first-program.py @@ -0,0 +1,31 @@ +# 'Hello, World' application with Tkinter module +# Author: Valeriy B. +# Language: Python 3.8.5 + + +# importing the module +from tkinter import * + + +# creating 'hello world' function +def hello_world(event): + print("Hello, World! First app with Tkinter") + + +# creating the main window +window = Tk() + + +# setting window size +window.geometry('150x150') + + +# Button settings +but = Button(window) +but['text'] = "Print" +but.bind("", hello_world) +but.pack() + + +# mainloop +window.mainloop() From 0de0ce6ebfe1c37c2de0e7460439dd06dc3fb661 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Mon, 4 Jan 2021 18:12:11 +0200 Subject: [PATCH 04/34] added feedback-form.py file --- tkinter/feedback-form.py | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tkinter/feedback-form.py diff --git a/tkinter/feedback-form.py b/tkinter/feedback-form.py new file mode 100644 index 0000000..74afdcd --- /dev/null +++ b/tkinter/feedback-form.py @@ -0,0 +1,54 @@ +# Feedback form with Tkinter module +# Author: Valeriy B. +# Language: Python 3.8.5 + +# importing the module +from tkinter import * + + +# creating 'print' information function +def print_info(): + user_email = email_input_field.get() + user_message = message_text_field.get('1.0', END) # for text fields you have to specify the begin and the end of a text to print + print(f"{user_email}: {user_message}") + + +# creating the main window +window = Tk() +window.title("Feedback Form") + + +# setting window size +window.geometry('400x400') + + +# creating a label for 'email' input field +email_label = Label(window, text="Your email:", bg='lemon chiffon') + + +# entry input field settings +email_input_field = Entry(window, width=20, bd=3, bg='lemon chiffon') + + +# 'comments' label settings +message_label = Label(window, text='Your message:') + + +# 'input field' settings +message_text_field = Text(window, width=25, height='5', wrap=WORD) + + +# button settings +submit = Button(window, text='Send', width=20, bg='sky blue', command=print_info) + + +# declaring widgets position +email_label.pack() +email_input_field.pack() +message_label.pack() +message_text_field.pack() +submit.pack() + + +# mainloop +window.mainloop() \ No newline at end of file From a20a759522ad15623de4f9e03d6c3d1540de6986 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Mon, 4 Jan 2021 18:13:08 +0200 Subject: [PATCH 05/34] added feedback form app to README file --- tkinter/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tkinter/README.md b/tkinter/README.md index db661c4..216cd04 100644 --- a/tkinter/README.md +++ b/tkinter/README.md @@ -2,7 +2,7 @@ Content: -#### 1. Hello World application with Tkinter module - [first-program.py](#) +#### 1. 'Hello World' application with Tkinter module - [first-program.py](https://github.com/valeriybercha/python-demos/blob/master/tkinter/first-program.py) Topics covered: * module import @@ -11,3 +11,9 @@ Topics covered: * creating a button * mainloop + +#### 2. 'Feedback Form' application with Tkinter module - [feedback-form.py](https://github.com/valeriybercha/python-demos/blob/master/tkinter/feedback-form.py) + +Topics covered: +* creating labels +* creating input fields \ No newline at end of file From f026bd35af09d7d41dc79f15945651f9954ba7d8 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Mon, 4 Jan 2021 18:18:08 +0200 Subject: [PATCH 06/34] added tkinter project to README file --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d82e6fd..30bacff 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,5 @@ * [Movie Collection App](https://github.com/valeriybercha/python-demos/tree/master/movie-collection-app) * [Tic-Tac-Toe game](https://github.com/valeriybercha/python-demos/tree/master/tic-tac-toe) -* [Text Pro App](https://github.com/valeriybercha/python-demos/tree/master/text-pro-app) \ No newline at end of file +* [Text Pro App](https://github.com/valeriybercha/python-demos/tree/master/text-pro-app) +* [Tkinter](https://github.com/valeriybercha/python-demos/tree/master/tkinter) \ No newline at end of file From d63eb5b4a6aa8203441dae37bf423b43aa73427e Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Tue, 5 Jan 2021 19:29:34 +0200 Subject: [PATCH 07/34] added radio-buttons-checkboxes.py file --- tkinter/radio-buttons-checkboxes.py | 74 +++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tkinter/radio-buttons-checkboxes.py diff --git a/tkinter/radio-buttons-checkboxes.py b/tkinter/radio-buttons-checkboxes.py new file mode 100644 index 0000000..142eed4 --- /dev/null +++ b/tkinter/radio-buttons-checkboxes.py @@ -0,0 +1,74 @@ +# Feedback form with Tkinter module +# Author: Valeriy B. +# Language: Python 3.8.5 + + +# importing the module +from tkinter import * + + +# logic functions +def radiobuttons(): + if var.get() == 0: + return "0-10" + elif var.get() == 1: + return "11-20" + elif var.get() == 2: + return "21-30" + elif var.get() == 3: + return "31-40" + + +def checkboxes(): + check_list = [] + if c1.get() == 1: + check_list.append("RED") + if c2.get() == 1: + check_list.append("BLUE") + if c3.get() == 1: + check_list.append("GREEN") + if c4.get() == 1: + check_list.append("YELLOW") + return " ".join(check_list) + +# printing the result +def print_result(): + r = radiobuttons() + c = checkboxes() + print("Result: Pieces - " + r + " , Colors - " + c) + +# creating the main window +window = Tk() +window.title("Feedback Form") + + +# setting window size +window.geometry('400x400') + + +# creating radio buttons section +radio_label = Label(window, text='How many pieces?').pack() +var = IntVar() +var.set(1) +rad0 = Radiobutton(window, text='0-10', variable = var, value=0).pack() +rad1 = Radiobutton(window, text='11-20', variable = var, value=1).pack() +rad2 = Radiobutton(window, text='21-30', variable = var, value=2).pack() +rad3 = Radiobutton(window, text='31-40', variable = var, value=3).pack() + + +# creating checkboxes section +checkbox_label = Label(window, text='Pick a color').pack() +c1 = IntVar() +c2 = IntVar() +c3 = IntVar() +c4 = IntVar() +che1 = Checkbutton(window, text='RED', bg='red', variable=c1, onvalue=1, offvalue=0).pack() +che2 = Checkbutton(window, text='BLUE', bg='blue', variable=c2, onvalue=1, offvalue=0).pack() +che3 = Checkbutton(window, text='GREEN', bg='green', variable=c3, onvalue=1, offvalue=0).pack() +che4 = Checkbutton(window, text='YELLOW', bg='yellow', variable=c4, onvalue=1, offvalue=0).pack() + +# submit button +submit = Button(window, text='Send', width=20, bg='sky blue', command=print_result).pack() + + +window.mainloop() \ No newline at end of file From 7e2b07287f79d2d1e471ccbc6058604dbb0e43cf Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Tue, 5 Jan 2021 19:32:50 +0200 Subject: [PATCH 08/34] added radio-buttons-checkbxes link to README file --- tkinter/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tkinter/README.md b/tkinter/README.md index 216cd04..ea729e6 100644 --- a/tkinter/README.md +++ b/tkinter/README.md @@ -2,6 +2,7 @@ Content: + #### 1. 'Hello World' application with Tkinter module - [first-program.py](https://github.com/valeriybercha/python-demos/blob/master/tkinter/first-program.py) Topics covered: @@ -16,4 +17,11 @@ Topics covered: Topics covered: * creating labels -* creating input fields \ No newline at end of file +* creating input fields + + +#### 3. 'Radio buttons and checkboxes' application with Tkinter module - [radio-buttons-checkboxes.py](https://github.com/valeriybercha/python-demos/blob/master/tkinter/radio-buttons-checkboxes.py) + +Topics covered: +* creating radioboxes +* creating checkboxes \ No newline at end of file From 08ababb240550bf08aea32447ceed7f13feefc15 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Wed, 6 Jan 2021 16:29:08 +0200 Subject: [PATCH 09/34] minor changes to radio-buttons-checkboxes file --- tkinter/radio-buttons-checkboxes.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tkinter/radio-buttons-checkboxes.py b/tkinter/radio-buttons-checkboxes.py index 142eed4..5ce0b27 100644 --- a/tkinter/radio-buttons-checkboxes.py +++ b/tkinter/radio-buttons-checkboxes.py @@ -7,7 +7,7 @@ from tkinter import * -# logic functions +# logic for radiobuttons def radiobuttons(): if var.get() == 0: return "0-10" @@ -19,6 +19,7 @@ def radiobuttons(): return "31-40" +# logic for checkboxes def checkboxes(): check_list = [] if c1.get() == 1: @@ -31,12 +32,14 @@ def checkboxes(): check_list.append("YELLOW") return " ".join(check_list) + # printing the result def print_result(): r = radiobuttons() c = checkboxes() print("Result: Pieces - " + r + " , Colors - " + c) + # creating the main window window = Tk() window.title("Feedback Form") @@ -67,6 +70,7 @@ def print_result(): che3 = Checkbutton(window, text='GREEN', bg='green', variable=c3, onvalue=1, offvalue=0).pack() che4 = Checkbutton(window, text='YELLOW', bg='yellow', variable=c4, onvalue=1, offvalue=0).pack() + # submit button submit = Button(window, text='Send', width=20, bg='sky blue', command=print_result).pack() From 6f9c209b2fafdf3450bd44e8eec9ff11ea361e04 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Sun, 17 Jan 2021 23:51:33 +0200 Subject: [PATCH 10/34] added scale.py file --- tkinter/scale.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tkinter/scale.py diff --git a/tkinter/scale.py b/tkinter/scale.py new file mode 100644 index 0000000..43ba397 --- /dev/null +++ b/tkinter/scale.py @@ -0,0 +1,31 @@ +# 'Scale' with Tkinter module +# Author: Valeriy B. +# Language: Python 3.8.5 + + +# importing the module +from tkinter import * + + +# creating the main window +root = Tk() +root.title("Scale") + + +# creating frameworks +fra1 = Frame(root,width=700,height=200,bg="lightgreen",bd=20) +fra2 = Frame(root,width=300,height=50,bg="green",bd=20) +fra3 = Frame(root) + + +# creating a scale +sca1 = Scale(fra1,orient=HORIZONTAL,length=300,from_=0,to=100,tickinterval=10,resolution=5).pack() +ent1 = Entry(fra2,width=20).pack() + + +# packing the frames widgets +fra1.pack() +fra2.pack() + + +root.mainloop() \ No newline at end of file From 1c8e4deb27212e07df633585c46ba9243a572130 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Sun, 17 Jan 2021 23:54:19 +0200 Subject: [PATCH 11/34] added scale file to README --- tkinter/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tkinter/README.md b/tkinter/README.md index ea729e6..a99548a 100644 --- a/tkinter/README.md +++ b/tkinter/README.md @@ -24,4 +24,10 @@ Topics covered: Topics covered: * creating radioboxes -* creating checkboxes \ No newline at end of file +* creating checkboxes + + +#### 4. 'Scale' application with Tkinter module - [scale.py](https://github.com/valeriybercha/python-demos/blob/master/tkinter/scale.py) + +Topics covered: +* Creating scale in tkinter \ No newline at end of file From e3c611804a56a8e07d9a077203e3af1b23174661 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Mon, 18 Jan 2021 00:18:24 +0200 Subject: [PATCH 12/34] added scrollbar.py file --- tkinter/scrollbar.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tkinter/scrollbar.py diff --git a/tkinter/scrollbar.py b/tkinter/scrollbar.py new file mode 100644 index 0000000..a33f9d8 --- /dev/null +++ b/tkinter/scrollbar.py @@ -0,0 +1,28 @@ +# 'Scrollbar' with Tkinter module +# Author: Valeriy B. +# Language: Python 3.8.5 + + +# importing the module +from tkinter import * + + +# creating the main window +root = Tk() +root.title("Scrollbar") + + +# creating a scrollbar +scb = Scrollbar(root) +scb.pack(side = RIGHT, fill = Y) + + +# creating a text box +txt = Text(root,width=40,height=3,font='12', yscrollcommand = scb.set) + + +txt.pack() +scb.config(command = txt.yview) + + +root.mainloop() \ No newline at end of file From bed6909185cd14b1e87572f3ea8e816af8ce08cc Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Mon, 18 Jan 2021 00:21:01 +0200 Subject: [PATCH 13/34] minor changes to README file --- tkinter/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tkinter/README.md b/tkinter/README.md index a99548a..4978bc2 100644 --- a/tkinter/README.md +++ b/tkinter/README.md @@ -30,4 +30,10 @@ Topics covered: #### 4. 'Scale' application with Tkinter module - [scale.py](https://github.com/valeriybercha/python-demos/blob/master/tkinter/scale.py) Topics covered: -* Creating scale in tkinter \ No newline at end of file +* Creating scale in tkinter + + +#### 5. 'Scrollbar' application with Tkinter module - [scrollbar.py](https://github.com/valeriybercha/python-demos/blob/master/tkinter/scrollbar.py) + +Topics covered: +* Creating a scrollbar in tkinter \ No newline at end of file From 1e536fba74ae408612f035f037df963745162fdc Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Tue, 19 Jan 2021 22:50:55 +0200 Subject: [PATCH 14/34] added toplevel file --- tkinter/toplevel.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tkinter/toplevel.py diff --git a/tkinter/toplevel.py b/tkinter/toplevel.py new file mode 100644 index 0000000..4e35cb1 --- /dev/null +++ b/tkinter/toplevel.py @@ -0,0 +1,27 @@ +# 'Toplevel' window with Tkinter module +# Author: Valeriy B. +# Language: Python 3.8.5 + + +# importing the module +from tkinter import * + + +# creating the main window +root = Tk() +root.title("Toplevel") + + +# creating the first toplevel window +win1 = Toplevel(root, relief = SUNKEN, bd = 10, bg = "lightblue") +win1.title("First toplevel window") +win1.minsize(width=400, height=200) + + +# creating the second toplevel window +win1 = Toplevel(root, relief = SUNKEN, bd = 10, bg = "lightyellow") +win1.title("Second toplevel window") +win1.minsize(width=600, height=400) + + +root.mainloop() \ No newline at end of file From fe95a8b3027789f2504dbf24d372248fd135ecd0 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Tue, 19 Jan 2021 22:59:26 +0200 Subject: [PATCH 15/34] minor changes to README file --- tkinter/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tkinter/README.md b/tkinter/README.md index 4978bc2..09c2054 100644 --- a/tkinter/README.md +++ b/tkinter/README.md @@ -36,4 +36,10 @@ Topics covered: #### 5. 'Scrollbar' application with Tkinter module - [scrollbar.py](https://github.com/valeriybercha/python-demos/blob/master/tkinter/scrollbar.py) Topics covered: -* Creating a scrollbar in tkinter \ No newline at end of file +* Creating a scrollbar in tkinter + + +#### 6. 'Toplevel' app with Tkinter module - [toplevel.py](https://github.com/valeriybercha/python-demos/blob/master/tkinter/toplevel.py) + +Topics covered: +* Creating toplevel windows with Tkinter From d73f3a8fce8ef7f34553cd1b8a2634409c48caee Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Fri, 29 Jan 2021 22:05:41 +0200 Subject: [PATCH 16/34] added gui-calculator project --- gui-calculator/.vscode/settings.json | 4 ++ gui-calculator/calculator.py | 76 +++++++++++++++++++++++++++ gui-calculator/screen.png | Bin 0 -> 107716 bytes 3 files changed, 80 insertions(+) create mode 100644 gui-calculator/.vscode/settings.json create mode 100644 gui-calculator/calculator.py create mode 100644 gui-calculator/screen.png diff --git a/gui-calculator/.vscode/settings.json b/gui-calculator/.vscode/settings.json new file mode 100644 index 0000000..cc67606 --- /dev/null +++ b/gui-calculator/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "python.linting.pylintEnabled": true, + "python.linting.enabled": true +} \ No newline at end of file diff --git a/gui-calculator/calculator.py b/gui-calculator/calculator.py new file mode 100644 index 0000000..ba1bc92 --- /dev/null +++ b/gui-calculator/calculator.py @@ -0,0 +1,76 @@ +# GUI Calculator on Python with Tkinter +# Author: Valeriy B. +# Language: Python 3.8.5 + + +from tkinter import * + +# creating the main window +root = Tk() +root.title("ValiCalc") + +# setting window size +root.geometry('450x390') + +# defining a global variable +num = '' + +input_text = StringVar() + +def btn_equal(): + global num + if num[-1] == "0" and num[-2] == "/": + result = "Division by 0 is not possible" + else: + result = str(eval(num)) + input_text.set(result) + num = "" + +def btn_click(arg): + global num + num = num + str(arg) + input_text.set(num) + +def btn_clear(): + global num + num = "" + input_text.set("") + +input_frame = Frame(root, width = 312, height = 50, bd = 0, highlightbackground = "black", highlightcolor = "black", highlightthickness = 1) +input_frame.pack(side = TOP) + +input_field = Entry(input_frame, font = ('arial', 18, 'bold'), textvariable = input_text, width = 50, bg = "#eee", bd = 0, justify = RIGHT) +input_field.grid(row = 0, column = 0) +input_field.pack(ipady = 10) + +btn_frame = Frame(root, width = 312, height = 272.5, bg = "grey") +btn_frame.pack() + +# 1st row buttons +b_clear = Button(btn_frame, text = "Clear", fg = "black", width = 37, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_clear()).grid(row = 0, column = 0, columnspan = 3, padx = 1, pady = 1) +b_divide = Button(btn_frame, text = "/", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_click("/")).grid(row = 0, column = 3, padx = 1, pady = 1) + +# 2nd row buttons +b_seven = Button(btn_frame, text = "7", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(7)).grid(row = 1, column = 0, padx = 1, pady = 1) +b_eight = Button(btn_frame, text = "8", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(8)).grid(row = 1, column = 1, padx = 1, pady = 1) +b_nine = Button(btn_frame, text = "9", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(9)).grid(row = 1, column = 2, padx = 1, pady = 1) +b_multiply = Button(btn_frame, text = "*", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_click("*")).grid(row = 1, column = 3, padx = 1, pady = 1) + +# 3rd row buttons +b_four = Button(btn_frame, text = "4", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(4)).grid(row = 2, column = 0, padx = 1, pady = 1) +b_five = Button(btn_frame, text = "5", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(5)).grid(row = 2, column = 1, padx = 1, pady = 1) +b_six = Button(btn_frame, text = "6", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(6)).grid(row = 2, column = 2, padx = 1, pady = 1) +b_minus = Button(btn_frame, text = "-", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_click("-")).grid(row = 2, column = 3, padx = 1, pady = 1) + +# 4th row buttons +b_one = Button(btn_frame, text = "1", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(1)).grid(row = 3, column = 0, padx = 1, pady = 1) +b_two = Button(btn_frame, text = "2", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(2)).grid(row = 3, column = 1, padx = 1, pady = 1) +b_three = Button(btn_frame, text = "3", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(3)).grid(row = 3, column = 2, padx = 1, pady = 1) +b_plus = Button(btn_frame, text = "+", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_click("+")).grid(row = 3, column = 3, padx = 1, pady = 1) + +# 5th row buttons +b_zero = Button(btn_frame, text = "0", fg = "black", width = 23, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(0)).grid(row = 4, column = 0, columnspan = 2, padx = 1, pady = 1) +b_point = Button(btn_frame, text = ".", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_click(".")).grid(row = 4, column = 2, padx = 1, pady = 1) +b_equals = Button(btn_frame, text = "=", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_equal()).grid(row = 4, column = 3, padx = 1, pady = 1) + +root.mainloop() \ No newline at end of file diff --git a/gui-calculator/screen.png b/gui-calculator/screen.png new file mode 100644 index 0000000000000000000000000000000000000000..b3ca6db1e2650ee88c85909e4387e9707c935a52 GIT binary patch literal 107716 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
%cWJ;f16Ok-y%@KkoPHOJA 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%0D#@gU@<{+ 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 Date: Fri, 29 Jan 2021 22:09:03 +0200 Subject: [PATCH 17/34] added .gitignore file --- gui-calculator/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 gui-calculator/.gitignore diff --git a/gui-calculator/.gitignore b/gui-calculator/.gitignore new file mode 100644 index 0000000..1d74e21 --- /dev/null +++ b/gui-calculator/.gitignore @@ -0,0 +1 @@ +.vscode/ From 42f32382964ff29b989d61c896b8cc39db11e089 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Fri, 29 Jan 2021 22:17:43 +0200 Subject: [PATCH 18/34] added gui-calculator project --- gui-calculator/.vscode/settings.json | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 gui-calculator/.vscode/settings.json diff --git a/gui-calculator/.vscode/settings.json b/gui-calculator/.vscode/settings.json deleted file mode 100644 index cc67606..0000000 --- a/gui-calculator/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "python.linting.pylintEnabled": true, - "python.linting.enabled": true -} \ No newline at end of file From 4c090af79fa6eb2007f2052e2569d61e26906f69 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Fri, 29 Jan 2021 22:27:03 +0200 Subject: [PATCH 19/34] added README file --- gui-calculator/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 gui-calculator/README.md diff --git a/gui-calculator/README.md b/gui-calculator/README.md new file mode 100644 index 0000000..c7a5e5c --- /dev/null +++ b/gui-calculator/README.md @@ -0,0 +1,5 @@ +# GUI Calculator witj Tkinter module + +Screenshot: + +![gui calculator with tkinter](https://github.com/valeriybercha/python-demos/blob/master/gui-calculator/screen.png) From dff9d07377cd7b9bd83fd09f22f63c4866a80635 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Fri, 29 Jan 2021 22:28:57 +0200 Subject: [PATCH 20/34] added README file --- gui-calculator/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui-calculator/README.md b/gui-calculator/README.md index c7a5e5c..0e79bd8 100644 --- a/gui-calculator/README.md +++ b/gui-calculator/README.md @@ -1,4 +1,4 @@ -# GUI Calculator witj Tkinter module +# GUI Calculator with Tkinter module Screenshot: From 32e2554a056230d771c9a53ded60b46be65ec307 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Fri, 29 Jan 2021 22:37:03 +0200 Subject: [PATCH 21/34] added GUI Calculator to README file --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 30bacff..10eb37d 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,5 @@ * [Movie Collection App](https://github.com/valeriybercha/python-demos/tree/master/movie-collection-app) * [Tic-Tac-Toe game](https://github.com/valeriybercha/python-demos/tree/master/tic-tac-toe) * [Text Pro App](https://github.com/valeriybercha/python-demos/tree/master/text-pro-app) -* [Tkinter](https://github.com/valeriybercha/python-demos/tree/master/tkinter) \ No newline at end of file +* [Tkinter](https://github.com/valeriybercha/python-demos/tree/master/tkinter) +* [GUI Calculator](https://github.com/valeriybercha/python-demos/tree/master/gui-calculator) From ac0fcdc1ac4d7b703b4cba1cc04eca2032ec4cef Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Sun, 31 Jan 2021 13:05:42 +0200 Subject: [PATCH 22/34] added password generator project --- password-generator/README.md | 3 ++ password-generator/generator.py | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 password-generator/README.md create mode 100644 password-generator/generator.py diff --git a/password-generator/README.md b/password-generator/README.md new file mode 100644 index 0000000..3d64b63 --- /dev/null +++ b/password-generator/README.md @@ -0,0 +1,3 @@ +# Password Generator on Python + +User input password generator with the possibility to add symbols, numbers or uppercase letters. \ No newline at end of file diff --git a/password-generator/generator.py b/password-generator/generator.py new file mode 100644 index 0000000..6b33e98 --- /dev/null +++ b/password-generator/generator.py @@ -0,0 +1,53 @@ +# STRONG PASSWORD GENERATOR +# Author: Valeriy B. +# Language: Python 3.8.5 + +import random + +# password generator function logic +def generator(arr): + + # initiating a count variable + count = arr[0] - sum([1 for i in arr[1:] if i.lower() == "y"]) + + # creating symbols list + symbols = [chr(i) for i in range(33, 48)] + symbols_l = random.sample(symbols, 1) + + # creating numbers list + numbers = [chr(i) for i in range(48, 58)] + numbers_l = random.sample(numbers, 1) + + # crating lowercase letters list + lowers = [chr(i) for i in range(97, 123)] + lowers_l = random.sample(lowers, count) + + # creating uppercase letters + uppers = [chr(i) for i in range(65, 91)] + uppers_l = random.sample(uppers, 1) + + # creating generated password list + password_generator = lowers_l + if arr[1].lower() == "y": + password_generator += symbols_l + if arr[2].lower() == "y": + password_generator += numbers_l + if arr[3].lower() == "y": + password_generator += uppers_l + + # arrenging list randomly + random.shuffle(password_generator) + + return "Generated password: " + "".join(password_generator) + +print("Password generator") + +# user inputs +pswd_length = int(input("Password length: ")) +pswd_symbols = input("Include symbols (Y, N) (e.g. @#$%): ") +pswd_numbers = input("Include numbers (Y, N) (e.g. 123456): ") +pswd_uppercase = input("Include uppercase letters (Y, N) (e.g. ABCDEF): ") + +pswd_list = [pswd_length, pswd_symbols, pswd_numbers, pswd_uppercase] + +print(generator(pswd_list)) \ No newline at end of file From ba7882f38947bbad92f41870fba53d0978c351c6 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Sun, 31 Jan 2021 13:13:43 +0200 Subject: [PATCH 23/34] added screenshot --- password-generator/screen.png | Bin 0 -> 151833 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 password-generator/screen.png diff --git a/password-generator/screen.png b/password-generator/screen.png new file mode 100644 index 0000000000000000000000000000000000000000..b88b554887203abd748666bbde6312f7a71ea6a3 GIT binary patch literal 151833 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 vjHhZn9{2fkAn&oMkr93r$^RDe#fM_0 Date: Sun, 31 Jan 2021 13:15:20 +0200 Subject: [PATCH 24/34] minor chenges to README file --- password-generator/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/password-generator/README.md b/password-generator/README.md index 3d64b63..8c199b2 100644 --- a/password-generator/README.md +++ b/password-generator/README.md @@ -1,3 +1,7 @@ # Password Generator on Python -User input password generator with the possibility to add symbols, numbers or uppercase letters. \ No newline at end of file +User input password generator with the possibility to add symbols, numbers or uppercase letters. + +Screenshot: + +![Password Generator Screen](https://github.com/valeriybercha/python-demos/blob/master/password-generator/screen.png) \ No newline at end of file From ecb8f74db56afe0a2be346da687683c291f77ddb Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Sun, 31 Jan 2021 13:18:15 +0200 Subject: [PATCH 25/34] added password generator project to README file --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 10eb37d..f2358d3 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,4 @@ * [Text Pro App](https://github.com/valeriybercha/python-demos/tree/master/text-pro-app) * [Tkinter](https://github.com/valeriybercha/python-demos/tree/master/tkinter) * [GUI Calculator](https://github.com/valeriybercha/python-demos/tree/master/gui-calculator) +* [Password Generator](https://github.com/valeriybercha/python-demos/tree/master/password-generator) From a3a833ae989eb4f661c046238853fae7022ed14a Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Thu, 4 Feb 2021 19:23:56 +0200 Subject: [PATCH 26/34] changes to README file --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f2358d3..4591e37 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,7 @@ * [Tkinter](https://github.com/valeriybercha/python-demos/tree/master/tkinter) * [GUI Calculator](https://github.com/valeriybercha/python-demos/tree/master/gui-calculator) * [Password Generator](https://github.com/valeriybercha/python-demos/tree/master/password-generator) +* [To Do App with Flask framework](https://github.com/valeriybercha/py-todo-app) +* [Covid Telegram Bot](https://github.com/valeriybercha/py-covid-telegram-bot) +* [To Do App simplified version](https://github.com/valeriybercha/py-todo-s-app) + From 988d1a4728121af646046d0f62226c8182da1d52 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Sun, 31 Oct 2021 20:12:01 +0200 Subject: [PATCH 27/34] added flask-blog-corey project --- flask-blog-corey/.gitignore | 8 + flask-blog-corey/README.md | 192 ++++++++++++++++++ flask-blog-corey/flaskblog/__init__.py | 38 ++++ flask-blog-corey/flaskblog/config.py | 20 ++ flask-blog-corey/flaskblog/errors/__init__.py | 0 flask-blog-corey/flaskblog/errors/handlers.py | 18 ++ flask-blog-corey/flaskblog/main/__init__.py | 0 flask-blog-corey/flaskblog/main/routes.py | 21 ++ flask-blog-corey/flaskblog/models.py | 43 ++++ flask-blog-corey/flaskblog/posts/__init__.py | 0 flask-blog-corey/flaskblog/posts/forms.py | 10 + flask-blog-corey/flaskblog/posts/routes.py | 61 ++++++ flask-blog-corey/flaskblog/site.db | Bin 0 -> 28672 bytes flask-blog-corey/flaskblog/static/main.css | 3 + .../flaskblog/templates/about.html | 4 + .../flaskblog/templates/account.html | 68 +++++++ .../flaskblog/templates/create_post.html | 46 +++++ .../flaskblog/templates/errors/403.html | 8 + .../flaskblog/templates/errors/404.html | 8 + .../flaskblog/templates/errors/500.html | 8 + .../flaskblog/templates/home.html | 34 ++++ .../flaskblog/templates/layout.html | 108 ++++++++++ .../flaskblog/templates/login.html | 39 ++++ .../flaskblog/templates/post.html | 41 ++++ .../flaskblog/templates/register.html | 81 ++++++++ .../flaskblog/templates/reset_request.html | 26 +++ .../flaskblog/templates/reset_token.html | 30 +++ .../flaskblog/templates/user_post.html | 33 +++ flask-blog-corey/flaskblog/users/__init__.py | 0 flask-blog-corey/flaskblog/users/forms.py | 72 +++++++ flask-blog-corey/flaskblog/users/routes.py | 116 +++++++++++ flask-blog-corey/flaskblog/users/utils.py | 34 ++++ flask-blog-corey/requirements.txt | 29 +++ flask-blog-corey/run.py | 15 ++ 34 files changed, 1214 insertions(+) create mode 100644 flask-blog-corey/.gitignore create mode 100644 flask-blog-corey/README.md create mode 100644 flask-blog-corey/flaskblog/__init__.py create mode 100644 flask-blog-corey/flaskblog/config.py create mode 100644 flask-blog-corey/flaskblog/errors/__init__.py create mode 100644 flask-blog-corey/flaskblog/errors/handlers.py create mode 100644 flask-blog-corey/flaskblog/main/__init__.py create mode 100644 flask-blog-corey/flaskblog/main/routes.py create mode 100644 flask-blog-corey/flaskblog/models.py create mode 100644 flask-blog-corey/flaskblog/posts/__init__.py create mode 100644 flask-blog-corey/flaskblog/posts/forms.py create mode 100644 flask-blog-corey/flaskblog/posts/routes.py create mode 100644 flask-blog-corey/flaskblog/site.db create mode 100644 flask-blog-corey/flaskblog/static/main.css create mode 100644 flask-blog-corey/flaskblog/templates/about.html create mode 100644 flask-blog-corey/flaskblog/templates/account.html create mode 100644 flask-blog-corey/flaskblog/templates/create_post.html create mode 100644 flask-blog-corey/flaskblog/templates/errors/403.html create mode 100644 flask-blog-corey/flaskblog/templates/errors/404.html create mode 100644 flask-blog-corey/flaskblog/templates/errors/500.html create mode 100644 flask-blog-corey/flaskblog/templates/home.html create mode 100644 flask-blog-corey/flaskblog/templates/layout.html create mode 100644 flask-blog-corey/flaskblog/templates/login.html create mode 100644 flask-blog-corey/flaskblog/templates/post.html create mode 100644 flask-blog-corey/flaskblog/templates/register.html create mode 100644 flask-blog-corey/flaskblog/templates/reset_request.html create mode 100644 flask-blog-corey/flaskblog/templates/reset_token.html create mode 100644 flask-blog-corey/flaskblog/templates/user_post.html create mode 100644 flask-blog-corey/flaskblog/users/__init__.py create mode 100644 flask-blog-corey/flaskblog/users/forms.py create mode 100644 flask-blog-corey/flaskblog/users/routes.py create mode 100644 flask-blog-corey/flaskblog/users/utils.py create mode 100644 flask-blog-corey/requirements.txt create mode 100644 flask-blog-corey/run.py diff --git a/flask-blog-corey/.gitignore b/flask-blog-corey/.gitignore new file mode 100644 index 0000000..b407793 --- /dev/null +++ b/flask-blog-corey/.gitignore @@ -0,0 +1,8 @@ +__pycache__/ +venv/ +flaskblog/__pycache__/ +flaskblog/users/__pycache__/ +flaskblog/errors/__pycache__/ +flaskblog/main/__pycache__/ +flaskblog/posts/__pycache__/ + diff --git a/flask-blog-corey/README.md b/flask-blog-corey/README.md new file mode 100644 index 0000000..ff73440 --- /dev/null +++ b/flask-blog-corey/README.md @@ -0,0 +1,192 @@ +# Demo blog with Flask framework on Python + +This blog is created under [Corey Schafer](https://www.youtube.com/channel/UCCezIgC97PvUuR4_gbFUs5g) youtube tutorials + +### Blog functionality: + +- User registration +- User login +- Add post +- Update post +- Delete post +- Blog pagination +- Display posts by author + +## Setting up and create a blog using Flask + +Pre-requisites: +- Python should be already installed on the system. To check this: ```python3 --version``` +- Python virtual environment package should be installed: ```sudo apt install python3-venv``` + +Additional for Linux: update and install header files and static libraries for Python Dev: +``` +sudo apt-get install python-dev # for python2.x installs +sudo apt-get install python3-dev # for python3.x installs +``` + +#### Modules and packages needed to be installed: + +- Flask: ```pip install flask``` +- Flask forms: ```pip install flask-wtf``` +- Wtf forms 'email_validator' package: ```pip install wtforms[email]``` +- Data base 'SQLAlchemy' for Flask: ```pip install flask-sqlalchemy``` +- 'Flask-Bcrypt' for hashing passwords: ```pip install flask-bcrypt``` +- Flask Login: ```pip install flask-login``` +- 'Pillow' package for resizing images: ```pip install Pillow``` +- 'Flask Email' for sending emails: ```pip install flask-mail``` + +### Setting up a Flask project on Linux: + +1. Create a project folder: ```mkdir flask-blog``` +2. Navigate to the project folder: ```cd flask-blog``` +3. Create a virtual environment inside your project directory: ```python3 -m venv venv``` +4. Activate the virtual environment: ```source venv/bin/activate``` +5. Install Flask: ```pip install Flask``` +6. To verify if Flask was installed on the system: ```python -m flask --version``` +7. Create the simpliest 'Hello, World!' program. Create a python file: ```touch flaskblog.py``` +8. Open the 'flaskblog.py' file and paste in it the following code: +``` +from flask import Flask +app = Flask(__name__) + +@ app.route('/') +def hello_world(): + return "Hello, World!" +``` +9. Launch the development server: ```export FLASK_APP=flaskblog.py``` and then run the Flask app: ```flask run``` +10. The ```http://127.0.01:5000``` or ```http://localhost:5000``` server address should be displayed. Open it in the browser and the 'Hello, World!' message should be displayed +11. Use ```deactivate``` command to stop the server + +### Start the development server in Debug mode + +1. Paste the following code in the python file ```flaskblog.py```: +``` +if __name__=='__main__': + app.run(debug=True) +``` +2. Run the command: ```export FLASK_DEBUG=1``` +3. Then run the flask app with the command: ```flask run``` or ```python flaskblog.py``` + +### Flask Blog Project Structure (before creating packages) + +- flask-blog (project directory): + - venv (virtaul environment folder: ```python3 -m venv venv```) + - templates (templates folder: home.html, layout.html ...): + - layout.html + - home.html + - about.html + - login.html + - register.html + - static (static folder: css, js files ...): + - main.css + - flaskblog.py (main project file) + - forms.py (Login and Registration logic creation) + - site.db (blog SQLite database) + - models.py (storing project models) + +### Creating and testing SQLite project database with SQLAlchemy + +1. Install Flask SQLAlchemy package: ```pip install flask-sqlalchemy``` +2. Create the tables for the project: +``` +from flask_sqlalchemy import SQLAlchemy + +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' + +db = SQLAlchemy(app) + +class User(db.Model): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(20), unique=True, nullable=False) + email = db.Column(db.String(120), unique=True, nullable=False) + image_file = db.Column(db.String(20), nullable=False, default='default.jpg') + password = db.Column(db.String(60), nullable=False) + post = db.relationship('Post', backref='author', lazy=True) + + def __repr__(self): + return f"User('{self.username}', '{self.email}', '{self.image_file}')" + + +class Post(db.Model): + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.String(100), nullable=False) + date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + content = db.Column(db.Text, nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + + def __repr__(self): + return f"User('{self.title}', '{self.date_posted}')" +``` +3. Open ```python3``` in terminal in the virtual environment +4. From application 'flaskblog' import 'db', 'User' and 'Post': + - ```from flaskblog import db``` + - ```from flaskblog import User, Post``` +5. Create a database with the command: ```db.create_all()``` "site.db" file shoulf be created in the project directory +6. Create a new user: +``` +user_1 = User(username="John", email="JohnDoe@company.com", password="password") +db.session.add(user_1) +db.session.commit() +``` +7. Verify if users were added to database (will display all the users): ```User.query.all()``` +8. Verify the first user added: ```User.query.first()``` +9. Filter users added by name (case sensitive): ```User.query.filter_by(username="John").all()``` +10. Additional queries: + - Set up a variable "user" ```user = User.query.first()``` + - display user id: ```user.id``` + - display the user by id: ```User.query.get(1)``` + - display users posts: ```user.post``` +11. Create a new post: +``` +post_1 = Post(title="First blog post", content="First post content", user_id=user.id) +db.session.add(post_1) +db.session.commit() +``` +12. Additional queries: + - ```user = User.query.get(1)``` + - ```for post in user.post: print(post)``` + - ```post.author``` +13. Delete all data: ```db.drop_all()``` +14. Create a new blank database: ```db.create_all()``` + +### Creating project packages - Package Structure + +- flask-blog (project directory): + - venv (virtaul environment folder: ```python3 -m venv venv```) + - run.py (renaming 'flaskblog.py' in the 'run.py' file) + - flaskblog (project python package): + - __init__.py (project package file) + - templates (templates folder: home.html, layout.html ...): + - layout.html + - home.html + - about.html + - login.html + - register.html + - static (static folder: css, js files ...): + - main.css + - forms.py (Login and Registration logic creation) + - site.db (blog SQLite database) + - models.py (storing project models) + - routes.py (project routes file) + +Note: After creating project packages when deleting or creating tables in database an error could occur. The solution is to create and push application context when deleting or creating tables in project database. If it is needed to remove or create tables in the database: +- ```from flaskblog import db``` +- ```from flaskblog import create_app``` +- ```app = create_app()``` +- ```app.app_context().push()``` +- ```db.create_all()``` or ```db.drop_all()``` + +### Using Flask-Bcrypt package for hashing passwords in the application project + +Pre-requisites (for Linux): +- In order to install 'py-bcrypt' package Python Development Headers need to be installed: ```sudo apt-get install python3-dev``` + +Steps: +1. Install the package: ```pip install flask-bcrypt``` +2. Open ```python``` in terminal +3. Import the package: ```from flask_bcrypt import Bcrypt``` +4. Initiate a variable ```bcrypt```: ```bcrypt = Bcrypt()``` +5. Generate a hashed version of 'testing' password: ```bcrypt.generate_password_hash('testing').decode('utf-8')``` +6. Create a variable 'hashed_pas': ```hashed_pas = bcrypt.generate_password_hash('testing').decode('utf-8')``` +7. Verify if the hashed variable == hashed password: ```bcrypt.check_password_hash(hashed_pas, 'testing')``` +8. The result should equal ```True``` diff --git a/flask-blog-corey/flaskblog/__init__.py b/flask-blog-corey/flaskblog/__init__.py new file mode 100644 index 0000000..5fdba3e --- /dev/null +++ b/flask-blog-corey/flaskblog/__init__.py @@ -0,0 +1,38 @@ +# Importin modules and packages + +from flask import Flask +from flask_sqlalchemy import SQLAlchemy +from flask_bcrypt import Bcrypt +from flask_login import LoginManager +from flask_mail import Mail +from flaskblog.config import Config + + +db = SQLAlchemy() +bcrypt = Bcrypt() +login_manager = LoginManager() +login_manager.login_view = 'users.login' +login_manager.login_message_category = 'info' +mail = Mail() + + +def create_app(config_class=Config): + app = Flask(__name__) + app.config.from_object(Config) + + db.init_app(app) + bcrypt.init_app(app) + login_manager.init_app(app) + mail.init_app(app) + + from flaskblog.users.routes import users + from flaskblog.posts.routes import posts + from flaskblog.main.routes import main + from flaskblog.errors.handlers import errors + + app.register_blueprint(users) + app.register_blueprint(posts) + app.register_blueprint(main) + app.register_blueprint(errors) + + return app diff --git a/flask-blog-corey/flaskblog/config.py b/flask-blog-corey/flaskblog/config.py new file mode 100644 index 0000000..6613b2b --- /dev/null +++ b/flask-blog-corey/flaskblog/config.py @@ -0,0 +1,20 @@ +# Project configuration file + + +class Config: + """ + Creating secret key string variable: + - open python interpreter in terminal: 'python3' + - import 'secrets' module: 'import secrets' + - generating random token: 'secrets.token_hex(16)' + """ + SECRET_KEY = 'your_secret_key' + SQLALCHEMY_DATABASE_URI = 'sqlite:///site.db' + SQLALCHEMY_TRACK_MODIFICATIONS = False + + # Mail configuration for password restoring by email + MAIL_SERVER = 'smtp.googlemail.com' + MAIL_PORT = 587 + MAIL_USE_TLS = True + MAIL_USERNAME = 'your_email_here' + MAIL_PASSWORD = 'your_email_password_here' diff --git a/flask-blog-corey/flaskblog/errors/__init__.py b/flask-blog-corey/flaskblog/errors/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/flask-blog-corey/flaskblog/errors/handlers.py b/flask-blog-corey/flaskblog/errors/handlers.py new file mode 100644 index 0000000..d798b31 --- /dev/null +++ b/flask-blog-corey/flaskblog/errors/handlers.py @@ -0,0 +1,18 @@ +from flask import Blueprint, render_template + +errors = Blueprint('errors', __name__) + + +@errors.app_errorhandler(404) +def error_404(error): + return render_template('errors/404.html'), 404 + + +@errors.app_errorhandler(403) +def error_403(error): + return render_template('errors/403.html'), 403 + + +@errors.app_errorhandler(500) +def error_500(error): + return render_template('errors/500.html'), 500 diff --git a/flask-blog-corey/flaskblog/main/__init__.py b/flask-blog-corey/flaskblog/main/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/flask-blog-corey/flaskblog/main/routes.py b/flask-blog-corey/flaskblog/main/routes.py new file mode 100644 index 0000000..90eb4f3 --- /dev/null +++ b/flask-blog-corey/flaskblog/main/routes.py @@ -0,0 +1,21 @@ +# Routes for Main package + +from flask import render_template, request, Blueprint +from flaskblog.models import Post + +main = Blueprint('main', __name__) + + +# Routing for Home page +@main.route('/') +@main.route('/home') +def home(): + page = request.args.get('page', 1, type=int) + posts = Post.query.order_by(Post.date_posted.desc()).paginate(page=page, per_page=5) + return render_template('home.html', posts=posts) + + +# Routing for About page +@main.route('/about') +def about(): + return render_template('about.html', title="About") diff --git a/flask-blog-corey/flaskblog/models.py b/flask-blog-corey/flaskblog/models.py new file mode 100644 index 0000000..5cf436a --- /dev/null +++ b/flask-blog-corey/flaskblog/models.py @@ -0,0 +1,43 @@ +from flaskblog import db, login_manager +from flask import current_app +from flask_login import UserMixin +from datetime import datetime +from itsdangerous import TimedJSONWebSignatureSerializer as Serializer + +@login_manager.user_loader +def load_user(user_id): + return User.query.get(int(user_id)) + +class User(db.Model, UserMixin): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(20), unique=True, nullable=False) + email = db.Column(db.String(120), unique=True, nullable=False) + image_file = db.Column(db.String(20), nullable=False, default='default.jpg') + password = db.Column(db.String(60), nullable=False) + post = db.relationship('Post', backref='author', lazy=True) + + def get_reset_token(self, expires_sec=1800): + s = Serializer(current_app.config['SECRET_KEY'], expires_sec) + return s.dumps({'user_id': self.id}).decode('utf-8') + + @staticmethod + def verify_reset_token(token): + s = Serializer(current_app.config['SECRET_KEY']) + try: + user_id = s.loads(token)['user_id'] + except: + return None + return User.query.get(user_id) + + def __repr__(self): + return f"User('{self.username}', '{self.email}', '{self.image_file}')" + +class Post(db.Model): + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.String(100), nullable=False) + date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + content = db.Column(db.Text, nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + + def __repr__(self): + return f"User('{self.title}', '{self.date_posted}')" diff --git a/flask-blog-corey/flaskblog/posts/__init__.py b/flask-blog-corey/flaskblog/posts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/flask-blog-corey/flaskblog/posts/forms.py b/flask-blog-corey/flaskblog/posts/forms.py new file mode 100644 index 0000000..0460e57 --- /dev/null +++ b/flask-blog-corey/flaskblog/posts/forms.py @@ -0,0 +1,10 @@ +from flask_wtf import FlaskForm +from wtforms import StringField, SubmitField, TextAreaField +from wtforms.validators import DataRequired + + +# Post form +class PostForm(FlaskForm): + title = StringField('Title', validators=[DataRequired()]) + content = TextAreaField('Content', validators=[DataRequired()]) + submit = SubmitField('Post') diff --git a/flask-blog-corey/flaskblog/posts/routes.py b/flask-blog-corey/flaskblog/posts/routes.py new file mode 100644 index 0000000..2d30aef --- /dev/null +++ b/flask-blog-corey/flaskblog/posts/routes.py @@ -0,0 +1,61 @@ +# Routes for Posts package + +from flask import (render_template, url_for, flash, + redirect, request, abort, Blueprint) +from flask_login import current_user, login_required +from flaskblog import db +from flaskblog.models import Post +from flaskblog.posts.forms import PostForm + +posts = Blueprint('posts', __name__) + + +# Routing for Posts +@posts.route('/post/new', methods=["GET", "POST"]) +@login_required +def new_post(): + form = PostForm() + if form.validate_on_submit(): + post = Post(title=form.title.data, content=form.content.data, author=current_user) + db.session.add(post) + db.session.commit() + flash("Your post has been created", "success") + return redirect(url_for('main.home')) + return render_template('create_post.html', title='New Post', form=form, legend='New Post') + + +@posts.route('/post/') +def post(post_id): + post = Post.query.get_or_404(post_id) + return render_template('post.html', title=post.title,post=post) + + +@posts.route('/post//update', methods=["GET", "POST"]) +@login_required +def update_post(post_id): + post = Post.query.get_or_404(post_id) + if post.author != current_user: + abort(403) + form = PostForm() + if form.validate_on_submit(): + post.title = form.title.data + post.content = form.content.data + db.session.commit() + flash('Your post has been updated', 'success') + return redirect(url_for('posts.post', post_id=post.id)) + elif request.method == "GET": + form.title.data = post.title + form.content.data = post.content + return render_template('create_post.html', title='Update Post', form=form, legend='Update Post') + + +@posts.route('/post//delete', methods=["POST"]) +@login_required +def delete_post(post_id): + post = Post.query.get_or_404(post_id) + if post.author != current_user: + abort(403) + db.session.delete(post) + db.session.commit() + flash('Your post has been deleted', 'success') + return redirect(url_for('main.home')) diff --git a/flask-blog-corey/flaskblog/site.db b/flask-blog-corey/flaskblog/site.db new file mode 100644 index 0000000000000000000000000000000000000000..3532e3877776165b61f1b2f95af8505ec94eef43 GIT binary patch literal 28672 zcmeI)O-~y~7zgk*FQHIT_kwb1q(=&Bu;gs92~g5YT(hKB!GJNP^kNOWV>4vm*qL?H zOC?nG(htyY(B3NboAi6++(VCj#&5i+NpF>!{8t_ucIV}Je!Cpj?99>Ot}>FkNfrr1 zYtDyGq2N3tavW!!%N&<`T&B1zaGBvU-U{O%-tf8ZxF7w#Sp3VGS^UlU;Fsbb#b5ac zY!H9|1Rwwb2tWV=5P$##An;~^t9)ke{?bz6hdm?CLYXGo*fLvhd9}7j?b_$N9@#y# zvM{d#YBby4bFW3s{Wdj^cX!LQFmIFzC4E(E)xW5kW&y86B_%)2wl+a9rH>Q>&v`mfE~9*#wHoqF|7<}wm0yoR}ZSVf{I zJ6&}H?{1Y;X#H)H1(QxT?hNry49CsJ;ju>p0vq4JX1sF{Q)!{}X!_p$&z1^~iUavl zUxs|k-VwP;2ETV~YMrWmpLsO(uN5n{;xu1q@7arOkxQZYv%@cJ5P$##AOHafKmY;| zfB*y_009X6rvm4NIp;y;;nl2>+SvQ`@#nL_Hv+DoM1kyzJT&e_+FP!kEmx|`-yCmT zp0`ii;-uB^&67{6%Jet)yE`UJ!_E4O7hZikt)E<+e!6Lnwxh;=_2qW+JNr-lLh(n*(DZYA(5=1HxfB*y_009U< z00Izz00bZafp=D5X}U7G>%V@CVDS9^;>QlZut5L<5P$##AOHafKmY;|fPnMk2|tki zu=bNb-{uFhhg0k;)zxa{ab@*!^$Atho~~{@UE6fGwl=pa>$^!NBT}i(BMOo*$w(_h zJh|JHiRaI2=^JVCj6|SPrF|9mNb;O+mku%^wVhp`b9LX(BQ0VIRWA=knJ#msN%C8i z1k@iksD7ZLH~^jJ)43cFWw7j%(plMpxNVf!Ksxrc7XU_ zx-#!6&XxyG0+mcI7E1YKs6689;s!PigBF>ek5tPPCEUMJHWjv3arwqsj+mq-W64+2 zuq96(;46rSk=*m>kK3;0XV?0hAbout page

+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/account.html b/flask-blog-corey/flaskblog/templates/account.html new file mode 100644 index 0000000..9835467 --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/account.html @@ -0,0 +1,68 @@ +{% extends 'layout.html' %} +{% block content %} +
+

Account page

+
+ +
+

{{ current_user.username.title() }}

+

{{ current_user.email }}

+
+
+ +
+
+
+ + {{ form.hidden_tag() }} +
+ Account Info + +
+ {{ form.username.label(class="form-control-label") }} + + + {% if form.username.errors %} + {{ form.username(class="form-control form-control-lg is-invalid") }} +
+ {% for error in form.username.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + + {{ form.username(class="form-control form-control-lg") }} + {% endif %} +
+
+ {{ form.email.label(class="form-control-label") }} + {% if form.email.errors %} + {{ form.email(class="form-control form-control-lg is-invalid") }} +
+ {% for error in form.email.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.email(class="form-control form-control-lg") }} + {% endif %} +
+
+ {{ form.picture.label() }} + {{ form.picture(class="form-control-file") }} + {% if form.picture.errors %} + {% for error in form.picture.errors %} + {{ error }}
+ {% endfor %} + {% endif %} +
+
+
+ {{ form.submit(class="btn btn-outline-info") }} +
+
+
+
+ +
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/create_post.html b/flask-blog-corey/flaskblog/templates/create_post.html new file mode 100644 index 0000000..6856362 --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/create_post.html @@ -0,0 +1,46 @@ +{% extends 'layout.html' %} +{% block content %} +

Create Post page

+
+
+ + {{ form.hidden_tag() }} +
+ {{ legend }} + +
+ {{ form.title.label(class="form-control-label") }} + + + {% if form.title.errors %} + {{ form.title(class="form-control form-control-lg is-invalid") }} +
+ {% for error in form.title.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + + {{ form.title(class="form-control form-control-lg") }} + {% endif %} +
+
+ {{ form.content.label(class="form-control-label") }} + {% if form.content.errors %} + {{ form.content(class="form-control form-control-lg is-invalid") }} +
+ {% for error in form.content.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.content(class="form-control form-control-lg") }} + {% endif %} +
+
+
+ {{ form.submit(class="btn btn-outline-info") }} +
+
+
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/errors/403.html b/flask-blog-corey/flaskblog/templates/errors/403.html new file mode 100644 index 0000000..7102e02 --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/errors/403.html @@ -0,0 +1,8 @@ +{% extends 'layout.html' %} +{% block content %} +

Error Page

+
+

You don't have the permission to access this page (403)

+

Check your account and try again

+
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/errors/404.html b/flask-blog-corey/flaskblog/templates/errors/404.html new file mode 100644 index 0000000..85e95f1 --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/errors/404.html @@ -0,0 +1,8 @@ +{% extends 'layout.html' %} +{% block content %} +

Error Page

+
+

Oops. Page Not found (404)

+

Page does not exist. Try again

+
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/errors/500.html b/flask-blog-corey/flaskblog/templates/errors/500.html new file mode 100644 index 0000000..995ffb1 --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/errors/500.html @@ -0,0 +1,8 @@ +{% extends 'layout.html' %} +{% block content %} +

Error Page

+
+

Something went wrong (500)

+

We are experiencing some troubles. Try again later

+
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/home.html b/flask-blog-corey/flaskblog/templates/home.html new file mode 100644 index 0000000..590421f --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/home.html @@ -0,0 +1,34 @@ +{% extends 'layout.html' %} +{% block content %} +

Home page

+ {% for post in posts.items %} + + +
+
+ World +

+ {{ post.title }} +

+
+ {{ post.date_posted.strftime('%Y-%m-%d') }} by + {{ post.author.username }} +
+

{{ post.content }}

+ Continue reading +
+ +
+ {% endfor %} + {% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %} + {% if page_num %} + {% if posts.page == page_num %} + {{ page_num }} + {% else %} + {{ page_num }} + {% endif %} + {% else %} + ... + {% endif %} + {% endfor %} +{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/layout.html b/flask-blog-corey/flaskblog/templates/layout.html new file mode 100644 index 0000000..cb0a3cb --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/layout.html @@ -0,0 +1,108 @@ + + + + + + + + {% if title %} + Flask blog - {{ title }} + {% else %} + Flask blog + {% endif %} + + + + + + + + + + + +
+
+
+ + +
+ {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
+ {{ message }} +
+ {% endfor %} + {% endif %} + {% endwith %} + {% block content %}{% endblock content %} +
+ + +
+

Sidebar section

+

Polpular posts

+

Calendar

+

Tags

+
+
+
+
+ + + + + + + + diff --git a/flask-blog-corey/flaskblog/templates/login.html b/flask-blog-corey/flaskblog/templates/login.html new file mode 100644 index 0000000..1d10138 --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/login.html @@ -0,0 +1,39 @@ +{% extends 'layout.html' %} +{% block content %} +

Login page

+
+
+
+ + {{ form.hidden_tag() }} +
+ Login + +
+ {{ form.email.label(class="form-control-label") }} + {{ form.email(class="form-control form-control-lg") }} +
+
+ {{ form.password.label(class="form-control-label") }} + {{ form.password(class="form-control form-control-lg") }} +
+
+ {{ form.remember(class="form-check-input") }} + {{ form.remember.label(class="form-check-label") }} +
+
+
+ {{ form.submit(class="btn btn-outline-success") }} +
+ + Forgot Password? + +
+
+
+ + Need an account? Sign Up Now + +
+
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/post.html b/flask-blog-corey/flaskblog/templates/post.html new file mode 100644 index 0000000..83ee0f5 --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/post.html @@ -0,0 +1,41 @@ +{% extends 'layout.html' %} +{% block content %} +
+
+ {% if post.author == current_user %} + Update + + + + {% endif %} +
+

{{ post.title }}

+
+ {{ post.date_posted.strftime('%Y-%m-%d') }} by + {{ post.author.username }} +
+

{{ post.content }}

+
+
+
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/register.html b/flask-blog-corey/flaskblog/templates/register.html new file mode 100644 index 0000000..5c63693 --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/register.html @@ -0,0 +1,81 @@ +{% extends 'layout.html' %} +{% block content %} +

Register page

+
+
+
+
+ + {{ form.hidden_tag() }} +
+ Join Today + +
+ {{ form.username.label(class="form-control-label") }} + + + {% if form.username.errors %} + {{ form.username(class="form-control form-control-lg is-invalid") }} +
+ {% for error in form.username.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + + {{ form.username(class="form-control form-control-lg") }} + {% endif %} +
+
+ {{ form.email.label(class="form-control-label") }} + {% if form.email.errors %} + {{ form.email(class="form-control form-control-lg is-invalid") }} +
+ {% for error in form.email.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.email(class="form-control form-control-lg") }} + {% endif %} +
+
+ {{ form.password.label(class="form-control-label") }} + {% if form.password.errors %} + {{ form.password(class="form-control form-control-lg is-invalid") }} +
+ {% for error in form.password.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.password(class="form-control form-control-lg") }} + {% endif %} +
+
+ {{ form.password_confirmation.label(class="form-control-label") }} + {% if form.password_confirmation.errors %} + {{ form.password_confirmation(class="form-control form-control-lg is-invalid") }} +
+ {% for error in form.password_confirmation.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.password_confirmation(class="form-control form-control-lg") }} + {% endif %} +
+
+
+ {{ form.submit(class="btn btn-outline-info") }} +
+
+
+
+
+ + Already have an account? Sign in + +
+
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/reset_request.html b/flask-blog-corey/flaskblog/templates/reset_request.html new file mode 100644 index 0000000..7b5b9a2 --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/reset_request.html @@ -0,0 +1,26 @@ +{% extends 'layout.html' %} +{% block content %} +

Reset login

+
+
+
+ + {{ form.hidden_tag() }} +
+ Reset Password + +
+ {{ form.email.label(class="form-control-label") }} + {{ form.email(class="form-control form-control-lg") }} +
+
+
+ {{ form.submit(class="btn btn-outline-success") }} +
+ + Forgot Password? + +
+
+
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/reset_token.html b/flask-blog-corey/flaskblog/templates/reset_token.html new file mode 100644 index 0000000..bdd027c --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/reset_token.html @@ -0,0 +1,30 @@ +{% extends 'layout.html' %} +{% block content %} +

Reset login

+
+
+
+ + {{ form.hidden_tag() }} +
+ Reset Password + +
+ {{ form.password.label(class="form-control-label") }} + {{ form.password(class="form-control form-control-lg") }} +
+
+ {{ form.password_confirmation.label(class="form-control-label") }} + {{ form.password_confirmation(class="form-control form-control-lg") }} +
+
+
+ {{ form.submit(class="btn btn-outline-success") }} +
+ + Forgot Password? + +
+
+
+{% endblock content %} diff --git a/flask-blog-corey/flaskblog/templates/user_post.html b/flask-blog-corey/flaskblog/templates/user_post.html new file mode 100644 index 0000000..611005d --- /dev/null +++ b/flask-blog-corey/flaskblog/templates/user_post.html @@ -0,0 +1,33 @@ +{% extends 'layout.html' %} +{% block content %} +

Posts by {{ user.username }} ({{ posts.total }})

+ {% for post in posts.items %} + +
+
+ World +

+ {{ post.title }} +

+
+ {{ post.date_posted.strftime('%Y-%m-%d') }} by + {{ post.author.username }} +
+

{{ post.content }}

+ Continue reading +
+ +
+ {% endfor %} + {% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %} + {% if page_num %} + {% if posts.page == page_num %} + {{ page_num }} + {% else %} + {{ page_num }} + {% endif %} + {% else %} + ... + {% endif %} + {% endfor %} +{% endblock content %} diff --git a/flask-blog-corey/flaskblog/users/__init__.py b/flask-blog-corey/flaskblog/users/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/flask-blog-corey/flaskblog/users/forms.py b/flask-blog-corey/flaskblog/users/forms.py new file mode 100644 index 0000000..8398178 --- /dev/null +++ b/flask-blog-corey/flaskblog/users/forms.py @@ -0,0 +1,72 @@ +from flask_wtf import FlaskForm +from flask_wtf.file import FileField, FileAllowed +from wtforms import StringField, PasswordField, SubmitField, BooleanField +from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError +from flask_login import current_user +from flaskblog.models import User + +# Registration form variables +class RegistrationForm(FlaskForm): + username = StringField('Username', validators=[DataRequired(), + Length(min=2, max=20)]) + email = StringField('Email', validators=[DataRequired(), Email()]) + password = PasswordField('Password', validators=[DataRequired()]) + password_confirmation = PasswordField('Password Confirmation', validators=[DataRequired(), EqualTo('password')]) + submit = SubmitField('Sign Up') + + def validate_username(self, username): + user = User.query.filter_by(username=username.data).first() + if user: + raise ValidationError('That username already exist. Please choose different one!') + + def validate_email(self, email): + user = User.query.filter_by(email=email.data).first() + if user: + raise ValidationError('That email already exist. Please choose different one!') + + +# Login form variables +class LoginForm(FlaskForm): + email = StringField('Email', validators=[DataRequired(), Email()]) + password = PasswordField('Password', validators=[DataRequired()]) + remember = BooleanField('Remember Me') + submit = SubmitField('Login') + + +# Account form +class UpdateAccountForm(FlaskForm): + username = StringField('Username', validators=[DataRequired(), + Length(min=2, max=20)]) + email = StringField('Email', validators=[DataRequired(), Email()]) + picture = FileField('Update Profile Picture', validators=[FileAllowed(['jpg', 'png'])]) + submit = SubmitField('Update') + + def validate_username(self, username): + if username.data != current_user.username: + user = User.query.filter_by(username=username.data).first() + if user: + raise ValidationError('That username already exist. Please choose different one!') + + def validate_email(self, email): + if email.data != current_user.email: + user = User.query.filter_by(email=email.data).first() + if user: + raise ValidationError('That email already exist. Please choose different one!') + + +# Password reset form +class RequestResetForm(FlaskForm): + email = StringField('Email', validators=[DataRequired(), Email()]) + submit = SubmitField('Request Password Reset') + + def validate_email(self, email): + user = User.query.filter_by(email=email.data).first() + if user is None: + raise ValidationError('There is no account with that email. Register first!') + + +class ResetPasswordForm(FlaskForm): + password = PasswordField('Password', validators=[DataRequired()]) + password_confirmation = PasswordField('Password Confirmation', validators=[DataRequired(), EqualTo('password')]) + submit = SubmitField('Reset Password') + diff --git a/flask-blog-corey/flaskblog/users/routes.py b/flask-blog-corey/flaskblog/users/routes.py new file mode 100644 index 0000000..544b639 --- /dev/null +++ b/flask-blog-corey/flaskblog/users/routes.py @@ -0,0 +1,116 @@ +# Routes for Users package + +from flask import render_template, url_for, flash, redirect, request, Blueprint +from flask_login import login_user, current_user, logout_user, login_required +from flaskblog import db, bcrypt +from flaskblog.models import User, Post +from flaskblog.users.forms import (RegistrationForm, LoginForm, UpdateAccountForm, + RequestResetForm, ResetPasswordForm) +from flaskblog.users.utils import save_picture, send_reset_email + +users = Blueprint('users', __name__) + + +# Routing for Register page +@users.route('/register', methods=["GET", "POST"]) # Applying 'get' and 'post' requests methods to register page +def register(): + if current_user.is_authenticated: + return redirect(url_for('main.home')) + form = RegistrationForm() + # Printing the success message if validation was successful + if form.validate_on_submit(): + hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8') + user = User(username=form.username.data, email=form.email.data, password=hashed_password) + db.session.add(user) + db.session.commit() + flash(f'Your account has been created! You can now log in', 'success') # 'success' is the bootstrap class marked in green + return redirect(url_for('users.login')) + return render_template('register.html', title="Register", form=form) + + +# Routing for Login page +@users.route('/login', methods=["GET", "POST"]) +def login(): + if current_user.is_authenticated: + return redirect(url_for('main.home')) + form = LoginForm() + if form.validate_on_submit(): + user = User.query.filter_by(email=form.email.data).first() + if user and bcrypt.check_password_hash(user.password, form.password.data): + login_user(user, remember=form.remember.data) + next_page = request.args.get('next') + return redirect(next_page) if next_page else redirect(url_for('main.home')) + else: + flash('Login unsuccessful. Please check email and password again', 'danger') + return render_template('login.html', title="Login", form=form) + + +# Routing for Logout +@users.route('/logout') +def logout(): + logout_user() + return redirect(url_for('main.home')) + + +# Routing for account +@users.route('/account', methods=["GET", "POST"]) +@login_required +def account(): + form = UpdateAccountForm() + if form.validate_on_submit(): + if form.picture.data: + picture_file = save_picture(form.picture.data) + current_user.image_file = picture_file + current_user.username = form.username.data + current_user.email = form.email.data + db.session.commit() + flash('Your account has been updated', 'success') + return redirect(url_for('users.account')) + elif request.method == 'GET': + form.username.data = current_user.username + form.email.data = current_user.email + image_file = url_for('static', filename='profile_pics/' + current_user.image_file) + return render_template('account.html', title='Account', image_file=image_file, form=form) + + +# Routing for display user specific posts +@users.route('/user/') +def user_post(username): + page = request.args.get('page', 1, type=int) + user = User.query.filter_by(username=username).first_or_404() + posts = Post.query.filter_by(author=user)\ + .order_by(Post.date_posted.desc())\ + .paginate(page=page, per_page=5) + return render_template('user_post.html', posts=posts, user=user) + + +# Routing password reset +@users.route('/reset_password', methods=["GET", "POST"]) +def reset_request(): + if current_user.is_authenticated: + return redirect(url_for('main.home')) + form = RequestResetForm() + if form.validate_on_submit(): + user = User.query.filter_by(email=form.email.data).first() + send_reset_email(user) + flash('An email has been sent with instructions', 'info') + return redirect(url_for('main.home')) + return render_template('reset_request.html', title='Reset Password', form=form) + +@users.route('/reset_password/', methods=["GET", "POST"]) +def reset_token(token): + if current_user.is_authenticated: + return redirect(url_for('main.home')) + user = User.verify_reset_token(token) + if user is None: + flash('That is invalid token', 'warning') + return redirect(url_for('reset_request')) + form = ResetPasswordForm() + if form.validate_on_submit(): + hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8') + user.password = hashed_password + db.session.commit() + flash(f'Your password has been updated! You can now log in', 'success') # 'success' is the bootstrap class marked in green + return redirect(url_for('user.login')) + return render_template('reset_token.html', title='Reset Password', form=form) + diff --git a/flask-blog-corey/flaskblog/users/utils.py b/flask-blog-corey/flaskblog/users/utils.py new file mode 100644 index 0000000..72016e2 --- /dev/null +++ b/flask-blog-corey/flaskblog/users/utils.py @@ -0,0 +1,34 @@ +# User utils file + +import os +import secrets +from PIL import Image +from flask import url_for, current_app +from flask_mail import Message +from flaskblog import mail + + +def save_picture(form_picture): + + # creating a random picture name + random_hex = secrets.token_hex(8) + _, f_ext = os.path.splitext(form_picture.filename) + picture_fn = random_hex + f_ext + picture_path = os.path.join(current_app.root_path, 'static/profile_pics', picture_fn) + + # resizing the downloaded picture to the size of 'output size' + output_size = (200, 200) + i = Image.open(form_picture) + i.thumbnail(output_size) + i.save(picture_path) + return picture_fn + + +def send_reset_email(user): + token = user.get_reset_token() + msg = Message('Password Reset Request', sender='noreply@demo.com', recipients=[user.email]) + msg.body = f''' To reset your password, visit the following link: +{url_for('reset_token', token=token, _external=True)} +If you did not made this request, ignore the message +''' + mail.send(msg) diff --git a/flask-blog-corey/requirements.txt b/flask-blog-corey/requirements.txt new file mode 100644 index 0000000..50c0225 --- /dev/null +++ b/flask-blog-corey/requirements.txt @@ -0,0 +1,29 @@ +bcrypt==3.2.0 +blinker==1.4 +cffi==1.14.6 +click==8.0.1 +dataclasses==0.8 +dnspython==2.1.0 +email-validator==1.1.3 +Flask==2.0.1 +Flask-Bcrypt==0.7.1 +Flask-Login==0.5.0 +Flask-Mail==0.9.1 +Flask-SQLAlchemy==2.5.1 +Flask-WTF==0.15.1 +idna==3.2 +importlib-metadata==4.8.1 +itsdangerous==2.0.1 +Jinja2==3.0.1 +MarkupSafe==2.0.1 +pep517==0.11.0 +Pillow==8.3.2 +pkg_resources==0.0.0 +pycparser==2.20 +six==1.16.0 +SQLAlchemy==1.4.23 +tomli==1.2.1 +typing-extensions==3.10.0.2 +Werkzeug==2.0.1 +WTForms==2.3.3 +zipp==3.5.0 diff --git a/flask-blog-corey/run.py b/flask-blog-corey/run.py new file mode 100644 index 0000000..c8be7bc --- /dev/null +++ b/flask-blog-corey/run.py @@ -0,0 +1,15 @@ +# Flask Application created under Corey Schaffer youtube tutorials + +from flaskblog import create_app + +app = create_app() + +""" + Activating the debug mode. + Run in terminal: + - 'export FLASK_DEBUG=1' + - 'flask run' or 'python flaskblog.py' +""" +if __name__=='__main__': + app.run(debug=True) + From 219e822121f608e982eb9e9d2bf362a1b7ca997b Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Thu, 4 Nov 2021 19:43:00 +0200 Subject: [PATCH 28/34] added "flask-add-users" project --- flask-add-users/.gitignore | 2 + flask-add-users/README.md | 21 +++++++ flask-add-users/app.py | 76 ++++++++++++++++++++++++++ flask-add-users/requirements.txt | 13 +++++ flask-add-users/static/main.css | 11 ++++ flask-add-users/templates/index.html | 52 ++++++++++++++++++ flask-add-users/templates/layout.html | 32 +++++++++++ flask-add-users/templates/update.html | 23 ++++++++ flask-add-users/user.db | Bin 0 -> 8192 bytes 9 files changed, 230 insertions(+) create mode 100644 flask-add-users/.gitignore create mode 100644 flask-add-users/README.md create mode 100644 flask-add-users/app.py create mode 100644 flask-add-users/requirements.txt create mode 100644 flask-add-users/static/main.css create mode 100644 flask-add-users/templates/index.html create mode 100644 flask-add-users/templates/layout.html create mode 100644 flask-add-users/templates/update.html create mode 100644 flask-add-users/user.db diff --git a/flask-add-users/.gitignore b/flask-add-users/.gitignore new file mode 100644 index 0000000..92afa22 --- /dev/null +++ b/flask-add-users/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +venv/ diff --git a/flask-add-users/README.md b/flask-add-users/README.md new file mode 100644 index 0000000..088ccce --- /dev/null +++ b/flask-add-users/README.md @@ -0,0 +1,21 @@ +# Flask demo application for adding users to the database + +### App functionality: +- Add users to the database +- Display added users +- Delete users + +### Usage: + +Pre-requisites: +- Python should be already installed on the machine ```python3 --version``` to verify python installation + +1. Clone or download the project +2. Create a virtual environment inside the project: ```python3 -m venv venv``` +3. Activate the virtual environment: ```source venv/bin/activate``` +4. Install Flask package: ```pip install flask``` +5. Install Flask SQLAlchemy package: ```pip install flask-sqlalchemy``` +6. Start the application server: + - ```export FLASK_DEBUG=1``` + - ```python app.py``` +7. Open the browser at: ```localhost:5000``` diff --git a/flask-add-users/app.py b/flask-add-users/app.py new file mode 100644 index 0000000..34c6373 --- /dev/null +++ b/flask-add-users/app.py @@ -0,0 +1,76 @@ +# 'Add users to the database' demo app on Python and Flask +# Programming language version: Python 3.6.9 +# Developer: Valeriy B. + +from flask import Flask, render_template, url_for, request, redirect +from flask_sqlalchemy import SQLAlchemy +from datetime import datetime + +app = Flask(__name__) + +app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///user.db" +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + +db = SQLAlchemy(app) + +app_title = "Add Users App" + + +# Creating models for adding user to the database +class User(db.Model): + id = db.Column(db.Integer, primary_key=True) + first_name = db.Column(db.String(30), nullable=False) + last_name = db.Column(db.String(30), nullable=False) + date_added = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + + def __repr__(self): + return f"User {self.id}" + + +# Routing for index page +@app.route('/', methods=["POST", "GET"]) +def index(): + if request.method == "POST": + if request.form['fname'] == "": + first_name = "First name: Blank" + else: + first_name = request.form['fname'].title() + if request.form['lname'] == "": + last_name = "Last name: Blank" + else: + last_name = request.form['lname'].title() + user = User(first_name=first_name, last_name=last_name) + db.session.add(user) + db.session.commit() + users = User.query.all() + return render_template('index.html', app_title=app_title, users=users) + else: + users = User.query.all() + return render_template('index.html', app_title=app_title, users=users) + + +# Routing for updating user information +@app.route('/update/', methods=['POST', 'GET']) +def user_update(id): + if request.method == "POST": + updated_user = User.query.get_or_404(id) + updated_user.first_name = request.form['fname'] + updated_user.last_name = request.form['lname'] + db.session.commit() + return redirect(url_for('index')) + else: + user_to_update = User.query.get_or_404(id) + return render_template('update.html', user=user_to_update) + + +# Routing for deleting a user from the database +@app.route('/del/') +def user_delete(id): + user_to_delete = User.query.get_or_404(id) + db.session.delete(user_to_delete) + db.session.commit() + return redirect(url_for('index')) + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/flask-add-users/requirements.txt b/flask-add-users/requirements.txt new file mode 100644 index 0000000..cf76820 --- /dev/null +++ b/flask-add-users/requirements.txt @@ -0,0 +1,13 @@ +click==8.0.3 +dataclasses==0.8 +Flask==2.0.2 +Flask-SQLAlchemy==2.5.1 +importlib-metadata==4.8.1 +itsdangerous==2.0.1 +Jinja2==3.0.2 +MarkupSafe==2.0.1 +pkg-resources==0.0.0 +SQLAlchemy==1.4.26 +typing-extensions==3.10.0.2 +Werkzeug==2.0.2 +zipp==3.6.0 diff --git a/flask-add-users/static/main.css b/flask-add-users/static/main.css new file mode 100644 index 0000000..a349e85 --- /dev/null +++ b/flask-add-users/static/main.css @@ -0,0 +1,11 @@ +header { + padding: 50px 0 30px 0; +} + +h1.app, h2.app { + font-family: 'Comfortaa', cursive; +} + +h2.app { + padding-bottom: 20px; +} diff --git a/flask-add-users/templates/index.html b/flask-add-users/templates/index.html new file mode 100644 index 0000000..87343f9 --- /dev/null +++ b/flask-add-users/templates/index.html @@ -0,0 +1,52 @@ +{% extends 'layout.html' %} + +{% block main %} +
+
+
+
+
+ + +
+
+ + +
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + {% for user in users[::-1] %} + + + + + + + + {% endfor %} + +
#First NameLast NameDate AddedAction
{{ users[::-1].index(user) + 1 }}{{ user.first_name }}{{ user.last_name }}{{ user.date_added.strftime('%B %d %Y - %H:%M:%S') }} + Edit + Delete +
+
+
+
+{% endblock main %} diff --git a/flask-add-users/templates/layout.html b/flask-add-users/templates/layout.html new file mode 100644 index 0000000..183ec7d --- /dev/null +++ b/flask-add-users/templates/layout.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + {{ app_title }} + + +
+
+

{{ app_title }}

+
+
+ {% block main %}{% endblock main %} +
+
+ + + + + + + + diff --git a/flask-add-users/templates/update.html b/flask-add-users/templates/update.html new file mode 100644 index 0000000..06c9420 --- /dev/null +++ b/flask-add-users/templates/update.html @@ -0,0 +1,23 @@ +{% extends 'layout.html' %} + +{% block main %} +
+

Update User

+
+
+
+
+ + +
+
+ + +
+ + Back home +
+
+
+
+{% endblock main %} diff --git a/flask-add-users/user.db b/flask-add-users/user.db new file mode 100644 index 0000000000000000000000000000000000000000..36efe7018de2ae336f59e0a6b743f79561b53277 GIT binary patch literal 8192 zcmeI#zi!h&90%}ong}(CeMnUl5UP4CG=bLmUvQlT+|+6VNq~z%%2ZwORk4)Vl4BM& z$|Eo`G9s0C;2n@)U}R+I8}veziV#we7@*S6_Q~hFug*VxY!B`}ZiOi)2XQiDDKXJy zBuVHVAqb(qXc^I_+mh&Hrx)TZ{m@_3?IZQ>XL%CF9ufy^AOHd&00JNY0w4eaAOHd& z00JOzaRpv(Nteo{l62TjS%1i%k9jg_nFjS--y^=e-SWs}gjDj&VL+N4-`n*l={)pF z=Si!zLGsH7VKPqlBR1mXsY@GsF0GhabtW=oze@xx<@+oMctCcwGm_x<(7ePB>I2!H?xfB*=900@A<|0S^fcje$C1S<$aa5#OBz~Ri{)*pUZg6yA1 zub*41sBjv%eQt1Wa${~}@qmgCk-m8P7c*)$hpw%r8`@-+6^g(N-H8bh<0NBQ_iYej%r)Fra31(>V@L~ literal 0 HcmV?d00001 From cc4c869f7a4e5e02bb9d39a527626add3b5b874f Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Sat, 6 Nov 2021 11:22:07 +0200 Subject: [PATCH 29/34] added "flask-minimal-app project" --- flask-minimal-app/.gitignore | 2 + flask-minimal-app/README.md | 9 ++ flask-minimal-app/add_posts.py | 72 ++++++++++++++ flask-minimal-app/count.txt | 1 + flask-minimal-app/database.db | Bin 0 -> 16384 bytes flask-minimal-app/databases.py | 36 +++++++ flask-minimal-app/greeting.py | 16 ++++ flask-minimal-app/hello.py | 12 +++ flask-minimal-app/instruction.md | 89 ++++++++++++++++++ flask-minimal-app/posts.py | 42 +++++++++ flask-minimal-app/site_count.py | 28 ++++++ flask-minimal-app/static/main.css | 48 ++++++++++ .../templates/add-posts-all.html | 18 ++++ .../templates/add-posts-posts.html | 23 +++++ .../templates/add-posts-update.html | 20 ++++ flask-minimal-app/templates/add-posts.html | 20 ++++ .../templates/databases_index.html | 14 +++ flask-minimal-app/templates/layout.html | 14 +++ flask-minimal-app/templates/posts_index.html | 18 ++++ flask-minimal-app/templates/posts_post.html | 16 ++++ flask-minimal-app/templates/sc_index.html | 9 ++ flask-minimal-app/url.py | 34 +++++++ 22 files changed, 541 insertions(+) create mode 100644 flask-minimal-app/.gitignore create mode 100644 flask-minimal-app/README.md create mode 100644 flask-minimal-app/add_posts.py create mode 100644 flask-minimal-app/count.txt create mode 100644 flask-minimal-app/database.db create mode 100644 flask-minimal-app/databases.py create mode 100644 flask-minimal-app/greeting.py create mode 100644 flask-minimal-app/hello.py create mode 100644 flask-minimal-app/instruction.md create mode 100644 flask-minimal-app/posts.py create mode 100644 flask-minimal-app/site_count.py create mode 100644 flask-minimal-app/static/main.css create mode 100644 flask-minimal-app/templates/add-posts-all.html create mode 100644 flask-minimal-app/templates/add-posts-posts.html create mode 100644 flask-minimal-app/templates/add-posts-update.html create mode 100644 flask-minimal-app/templates/add-posts.html create mode 100644 flask-minimal-app/templates/databases_index.html create mode 100644 flask-minimal-app/templates/layout.html create mode 100644 flask-minimal-app/templates/posts_index.html create mode 100644 flask-minimal-app/templates/posts_post.html create mode 100644 flask-minimal-app/templates/sc_index.html create mode 100644 flask-minimal-app/url.py diff --git a/flask-minimal-app/.gitignore b/flask-minimal-app/.gitignore new file mode 100644 index 0000000..93526df --- /dev/null +++ b/flask-minimal-app/.gitignore @@ -0,0 +1,2 @@ +venv/ +__pycache__/ diff --git a/flask-minimal-app/README.md b/flask-minimal-app/README.md new file mode 100644 index 0000000..f2cb596 --- /dev/null +++ b/flask-minimal-app/README.md @@ -0,0 +1,9 @@ +# Flask demo applications + +- ['Hello, World' app](#) +- ['Greeting' app](#) +- ['Page counter' app](#) +- ['Posts' app](#) +- ['Display posts from database' app](#) +- ['Add post' app](#) +- ['Url's' app](#) diff --git a/flask-minimal-app/add_posts.py b/flask-minimal-app/add_posts.py new file mode 100644 index 0000000..9ba5add --- /dev/null +++ b/flask-minimal-app/add_posts.py @@ -0,0 +1,72 @@ +# Add posts app on Flask + +from flask import Flask, render_template, url_for, request, redirect +from flask_sqlalchemy import SQLAlchemy +from databases import BlogPost, db + +app = Flask(__name__) + +# App configuration file for the database creation +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + + +# Display all posts configuration +@app.route('/') +def all_posts(): + posts = BlogPost.query.order_by(BlogPost.date_posted.desc()).all() + return render_template('add-posts-all.html', posts=posts) + + +# Add a new post configuration +@app.route('/add-post', methods=['GET', 'POST']) +def add_posts(): + if request.method == "POST": + post_title = request.form['title'].title() + if request.form['author'] == "": + post_author = "Author Unknown" + else: + post_author = request.form['author'].title() + post_content = request.form['content'] + new_post = BlogPost(title=post_title, author=post_author, content=post_content) + db.session.add(new_post) + db.session.commit() + return redirect(url_for('all_posts')) + return render_template('add-posts.html') + + +# Detailed post view configuration +@app.route('/posts/') +def post(post_id): + post = BlogPost.query.get_or_404(post_id) + return render_template('add-posts-posts.html', post=post) + + +# Delete a post configuration +@app.route('/posts/delete/') +def delete_post(post_id): + post = BlogPost.query.get_or_404(post_id) + db.session.delete(post) + db.session.commit() + return redirect(url_for('all_posts')) + + +# Update a post configuration +@app.route('/posts/update/', methods=["POST", "GET"]) +def update_post(post_id): + if request.method == "POST": + updated_post = BlogPost.query.get_or_404(post_id) + updated_post.title = request.form['title'].title() + updated_post.author = request.form['author'].title() + updated_post.content = request.form['content'] + db.session.commit() + return redirect(url_for('all_posts')) + else: + post = BlogPost.query.get_or_404(post_id) + return render_template('add-posts-update.html', post=post) + + +db.init_app(app) + +if __name__ == '__main__': + app.run(debug=True) diff --git a/flask-minimal-app/count.txt b/flask-minimal-app/count.txt new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/flask-minimal-app/count.txt @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/flask-minimal-app/database.db b/flask-minimal-app/database.db new file mode 100644 index 0000000000000000000000000000000000000000..e5e8be528d7cb3b0b3501e9a2246b260969584b5 GIT binary patch literal 16384 zcmeI1&2Ah;5XX08q$oxfTo4yfNFz~k@=9C!*|hJVlOOza#u6RAcX^~_FxRQ>8-)_KzqG+d;Naz zGooIvcMIoRI5%)!Tes=HJ^Jm%f3&xH*$01ap+owdHlXoPNTtw)N>vfPck~k?o!1(U?W;+OtWG`Gd3E%D-**~g#o>Y zxScz-(uKkedNmVf^h9yaR(UGbg)Y<5ddjXMz4Wmhkma0=%C*&sqO+=-lT?6x4g;5L z40gxtUqpuC)5--bX1F2_6iskCXP?nYG)9q!u~vISD;*R!1{XRHvBY(1GCI9H-y-?1 zu=g%2H`Rp6d;l%RL@+JDUMyk(qP{4VVILKIoT-w1A__!Hn8S1SLBWjEh4NSc{g*Hl z8~=nYYAW@B@OHq4^^9!+91&|>>IBO(I*!ko&Xq0L`Q4q};ho{moxL3z9vtrO9PZuE z_78T4`};3{zIMHL=lA~h=$sL%OQC)SD-d7+C(U@FnJr zDpU@;y$%HL0xhFUw`#882coT4?3~Kzar8MSE_I+&1hFbD5k_|Ss0bHJ#4Djbi53q7 z(9dCu*C_}pg`k6E6qLwNP_2hr4&C@x7z1L9q0k*HTU*iG;YsqY6Gg3{R$vyEXo#p5 z1_W8zIpUgPfq3(J=*($5*GW013HNfL90#XJTiEF;jcL*viL-9}BIWWpc*SX*H0zui zK{(1bo?MUudhgS0fn9;HOd)@pE^2OR=EllV^Q!mMKDX6R_G;{h_Ye2>vwM5PgS~@a zKkXyS|9J1i(PQm^z02~g&8^Mjl-6sMMFoR8BL|mrnpB}7T4ddPy?U3WP&6Z#%L)oj zs?X?>q!PFF>`SLhXaaOP^;9m`WKbxYTxl~C68DiEqasYTL7Jm7DE@>VRZZ^K@ke^p z8M2l`ofe9Ij6PHpw9R!9k)y3LGipm(s|F9ZYlqiiT}88u0k6lvT$hb?iFq}{l`2rz zHB=@48m9be@j;3r>}@`9B)(|t4$o#fuPZ5E)J3SK(TZt+Y6itFbRKJ^Rn!^S=@UH~ zsUUGxOj2ztW|vvEvQ4E8b%klyp20cfw9e?uYGDDEUz5+l;k{vYcmLq-?)~+@xAZMP zecMmp`Q;D-LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{ LAs__aFarMqpKW;R literal 0 HcmV?d00001 diff --git a/flask-minimal-app/databases.py b/flask-minimal-app/databases.py new file mode 100644 index 0000000..0699f52 --- /dev/null +++ b/flask-minimal-app/databases.py @@ -0,0 +1,36 @@ +# Minimalistic app on Flask with SQLAlchemy database + +from flask import Flask, render_template +from flask_sqlalchemy import SQLAlchemy +from datetime import datetime + +app = Flask(__name__) + +# App configuration file for the database creation +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + +# Creating the 'db' database +db = SQLAlchemy(app) + + +# Creating 'Post' models for the database +class BlogPost(db.Model): + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.String(100), nullable=False) + content = db.Column(db.Text, nullable=False) + author = db.Column(db.String(50), nullable=False, default='Author Unknown') + date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + + def __repr__(self): + return 'Blog post ' + str(self.id) + + +@app.route('/') +def index(): + posts = BlogPost.query.all() + return render_template('databases_index.html', posts=posts) + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/flask-minimal-app/greeting.py b/flask-minimal-app/greeting.py new file mode 100644 index 0000000..74f5eb3 --- /dev/null +++ b/flask-minimal-app/greeting.py @@ -0,0 +1,16 @@ +# Simplistic greeting Flask app + +from flask import Flask + +app = Flask(__name__) + +@app.route("/") +def hello(): + return "

Hello there! Type your name in the browser address bar (right after '/', e.g.: '/john')

" + +@app.route("/") +def greetings(user): + return f"

Hello, {user.title()}! Great to see you here

" + +if __name__ == '__main__': + app.run(debug=True) diff --git a/flask-minimal-app/hello.py b/flask-minimal-app/hello.py new file mode 100644 index 0000000..ecfa740 --- /dev/null +++ b/flask-minimal-app/hello.py @@ -0,0 +1,12 @@ +# Flask Minimal App - Hello World page + +from flask import Flask + +app = Flask(__name__) + +@app.route("/") +def hello_world(): + return f"

Hello, World!

" + +if __name__ == '__main__': + app.run(debug=True) diff --git a/flask-minimal-app/instruction.md b/flask-minimal-app/instruction.md new file mode 100644 index 0000000..a3fcc0f --- /dev/null +++ b/flask-minimal-app/instruction.md @@ -0,0 +1,89 @@ +# Minimal Flask Apps + +### Pre-requisites: +- Python must be installed on the system: ```python3 --version``` to verify python installation +- Python virtual environment package should be installed: ```sudo apt install python3-venv``` + +Steps: +1. Create a project directory: ```mkdir flask-minimal-app``` +2. Navigate to the project folder: ```cd flask-blog``` +3. Create a virtual environment inside your project directory: ```python3 -m venv venv``` +4. Activate the virtual environment: ```source venv/bin/activate``` +5. Install Flask: ```pip install Flask``` +6. To verify if Flask was installed on the system: ```python -m flask --version``` +7. Create the simpliest 'Hello, World!' program. Create a python file: ```touch hello.py``` +8. Open the 'hello.py' file and paste in it the following code: +``` +from flask import Flask +app = Flask(__name__) + +@ app.route('/') +def hello_world(): + return "

Hello, World!

" + +if __name__ == '__main__': + app.run(debug=True) +``` +9. Launch the development server: ```export FLASK_APP=flaskblog.py``` and then run the Flask app: ```flask run``` +10. The ```http://127.0.01:5000``` or ```http://localhost:5000``` server address should be displayed. Open it in the browser and the 'Hello, World!' message should be displayed +11. Use ```deactivate``` command to stop the server + + +### Creating databses + +- Create a python file: ```touch databases.py``` +- Paste the minimal flask code in it: +``` +from flask import Flask, render_template + +app = Flask(__name__) + +@ app.route('/') +def index(): + return "

Hello, World!

" + +if __name__ == '__main__': + app.run(debug=True) +``` +- Install in the project virtual environment ```source venv/bin/activate``` the 'SQL Alchemy' database: ```pip install flask-sqlalchemy``` +- Import 'SQL Alchemy' library: ```from flask_sqlalchemy import SQLAlchemy +- Create an app configuration for the database: ```app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db' +- Create the database: ```db = SQLAlchemy(app) +- Create 'Post' model for the database: +``` +class BlogPost(db.Model): + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.String(100), nullable=False) + content = db.Column(db.Text, nullable=False) + author = db.Column(db.String(50), nullable=False, default='Author Unknown') + date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + + def __repr__(self): + return 'Blog post ' + str(self.id) +``` +- Open 'python' in terminal ```python``` +- Import the database: ```from app databases import db``` +- Create the database: ```db.create_all()``` +- Testing the created database: + - ```from databases import BlogPost``` (import the 'BlogPost model created earlier') + - ```posts = BlogPost``` (creating a 'posts' variable) + - ```posts.query.all()``` (displaying all the posts from the database. An empty list should be displayed) + - Adding records to the database: + - ```post1 = BlogPost(title='First Blog Post', content='First blog post content', author='Sammy Lee')``` (creating 'post1' variable with data to be added to the database) + - ```db.session.add(post1)``` (adding data to the database) + - ```db.session.commit()``` (commit all the changes to the database) + - Testing the database: + - ```posts.query.all()``` (displaying all posts) + - ```posts.query.all()[0].title``` (display the title of the first post) + - ```posts.query.get(1)``` (display the second post created by id) +- Additionally we can create a template to display the posts: + - ```from flask import render_template``` (importing render template module) + - ```touch templates/databases_index.html``` (creating a new html file in the templates directory) + - copy the data from the 'posts_index.html' to the new created file + - modify the index function in the 'databases.py' file: + ``` + @app.route('/') + def index(): + posts = BlogPost.query.all() + return render_template('databases_index.html', posts = posts) + ``` diff --git a/flask-minimal-app/posts.py b/flask-minimal-app/posts.py new file mode 100644 index 0000000..302791c --- /dev/null +++ b/flask-minimal-app/posts.py @@ -0,0 +1,42 @@ +# Posts Flask app + +from flask import Flask, render_template, request + +app = Flask(__name__) + + +# Dummy data for posts +posts = [ + { + 'title': 'First post on the blog', + 'content': 'This is the content of the first blog post', + 'author': 'John Doe', + 'date_posted': '2021-10-01' + }, + { + 'title': 'Second post on the blog', + 'content': 'This is the content of the second blog post', + 'author': 'John Doe', + 'date_posted': '2021-10-02' + }, + { + 'title': 'Third post on the blog', + 'content': 'This is the content of the third blog post', + 'date_posted': '2021-10-02' + } +] + + +@app.route('/') +def index(): + return render_template('posts_index.html', posts=posts) + + +@app.route('/posts/') +def post(post_id): + post = posts[post_id] + return render_template('posts_post.html', post=post) + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/flask-minimal-app/site_count.py b/flask-minimal-app/site_count.py new file mode 100644 index 0000000..076654e --- /dev/null +++ b/flask-minimal-app/site_count.py @@ -0,0 +1,28 @@ +# Page counting Flask app + +from flask import Flask, render_template, url_for + +app = Flask(__name__) + + +@app.route("/") +def home(): + + """Open the 'count.txt' file and read the stored count variable number""" + f = open('count.txt', 'r') + count = int(f.read()) + f.close() + + """Adding plus one count every time we visit the '/' page""" + count += 1 + + """Rewrite the count varible in the 'count.txt' file""" + f = open('count.txt', 'w') + f.write(str(count)) + f.close() + + return render_template('sc_index.html', count=count) + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/flask-minimal-app/static/main.css b/flask-minimal-app/static/main.css new file mode 100644 index 0000000..e21ac60 --- /dev/null +++ b/flask-minimal-app/static/main.css @@ -0,0 +1,48 @@ +body { + background-color: #f1f1f1; + +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Bebas Neue', cursive; +} + +p { + font-family: 'Roboto', sans-serif; +} + +.container { + margin: 40px; +} + +/* Site count app style */ +h1.sc , h3.sc { + text-align: center; +} + +h1.sc { + color: lightskyblue; + margin-top: 5em; +} + +/* Posts app style */ +h1.posts { + color: lightskyblue; + margin-top: 5em; +} + +a.posts { + color: black; + text-decoration: none; +} + +a.posts:hover { + color: lightskyblue; + text-decoration: underline; +} + +/* Add posts app style */ + +.addPosts { + margin-top: 20px; +} diff --git a/flask-minimal-app/templates/add-posts-all.html b/flask-minimal-app/templates/add-posts-all.html new file mode 100644 index 0000000..a65fdb3 --- /dev/null +++ b/flask-minimal-app/templates/add-posts-all.html @@ -0,0 +1,18 @@ +{% extends 'layout.html' %} + +{% block head %} + All posts app +{% endblock head %} +{% block body %} +
+

All Blog Posts Below

+

Want to add a new post?

+
+ {% for post in posts %} +
+ Posted on {{ post.date_posted }} by {{ post.author }} +

{{ post.title }}

+

{{ post.content }}

+
+ {% endfor %} +{% endblock body %} diff --git a/flask-minimal-app/templates/add-posts-posts.html b/flask-minimal-app/templates/add-posts-posts.html new file mode 100644 index 0000000..6a3845a --- /dev/null +++ b/flask-minimal-app/templates/add-posts-posts.html @@ -0,0 +1,23 @@ +{% extends 'layout.html' %} + +{% block head %} + Posts Page +{% endblock head %} +{% block body %} +
+ Posted on {{ post.date_posted }} by {{ post.author }} +

{{ post.title }}

+

{{ post.content }}

+
+
+
Back home
+
+
+
+ +
+
+ +
+
+{% endblock body %} diff --git a/flask-minimal-app/templates/add-posts-update.html b/flask-minimal-app/templates/add-posts-update.html new file mode 100644 index 0000000..cd38ab1 --- /dev/null +++ b/flask-minimal-app/templates/add-posts-update.html @@ -0,0 +1,20 @@ +{% extends 'layout.html' %} + +{% block head %} + Add Posts App +{% endblock head %} +{% block body %} +
+

Add a new post

+
+
+
+
+
+
+
+ +
+
+ +{% endblock body %} diff --git a/flask-minimal-app/templates/add-posts.html b/flask-minimal-app/templates/add-posts.html new file mode 100644 index 0000000..9235e66 --- /dev/null +++ b/flask-minimal-app/templates/add-posts.html @@ -0,0 +1,20 @@ +{% extends 'layout.html' %} + +{% block head %} + Add Posts App +{% endblock head %} +{% block body %} +
+

Add a new post

+
+
+
+
+
+
+
+ +
+
+ +{% endblock body %} diff --git a/flask-minimal-app/templates/databases_index.html b/flask-minimal-app/templates/databases_index.html new file mode 100644 index 0000000..a17a648 --- /dev/null +++ b/flask-minimal-app/templates/databases_index.html @@ -0,0 +1,14 @@ +{% extends 'layout.html' %} + +{% block head %} + Posts App +{% endblock head %} +{% block body %} + {% for post in posts[::-1] %} +
+ Posted on {{ post.date_posted }} by {{ post.author }} +

{{ post.title }}

+

{{ post.content }}

+
+ {% endfor %} +{% endblock body %} diff --git a/flask-minimal-app/templates/layout.html b/flask-minimal-app/templates/layout.html new file mode 100644 index 0000000..7dec41e --- /dev/null +++ b/flask-minimal-app/templates/layout.html @@ -0,0 +1,14 @@ + + + + {% block head %}{% endblock head %} + + + + + + + + {% block body %}{% endblock body %} + + diff --git a/flask-minimal-app/templates/posts_index.html b/flask-minimal-app/templates/posts_index.html new file mode 100644 index 0000000..074d2da --- /dev/null +++ b/flask-minimal-app/templates/posts_index.html @@ -0,0 +1,18 @@ +{% extends 'layout.html' %} + +{% block head %} + Posts App +{% endblock head %} +{% block body %} + {% for post in posts[::-1] %} +
+ {% if post.author %} + Posted on {{ post.date_posted }} by {{ post.author }} + {% else %} + Posted on {{ post.date_posted }} by Author Unknown + {% endif %} +

{{ post.title }}

+

{{ post.content }}

+
+ {% endfor %} +{% endblock body %} diff --git a/flask-minimal-app/templates/posts_post.html b/flask-minimal-app/templates/posts_post.html new file mode 100644 index 0000000..6f3cc38 --- /dev/null +++ b/flask-minimal-app/templates/posts_post.html @@ -0,0 +1,16 @@ +{% extends 'layout.html' %} + +{% block head %} + Posts Page +{% endblock head %} +{% block body %} +
+ {% if post.author %} + Posted on {{ post.date_posted }} by {{ post.author }} + {% else %} + Posted on {{ post.date_posted }} by Author Unknown + {% endif %} +

{{ post.title }}

+

{{ post.content }}

+
+{% endblock body %} diff --git a/flask-minimal-app/templates/sc_index.html b/flask-minimal-app/templates/sc_index.html new file mode 100644 index 0000000..ed3343e --- /dev/null +++ b/flask-minimal-app/templates/sc_index.html @@ -0,0 +1,9 @@ +{% extends 'layout.html' %} + +{% block head %} + Page counter +{% endblock head %} +{% block body %} +

Page Counter

+

This page was visited {{ count }} times

+{% endblock body %} diff --git a/flask-minimal-app/url.py b/flask-minimal-app/url.py new file mode 100644 index 0000000..382c74d --- /dev/null +++ b/flask-minimal-app/url.py @@ -0,0 +1,34 @@ +from flask import Flask, url_for + +app = Flask(__name__) + +@app.route("/") +@app.route("/home") +def home(): + return "

Home Page

    Other pages

  • /about
  • /login
  • /user/john
" + + +@app.route("/about") +def about(): + return "

About Page

" + + +@app.route("/login") +def login(): + return "

Login Page

" + + +@app.route("/user/") +def user(username): + return f"

{username.title()} Page

" + + +with app.test_request_context(): + print(url_for('home')) + print(url_for('about')) + print(url_for('login')) + print(url_for('user', username="john")) + + +if __name__ == '__main__': + app.run(debug=True) From 17df6b91d2b4ff87bfac6d189386d0b8ae312264 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Sat, 6 Nov 2021 11:39:46 +0200 Subject: [PATCH 30/34] modified README file --- flask-minimal-app/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/flask-minimal-app/README.md b/flask-minimal-app/README.md index f2cb596..fe13d78 100644 --- a/flask-minimal-app/README.md +++ b/flask-minimal-app/README.md @@ -1,9 +1,9 @@ -# Flask demo applications +# Flask minimal demo applications -- ['Hello, World' app](#) -- ['Greeting' app](#) -- ['Page counter' app](#) -- ['Posts' app](#) -- ['Display posts from database' app](#) -- ['Add post' app](#) -- ['Url's' app](#) +- ['Hello, World' app](https://github.com/valeriybercha/python-demos/blob/master/flask-minimal-app/hello.py) +- ['Greeting' app](https://github.com/valeriybercha/python-demos/blob/master/flask-minimal-app/greeting.py) +- ['Page counter' app](https://github.com/valeriybercha/python-demos/blob/master/flask-minimal-app/site_count.py) +- ['Posts' app](https://github.com/valeriybercha/python-demos/blob/master/flask-minimal-app/posts.py) +- ['Display posts from database' app](https://github.com/valeriybercha/python-demos/blob/master/flask-minimal-app/databases.py) +- ['Add post' app](https://github.com/valeriybercha/python-demos/blob/master/flask-minimal-app/add_posts.py) +- ['Url's' app](https://github.com/valeriybercha/python-demos/blob/master/flask-minimal-app/url.py) From 500ddf7b68bc98a7ae45a460e018c183cead54dd Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Tue, 9 Nov 2021 23:23:03 +0200 Subject: [PATCH 31/34] added "flask-simple-blog" project --- flask-simple-blog/.gitignore | 2 + flask-simple-blog/README.md | 22 +++ flask-simple-blog/app.py | 182 ++++++++++++++++++ flask-simple-blog/blog.db | Bin 0 -> 16384 bytes flask-simple-blog/requirements.txt | 13 ++ flask-simple-blog/static/blog.css | 166 ++++++++++++++++ flask-simple-blog/static/main.css | 0 flask-simple-blog/templates/about.html | 38 ++++ flask-simple-blog/templates/add-pages.html | 23 +++ flask-simple-blog/templates/add-posts.html | 27 +++ flask-simple-blog/templates/base-posts.html | 49 +++++ flask-simple-blog/templates/base.html | 74 +++++++ flask-simple-blog/templates/index.html | 33 ++++ flask-simple-blog/templates/page.html | 17 ++ flask-simple-blog/templates/posts.html | 20 ++ flask-simple-blog/templates/update-pages.html | 21 ++ flask-simple-blog/templates/update-posts.html | 25 +++ 17 files changed, 712 insertions(+) create mode 100644 flask-simple-blog/.gitignore create mode 100644 flask-simple-blog/README.md create mode 100644 flask-simple-blog/app.py create mode 100644 flask-simple-blog/blog.db create mode 100644 flask-simple-blog/requirements.txt create mode 100644 flask-simple-blog/static/blog.css create mode 100644 flask-simple-blog/static/main.css create mode 100644 flask-simple-blog/templates/about.html create mode 100644 flask-simple-blog/templates/add-pages.html create mode 100644 flask-simple-blog/templates/add-posts.html create mode 100644 flask-simple-blog/templates/base-posts.html create mode 100644 flask-simple-blog/templates/base.html create mode 100644 flask-simple-blog/templates/index.html create mode 100644 flask-simple-blog/templates/page.html create mode 100644 flask-simple-blog/templates/posts.html create mode 100644 flask-simple-blog/templates/update-pages.html create mode 100644 flask-simple-blog/templates/update-posts.html diff --git a/flask-simple-blog/.gitignore b/flask-simple-blog/.gitignore new file mode 100644 index 0000000..93526df --- /dev/null +++ b/flask-simple-blog/.gitignore @@ -0,0 +1,2 @@ +venv/ +__pycache__/ diff --git a/flask-simple-blog/README.md b/flask-simple-blog/README.md new file mode 100644 index 0000000..4698ab4 --- /dev/null +++ b/flask-simple-blog/README.md @@ -0,0 +1,22 @@ +# Basic demo blog created with Flask + +### Basic information: + +- Blog app created with Flask and Python +- Programming language: Python 3.6.9 +- Developer: Valeriy B. + +### Blog functionality: + +- Add a post +- Add a page +- Update a post +- Delete a post +- Update a page +- Delete a page + +### Libraries to install: +- ```pip install flask``` +- ```pip install flask-sqlalchemy``` + +* This app is created for showcase purposes only diff --git a/flask-simple-blog/app.py b/flask-simple-blog/app.py new file mode 100644 index 0000000..78102f7 --- /dev/null +++ b/flask-simple-blog/app.py @@ -0,0 +1,182 @@ +# Basic blog app created with Flask +# Programming language: Python 3.6.9 +# Developer: Valeriy B. + +from flask import Flask, render_template, url_for, request, redirect +from flask_sqlalchemy import SQLAlchemy +from datetime import datetime + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + +# Creating 'db' database +db = SQLAlchemy(app) + +# Creating default variables +default_blog_title = "Simple Flask Blog" +default_blog_description = "Demo blog created with Flask where you can add posts and pages" +default_author_name = "Author Unknown" + + +# Models for adding posts to the database +class Post(db.Model): + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.String(100), nullable=False) + author = db.Column(db.String(30), nullable=False) + content = db.Column(db.Text, nullable=False) + date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + + def __repr__(self): + return f"Post {self.id}" + + +# Models for adding new pages to the database +class Page(db.Model): + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.String(100), nullable=False) + content = db.Column(db.Text, nullable=False) + date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + + def __repr__(self): + return f"Page {self.id}" + + +# Quering all pages +def all_pages(): + return Page.query.all() + + +# Routing for adding pages to menu +def menu_pages(): + return render_template('base.html', pages=pages) + + +# Routing for adding blog description to sidebar +def about_sidebar(): + about = default_blog_description + return render_template('base-posts.html', about=about) + + +# Routing for 'Index' blog page (display all posts) +@app.route('/') +def index(): + posts = Post.query.all() + pages = all_pages() + default_variables = [default_blog_title, default_blog_description] + about = default_blog_description + return render_template('index.html', posts=posts, pages=pages, default_variables=default_variables, about=about) + + +# Routing for post display +@app.route('/post/') +def posts(id): + post = Post.query.get_or_404(id) + pages = all_pages() + return render_template('posts.html', post=post, pages=pages) + + +# Routing for adding a new post +@app.route('/add-post', methods=["POST", "GET"]) +def add_post(): + if request.method == "POST": + title = request.form['title'].title() + if request.form['author'] == "": + author = default_author_name + else: + author = request.form['author'].title() + content = request.form['content'] + post = Post(title=title, author=author, content=content) + db.session.add(post) + db.session.commit() + return redirect(url_for('index')) + else: + pages = all_pages() + about = default_blog_description + return render_template('add-posts.html', pages=pages, about=about) + + +# Routing for deleting posts +@app.route('/post//delete') +def delete_post(id): + post_to_delete = Post.query.get_or_404(id) + db.session.delete(post_to_delete) + db.session.commit() + return redirect(url_for('index')) + + +# Routing for updating posts +@app.route('/post//update', methods=["POST", "GET"]) +def update_post(id): + if request.method == "POST": + updated_post = Post.query.get_or_404(id) + updated_post.title = request.form['title'].title() + if request.form['author'] == "": + updated_post.author = default_author_name + else: + updated_post.author = request.form['author'].title() + updated_post.content = request.form['content'] + db.session.commit() + return redirect(url_for('index')) + else: + pages = all_pages() + post = Post.query.get_or_404(id) + return render_template('update-posts.html', post=post, pages=pages) + + +# Routing for 'About' page +@app.route('/about') +def about(): + pages = all_pages() + return render_template('about.html', pages=pages) + + +# Routing for adding pages +@app.route('/add-page', methods=["POST", "GET"]) +def add_page(): + if request.method == "POST": + title = request.form['title'].title() + content = request.form['content'] + post_to_add = Page(title=title, content=content) + db.session.add(post_to_add) + db.session.commit() + return redirect(url_for('index')) + else: + pages = all_pages() + about = default_blog_description + return render_template('add-pages.html', pages=pages, about=about, active_add_page="active") + + +# Routing for 'Page' display +@app.route('/page/') +def pages(id): + page = Page.query.get_or_404(id) + pages = all_pages() + return render_template('page.html', page=page, pages=pages) + + +# Routing for deleting pages +@app.route('/page//delete') +def delete_page(id): + page_to_delete = Page.query.get_or_404(id) + db.session.delete(page_to_delete) + db.session.commit() + return redirect(url_for('index')) + + +# Routing for updating pages +@app.route('/page//update', methods=["POST", "GET"]) +def update_page(id): + if request.method == "POST": + page_to_update = Page.query.get_or_404(id) + page_to_update.title = request.form['title'] + page_to_update.content = request.form['content'] + db.session.commit() + return redirect(url_for('index')) + page = Page.query.get_or_404(id) + pages = all_pages() + return render_template('update-pages.html', page=page, pages=pages) + + +if __name__ == "__main__": + app.run(debug=True) diff --git a/flask-simple-blog/blog.db b/flask-simple-blog/blog.db new file mode 100644 index 0000000000000000000000000000000000000000..e5530b5ada2751f6727587a6566d38841a96d8fd GIT binary patch literal 16384 zcmeI&%TC)s6b9g#B!Cjhm<`H;E>3re2*Hj?bK79REm1C{u0gOu4spR!8b`?>6|sU9 zPr)+)Z_qdEm=Hv$R8^HCars9c*&chw=X^WQ%(t&~UwHIA82oSr8Ek=Z&en+-V}`6T zS;s|{7f&=X!ykYnx3K2Q2}T;Uz|gQ4&`v?aghR2$aB3oX0aFzo}XSqGHz zJLyFFq81s2do~JJb`A%KPKGO6{y$vzRGb8Z$8?NoX4B+z$z+mWoW$e zDiR9+&AEEZ li > a { + width: 140px; + padding: 10px 20px; + text-align: center; + border-radius: 30px; +} + + +/* + * Blog posts + */ + +.blog-post { + margin-bottom: 60px; +} +.blog-post-title { + margin-bottom: 5px; + font-size: 40px; +} +.blog-post-meta { + margin-bottom: 20px; + color: #999; +} + + +/* + * Footer + */ + +.blog-footer { + padding: 40px 0; + color: #999; + text-align: center; + background-color: #f9f9f9; + border-top: 1px solid #e5e5e5; +} +.blog-footer p:last-child { + margin-bottom: 0; +} diff --git a/flask-simple-blog/static/main.css b/flask-simple-blog/static/main.css new file mode 100644 index 0000000..e69de29 diff --git a/flask-simple-blog/templates/about.html b/flask-simple-blog/templates/about.html new file mode 100644 index 0000000..3503c3c --- /dev/null +++ b/flask-simple-blog/templates/about.html @@ -0,0 +1,38 @@ +{% extends 'base.html' %} + +{% block title %}About page{% endblock title %} + +{% block body %} +
+

About

+
+
+
+

This app is created for showcase purposes only

+
+ +

Basic information:

+
    +
  • Blog app created with Flask and Python
  • +
  • Programming language: Python 3.6.9
  • +
  • Developer: Valeriy B.
  • +
+ +

Functionality:

+
    +
  • Add a post
  • +
  • Add a page
  • +
  • Update a post
  • +
  • Delete a post
  • +
  • Update a page
  • +
  • Delete a page
  • +
+ +

Libraries to install:

+
    +
  • pip install flask
  • +
  • pip install flask-sqlalchemy
  • +
+
+ +{% endblock body %} diff --git a/flask-simple-blog/templates/add-pages.html b/flask-simple-blog/templates/add-pages.html new file mode 100644 index 0000000..8ec9da4 --- /dev/null +++ b/flask-simple-blog/templates/add-pages.html @@ -0,0 +1,23 @@ +{% extends 'base-posts.html' %} + +{% set active_page = 'active_add_page' %} + +{% block blog_header %} +
+

Add a new page

+
+{% endblock blog_header %} + +{% block main %} +
+
+ + +
+
+ + +
+ +
+{% endblock main %} diff --git a/flask-simple-blog/templates/add-posts.html b/flask-simple-blog/templates/add-posts.html new file mode 100644 index 0000000..f88eacf --- /dev/null +++ b/flask-simple-blog/templates/add-posts.html @@ -0,0 +1,27 @@ +{% extends 'base-posts.html' %} + +{% set active_page = 'active_add_post' %} + +{% block blog_header %} +
+

Add a new post

+
+{% endblock blog_header %} + +{% block main %} +
+
+ + +
+
+ + +
+
+ + +
+ +
+{% endblock main %} diff --git a/flask-simple-blog/templates/base-posts.html b/flask-simple-blog/templates/base-posts.html new file mode 100644 index 0000000..d84b5ef --- /dev/null +++ b/flask-simple-blog/templates/base-posts.html @@ -0,0 +1,49 @@ +{% extends 'base.html' %} + + +{% block body %} + + {% block blog_header %}{% endblock blog_header %} + +
+ +
+ + {% block main %}{% endblock main %} + +
+ +
+ + + +
+ +
+{% endblock body %} diff --git a/flask-simple-blog/templates/base.html b/flask-simple-blog/templates/base.html new file mode 100644 index 0000000..9a1e18f --- /dev/null +++ b/flask-simple-blog/templates/base.html @@ -0,0 +1,74 @@ + + + + + + + + + + + + + {% block title %}Blog Template for Bootstrap{% endblock title %} + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ +
+ + {% block body %}{% endblock body %} + +
+ + + + + + + + + + + + + diff --git a/flask-simple-blog/templates/index.html b/flask-simple-blog/templates/index.html new file mode 100644 index 0000000..e6c88aa --- /dev/null +++ b/flask-simple-blog/templates/index.html @@ -0,0 +1,33 @@ +{% extends 'base-posts.html' %} + +{% set active_page = 'active_index' %} + +{% block blog_header %} +
+

{{ default_variables[0] }}

+

{{ default_variables[1] }}

+
+{% endblock blog_header %} + +{% block main %} + {% if posts|length == 0 %} +
+

There are NO posts created yet!

+

Create your first post

+
+ {% else %} + {% for post in posts[::-1] %} +
+

{{ post.title }}

+ +

{{ post.content }}

+
+ {% endfor %} + + {% endif %} +{% endblock main %} diff --git a/flask-simple-blog/templates/page.html b/flask-simple-blog/templates/page.html new file mode 100644 index 0000000..c8d85b6 --- /dev/null +++ b/flask-simple-blog/templates/page.html @@ -0,0 +1,17 @@ +{% extends 'base.html' %} + +{% set active_page = 'page.id' %} + +{% block body %} +
+

{{ page.title }}

+
+
+

{{ page.content }}

+ +
+ Update + Delete +
+ +{% endblock body %} diff --git a/flask-simple-blog/templates/posts.html b/flask-simple-blog/templates/posts.html new file mode 100644 index 0000000..f0f7f52 --- /dev/null +++ b/flask-simple-blog/templates/posts.html @@ -0,0 +1,20 @@ +{% extends 'base-posts.html' %} + +{% block blog_header %} +
+

{{ post.title }}

+ +
+{% endblock blog_header %} + +{% block main %} + +
+

{{ post.content }}

+ +
+ Update + Delete +
+ +{% endblock main %} diff --git a/flask-simple-blog/templates/update-pages.html b/flask-simple-blog/templates/update-pages.html new file mode 100644 index 0000000..8189ee0 --- /dev/null +++ b/flask-simple-blog/templates/update-pages.html @@ -0,0 +1,21 @@ +{% extends 'base-posts.html' %} + +{% block blog_header %} +
+

Update page

+
+{% endblock blog_header %} + +{% block main %} +
+
+ + +
+
+ + +
+ +
+{% endblock main %} diff --git a/flask-simple-blog/templates/update-posts.html b/flask-simple-blog/templates/update-posts.html new file mode 100644 index 0000000..f95f61d --- /dev/null +++ b/flask-simple-blog/templates/update-posts.html @@ -0,0 +1,25 @@ +{% extends 'base-posts.html' %} + +{% block blog_header %} +
+

Update post

+
+{% endblock blog_header %} + +{% block main %} +
+
+ + +
+
+ + +
+
+ + +
+ +
+{% endblock main %} From afb8645619b05aaffed2600e584454f374238ae5 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Tue, 9 Nov 2021 23:26:18 +0200 Subject: [PATCH 32/34] minor changes to README file --- flask-simple-blog/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flask-simple-blog/README.md b/flask-simple-blog/README.md index 4698ab4..bb8d74f 100644 --- a/flask-simple-blog/README.md +++ b/flask-simple-blog/README.md @@ -19,4 +19,4 @@ - ```pip install flask``` - ```pip install flask-sqlalchemy``` -* This app is created for showcase purposes only +This app is created for showcase purposes only From 1f4baf6d74b7b98ac70d3a530eef8b3e875b7e4b Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Mon, 6 Dec 2021 21:23:39 +0200 Subject: [PATCH 33/34] added flask-app-register-login project --- flask-app-register-login/.README.md.swp | Bin 0 -> 1024 bytes flask-app-register-login/.gitignore | 2 + flask-app-register-login/README.md | 36 ++++++ flask-app-register-login/app.db | Bin 0 -> 16384 bytes flask-app-register-login/app.py | 120 ++++++++++++++++++ flask-app-register-login/requirements.txt | 15 +++ flask-app-register-login/templates/index.html | 52 ++++++++ .../templates/layout.html | 24 ++++ flask-app-register-login/templates/login.html | 33 +++++ .../templates/success.html | 7 + flask-app-register-login/templates/users.html | 21 +++ 11 files changed, 310 insertions(+) create mode 100644 flask-app-register-login/.README.md.swp create mode 100644 flask-app-register-login/.gitignore create mode 100644 flask-app-register-login/README.md create mode 100644 flask-app-register-login/app.db create mode 100644 flask-app-register-login/app.py create mode 100644 flask-app-register-login/requirements.txt create mode 100644 flask-app-register-login/templates/index.html create mode 100644 flask-app-register-login/templates/layout.html create mode 100644 flask-app-register-login/templates/login.html create mode 100644 flask-app-register-login/templates/success.html create mode 100644 flask-app-register-login/templates/users.html diff --git a/flask-app-register-login/.README.md.swp b/flask-app-register-login/.README.md.swp new file mode 100644 index 0000000000000000000000000000000000000000..642ad4475227b179abe041ca62c8b52ca6ec3e13 GIT binary patch literal 1024 zcmYc?$V<%2S1{4DU_b#^xEL795_2+91aWXmOpFXt5{pW3NW+DLTpe9}UG;KP;3A`p M(GVC7fq@JG09DTlu2)A_)R?8 z4mR8h1CNe>AZe34Nt0i5$^FO-GeMI$nfe)>unvk(q=htYEU>Du^bKTTibBv=Nl55KdG8*Y#3S|5`d23ol) z*D^+~PU>QHD~@v2YfMxAY|{uHT-YXYsu5RS>*ErK!Pdf19FTnWA1C zsQvO#waTJX7Dy0)00bZa0SG_<0uX=z1Rwwb2yCl>Ty6~a|84!f*cSvK009U<00Izz n00bZa0SG`~E`a+#4gv%q009U<00Izz00bZa0SG`~`vragPMeZ@ literal 0 HcmV?d00001 diff --git a/flask-app-register-login/app.py b/flask-app-register-login/app.py new file mode 100644 index 0000000..21b3413 --- /dev/null +++ b/flask-app-register-login/app.py @@ -0,0 +1,120 @@ +# Basic app registration app created with Flask, Flask-SQLAlchemy, Flask-WTForms +# The app was created in WSL (Windows Subsystem for Linux) environment using the Nano editor + +from flask import Flask, render_template, url_for, redirect, flash +from flask_sqlalchemy import SQLAlchemy +from flask_wtf import FlaskForm +from wtforms import StringField, PasswordField, SubmitField +from wtforms.validators import DataRequired, Email, EqualTo, ValidationError, Length +from flask_login import LoginManager, UserMixin, login_user, logout_user +from werkzeug.security import generate_password_hash, check_password_hash + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +app.config['SECRET_KEY'] = "your_secret_key" + +db = SQLAlchemy(app) +login_manager = LoginManager(app) + + +################ FORMS SECTION - forms.py ############### + +# Creating models for user registration for FLask-SQLALchemy +class UserRegistration(db.Model, UserMixin): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(20), unique=True, nullable=False) + fullname = db.Column(db.String(120), nullable=False) + email = db.Column(db.String(50), unique=True, nullable=False) + password = db.Column(db.String(20), nullable=False) + + def __repr__(self): + return f'User({self.username}, {self.fullname}, {self.email})' + + +# User registration form validation with Flask-WTForms +class UserForm(FlaskForm): + username = StringField('Username', validators=[DataRequired(), Length(min=4, max=20)]) + fullname = StringField('Full Name', validators=[DataRequired(), Length(min=4, max=120)]) + email = StringField('Email', validators=[DataRequired(), Email(), Length(min=5, max=50)]) + password = PasswordField('Password', validators=[DataRequired(), Length(min=8, max=20)]) + confirmPassword = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')]) + submit = SubmitField('Register') + + def validate_username(self, username): + form= UserForm() + check_username = UserRegistration.query.filter_by(username=form.username.data).first() + + if check_username: + raise ValidationError("This username already exists. Choose another one") + + def validate_email(self, email): + form = UserForm() + check_email = UserRegistration.query.filter_by(email=form.email.data).first() + if check_email: + raise ValidationError("This email already exists. Go to Login page") + + +# User login form validation with Flask-WTForms +class UserLogin(FlaskForm): + email = StringField('Email', validators=[DataRequired(), Email()]) + password = PasswordField('Password', validators=[DataRequired()]) + submit = SubmitField('Login') + + +################ ROUTING SECTION - routes.py ################### + +# Creating login manager session +@login_manager.user_loader +def load_user(user_id): + return UserRegistration.query.get(user_id) + + +# Routing for 'index/registartion' page with form for user registration +@app.route('/', methods=["POST", "GET"]) +def index(): + form = UserForm() + if form.validate_on_submit(): + user_to_register = UserRegistration(username=form.username.data.lower(), fullname=form.fullname.data.title(), email=form.email.data.lower(), password=generate_password_hash(form.password.data)) + db.session.add(user_to_register) + db.session.commit() + return render_template('success.html', message="Register") + return render_template('index.html', form=form) + + +# Routing for 'login' function +@app.route('/login', methods=["GET", "POST"]) +def login(): + form = UserLogin() + if form.validate_on_submit(): + user = UserRegistration.query.filter_by(email=form.email.data).first() + if user and check_password_hash(user.password, form.password.data): + login_user(user) + return render_template('success.html', message="Login") + else: + flash('Incorrect login or password. Try again') + return render_template('login.html', form=form) + + +# Routing for 'logout' function +@app.route('/logout') +def logout(): + logout_user() + return redirect(url_for('index')) + + +# Routing for displaying all users +@app.route('/users') +def users(): + users = UserRegistration.query.all() + return render_template('users.html', users=users) + + +# Routing for 'success' function +@app.route('/success') +def success(): + return render_template('success.html') + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/flask-app-register-login/requirements.txt b/flask-app-register-login/requirements.txt new file mode 100644 index 0000000..cc1b823 --- /dev/null +++ b/flask-app-register-login/requirements.txt @@ -0,0 +1,15 @@ +click==8.0.3 +dnspython==2.1.0 +email-validator==1.1.3 +Flask==2.0.2 +Flask-Login==0.5.0 +Flask-SQLAlchemy==2.5.1 +Flask-WTF==1.0.0 +greenlet==1.1.2 +idna==3.3 +itsdangerous==2.0.1 +Jinja2==3.0.3 +MarkupSafe==2.0.1 +SQLAlchemy==1.4.27 +Werkzeug==2.0.2 +WTForms==3.0.0 diff --git a/flask-app-register-login/templates/index.html b/flask-app-register-login/templates/index.html new file mode 100644 index 0000000..91e09b5 --- /dev/null +++ b/flask-app-register-login/templates/index.html @@ -0,0 +1,52 @@ + +{% extends 'layout.html' %} +{% block title %}Home/Register{% endblock title %} +{% block header %}User registration and login{% endblock header %} +{% block main %} +

Register a user to the database

+
+ {{ form.csrf_token }} + {{ form.username.label }}
+ {{ form.username(size=25) }}
+ {{ form.fullname.label }}
+ {{ form.fullname(size=25) }}
+ {{ form.email.label }}
+ {{ form.email(size=25) }}
+ {{ form.password.label }}
+ {{ form.password(size=25) }}
+ {{ form.confirmPassword.label }}
+ {{ form.confirmPassword(size=25) }}
+ {{ form.submit() }} +
+ {% if form.username.errors %} +
    + {% for error in form.username.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% elif form.fullname.errors %} +
    + {% for error in form.fullname.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% elif form.email.errors %} +
    + {% for error in form.email.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% elif form.password.errors %} +
    + {% for error in form.password.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% elif form.confirmPassword.errors %} +
    + {% for error in form.confirmPassword.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} +{% endblock main %} diff --git a/flask-app-register-login/templates/layout.html b/flask-app-register-login/templates/layout.html new file mode 100644 index 0000000..343994d --- /dev/null +++ b/flask-app-register-login/templates/layout.html @@ -0,0 +1,24 @@ + + + + + {% block title %}{% endblock title %} - User registration and login + + +

{% block header %}{% endblock header %}

+

+ Register | + {% if not current_user.is_authenticated %} + Login + {% endif %} + {% if current_user.is_authenticated %} + Logout | + Users + {% endif %} + +

+ {% block main %}{% endblock main %} +
+

* Demo application created using Python, Flask, Flask-SQLAlchemy, Flask-WTForms, Flask-Login + + diff --git a/flask-app-register-login/templates/login.html b/flask-app-register-login/templates/login.html new file mode 100644 index 0000000..805b64a --- /dev/null +++ b/flask-app-register-login/templates/login.html @@ -0,0 +1,33 @@ + +{% extends 'layout.html' %} +{% block title %}Login{% endblock title %} +{% block header %}User login{% endblock header %} +{% block main %} +

Login a user to the database

+
+ {{ form.csrf_token }} + {{ form.email.label }}
+ {{ form.email(size=25) }}
+ {{ form.password.label }}
+ {{ form.password(size=25) }}
+ {{ form.submit() }} +
+ {% if form.email.errors %} +
    + {% for error in form.email.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% elif form.password.errors %} +
    + {% for error in form.password.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} + {% for message in get_flashed_messages() %} +
    +
  • {{ message }}
  • +
+ {% endfor %} +{% endblock main %} diff --git a/flask-app-register-login/templates/success.html b/flask-app-register-login/templates/success.html new file mode 100644 index 0000000..0601e43 --- /dev/null +++ b/flask-app-register-login/templates/success.html @@ -0,0 +1,7 @@ + +{% extends 'layout.html' %} +{% block title %}Success{% endblock title %} +{% block header %}{{ message }} successfully!{% endblock header %} +{% block main %} +

You {{ message.lower() }} successfully!

+{% endblock main %} diff --git a/flask-app-register-login/templates/users.html b/flask-app-register-login/templates/users.html new file mode 100644 index 0000000..b43be54 --- /dev/null +++ b/flask-app-register-login/templates/users.html @@ -0,0 +1,21 @@ + +{% extends 'layout.html' %} +{% block title %}Users{% endblock title %} +{% block header %}All registered users{% endblock header %} +{% block main %} +

There are currently {{ users|length }} users registered in the database

+ + + + + + + {% for user in users[::-1] %} + + + + + + {% endfor %} +
FULL NAMEUSERNAMEEMAIL
{{ user.fullname }}{{ user.username }}{{ user.email }}
+{% endblock main %} From acd1ee2334c6825ca736784478a8db7322125595 Mon Sep 17 00:00:00 2001 From: Valeriy Bercha Date: Fri, 10 Dec 2021 23:24:35 +0200 Subject: [PATCH 34/34] added flask-to-do-app project --- flask-to-do-app/.gitignore | 2 + flask-to-do-app/README.md | 39 ++++ flask-to-do-app/app.db | Bin 0 -> 28672 bytes flask-to-do-app/app.py | 211 ++++++++++++++++++++ flask-to-do-app/requirements.txt | 20 ++ flask-to-do-app/templates/about.html | 7 + flask-to-do-app/templates/completed.html | 25 +++ flask-to-do-app/templates/index.html | 45 +++++ flask-to-do-app/templates/layout.html | 25 +++ flask-to-do-app/templates/login.html | 36 ++++ flask-to-do-app/templates/register.html | 52 +++++ flask-to-do-app/templates/test-success.html | 7 + flask-to-do-app/templates/test-users.html | 18 ++ flask-to-do-app/templates/update-task.html | 11 + 14 files changed, 498 insertions(+) create mode 100644 flask-to-do-app/.gitignore create mode 100644 flask-to-do-app/README.md create mode 100644 flask-to-do-app/app.db create mode 100644 flask-to-do-app/app.py create mode 100644 flask-to-do-app/requirements.txt create mode 100644 flask-to-do-app/templates/about.html create mode 100644 flask-to-do-app/templates/completed.html create mode 100644 flask-to-do-app/templates/index.html create mode 100644 flask-to-do-app/templates/layout.html create mode 100644 flask-to-do-app/templates/login.html create mode 100644 flask-to-do-app/templates/register.html create mode 100644 flask-to-do-app/templates/test-success.html create mode 100644 flask-to-do-app/templates/test-users.html create mode 100644 flask-to-do-app/templates/update-task.html diff --git a/flask-to-do-app/.gitignore b/flask-to-do-app/.gitignore new file mode 100644 index 0000000..92afa22 --- /dev/null +++ b/flask-to-do-app/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +venv/ diff --git a/flask-to-do-app/README.md b/flask-to-do-app/README.md new file mode 100644 index 0000000..88e7cf2 --- /dev/null +++ b/flask-to-do-app/README.md @@ -0,0 +1,39 @@ +# Demo task manager built with Python and Flask + +### Features: +- Register a user to the database: + - Registration form fields: + - Email (Unique, Length: 4 - 50) + - Full Name (Length: 5 - 120) + - Password (Length: 8 - 20) + - Confirm password (EqualTo: password) +- Verification if email already exists in the database when registring a new user +- Login into the system for registered users: + - Login form fields: + - Email (Required) + - Password (Required) +- Successdul message display when users are registered ir logged into the system +- Logged user can create a task +- Logged user can complete a task marking it as 'Done' +- All completed tasks will be stored in 'Completed tasks' page +- User can 'Undone' a completed task. Task will appeat in the task list again +- Logged user can update created task +- Logged user can delete created task + +### Pre-requistites: +- Python should be installed: ```python3 --version```. If python is not installed: ```sudo apt install python3 python3-pip python3-venv``` + +### Install and run the application +- Clone the project from github repository: ```git svn clone https://github.com/valeriybercha/python-demos/trunk/flask-to-do-app``` +- Create project virtual environment: ```python -m venv venv``` +- Start the virtual environment server: ```source venv/bin/activate``` +- Install needed libraries: + - Flask: ```pip install flask``` + - Flask WTForms: ```pip install flask-wtf``` + - WTForms Email validation ```pip install wtforms[email]``` + - Flask SQLAlchemy: ```pip install flask-sqlalchemy``` + - Flask Login: ```pip install flask-login``` + OR, install libraries from ```requirements.txt``` file +- Enable the debug mode for development server: ```export FLASK_DEBUG=1``` +- Start flask project: ```export FLASK_APP=app.py``` and ```flask run``` +- Open the project in browser with address: ```localhost:5000``` diff --git a/flask-to-do-app/app.db b/flask-to-do-app/app.db new file mode 100644 index 0000000000000000000000000000000000000000..7a8b6ae24f162fc02e4a6f42334e6da14d152bd4 GIT binary patch literal 28672 zcmeI&&u`LT9LMoi84MKIh4lK|EQuO7-N_hN@Yy6|#dTn|Q&Vjv6mW|NFE;Nc{q;N#JbYf?Hlcxo{dPZz#JkaW7$oAcv1XX2u_c6I7#C_S zsCBkHQ3tu%iQ1dL9bb2NVLW{Ptz0=Y@^>ai`9tNw-BGnv{i;q_5I_I{1Q0*~0R#}p zzCh*h@>}yXDHg0+%{<>tf;WRG3F41>%{4vgbfxGzjkXlJMcAccKNKyuD|e(P+)h`x zy>|P)C>7K0*N)eG>3H_W=A-&juOEbA6p9z>ExWBfx!nJDG(1tWt1*pEr!5_KZpdjI zjs0Jf>p5R}tv$y(61(z9*!{4s+qOHNZ0)$Z&Axm|U3hX^deUvm1EJf}!KM0ik}p`6 zWuAAgV#hj0Tv!SoXC%4Gp`29oty~)Y%ul0hlsMh2%tcR|ZipTYgZ@Cws=iqC<6szF z+j$bi@#oPvoDG<(^`8pcb6fj8DeQDk6`{V8x1L$1(LWBON&IP`o*ez)G#RDme)`G% z^>ml7emB1SU$^tLQAqE|v-el^(NS(KRp;LnXMJPgeqF4Ny*S`+Ds*o(Z#}KuRH2^* zx~*!ns_RqMn>D>*K>z^+5I_I{1Q0*~0R#|00D-Iulyoqj|Fc?Nav^{K0tg_000Iag zfB*srAdm|1`#%=~0tg_000IagfB*srAbfB*srAb') +def task_done(task_id): + done_task = Task.query.get_or_404(task_id) + done_task.task_completed = False + db.session.commit() + return redirect(url_for('index')) + + +# Routing for task 'complete/done' function +@app.route('/completed') +@login_required +def completed_tasks(): + curr_user_id = current_user.get_id() + tasks = Task.query.filter(Task.user_id==curr_user_id).filter_by(task_completed=False).all() + return render_template('completed.html', tasks=tasks) + + +# Routing for task 'update' function +@app.route('/update/', methods=["GET", "POST"]) +@login_required +def task_update(task_id): + task_to_update = Task.query.get_or_404(task_id) + if request.method == "POST": + task_to_update.task = request.form['task'] + db.session.commit() + return redirect(url_for('index')) + return render_template('update-task.html', task_to_update=task_to_update) + + +# Rounting for task 'delete' function from home page +@app.route('/delete/') +@login_required +def task_delete(task_id): + task_to_delete = Task.query.get_or_404(task_id) + db.session.delete(task_to_delete) + db.session.commit() + return redirect(url_for('index')) + + +# Routing for task 'delete' function from completed tasks page +@app.route('/deletec/') +@login_required +def task_delete_complete(task_id): + task_to_delete = Task.query.get_or_404(task_id) + db.session.delete(task_to_delete) + db.session.commit() + return redirect(url_for('completed_tasks')) + + +# Routing for task 'undone' function from completed tasks page +@app.route('/undone/') +@login_required +def task_undone(task_id): + undone_task = Task.query.get_or_404(task_id) + undone_task.task_completed = True + db.session.commit() + return redirect(url_for('completed_tasks')) + + +# TEST Routing for 'success' function +@app.route('/success') +def success(): + return render_template('test-success.html') + + +# TEST Rouiting for 'users' function +@app.route('/users') +@login_required +def users(): + users = User.query.all() + return render_template('test-users.html', users=users) + + +if __name__ == "__main__": + app.run(debug=True) diff --git a/flask-to-do-app/requirements.txt b/flask-to-do-app/requirements.txt new file mode 100644 index 0000000..0fa0279 --- /dev/null +++ b/flask-to-do-app/requirements.txt @@ -0,0 +1,20 @@ +click==8.0.3 +dataclasses==0.8 +dnspython==2.1.0 +email-validator==1.1.3 +Flask==2.0.2 +Flask-Login==0.5.0 +Flask-SQLAlchemy==2.5.1 +Flask-WTF==1.0.0 +greenlet==1.1.2 +idna==3.3 +importlib-metadata==4.8.2 +itsdangerous==2.0.1 +Jinja2==3.0.3 +MarkupSafe==2.0.1 +pkg-resources==0.0.0 +SQLAlchemy==1.4.27 +typing-extensions==4.0.0 +Werkzeug==2.0.2 +WTForms==3.0.0 +zipp==3.6.0 diff --git a/flask-to-do-app/templates/about.html b/flask-to-do-app/templates/about.html new file mode 100644 index 0000000..6c81455 --- /dev/null +++ b/flask-to-do-app/templates/about.html @@ -0,0 +1,7 @@ + +{% extends 'layout.html' %} +{% block title %}About{% endblock title %} +{% block header %}About page{% endblock header %} +{% block main %} +

This app is created using Flask, Flask-WTForms, Flask-SQLAlchemy, Flask-Login

+{% endblock main %} diff --git a/flask-to-do-app/templates/completed.html b/flask-to-do-app/templates/completed.html new file mode 100644 index 0000000..537277f --- /dev/null +++ b/flask-to-do-app/templates/completed.html @@ -0,0 +1,25 @@ + +{% extends 'layout.html' %} +{% block title %}Completed{% endblock title %} +{% block header %}Completed tasks{% endblock header %} +{% block main %} +

There are currently {{ tasks|length }} completed tasks on the list

+ {% if tasks %} + + + + + + + + {% for task in tasks %} + + + + + + + {% endfor %} +
Nr.TASKADDED DATAACTION
{{ tasks.index(task) + 1 }}{{ task.task }}{{ task.task_added.strftime('%Y-%m-%d, %H:%M') }}Undone | Delete
+ {% endif %} +{% endblock main %} diff --git a/flask-to-do-app/templates/index.html b/flask-to-do-app/templates/index.html new file mode 100644 index 0000000..5c8c191 --- /dev/null +++ b/flask-to-do-app/templates/index.html @@ -0,0 +1,45 @@ + +{% extends 'layout.html' %} +{% block title %}Home{% endblock title %} +{% block header %}'To Do' application{% endblock header %} +{% block main %} + {% if current_user.is_authenticated %} +
+ {{ form.csrf_token }} + {{ form.task.label }}
+ {{ form.task() }}
+

+ {{ form.submit() }} +
+ {% if form.task.errors %} +
    + {% for error in form.task.errors %} +
  • {{ error }}
  • + {% endfor %} + {% endif %} +

    Tasks to do

    +

    There are currently {{ tasks|length }} tasks on the list

    + {% if tasks %} + + + + + + + + {% for task in tasks %} + + + + + + + {% endfor %} +
    Nr.TASKADDED DATAACTION
    {{ tasks.index(task) + 1 }}{{ task.task }}{{ task.task_added.strftime('%Y-%m-%d, %H:%M') }}Done | Update | Delete
    + {% endif %} + {% else %} +

    Welcome!

    +

    Login into the system for using the app

    +

    Don't have an account yet? Create an account

    + {% endif %} +{% endblock main %} diff --git a/flask-to-do-app/templates/layout.html b/flask-to-do-app/templates/layout.html new file mode 100644 index 0000000..738a5e4 --- /dev/null +++ b/flask-to-do-app/templates/layout.html @@ -0,0 +1,25 @@ + + + + + {% block title %}{% endblock title %} - Registration and login app + + +

    {% block header %}{% endblock header %}

    +

    + Home | + {% if current_user.is_authenticated %} + Users | + Completed | + Logout | + {% else %} + Login | + Register | + {% endif %} + About +

    + {% block main %}{% endblock main %} +
    +

    This app is created using Flask, Flask-WTForms, Flask-SQLAlchemy, Flask-Login

    + + diff --git a/flask-to-do-app/templates/login.html b/flask-to-do-app/templates/login.html new file mode 100644 index 0000000..8a5bf5b --- /dev/null +++ b/flask-to-do-app/templates/login.html @@ -0,0 +1,36 @@ + +{% extends 'layout.html' %} +{% block title %}Login{% endblock title %} +{% block header %}Login Page{% endblock header %} +{% block main %} +
    + {{ form.csrf_token }} + {{ form.email.label }}
    + {{ form.email() }}
    + {{ form.password.label }}
    + {{ form.password() }}
    +

    + + {{ form.submit() }} +
    + {% if form.email.errors %} +
      + {% for error in form.email.errors %} +
    • {{ error }}
    • + {% endfor %} +
    + {% elif form.password.errors %} +
      + {% for error in form.password.errors %} +
    • {{ error }}
    • + {% endfor %} +
    + {% endif %} + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +

    {{ message }}

    + {% endfor %} + {% endif %} + {% endwith %} +{% endblock main %} diff --git a/flask-to-do-app/templates/register.html b/flask-to-do-app/templates/register.html new file mode 100644 index 0000000..1de3390 --- /dev/null +++ b/flask-to-do-app/templates/register.html @@ -0,0 +1,52 @@ + +{% extends 'layout.html' %} +{% block title %}Home{% endblock title %} +{% block header %}User register and login{% endblock header %} +{% block main %} +
    + {{ form.csrf_token }} + {{ form.email.label }}
    + {{ form.email() }}
    + {{ form.name.label }}
    + {{ form.name() }}
    + {{ form.password.label }}
    + {{ form.password() }}
    + {{ form.confirm_password.label }}
    + {{ form.confirm_password() }}
    +

    + + {{ form.submit() }} +
    + {% if form.email.errors %} +
      + {% for error in form.email.errors %} +
    • {{ error }}
    • + {% endfor %} +
    + {% elif form.name.errors %} +
      + {% for error in form.name.errors %} +
    • {{ error }}
    • + {% endfor %} +
    + {% elif form.password.errors %} +
      + {% for error in form.password.errors %} +
    • {{ error }}
    • + {% endfor %} +
    + {% elif form.confirm_password.errors %} +
      + {% for error in form.confirm_password.errors %} +
    • {{ error }}
    • + {% endfor %} +
    + {% endif %} + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +

    {{ message }}

    + {% endfor %} + {% endif %} + {% endwith %} +{% endblock main %} diff --git a/flask-to-do-app/templates/test-success.html b/flask-to-do-app/templates/test-success.html new file mode 100644 index 0000000..1c91866 --- /dev/null +++ b/flask-to-do-app/templates/test-success.html @@ -0,0 +1,7 @@ + +{% extends 'layout.html' %} +{% block title %}Success{% endblock title %} +{% block header %}TEST Success Page{% endblock header %} +{% block main %} +

    You logined or registered successfully!

    +{% endblock main %} diff --git a/flask-to-do-app/templates/test-users.html b/flask-to-do-app/templates/test-users.html new file mode 100644 index 0000000..ece57ce --- /dev/null +++ b/flask-to-do-app/templates/test-users.html @@ -0,0 +1,18 @@ + +{% extends 'layout.html' %} +{% block title %}Users{% endblock title %} +{% block header %}TEST Users Page{% endblock header %} +{% block main %} + + + + + + {% for user in users[::-1] %} + + + + + {% endfor %} +
    NAMEEMAIL
    {{ user.name }}{{ user.email }}
    +{% endblock main %} diff --git a/flask-to-do-app/templates/update-task.html b/flask-to-do-app/templates/update-task.html new file mode 100644 index 0000000..d817d0b --- /dev/null +++ b/flask-to-do-app/templates/update-task.html @@ -0,0 +1,11 @@ + +{% extends 'layout.html' %} +{% block title %}Update{% endblock title %} +{% block header %}Task update{% endblock header %} +{% block main %} +
    + + + +
    +{% endblock main %}