├── .gitignore ├── Day_1.ipynb ├── Day_10.ipynb ├── Day_11 ├── Day_11.ipynb ├── extracted_images │ └── 0Im0.jpg ├── input │ ├── Day_9.pdf │ ├── Day_9_1.pdf │ └── image-pdf-sample.pdf └── output │ ├── Day_9_rotated.pdf │ ├── document-output.pdf │ └── removed_pages_day_9.pdf ├── Day_12 ├── Day_12.ipynb ├── imgs │ ├── art.jpg │ ├── b_and_c.jpg │ ├── yoga.jpg │ └── yoga1.jpg ├── input │ ├── Day_9.pdf │ ├── Day_9_1.pdf │ └── image-pdf-sample.pdf └── output │ ├── after_reduce.pdf │ ├── decrypted-pdf.pdf │ ├── encrypted-pdf.pdf │ └── img_to_pdf.pdf ├── Day_13 ├── Day_13.ipynb └── output │ └── sample.pdf ├── Day_14 └── Day_14.ipynb ├── Day_15 └── Day_15.ipynb ├── Day_16 ( Task Manager CLI ) ├── task_manager.py └── tasks.pkl ├── Day_17 └── Day_17.ipynb ├── Day_18 └── python_metaclasses.ipynb ├── Day_19 ├── data │ └── use_text.txt └── generators_and_yield.ipynb ├── Day_2.ipynb ├── Day_20 └── args_and_kwargs.ipynb ├── Day_21 └── inner_function_and_decorators.ipynb ├── Day_22 └── Data Structures 1.ipynb ├── Day_23 ├── context_managers.ipynb └── files │ ├── hello.txt │ └── travel.txt ├── Day_24 and 25 └── Linked List Types - Data Structures 2.ipynb ├── Day_26 └── Data Structures 3 - Stack and Queue.ipynb ├── Day_27 └── Data Structures 4 - Binary Search Tree.ipynb ├── Day_28 └── Data Structure 5 - Heaps ( Min heap and Max heap ).ipynb ├── Day_29 └── Data Structures 6 - Hash Table.ipynb ├── Day_3.ipynb ├── Day_30 └── Data Strucutres 7 - Recursion.ipynb ├── Day_31 └── Algorithms 1 - Linear and Binary Search.ipynb ├── Day_32 └── Data Structures 8 - Graph.ipynb ├── Day_33_34 └── Algorithms 2 - BFS and DFS.ipynb ├── Day_35 └── Algorithms 3 - Bubble Sort and Selection Sort.ipynb ├── Day_36 └── Algorithms 4 - Insertion sort and Merge sort.ipynb ├── Day_37 └── Algorithms 5 - Quick sort and Heap sort.ipynb ├── Day_38 └── Algorithms 6 - Shell sort and counting sort.ipynb ├── Day_39 └── Algorithms 7 - Radix sort and Bucket sort.ipynb ├── Day_4.ipynb ├── Day_44 ├── Introduction to Flask.ipynb ├── flask_forms_and_static │ ├── app.py │ ├── static │ │ └── style.css │ └── templates │ │ ├── form.html │ │ └── index.html ├── flask_intro │ ├── app │ │ ├── __init__.py │ │ └── routes.py │ └── flask_intro.py └── flask_templates │ ├── app.py │ └── templates │ └── index.html ├── Day_45 ├── Python Flask - Templates in detail.ipynb ├── flask_templates.py └── templates │ ├── base.html │ ├── conditional.html │ ├── index.html │ ├── inheritance.html │ └── loops.html ├── Day_46 ├── Python Flask - Templates in detail 2.ipynb ├── error_pages.py ├── flask_bootstrap_int.py ├── local_date_time.py └── templates │ ├── 404.html │ ├── 500.html │ ├── boot.html │ └── local.html ├── Day_47 ├── Python Flask - Web Forms.ipynb ├── flask_web_forms.py ├── message_flashing.py ├── sessions and redirections.py └── templates │ ├── base.html │ ├── flash_alert.html │ └── index.html ├── Day_48 ├── Python Flask - Database Integration.ipynb ├── data_integrate │ ├── data.sqlite │ └── data_integration.py └── forms_database │ ├── data.sqlite │ ├── forms.py │ └── templates │ ├── base.html │ └── index.html ├── Day_49 ├── Python Flask - Email Integration.ipynb ├── check_mail_server.py ├── flask_mail_int.py └── templates │ ├── Mail │ ├── new_user.html │ └── new_user.txt │ ├── base.html │ └── index.html ├── Day_5.ipynb ├── Day_50 ├── Python Flask - Large Application Structure.ipynb └── nkblog │ ├── app │ ├── __init__.py │ ├── email.py │ ├── main │ │ ├── __init__.py │ │ ├── errors.py │ │ ├── forms.py │ │ └── views.py │ ├── models.py │ └── templates │ │ ├── 404.html │ │ ├── 500.html │ │ ├── Mail │ │ ├── new_user.html │ │ └── new_user.txt │ │ ├── base.html │ │ └── index.html │ ├── config.py │ └── nkblog.py ├── Day_51 └── Python Flask - User Authentication.ipynb ├── Day_52 └── Python Flask - User Roles.ipynb ├── Day_53 └── Python Flask - User Profiles.ipynb ├── Day_54-57 └── Python Flask - SQLAlchemy.ipynb ├── Day_6.ipynb ├── Day_64-65 └── Python - API and REST APIs.ipynb ├── Day_7.ipynb ├── Day_75-79 └── Selenium with python.ipynb ├── Day_8.ipynb ├── Day_80-81 └── code_profiling_python_flask.ipynb ├── Day_9.ipynb ├── Day_91-96 └── python_basic_interview_questions.ipynb └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # vscode 2 | .vscode/* 3 | !.vscode/settings.json 4 | !.vscode/tasks.json 5 | !.vscode/launch.json 6 | !.vscode/extensions.json 7 | 8 | *.code-workspace 9 | 10 | #Database 11 | */*.db 12 | */*.sqlite 13 | *.sqlite 14 | *.db 15 | database/* 16 | 17 | 18 | # Local History for VS Code 19 | .history/ 20 | 21 | # ipynb checkpoints 22 | .ipynb_checkpoints/* 23 | .ipynb_checkpoints 24 | */.ipynb_checkpoints 25 | 26 | # pycache 27 | __pycache__/* 28 | __pycache__ 29 | .__pycache__ -------------------------------------------------------------------------------- /Day_11/Day_11.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "cc5880e8", 6 | "metadata": {}, 7 | "source": [ 8 | "# Day 11 \n", 9 | "\n", 10 | "## Practicing Python from basics" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "id": "ba5b756c", 16 | "metadata": {}, 17 | "source": [ 18 | "## PyPDF2\n", 19 | "\n", 20 | "**Working with PDFs using python's PyPDF2 module**" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 16, 26 | "id": "56e23fc3", 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "name": "stdout", 31 | "output_type": "stream", 32 | "text": [ 33 | "Requirement already satisfied: pypdf in c:\\users\\nitin\\anaconda3\\lib\\site-packages (4.2.0)\n" 34 | ] 35 | } 36 | ], 37 | "source": [ 38 | "# installing pypdf module\n", 39 | "!pip install pypdf" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "id": "710edafc", 45 | "metadata": {}, 46 | "source": [ 47 | "### **Importing the module**" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 7, 53 | "id": "32092922", 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "import pypdf\n", 58 | "from pypdf import PdfReader" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "id": "28f47cef", 64 | "metadata": {}, 65 | "source": [ 66 | "### 1. Extracting text from pdf." 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 8, 72 | "id": "5a3d380b", 73 | "metadata": {}, 74 | "outputs": [ 75 | { 76 | "name": "stdout", 77 | "output_type": "stream", 78 | "text": [ 79 | "Day_9\n", 80 | "May 10, 2024\n", 81 | "1 Day 9\n", 82 | "1.1 Revising Day 1 to Day 8\n", 83 | "Introduction to Python and Installation\n", 84 | "Python\n" 85 | ] 86 | } 87 | ], 88 | "source": [ 89 | "# creating object \n", 90 | "reader = PdfReader(\"Day_9.pdf\")\n", 91 | "\n", 92 | "# gating all pages from pdf\n", 93 | "pages = reader.pages\n", 94 | "\n", 95 | "# extracting text from page 1\n", 96 | "page1 = pages[0].extract_text() # returns extracted text as string\n", 97 | "\n", 98 | "# printing only 1st 101 characters.\n", 99 | "print(page1[:101])" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "id": "6440d5b2", 105 | "metadata": {}, 106 | "source": [ 107 | "### 2. Extracting images from pages" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 2, 113 | "id": "c264e67e", 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "name": "stdout", 118 | "output_type": "stream", 119 | "text": [ 120 | "Extracte Image : 1Im0.jpg\n" 121 | ] 122 | } 123 | ], 124 | "source": [ 125 | "import pypdf\n", 126 | "from pypdf import PdfReader\n", 127 | "\n", 128 | "# reading pdf\n", 129 | "reader1 = PdfReader(\"image-pdf-sample.pdf\")\n", 130 | "page = reader1.pages[0]\n", 131 | "\n", 132 | "# creating a variable to count\n", 133 | "count = 0\n", 134 | "\n", 135 | "# getting 10 images from 1st page \n", 136 | "for image_file_object in page.images:\n", 137 | " \n", 138 | " # writing images / saving images in directory\n", 139 | " with open(f\"extracted_images/{str(count) + image_file_object.name}\", \"wb\") as fp:\n", 140 | " fp.write(image_file_object.data)\n", 141 | " count += 1\n", 142 | " print(f\"Extracte Image : {str(count) + image_file_object.name}\")\n", 143 | " if count == 10:\n", 144 | " break" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "id": "ea3372f6", 150 | "metadata": {}, 151 | "source": [ 152 | "### 3. Merging pdfs" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": 19, 158 | "id": "4ad82332", 159 | "metadata": {}, 160 | "outputs": [ 161 | { 162 | "name": "stdout", 163 | "output_type": "stream", 164 | "text": [ 165 | "pdf merged successfully.\n" 166 | ] 167 | } 168 | ], 169 | "source": [ 170 | "from pypdf import PdfWriter\n", 171 | "\n", 172 | "merger = PdfWriter()\n", 173 | "\n", 174 | "input1 = open(\"Day_9.pdf\", \"rb\")\n", 175 | "input2 = open(\"Day_9_1.pdf\", \"rb\")\n", 176 | "\n", 177 | "# adding the first 3 pages of input1 document to output\n", 178 | "merger.append(fileobj=input1, pages=(0, 3))\n", 179 | "\n", 180 | "# inserting the first page of input2 into the output beginning after the second page\n", 181 | "merger.merge(position=2, fileobj=input2, pages=(0, 1))\n", 182 | "\n", 183 | "# Writing to an output PDF document\n", 184 | "output = open(\"output/document-output.pdf\", \"wb\")\n", 185 | "merger.write(output)\n", 186 | "\n", 187 | "# message\n", 188 | "print(\"pdf merged successfully.\")\n", 189 | "\n", 190 | "# Close File Descriptors\n", 191 | "merger.close()\n", 192 | "output.close()" 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "id": "0a99e0d4", 198 | "metadata": {}, 199 | "source": [ 200 | "### 4. Rotating page" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 20, 206 | "id": "273b6be6", 207 | "metadata": {}, 208 | "outputs": [], 209 | "source": [ 210 | "# importing module\n", 211 | "from pypdf import PdfWriter, PdfReader\n", 212 | "\n", 213 | "# creating objects\n", 214 | "reader = PdfReader(\"Day_9.pdf\")\n", 215 | "writer = PdfWriter()\n", 216 | "\n", 217 | "# rotating page\n", 218 | "writer.add_page(reader.pages[0])\n", 219 | "writer.pages[0].rotate(90)\n", 220 | "\n", 221 | "# writing page to new filel\n", 222 | "with open(\"output/Day_9_rotated.pdf\", \"wb\") as fp:\n", 223 | " writer.write(fp)" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "id": "f309327a", 229 | "metadata": {}, 230 | "source": [ 231 | "### 5. Removing pages" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": 24, 237 | "id": "a5577863", 238 | "metadata": {}, 239 | "outputs": [ 240 | { 241 | "name": "stdout", 242 | "output_type": "stream", 243 | "text": [ 244 | "Removed Page 2\n", 245 | "Removed Page 4\n" 246 | ] 247 | } 248 | ], 249 | "source": [ 250 | "from pypdf import PdfWriter, PdfReader\n", 251 | "\n", 252 | "# reading pdf\n", 253 | "reader = PdfReader(\"Day_9.pdf\")\n", 254 | "\n", 255 | "# creating writer object\n", 256 | "writer = PdfWriter()\n", 257 | "\n", 258 | "# pages to remove\n", 259 | "pages_to_remove = [2,4]\n", 260 | "\n", 261 | "# reading page numbers\n", 262 | "for page_num in range(len(reader.pages)):\n", 263 | " if page_num+1 in pages_to_remove:\n", 264 | " print(f\"Removed Page {page_num+1}\")\n", 265 | " continue\n", 266 | " writer.add_page(reader.pages[page_num])\n", 267 | "\n", 268 | "# writing pdf after removing pages\n", 269 | "with open(\"output/removed_pages_day_9.pdf\",\"wb\") as pd:\n", 270 | " writer.write(pd)" 271 | ] 272 | } 273 | ], 274 | "metadata": { 275 | "kernelspec": { 276 | "display_name": "Python 3 (ipykernel)", 277 | "language": "python", 278 | "name": "python3" 279 | }, 280 | "language_info": { 281 | "codemirror_mode": { 282 | "name": "ipython", 283 | "version": 3 284 | }, 285 | "file_extension": ".py", 286 | "mimetype": "text/x-python", 287 | "name": "python", 288 | "nbconvert_exporter": "python", 289 | "pygments_lexer": "ipython3", 290 | "version": "3.11.7" 291 | } 292 | }, 293 | "nbformat": 4, 294 | "nbformat_minor": 5 295 | } 296 | -------------------------------------------------------------------------------- /Day_11/extracted_images/0Im0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_11/extracted_images/0Im0.jpg -------------------------------------------------------------------------------- /Day_11/input/Day_9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_11/input/Day_9.pdf -------------------------------------------------------------------------------- /Day_11/input/Day_9_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_11/input/Day_9_1.pdf -------------------------------------------------------------------------------- /Day_11/input/image-pdf-sample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_11/input/image-pdf-sample.pdf -------------------------------------------------------------------------------- /Day_11/output/Day_9_rotated.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_11/output/Day_9_rotated.pdf -------------------------------------------------------------------------------- /Day_11/output/document-output.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_11/output/document-output.pdf -------------------------------------------------------------------------------- /Day_11/output/removed_pages_day_9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_11/output/removed_pages_day_9.pdf -------------------------------------------------------------------------------- /Day_12/Day_12.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "8a767f90", 6 | "metadata": {}, 7 | "source": [ 8 | "# Day 12 (PyPDF and PILLOW)\n", 9 | "\n", 10 | "### Practicing python from basics" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "id": "e47d47c3", 16 | "metadata": {}, 17 | "source": [ 18 | "### Extracting metadata of a pdf" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 6, 24 | "id": "4e55e47b", 25 | "metadata": {}, 26 | "outputs": [ 27 | { 28 | "name": "stdout", 29 | "output_type": "stream", 30 | "text": [ 31 | "5\n", 32 | "None\n", 33 | "LaTeX with hyperref\n", 34 | "MiKTeX-dvipdfmx (20231124)\n", 35 | "None\n", 36 | "None\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "# importing the module\n", 42 | "from pypdf import PdfReader\n", 43 | "\n", 44 | "# creating the reader object to read pdf\n", 45 | "reader = PdfReader(\"input/Day_9.pdf\")\n", 46 | "\n", 47 | "# reading metadata from pdf\n", 48 | "meta = reader.metadata\n", 49 | "\n", 50 | "# printing number of pages from pdf\n", 51 | "print(len(reader.pages))\n", 52 | "\n", 53 | "# printing the metadata\n", 54 | "# sometimes this data is not available so it can print None.\n", 55 | "print(meta.author)\n", 56 | "print(meta.creator)\n", 57 | "print(meta.producer)\n", 58 | "print(meta.subject)\n", 59 | "print(meta.title)" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "id": "4210cd9f", 65 | "metadata": {}, 66 | "source": [ 67 | "### Reducing PDF size (By reducing image size in page)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 20, 73 | "id": "f7f507ad", 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "name": "stdout", 78 | "output_type": "stream", 79 | "text": [ 80 | "Filesize before compression is :: 2.055771 bytes\n" 81 | ] 82 | } 83 | ], 84 | "source": [ 85 | "# importing os module\n", 86 | "import os\n", 87 | "\n", 88 | "filesize = os.path.getsize(\"input/day_9_1.pdf\")\n", 89 | "print(f\"Filesize before compression is :: {filesize/1000000} bytes\")" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 15, 95 | "id": "3ce6306e", 96 | "metadata": {}, 97 | "outputs": [ 98 | { 99 | "name": "stdout", 100 | "output_type": "stream", 101 | "text": [ 102 | " Reducing file size\n", 103 | "File Size reduced\n" 104 | ] 105 | } 106 | ], 107 | "source": [ 108 | "from pypdf import PdfReader, PdfWriter\n", 109 | "\n", 110 | "reader = PdfReader(\"input/Day_9_1.pdf\")\n", 111 | "writer = PdfWriter()\n", 112 | "\n", 113 | "for page in reader.pages:\n", 114 | " writer.add_page(page)\n", 115 | "\n", 116 | "for page in writer.pages:\n", 117 | " for img in page.images:\n", 118 | " img.replace(img.image, quality=25)\n", 119 | " print(\"\\r Reducing file size\",end='')\n", 120 | "\n", 121 | "print(\"\\nFile Size reduced\")\n", 122 | "with open(\"output/after_reduce.pdf\", \"wb\") as f:\n", 123 | " writer.write(f)" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 19, 129 | "id": "3a6c6144", 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "name": "stdout", 134 | "output_type": "stream", 135 | "text": [ 136 | "Filesize after compression/ reducing is :: 1.589743 Mb\n" 137 | ] 138 | } 139 | ], 140 | "source": [ 141 | "filesize = os.path.getsize(\"output/after_reduce.pdf\")\n", 142 | "print(f\"Filesize after compression/ reducing is :: {filesize/1000000} Mb\")" 143 | ] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "id": "16f93ddb", 148 | "metadata": {}, 149 | "source": [ 150 | "### Encrypting a PDF (or Adding a password to open the pdf)" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 1, 156 | "id": "88cb3bc2", 157 | "metadata": {}, 158 | "outputs": [ 159 | { 160 | "name": "stdout", 161 | "output_type": "stream", 162 | "text": [ 163 | "PDF Encrypted successfully\n" 164 | ] 165 | } 166 | ], 167 | "source": [ 168 | "# importing a module\n", 169 | "from pypdf import PdfReader, PdfWriter\n", 170 | "\n", 171 | "reader = PdfReader(\"input/image-pdf-sample.pdf\")\n", 172 | "writer = PdfWriter(clone_from=reader)\n", 173 | "\n", 174 | "# Adding a password to the new PDF using Secure algorithm\n", 175 | "writer.encrypt(\"welcome@pypdf\", algorithm=\"AES-256\")\n", 176 | "\n", 177 | "# Saving the new PDF to a file\n", 178 | "with open(\"output/encrypted-pdf.pdf\", \"wb\") as f:\n", 179 | " writer.write(f)\n", 180 | " \n", 181 | "print(\"PDF Encrypted successfully\")" 182 | ] 183 | }, 184 | { 185 | "cell_type": "markdown", 186 | "id": "745a31e3", 187 | "metadata": {}, 188 | "source": [ 189 | "### Decrypting the pdf (or Removing the password)" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 3, 195 | "id": "28c1563f", 196 | "metadata": {}, 197 | "outputs": [ 198 | { 199 | "name": "stdout", 200 | "output_type": "stream", 201 | "text": [ 202 | "PDf Decrypted successfully\n" 203 | ] 204 | } 205 | ], 206 | "source": [ 207 | "# importing modules\n", 208 | "from pypdf import PdfReader, PdfWriter\n", 209 | "\n", 210 | "# creating reader object to read the pdf\n", 211 | "reader = PdfReader(\"output/encrypted-pdf.pdf\")\n", 212 | "\n", 213 | "# checking if the file is encrypted of not\n", 214 | "if reader.is_encrypted:\n", 215 | " reader.decrypt(\"welcome@pypdf\")\n", 216 | "\n", 217 | "# Writing decrypted file to the writer object\n", 218 | "writer = PdfWriter(clone_from=reader)\n", 219 | "\n", 220 | "# Saving the new PDF to a file\n", 221 | "with open(\"output/decrypted-pdf.pdf\", \"wb\") as f:\n", 222 | " writer.write(f)\n", 223 | " \n", 224 | "# message\n", 225 | "print(\"PDf Decrypted successfully\")" 226 | ] 227 | }, 228 | { 229 | "cell_type": "markdown", 230 | "id": "93d5356b", 231 | "metadata": {}, 232 | "source": [ 233 | "### Converting images to pdf" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": 45, 239 | "id": "a829e73b", 240 | "metadata": {}, 241 | "outputs": [ 242 | { 243 | "name": "stdout", 244 | "output_type": "stream", 245 | "text": [ 246 | "converting images to pdf in progress ........\n", 247 | "Conversion complete : file saved to output/img_to_pdf.pdf\n" 248 | ] 249 | } 250 | ], 251 | "source": [ 252 | "# importing modules\n", 253 | "import os\n", 254 | "from PIL import Image\n", 255 | "\n", 256 | "# defining function to create pdf using images\n", 257 | "def image_to_pdf(img_folder, out_pdf):\n", 258 | " \n", 259 | " # creating image list\n", 260 | " img_list = []\n", 261 | " \n", 262 | " # reading all images\n", 263 | " for img_file in sorted(os.listdir(img_folder)):\n", 264 | " \n", 265 | " # checking file type for only images\n", 266 | " if img_file.endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp')):\n", 267 | " \n", 268 | " # reading images using pillow\n", 269 | " img = Image.open(os.path.join(img_folder, img_file))\n", 270 | " \n", 271 | " # appending all images to list\n", 272 | " img_list.append(img)\n", 273 | " \n", 274 | " # getting any one image from list to save images\n", 275 | " img1 = img_list.pop(0)\n", 276 | " \n", 277 | " # saving images as pdf\n", 278 | " img1.save(out_pdf,save_all=True,append_images = img_list)\n", 279 | " \n", 280 | "\n", 281 | " \n", 282 | "## calling function\n", 283 | "print(\"converting images to pdf in progress ........\")\n", 284 | "img_folder_path = 'imgs'\n", 285 | "output_file = 'output/img_to_pdf.pdf'\n", 286 | "\n", 287 | "## calling\n", 288 | "image_to_pdf(img_folder_path,output_file)\n", 289 | "\n", 290 | "print(f\"Conversion complete : file saved to {output_file}\")" 291 | ] 292 | } 293 | ], 294 | "metadata": { 295 | "kernelspec": { 296 | "display_name": "Python 3 (ipykernel)", 297 | "language": "python", 298 | "name": "python3" 299 | }, 300 | "language_info": { 301 | "codemirror_mode": { 302 | "name": "ipython", 303 | "version": 3 304 | }, 305 | "file_extension": ".py", 306 | "mimetype": "text/x-python", 307 | "name": "python", 308 | "nbconvert_exporter": "python", 309 | "pygments_lexer": "ipython3", 310 | "version": "3.11.7" 311 | } 312 | }, 313 | "nbformat": 4, 314 | "nbformat_minor": 5 315 | } 316 | -------------------------------------------------------------------------------- /Day_12/imgs/art.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/imgs/art.jpg -------------------------------------------------------------------------------- /Day_12/imgs/b_and_c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/imgs/b_and_c.jpg -------------------------------------------------------------------------------- /Day_12/imgs/yoga.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/imgs/yoga.jpg -------------------------------------------------------------------------------- /Day_12/imgs/yoga1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/imgs/yoga1.jpg -------------------------------------------------------------------------------- /Day_12/input/Day_9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/input/Day_9.pdf -------------------------------------------------------------------------------- /Day_12/input/Day_9_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/input/Day_9_1.pdf -------------------------------------------------------------------------------- /Day_12/input/image-pdf-sample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/input/image-pdf-sample.pdf -------------------------------------------------------------------------------- /Day_12/output/after_reduce.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/output/after_reduce.pdf -------------------------------------------------------------------------------- /Day_12/output/decrypted-pdf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/output/decrypted-pdf.pdf -------------------------------------------------------------------------------- /Day_12/output/encrypted-pdf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/output/encrypted-pdf.pdf -------------------------------------------------------------------------------- /Day_12/output/img_to_pdf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_12/output/img_to_pdf.pdf -------------------------------------------------------------------------------- /Day_13/output/sample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_13/output/sample.pdf -------------------------------------------------------------------------------- /Day_16 ( Task Manager CLI )/task_manager.py: -------------------------------------------------------------------------------- 1 | import click 2 | import pickle 3 | import os 4 | 5 | # Path to the tasks file 6 | TASKS_FILE = 'tasks.pkl' 7 | 8 | # creating class for tasks 9 | class TaskManager: 10 | def __init__(self, file_path): 11 | self.file_path = file_path 12 | self.tasks = self.load_tasks() 13 | 14 | # Function to load a task 15 | def load_tasks(self): 16 | if os.path.exists(self.file_path): 17 | with open(self.file_path, 'rb') as file: 18 | return pickle.load(file) 19 | return [] 20 | 21 | # function to save a task 22 | def save_tasks(self): 23 | with open(self.file_path, 'wb') as file: 24 | pickle.dump(self.tasks, file) 25 | 26 | # function to add a task 27 | def add_task(self, task): 28 | task_id = len(self.tasks) + 1 29 | self.tasks.append({'id': task_id, 'task': task, 'completed': False}) 30 | self.save_tasks() 31 | 32 | # Function to list a task 33 | def list_tasks(self): 34 | for task in self.tasks: 35 | status = '✓' if task['completed'] else '✗' 36 | click.echo(f"{task['id']}. {task['task']} [{status}]") 37 | 38 | # function to add flag if task is completed 39 | def complete_task(self, task_id): 40 | for task in self.tasks: 41 | if task['id'] == task_id: 42 | task['completed'] = True 43 | self.save_tasks() 44 | click.echo(f"Task {task_id} marked as complete.") 45 | return 46 | click.echo(f"Task {task_id} not found.") 47 | 48 | # function to delete a task 49 | def delete_task(self, task_id): 50 | self.tasks = [task for task in self.tasks if task['id'] != task_id] 51 | self.save_tasks() 52 | if task_id in self.tasks: 53 | click.echo(f"Task {task_id} deleted.") 54 | else: 55 | click.echo("Task not present in list.") 56 | 57 | # function to search a task 58 | def search_tasks(self, keyword): 59 | results = [task for task in self.tasks if keyword.lower() in task['task'].lower()] 60 | for task in results: 61 | status = '✓' if task['completed'] else '✗' 62 | click.echo(f"{task['id']}. {task['task']} [{status}]") 63 | 64 | # creating object for class 65 | task_manager = TaskManager(TASKS_FILE) 66 | 67 | # Creating commands group 68 | @click.group() 69 | def cli_group(): 70 | pass 71 | 72 | # command for add 73 | @click.command() 74 | def add(): 75 | task = click.prompt('Please enter the task') 76 | task_manager.add_task(task) 77 | click.echo(f'Task added:)') 78 | 79 | # Command for listing tasks 80 | @click.command() 81 | def list(): 82 | task_manager.list_tasks() 83 | 84 | # command for complete task 85 | @click.command() 86 | def complete(): 87 | task_id = click.prompt('Please enter the task ID to mark as complete', type=int) 88 | task_manager.complete_task(task_id) 89 | 90 | # command for deleting task 91 | @click.command() 92 | def delete(): 93 | task_id = click.prompt('Please enter the task ID to delete', type=int) 94 | task_manager.delete_task(task_id) 95 | 96 | # command for searching task 97 | @click.command() 98 | def search(): 99 | keyword = click.prompt('Please enter the keyword to search for') 100 | task_manager.search_tasks(keyword) 101 | 102 | # adding all commands to group 103 | cli_group.add_command(add) 104 | cli_group.add_command(list) 105 | cli_group.add_command(complete) 106 | cli_group.add_command(delete) 107 | cli_group.add_command(search) 108 | 109 | if __name__ == '__main__': 110 | cli_group() 111 | -------------------------------------------------------------------------------- /Day_16 ( Task Manager CLI )/tasks.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_16 ( Task Manager CLI )/tasks.pkl -------------------------------------------------------------------------------- /Day_18/python_metaclasses.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "8dd679f2", 6 | "metadata": {}, 7 | "source": [ 8 | "# Day 18\n", 9 | "\n", 10 | "**Practicing Python from Basics**" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "id": "14152fa7", 16 | "metadata": {}, 17 | "source": [ 18 | "# Python Metaclasses\n", 19 | "\n", 20 | "Metaclasses in Python are a powerful but advanced feature of the language, used to customize the behavior of classes themselves. A metaclass is a class of a class that defines how a class behaves. In essence, a class is an instance of a metaclass, just as an object is an instance of a class. By using metaclasses, you can:\n", 21 | "\n", 22 | "1. **Modify Class Attributes**: Change or enforce the presence of class attributes at the time of class creation.\n", 23 | "2. **Validate Class Structure**: Ensure that classes meet certain criteria, such as having specific methods or attributes.\n", 24 | "3. **Add Functionality**: Automatically modify or wrap methods of a class to add additional behavior, such as logging or validation.\n", 25 | "\n", 26 | "Metaclasses are defined by inheriting from type and overriding its methods like `__new__` or `__init__`. They are specified in a class by using the `metaclass` keyword." 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 2, 32 | "id": "7e9dab44", 33 | "metadata": {}, 34 | "outputs": [ 35 | { 36 | "name": "stdout", 37 | "output_type": "stream", 38 | "text": [ 39 | "Creating class new_cls\n" 40 | ] 41 | } 42 | ], 43 | "source": [ 44 | "class meta_cls(type):\n", 45 | " def __new__(cls,name,bases,dct):\n", 46 | " print(f\"Creating class {name}\")\n", 47 | " return super().__new__(cls,name,bases,dct)\n", 48 | " \n", 49 | "class new_cls(metaclass=meta_cls):\n", 50 | " pass" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "id": "b60239eb", 56 | "metadata": {}, 57 | "source": [ 58 | "- In above example, `meta_cls` is a metaclass that prints a message whenever a new class is created using it. \n", 59 | "- `new_cls` is defined to use `meta_cls` as its metaclass, so when `new_cls` is created, the message is printed.\n", 60 | "- Sure, here are the explanations for each parameter:\n", 61 | "\n", 62 | "- **cls**: The metaclass itself, typically passed as the first argument to `__new__` and `__init__` methods of the metaclass.\n", 63 | "- **name**: The name of the class being created, represented as a string.\n", 64 | "- **bases**: A tuple containing the base classes from which the new class inherits.\n", 65 | "- **dct**: A dictionary containing the class's attributes and methods." 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "id": "2395f191", 71 | "metadata": {}, 72 | "source": [ 73 | "## Exercises" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "id": "0f5b65ae", 79 | "metadata": {}, 80 | "source": [ 81 | "### Exercise 1: Creating a Simple Metaclass\n", 82 | "\n", 83 | "**Objective:** Understand the basics of metaclasses by creating a simple one.\n", 84 | "\n", 85 | "**Instructions:**\n", 86 | "\n", 87 | "1. Create a metaclass called `UpperAttrMetaclass` that converts all attribute names to uppercase.\n", 88 | "2. Create a class `Foo` that uses `UpperAttrMetaclass`.\n", 89 | "3. Add some attributes to `Foo` and check if their names are converted to uppercase." 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 17, 95 | "id": "fdfc8584", 96 | "metadata": {}, 97 | "outputs": [ 98 | { 99 | "name": "stdout", 100 | "output_type": "stream", 101 | "text": [ 102 | "False\n", 103 | "False\n", 104 | "True\n", 105 | "nsk\n" 106 | ] 107 | } 108 | ], 109 | "source": [ 110 | "# creating metaclass to convert attributes name in uppercase.\n", 111 | "class UpperAttrMetaClass(type):\n", 112 | " \n", 113 | " # dunder method\n", 114 | " def __new__(cls,name,bases,dct):\n", 115 | " \n", 116 | " # dictionary to store uppercased attributes.\n", 117 | " upper_case = {}\n", 118 | " \n", 119 | " # converting names to uppercase\n", 120 | " for attr_name,attr_val in dct.items():\n", 121 | " if not attr_name.startswith('__'):\n", 122 | " upper_case[attr_name.upper()] = attr_val\n", 123 | " else:\n", 124 | " upper_case[attr_name] = attr_val\n", 125 | " \n", 126 | " return super().__new__(cls,name,bases,upper_case)\n", 127 | " \n", 128 | "# class using above metaclass\n", 129 | "class Foo(metaclass=UpperAttrMetaClass):\n", 130 | " name = 'nsk'\n", 131 | " place = 'BLR'\n", 132 | " \n", 133 | "print(hasattr(Foo,'name')) # returns false becase attribute name converted to uppercase\n", 134 | "print(hasattr(Foo,'place'))\n", 135 | "\n", 136 | "print(hasattr(Foo,'NAME')) # returns True\n", 137 | "print(Foo.NAME)" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "id": "081e36e5", 143 | "metadata": {}, 144 | "source": [ 145 | "### Exercise 2: Customizing Class Creation\n", 146 | "\n", 147 | "**Objective:** Use metaclasses to enforce certain class attributes.\n", 148 | "\n", 149 | "**Instructions:**\n", 150 | "\n", 151 | "1. Create a metaclass `AttributeValidatorMetaclass` that ensures a class has a `required_attrs` attribute containing a list of strings.\n", 152 | "2. If a class using this metaclass does not have the `required_attrs` attribute, raise an exception during class creation.\n", 153 | "3. Create a class `MyClass` using this metaclass and test it with and without the `required_attrs` attribute." 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 12, 159 | "id": "3f125363", 160 | "metadata": {}, 161 | "outputs": [ 162 | { 163 | "name": "stdout", 164 | "output_type": "stream", 165 | "text": [ 166 | "Error :: Class do not have required attribute.\n", 167 | "Class Created Successfully!.\n" 168 | ] 169 | } 170 | ], 171 | "source": [ 172 | "# creating meta class\n", 173 | "class AttributeValidatorMetaclass(type):\n", 174 | " \n", 175 | " # class attribute\n", 176 | " required_attrs = ['akt','tks','tws','rcb']\n", 177 | " def __new__(cls,name,bases,dct):\n", 178 | " if 'required_attrs' not in dct:\n", 179 | " # raising error\n", 180 | " raise TypeError(\"Class do not have required attribute.\")\n", 181 | " return super().__new__(cls,name,bases,dct)\n", 182 | " \n", 183 | "# creating class using above metaclass\n", 184 | "class MyClass(metaclass=AttributeValidatorMetaclass):\n", 185 | " required_attrs = ['arg1','arg2']\n", 186 | " \n", 187 | "# creating another class using metaclass to check if rasing error working or not. \n", 188 | "try:\n", 189 | " class Trying(metaclass=AttributeValidatorMetaclass):\n", 190 | " pass\n", 191 | "except TypeError as e:\n", 192 | " print(\"Error :: \",e)\n", 193 | " \n", 194 | "\n", 195 | "# Correct class\n", 196 | "mc = MyClass()\n", 197 | "print(\"Class Created Successfully!.\")" 198 | ] 199 | } 200 | ], 201 | "metadata": { 202 | "kernelspec": { 203 | "display_name": "Python 3 (ipykernel)", 204 | "language": "python", 205 | "name": "python3" 206 | }, 207 | "language_info": { 208 | "codemirror_mode": { 209 | "name": "ipython", 210 | "version": 3 211 | }, 212 | "file_extension": ".py", 213 | "mimetype": "text/x-python", 214 | "name": "python", 215 | "nbconvert_exporter": "python", 216 | "pygments_lexer": "ipython3", 217 | "version": "3.11.7" 218 | } 219 | }, 220 | "nbformat": 4, 221 | "nbformat_minor": 5 222 | } 223 | -------------------------------------------------------------------------------- /Day_19/data/use_text.txt: -------------------------------------------------------------------------------- 1 | Day 19 of 100DaysOfCode Python - Generators and Yield 2 | Day 19 of 100DaysOfCode Python - Generators and Yield 3 | Day 19 of 100DaysOfCode Python - Generators and Yield 4 | Day 19 of 100DaysOfCode Python - Generators and Yield 5 | Day 19 of 100DaysOfCode Python - Generators and Yield 6 | Day 19 of 100DaysOfCode Python - Generators and Yield 7 | Day 19 of 100DaysOfCode Python - Generators and Yield 8 | Day 19 of 100DaysOfCode Python - Generators and Yield 9 | Day 19 of 100DaysOfCode Python - Generators and Yield 10 | Day 19 of 100DaysOfCode Python - Generators and Yield 11 | Day 19 of 100DaysOfCode Python - Generators and Yield -------------------------------------------------------------------------------- /Day_19/generators_and_yield.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "21c7499e", 6 | "metadata": {}, 7 | "source": [ 8 | "# Day 19\n", 9 | "\n", 10 | "**Practicing Python from Basics**" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "id": "fe77deef", 16 | "metadata": {}, 17 | "source": [ 18 | "# Generators and yield" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "id": "19212601", 24 | "metadata": {}, 25 | "source": [ 26 | "Generators and the `yield` keyword are powerful features in Python for creating iterators. They allow you to iterate over a sequence of data without creating the entire sequence in memory at once, making them memory-efficient and often faster than traditional iteration methods." 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "id": "9a9fc09b", 32 | "metadata": {}, 33 | "source": [ 34 | "## Exercises" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "id": "71a5ea08", 40 | "metadata": {}, 41 | "source": [ 42 | "### 1. Simple Generator :\n", 43 | "\n", 44 | "Write a generator function that yields numbers from 1 to N." 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 1, 50 | "id": "7f27f682", 51 | "metadata": {}, 52 | "outputs": [ 53 | { 54 | "name": "stdout", 55 | "output_type": "stream", 56 | "text": [ 57 | "1\n", 58 | "2\n", 59 | "3\n", 60 | "4\n", 61 | "5\n" 62 | ] 63 | } 64 | ], 65 | "source": [ 66 | "# Function to generate a number\n", 67 | "def number_generator(n):\n", 68 | " for i in range(1,n+1):\n", 69 | " yield i\n", 70 | "\n", 71 | "# variables\n", 72 | "n = 5\n", 73 | "\n", 74 | "# calling function to generate numbers\n", 75 | "result = number_generator(n)\n", 76 | "\n", 77 | "# printing numbers \n", 78 | "for number in result:\n", 79 | " print(number)" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "id": "6ccab633", 85 | "metadata": {}, 86 | "source": [ 87 | "- **The `yield` keyword is used to return a value from the generator function while pausing its execution state. When the function is called again, it resumes from where it left off.**\n", 88 | "- **Generators are iterables, but unlike lists or tuples, they generate values on-the-fly, so they don't store the entire sequence in memory.**" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "id": "8c819c1d", 94 | "metadata": {}, 95 | "source": [ 96 | "### 2. Fibonacci Sequence Generator:\n", 97 | "Write a generator function to generate the Fibonacci sequence up to a certain limit. " 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 3, 103 | "id": "b17fbb31", 104 | "metadata": {}, 105 | "outputs": [ 106 | { 107 | "name": "stdout", 108 | "output_type": "stream", 109 | "text": [ 110 | "0\n", 111 | "1\n", 112 | "1\n", 113 | "2\n", 114 | "3\n", 115 | "5\n", 116 | "8\n" 117 | ] 118 | } 119 | ], 120 | "source": [ 121 | "# defining function to generate fibonacci sequence.\n", 122 | "def fibonacci_sequence(limit):\n", 123 | " first_value, second_value = 0, 1\n", 124 | " \n", 125 | " while first_value arr[j+1]:\n", 54 | " arr[j], arr[j+1] = arr[j+1], arr[j]\n", 55 | " swapped = True\n", 56 | " \n", 57 | " # break if no swaps\n", 58 | " if not swapped:\n", 59 | " break\n", 60 | " \n", 61 | " return arr" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "id": "bdbbb68b", 67 | "metadata": {}, 68 | "source": [ 69 | "## Calling bubble_sort() function to sort example list" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 5, 75 | "id": "9470bb96", 76 | "metadata": {}, 77 | "outputs": [ 78 | { 79 | "name": "stdout", 80 | "output_type": "stream", 81 | "text": [ 82 | "Sorted_list :: [11, 12, 22, 25, 34, 64, 90]\n" 83 | ] 84 | } 85 | ], 86 | "source": [ 87 | "ex_list = [64, 34, 25, 12, 22, 11, 90]\n", 88 | "sorted_list = bubble_sort(ex_list)\n", 89 | "print(f\"Sorted_list :: {sorted_list}\")" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "id": "d841da9b", 95 | "metadata": {}, 96 | "source": [ 97 | "# Selection Sort\n", 98 | "\n", 99 | "Selection Sort divides the list into a sorted and an unsorted region. It repeatedly selects the smallest (or largest) element from the unsorted region and moves it to the sorted region.\n", 100 | "\n", 101 | " - **Complexity**: \\(O(n^2)\\).\n", 102 | " \n", 103 | " - **Best for**: Small datasets.\n", 104 | " \n", 105 | " - **Pros**: Simple and easy to understand.\n", 106 | " \n", 107 | " - **Cons**: Inefficient on large lists.\n", 108 | "\n", 109 | "\n", 110 | "\n", 111 | "\n", 112 | "_For detailed article :- https://www.geeksforgeeks.org/selection-sort/ or https://www.tutorchase.com/answers/a-level/computer-science/how-does-the-selection-sort-algorithm-function_" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "id": "a320b81f", 118 | "metadata": {}, 119 | "source": [ 120 | "## Implementation" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 6, 126 | "id": "6da0ed59", 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "def selection_sort(arr):\n", 131 | " n = len(arr)\n", 132 | " \n", 133 | " for i in range(n):\n", 134 | " # to find minimum element in the unsorted region\n", 135 | " min_index = i\n", 136 | " \n", 137 | " for j in range(i+1, n):\n", 138 | " if arr[j]=0 and arr[j]>key:\n", 55 | " arr[j+1] = arr[j]\n", 56 | " j -= 1\n", 57 | "\n", 58 | " arr[j+1] = key\n", 59 | " return arr" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "id": "caa28c6b-3738-4a42-8ee8-b728aa8e1bcc", 65 | "metadata": {}, 66 | "source": [ 67 | "## Calling insertion_sort() to sort example list" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 3, 73 | "id": "cef27c8a-753c-4e1a-a1e7-ab06d616bbd4", 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "name": "stdout", 78 | "output_type": "stream", 79 | "text": [ 80 | "Sorted List : [5, 6, 11, 12, 13]\n" 81 | ] 82 | } 83 | ], 84 | "source": [ 85 | "ex_list = [12, 11, 13, 5, 6]\n", 86 | "sorted_list = insertion_sort(ex_list)\n", 87 | "print(f\"Sorted List : {sorted_list}\")" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "id": "e2418416-10fe-4e1b-9362-b3dac96340b3", 93 | "metadata": {}, 94 | "source": [ 95 | "## To get how much time needed we can use `%%time`" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 7, 101 | "id": "08c8fb7f-3606-4108-819f-6394de6e8f98", 102 | "metadata": {}, 103 | "outputs": [ 104 | { 105 | "name": "stdout", 106 | "output_type": "stream", 107 | "text": [ 108 | "sorted list : [5, 6, 11, 12, 13]\n", 109 | "CPU times: total: 0 ns\n", 110 | "Wall time: 0 ns\n" 111 | ] 112 | } 113 | ], 114 | "source": [ 115 | "%%time\n", 116 | "sorted_list = insertion_sort(ex_list)\n", 117 | "print(F\"sorted list : {sorted_list}\")" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "id": "a285704e-a895-43e5-8056-286d7a78851e", 123 | "metadata": {}, 124 | "source": [ 125 | "# Merge Sort\n", 126 | "\n", 127 | "Merge Sort is a divide-and-conquer algorithm that splits the array into two halves, recursively sorts each half, and then merges the sorted halves to produce the final sorted array.\n", 128 | "\n", 129 | "- **Complexity**: O(n log n) for both average and worst-case.\n", 130 | "- **Best for**: Large datasets.\n", 131 | "- **Pros**: \n", 132 | " - Consistent performance.\n", 133 | " - Stable sort.\n", 134 | " - Can handle large datasets efficiently.\n", 135 | "- **Cons**: \n", 136 | " - Requires additional space proportional to the size of the array (not in-place).\n", 137 | " - More complex to implement than simple algorithms like Bubble Sort and Insertion Sort.\n" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "id": "c26b645a-103d-453b-bb7f-1b4973ddf116", 143 | "metadata": {}, 144 | "source": [ 145 | "## Implementation" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 4, 151 | "id": "9c475ff4-bf67-45cc-8ead-8979d88e7bd8", 152 | "metadata": {}, 153 | "outputs": [], 154 | "source": [ 155 | "def merge_sort(arr):\n", 156 | " if len(arr)>1:\n", 157 | " mid = len(arr)//2\n", 158 | " left = arr[:mid]\n", 159 | " right = arr[mid:]\n", 160 | "\n", 161 | " # Sorting left and right\n", 162 | " merge_sort(left)\n", 163 | " merge_sort(right)\n", 164 | "\n", 165 | " # Merging\n", 166 | " i = j = k = 0\n", 167 | " while i\n", 101 | "\n", 102 | " \n", 103 | " {{ title }}\n", 104 | " \n", 105 | " \n", 106 | "

{{ heading }}

\n", 107 | "

{{ message }}

\n", 108 | " \n", 109 | "\n", 110 | "```\n", 111 | "\n", 112 | "Modify `app.py` to render this template:\n", 113 | "\n", 114 | "```python\n", 115 | "from flask import render_template\n", 116 | "\n", 117 | "@app.route('/')\n", 118 | "def home():\n", 119 | " return render_template('index.html', title='Home Page', heading='Welcome to Flask', message='This is a Flask web application')\n", 120 | "```\n", 121 | "\n", 122 | "### Handling Forms and Requests\n", 123 | "\n", 124 | "Flask can handle various types of HTTP requests (GET, POST, etc.). Create a simple form in `templates/form.html`:\n", 125 | "\n", 126 | "```html\n", 127 | "\n", 128 | "\n", 129 | " \n", 130 | "
\n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | "
\n", 135 | " \n", 136 | "\n", 137 | "```\n", 138 | "\n", 139 | "Update `app.py` to handle form submissions:\n", 140 | "\n", 141 | "```python\n", 142 | "from flask import request\n", 143 | "\n", 144 | "@app.route('/form')\n", 145 | "def form():\n", 146 | " return render_template('form.html')\n", 147 | "\n", 148 | "@app.route('/submit', methods=['POST'])\n", 149 | "def submit():\n", 150 | " name = request.form['name']\n", 151 | " return f'Hello, {name}!'\n", 152 | "```\n", 153 | "\n", 154 | "### Static Files\n", 155 | "\n", 156 | "Flask automatically serves static files from the `static` directory. Create a `static` folder and add a CSS file, `style.css`:\n", 157 | "\n", 158 | "```css\n", 159 | "body {\n", 160 | " background-color: #f0f0f0;\n", 161 | "}\n", 162 | "```\n", 163 | "\n", 164 | "Link this CSS file in your `index.html`:\n", 165 | "\n", 166 | "```html\n", 167 | "\n", 168 | " \n", 169 | "\n", 170 | "```\n", 171 | "\n", 172 | "## Conclusion\n", 173 | "\n", 174 | "This guide provides a basic introduction to Flask. You should now have a working Flask application with routing, template rendering, form handling, and static files. Flask has many extensions for database integration, form validation, authentication, and more, which you can explore as you continue learning.\n", 175 | "\n", 176 | "## Additional Resources\n", 177 | "\n", 178 | "- [Flask Documentation](https://flask.palletsprojects.com/)\n", 179 | "- [Jinja2 Documentation](https://jinja.palletsprojects.com/)\n", 180 | "- [Flask Mega-Tutorial](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world)\n", 181 | "\n", 182 | "Happy coding!" 183 | ] 184 | } 185 | ], 186 | "metadata": { 187 | "kernelspec": { 188 | "display_name": "Python 3 (ipykernel)", 189 | "language": "python", 190 | "name": "python3" 191 | }, 192 | "language_info": { 193 | "codemirror_mode": { 194 | "name": "ipython", 195 | "version": 3 196 | }, 197 | "file_extension": ".py", 198 | "mimetype": "text/x-python", 199 | "name": "python", 200 | "nbconvert_exporter": "python", 201 | "pygments_lexer": "ipython3", 202 | "version": "3.10.3" 203 | } 204 | }, 205 | "nbformat": 4, 206 | "nbformat_minor": 5 207 | } 208 | -------------------------------------------------------------------------------- /Day_44/flask_forms_and_static/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request 2 | 3 | app = Flask(__name__) 4 | 5 | @app.route('/') 6 | @app.route('/index') 7 | def index(): 8 | return render_template('index.html', title="home page", heading="Welcome to Flask", message="This is a Flask web app starting") 9 | 10 | @app.route('/form') 11 | def form(): 12 | return render_template('form.html') 13 | 14 | @app.route('/submit', methods=['POST']) 15 | def submit(): 16 | name = request.form['name'] 17 | return f"Hello, {name}" 18 | 19 | if __name__=="__main__": 20 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_44/flask_forms_and_static/static/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #b67070; 3 | } -------------------------------------------------------------------------------- /Day_44/flask_forms_and_static/templates/form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | contact form 8 | 9 | 10 |
11 | 12 | 13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /Day_44/flask_forms_and_static/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ title }} 7 | 8 | 9 |

{{ heading }}

10 |

{{ message }}

11 | 12 | -------------------------------------------------------------------------------- /Day_44/flask_intro/app/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | from app import routes 6 | 7 | -------------------------------------------------------------------------------- /Day_44/flask_intro/app/routes.py: -------------------------------------------------------------------------------- 1 | from app import app 2 | 3 | @app.route('/') 4 | @app.route('/index') 5 | def index(): 6 | return "Hello, world!." 7 | 8 | @app.route('/about') 9 | def about(): 10 | return 'this is about page.' 11 | 12 | -------------------------------------------------------------------------------- /Day_44/flask_intro/flask_intro.py: -------------------------------------------------------------------------------- 1 | from app import app 2 | 3 | if __name__=="__main__": 4 | app.run(debug=True) 5 | -------------------------------------------------------------------------------- /Day_44/flask_templates/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask(__name__) 4 | 5 | @app.route('/') 6 | @app.route('/index') 7 | def index(): 8 | return render_template('index.html', title="home page", heading="Welcome to Flask", message="This is a Flask web app starting") 9 | 10 | if __name__=="__main__": 11 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_44/flask_templates/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ title }} 7 | 8 | 9 |

{{ heading }}

10 |

{{ message }}

11 | 12 | -------------------------------------------------------------------------------- /Day_45/Python Flask - Templates in detail.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "61fed98c", 6 | "metadata": {}, 7 | "source": [ 8 | "# Python Flask (Day 45)\n", 9 | "\n", 10 | "## Background on Flask Templates\n", 11 | "\n", 12 | "Flask templates use the Jinja2 templating engine to create dynamic web pages. This allows for a clear separation of HTML (presentation layer) and Python code (application logic), making web development more organized and maintainable. Templates enable you to embed Python-like expressions within HTML files, making it easy to generate dynamic content.\n", 13 | "\n", 14 | "## Code Examples Explained\n", 15 | "\n", 16 | "### Variables\n", 17 | "\n", 18 | "Templates can display dynamic data by embedding variables within HTML using double curly braces `{{ }}`. This is useful for injecting data passed from Flask routes.\n", 19 | "\n", 20 | "**Example:**\n", 21 | "```html\n", 22 | "\n", 23 | "

Hello, {{ name }}!

\n", 24 | "```\n", 25 | "In the Flask route, you can pass the `name` variable to the template:\n", 26 | "```python\n", 27 | "from flask import Flask, render_template\n", 28 | "\n", 29 | "app = Flask(__name__)\n", 30 | "\n", 31 | "@app.route('/')\n", 32 | "def index():\n", 33 | " return render_template('index.html', name='Alice')\n", 34 | "```\n", 35 | "**Explanation:** When the `/` route is accessed, the Flask app renders the `index.html` template and passes the value `'Alice'` to the `name` variable. The template then displays \"Hello, Alice!\".\n", 36 | "\n", 37 | "### Conditionals\n", 38 | "\n", 39 | "Conditionals in templates allow you to render content based on certain conditions using `{% if %}` and `{% endif %}`.\n", 40 | "\n", 41 | "**Example:**\n", 42 | "```html\n", 43 | "\n", 44 | "{% if user %}\n", 45 | "

Welcome, {{ user.name }}!

\n", 46 | "{% else %}\n", 47 | "

Please log in.

\n", 48 | "{% endif %}\n", 49 | "```\n", 50 | "In the Flask route, you can pass the `user` object:\n", 51 | "```python\n", 52 | "@app.route('/')\n", 53 | "def index():\n", 54 | " user = {'name': 'Alice'}\n", 55 | " return render_template('index.html', user=user)\n", 56 | "```\n", 57 | "**Explanation:** This template checks if the `user` variable is defined. If it is, it displays a welcome message with the user's name. Otherwise, it prompts the user to log in.\n", 58 | "\n", 59 | "### Loops\n", 60 | "\n", 61 | "Loops allow you to iterate over lists or other iterable objects and render content multiple times using `{% for %}` and `{% endfor %}`.\n", 62 | "\n", 63 | "**Example:**\n", 64 | "```html\n", 65 | "\n", 66 | "
    \n", 67 | "{% for item in items %}\n", 68 | "
  • {{ item }}
  • \n", 69 | "{% endfor %}\n", 70 | "
\n", 71 | "```\n", 72 | "In the Flask route, you can pass the `items` list:\n", 73 | "```python\n", 74 | "@app.route('/items')\n", 75 | "def items():\n", 76 | " items = ['Apple', 'Banana', 'Cherry']\n", 77 | " return render_template('items.html', items=items)\n", 78 | "```\n", 79 | "**Explanation:** This template iterates over the `items` list and creates a list item `
  • ` for each element. When the `/items` route is accessed, the app renders the `items.html` template and passes the list `['Apple', 'Banana', 'Cherry']`, resulting in a bulleted list of fruits.\n", 80 | "\n", 81 | "### Inheritance\n", 82 | "\n", 83 | "Template inheritance allows you to create a base template with common layout elements and extend it in other templates to avoid redundancy. This is done using `{% extends %}` and `{% block %}`.\n", 84 | "\n", 85 | "**Example:**\n", 86 | "```html\n", 87 | "\n", 88 | "\n", 89 | "\n", 90 | "\n", 91 | " {% block title %}My Site{% endblock %}\n", 92 | "\n", 93 | "\n", 94 | "
    \n", 95 | "

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

    \n", 96 | "
    \n", 97 | "
    \n", 98 | " {% block content %}{% endblock %}\n", 99 | "
    \n", 100 | "\n", 101 | "\n", 102 | "```\n", 103 | "Child templates can extend the base template and fill in the blocks:\n", 104 | "```html\n", 105 | "\n", 106 | "{% extends \"base.html\" %}\n", 107 | "{% block title %}Child Page{% endblock %}\n", 108 | "{% block content %}\n", 109 | "

    This is the child page content.

    \n", 110 | "{% endblock %}\n", 111 | "```\n", 112 | "In the Flask route, you render the child template:\n", 113 | "```python\n", 114 | "@app.route('/child')\n", 115 | "def child():\n", 116 | " return render_template('child.html')\n", 117 | "```\n", 118 | "**Explanation:** The `base.html` template defines a general structure with blocks for `title`, `header`, and `content`. The `child.html` template extends `base.html` and provides specific content for these blocks. This way, common elements are centralized in `base.html`, and specific content is defined in child templates.\n", 119 | "\n", 120 | "## Conclusion\n", 121 | "\n", 122 | "Using variables, conditionals, loops, and inheritance in Flask templates helps create dynamic, maintainable, and reusable web pages. By leveraging these features, you can build sophisticated web applications with clean and efficient code structure. For more detailed information, refer to the original [Flask Mega-Tutorial Part II: Templates](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-ii-templates).\n", 123 | "\n", 124 | "**Happy Coding!**" 125 | ] 126 | } 127 | ], 128 | "metadata": { 129 | "kernelspec": { 130 | "display_name": "Python 3 (ipykernel)", 131 | "language": "python", 132 | "name": "python3" 133 | }, 134 | "language_info": { 135 | "codemirror_mode": { 136 | "name": "ipython", 137 | "version": 3 138 | }, 139 | "file_extension": ".py", 140 | "mimetype": "text/x-python", 141 | "name": "python", 142 | "nbconvert_exporter": "python", 143 | "pygments_lexer": "ipython3", 144 | "version": "3.11.7" 145 | } 146 | }, 147 | "nbformat": 4, 148 | "nbformat_minor": 5 149 | } 150 | -------------------------------------------------------------------------------- /Day_45/flask_templates.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask(__name__) 4 | 5 | user = {'username':'nk_boy'} 6 | 7 | def add_post(): 8 | posts = [ 9 | { 10 | 'author':{'username':'thor'}, 11 | 'body' : 'Today there will be some lighting. please take care.' 12 | }, 13 | 14 | { 15 | 'author':{'username':'ironman'}, 16 | 'body':'Chotimaster :-|' 17 | } 18 | 19 | ] 20 | 21 | return posts 22 | 23 | @app.route('/') 24 | @app.route('/index') 25 | def index(): 26 | return f""" 27 | 28 | 29 | 30 | Home Page - nk_blog 31 | 32 | 33 |

    Hello, {user['username']}!

    34 | 35 | 36 | 37 | """ 38 | 39 | @app.route('/render-template') 40 | def rend_temp(): 41 | return render_template('index.html',user=user,title="Rendering Template",page="rendering page.") 42 | 43 | @app.route('/conditional') 44 | def conditional(): 45 | return render_template('conditional.html',title="Conditionals",user=user,page="conditional") 46 | 47 | @app.route('/loops') 48 | def loops(): 49 | posts = add_post() 50 | return render_template('loops.html',title='Loops',user=user,posts=posts) 51 | 52 | @app.route('/inheritance') 53 | def inherit(): 54 | posts = add_post() 55 | return render_template('inheritance.html', title="Inheritance",user=user,posts=posts) 56 | 57 | if __name__=="__main__": 58 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_45/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {%if title%} 4 | {{title}} - nkblog 5 | {%else%} 6 | intro to inheritance - nkblog 7 | {%endif%} 8 | 9 | 10 |
    nkblog : Home
    11 |
    12 | {%block content%}{%endblock%} 13 | 14 | -------------------------------------------------------------------------------- /Day_45/templates/conditional.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {%if title%} 7 | {{ title }} - nkblog 8 | {%else%} 9 | Welcome to conditionals - nkblog 10 | {%endif%} 11 | 12 | 13 |

    Hello, {{user.username}}!

    14 |

    {{page}}

    15 | 16 | -------------------------------------------------------------------------------- /Day_45/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{title}} - nkblog 4 | 5 | 6 |

    Hello, {{user.username}}!

    7 |

    {{ page }}

    8 | 9 | -------------------------------------------------------------------------------- /Day_45/templates/inheritance.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |

    Hi, {{ user.username }}

    4 | {%for post in posts%} 5 |

    {{ post.author.username }} says: {{post.body}}

    6 | {%endfor%} 7 | {% endblock %} -------------------------------------------------------------------------------- /Day_45/templates/loops.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {%if title%} 7 | {{title}} - nkblog 8 | {%else%} 9 | Intro to loops - nkblog 10 | {%endif%} 11 | 12 | 13 |

    Hi, {{user.username}}!

    14 | {%for post in posts%} 15 |

    {{post.author.username}} says: {{post.body}}

    16 | {%endfor%} 17 | 18 | -------------------------------------------------------------------------------- /Day_46/error_pages.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | from flask_bootstrap import Bootstrap 3 | 4 | app = Flask(__name__) 5 | bootstrap = Bootstrap(app) 6 | 7 | user = {'username':'nk_boy'} 8 | 9 | @app.route('/') 10 | @app.route('/index') 11 | @app.route('/home') 12 | def index(): 13 | return render_template('boot.html',name=user['username']) 14 | 15 | @app.errorhandler(404) 16 | def page_not_found(e): 17 | return render_template('404.html'), 404 18 | 19 | @app.errorhandler(500) 20 | def internal_server_error(e): 21 | return render_template('500.html'), 500 22 | 23 | if __name__=="__main__": 24 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_46/flask_bootstrap_int.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | from flask_bootstrap import Bootstrap 3 | 4 | app = Flask(__name__) 5 | bootstrap = Bootstrap(app) 6 | 7 | user = {'username':'nk_boy'} 8 | 9 | @app.route('/') 10 | @app.route('/index') 11 | @app.route('/home') 12 | def index(): 13 | return render_template('boot.html',name=user['username']) 14 | 15 | if __name__=="__main__": 16 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_46/local_date_time.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | from flask_bootstrap import Bootstrap 3 | from flask_moment import Moment 4 | from datetime import datetime, timezone 5 | 6 | app = Flask(__name__) 7 | bootstrap = Bootstrap(app) 8 | moment = Moment(app) 9 | 10 | # print(datetime.now(timezone.utc)) 11 | 12 | user = {'username':'nk_boy'} 13 | 14 | @app.route('/') 15 | @app.route('/index') 16 | def index(): 17 | return render_template('local.html',name=user['username'], current_time=datetime.now(timezone.utc)) 18 | 19 | if __name__=="__main__": 20 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_46/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | {% block title %} Error - nkblog {% endblock %} 4 | 5 | {% block navbar %} 6 | 7 | 25 | 26 | {% endblock %} 27 | 28 | {% block content %} 29 |
    30 | {% block page_content %} 31 | 34 | {% endblock %} 35 |
    36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /Day_46/templates/500.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | {% block title %} Error - nkblog {% endblock %} 4 | 5 | {% block navbar %} 6 | 7 | 25 | 26 | {% endblock %} 27 | 28 | {% block content %} 29 |
    30 | {% block page_content %} 31 | 34 | {% endblock %} 35 |
    36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /Day_46/templates/boot.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | {% block title %} bootstrap - nkblog {% endblock %} 4 | 5 | {% block navbar %} 6 | 7 | 25 | 26 | {% endblock %} 27 | 28 | {% block content %} 29 |
    30 | 33 |
    34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /Day_46/templates/local.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | 4 | {% block title %} Local time and date - nkblog {% endblock %} 5 | 6 | {% block navbar %} 7 | 8 | 26 | 27 | {% endblock %} 28 | 29 | {% block content %} 30 |
    31 | 34 | {% block page_content %} 35 |
    36 |

    The local date and time is {{ moment(current_time).format('MMMM Do YYYY, h:mm:ss a') }}.

    37 |

    That was {{ moment(current_time).fromNow(refresh=True) }}

    38 |
    39 | {% endblock %} 40 |
    41 | {% endblock %} 42 | 43 | {% block scripts %} 44 | {{ super() }} 45 | {{ moment.include_moment() }} 46 | {% endblock %} 47 | -------------------------------------------------------------------------------- /Day_47/Python Flask - Web Forms.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "ccd41d38-789c-4c20-84fc-3776cddaa874", 6 | "metadata": {}, 7 | "source": [ 8 | "# Learning Python Flask (Day 47)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "688c85a5-50db-45d9-a923-0aa124d24a71", 14 | "metadata": {}, 15 | "source": [ 16 | "# Web Forms\n", 17 | "## Overview of Web Forms\n", 18 | "- Web forms are critical for web applications as they enable the collection of user input. \n", 19 | "- Flask-WTF is an extension that integrates Flask with WTForms, providing a simple interface for form handling.\n", 20 | "\n", 21 | "## Installing Flask-WTF\n", 22 | " - Flask-WTF can be installed via pip:\n", 23 | " \n", 24 | " ```bash\n", 25 | " pip install flask-wtf\n", 26 | " \n", 27 | " ```\n", 28 | "\n", 29 | "## Creating Forms\n", 30 | " - Forms in Flask-WTF are defined as Python classes that inherit from `FlaskForm`.\n", 31 | " - Example of creating a simple form with a text field and a submit button:\n", 32 | " \n", 33 | " ```python\n", 34 | " from flask_wtf import FlaskForm\n", 35 | " from wtforms import StringField, SubmitField\n", 36 | " from wtforms.validators import DataRequired\n", 37 | "\n", 38 | " class NameForm(FlaskForm):\n", 39 | " name = StringField('What is your name?', validators=[DataRequired()])\n", 40 | " submit = SubmitField('Submit')\n", 41 | " \n", 42 | " ```\n", 43 | " - `StringField` is used for text input, and `SubmitField` creates a submit button.\n", 44 | " - `DataRequired` is a validator that ensures the field is not empty.\n", 45 | "\n", 46 | "## CSRF Protection\n", 47 | " - Flask-WTF provides CSRF protection to prevent cross-site request forgery attacks.\n", 48 | " - To enable CSRF protection, you must set a secret key in your Flask application:\n", 49 | " \n", 50 | " ```python\n", 51 | " app = Flask(__name__)\n", 52 | " app.config['SECRET_KEY'] = 'your_secret_key'\n", 53 | " \n", 54 | " ```\n", 55 | " - CSRF protection works by including a hidden CSRF token in every form.\n", 56 | "\n", 57 | "## Rendering Forms\n", 58 | " - To render a form in a template, pass the form instance to the template context.\n", 59 | " - Use the form instance to render form fields and the CSRF token:\n", 60 | " \n", 61 | " ```html\n", 62 | "
    \n", 63 | " {{ form.hidden_tag() }}\n", 64 | "

    \n", 65 | " {{ form.name.label }}
    \n", 66 | " {{ form.name(size=32) }}
    \n", 67 | " {{ form.submit() }}\n", 68 | "

    \n", 69 | "
    \n", 70 | " \n", 71 | " ```\n", 72 | " - `form.hidden_tag()` generates hidden fields, including the CSRF token.\n", 73 | " - `form.name.label` and `form.name()` render the label and input field for the `name` field, respectively.\n", 74 | " - `form.submit()` renders the submit button.\n", 75 | "\n", 76 | "## Processing Form Data\n", 77 | " - Handle form submission in the corresponding view function.\n", 78 | " - Check if the form is submitted and valid using `form.validate_on_submit()`:\n", 79 | " \n", 80 | " ```python\n", 81 | " from flask import Flask, render_template, flash, redirect, url_for\n", 82 | "\n", 83 | " @app.route('/', methods=['GET', 'POST'])\n", 84 | " def index():\n", 85 | " form = NameForm()\n", 86 | " if form.validate_on_submit():\n", 87 | " name = form.name.data\n", 88 | " flash(f'Hello, {name}!')\n", 89 | " return redirect(url_for('index'))\n", 90 | " return render_template('index.html', form=form)\n", 91 | " \n", 92 | " ```\n", 93 | " - If the form is submitted and validated, retrieve form data using `form.name.data` and perform necessary actions (e.g., flashing a message).\n", 94 | "\n", 95 | "## Validation\n", 96 | " - WTForms provides a range of validators to enforce rules on form fields.\n", 97 | " - Common validators include `DataRequired`, `Email`, `Length`, etc.:\n", 98 | " \n", 99 | " ```python\n", 100 | " from wtforms.validators import Email, Length\n", 101 | "\n", 102 | " class RegistrationForm(FlaskForm):\n", 103 | " email = StringField('Email', validators=[DataRequired(), Email()])\n", 104 | " password = StringField('Password', validators=[DataRequired(), Length(min=6)])\n", 105 | " submit = SubmitField('Register')\n", 106 | " \n", 107 | " ```\n", 108 | " - `Email` ensures the field contains a valid email address, and `Length` enforces minimum and maximum length constraints.\n", 109 | "\n", 110 | "## Example Application\n", 111 | " - A complete Flask application example integrating all the discussed concepts:\n", 112 | " \n", 113 | " ```python\n", 114 | " from flask import Flask, render_template, flash, redirect, url_for\n", 115 | " from flask_wtf import FlaskForm\n", 116 | " from wtforms import StringField, SubmitField\n", 117 | " from wtforms.validators import DataRequired\n", 118 | "\n", 119 | " app = Flask(__name__)\n", 120 | " app.config['SECRET_KEY'] = 'your_secret_key'\n", 121 | "\n", 122 | " class NameForm(FlaskForm):\n", 123 | " name = StringField('What is your name?', validators=[DataRequired()])\n", 124 | " submit = SubmitField('Submit')\n", 125 | "\n", 126 | " @app.route('/', methods=['GET', 'POST'])\n", 127 | " def index():\n", 128 | " form = NameForm()\n", 129 | " if form.validate_on_submit():\n", 130 | " name = form.name.data\n", 131 | " flash(f'Hello, {name}!')\n", 132 | " return redirect(url_for('index'))\n", 133 | " return render_template('index.html', form=form)\n", 134 | "\n", 135 | " if __name__ == '__main__':\n", 136 | " app.run(debug=True)\n", 137 | " \n", 138 | " ```\n", 139 | " - This example demonstrates form creation, CSRF protection, form rendering in templates, form submission handling, and validation.\n", 140 | " - The app displays a form to collect a user's name and greets the user upon form submission." 141 | ] 142 | } 143 | ], 144 | "metadata": { 145 | "kernelspec": { 146 | "display_name": "Python 3 (ipykernel)", 147 | "language": "python", 148 | "name": "python3" 149 | }, 150 | "language_info": { 151 | "codemirror_mode": { 152 | "name": "ipython", 153 | "version": 3 154 | }, 155 | "file_extension": ".py", 156 | "mimetype": "text/x-python", 157 | "name": "python", 158 | "nbconvert_exporter": "python", 159 | "pygments_lexer": "ipython3", 160 | "version": "3.10.3" 161 | } 162 | }, 163 | "nbformat": 4, 164 | "nbformat_minor": 5 165 | } 166 | -------------------------------------------------------------------------------- /Day_47/flask_web_forms.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | from flask_bootstrap import Bootstrap 3 | from flask_moment import Moment 4 | 5 | app = Flask(__name__) 6 | app.config['SECRET_KEY'] = 'DipWdasTwstDgh' 7 | bootstrap = Bootstrap(app) 8 | moment = Moment(app) 9 | 10 | # Creating class 11 | from flask_wtf import FlaskForm 12 | from wtforms import StringField, SubmitField 13 | from wtforms.validators import DataRequired 14 | 15 | class NameForm(FlaskForm): 16 | name = StringField("What is your name?", validators=[DataRequired()]) 17 | submit = SubmitField("Submit") 18 | 19 | 20 | @app.route('/', methods=['GET','POST']) 21 | def index(): 22 | name = None 23 | form = NameForm() 24 | if form.validate_on_submit(): 25 | name = form.name.data 26 | form.name.data = '' 27 | 28 | return render_template("index.html",form=form, name=name) 29 | 30 | if __name__=="__main__": 31 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_47/message_flashing.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, redirect, url_for, session, flash 2 | from flask_bootstrap import Bootstrap 3 | 4 | app = Flask(__name__) 5 | app.config['SECRET_KEY'] = 'alskdjfjnjnchuiadf' 6 | bootstrap = Bootstrap(app) 7 | 8 | # Class for form 9 | from flask_wtf import FlaskForm 10 | from wtforms import StringField, SubmitField 11 | from wtforms.validators import DataRequired 12 | 13 | class NameForm(FlaskForm): 14 | name = StringField("What is your name?", validators=[DataRequired()]) 15 | submit = SubmitField("Submit") 16 | 17 | 18 | # Index 19 | @app.route('/',methods = ['GET', "POST"]) 20 | def index(): 21 | form = NameForm() 22 | if form.validate_on_submit(): 23 | old_name = session.get('name') 24 | if old_name is not None and old_name != form.name.data: 25 | flash('Looks like you have changed your name!.') 26 | 27 | session['name'] = form.name.data 28 | return redirect(url_for('index')) 29 | return render_template('index.html', form=form, name = session.get('name')) 30 | 31 | if __name__=="__main__": 32 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_47/sessions and redirections.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, redirect, request, session, url_for 2 | from flask_bootstrap import Bootstrap 3 | from flask_moment import Moment 4 | 5 | app = Flask(__name__) 6 | app.config['SECRET_KEY'] = 'DipWdasTwstDgh' 7 | bootstrap = Bootstrap(app) 8 | moment = Moment(app) 9 | 10 | # class 11 | from flask_wtf import FlaskForm 12 | from wtforms import SubmitField, StringField 13 | from wtforms.validators import DataRequired 14 | 15 | class NameForm(FlaskForm): 16 | name = StringField("What is your name?", validators=[DataRequired()]) 17 | submit = SubmitField("Submit") 18 | 19 | 20 | @app.route('/',methods = ["POST", "GET"]) 21 | def index(): 22 | form = NameForm() 23 | if form.validate_on_submit(): 24 | session['name'] = form.name.data 25 | return redirect(url_for('index')) 26 | return render_template('index.html',form=form, name=session.get('name')) 27 | 28 | if __name__=="__main__": 29 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_47/templates/base.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | {% block title %} Webforms - nkblog {% endblock %} 4 | 5 | {% block navbar %} 6 | 7 | 25 | 26 | {% endblock %} -------------------------------------------------------------------------------- /Day_47/templates/flash_alert.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 |
    3 | {% for msg in get_flashed_messages() %} 4 |
    5 | 6 | {{ msg }} 7 |
    8 | {% endfor %} 9 |
    10 | {% endblock %} -------------------------------------------------------------------------------- /Day_47/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% import 'bootstrap/wtf.html' as wtf %} 4 | 5 | {% block content %} 6 | {% include "flash_alert.html" %} 7 |
    8 | 15 | {% block page_content %} 16 |
    17 | {{ wtf.quick_form(form) }} 18 |
    19 | 20 | {% endblock %} 21 |
    22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /Day_48/Python Flask - Database Integration.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "f65be257-df91-4a1a-876b-a0c4bbe651b3", 6 | "metadata": {}, 7 | "source": [ 8 | "# Learning Python Flask (Day 48)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "dda937f9-8f33-4c48-a7d8-4f58fd56cd9d", 14 | "metadata": {}, 15 | "source": [ 16 | "# Flask Database Integration\n", 17 | "## Introduction to Databases\n", 18 | "- **Purpose**: Databases are crucial for storing, retrieving, and managing data in web applications.\n", 19 | "- **Support in Flask**: Flask can work with various databases through extensions, with SQLAlchemy being a widely-used option for its ORM capabilities.\n", 20 | "\n", 21 | "## SQLAlchemy\n", 22 | "- **Definition**: SQLAlchemy is a SQL toolkit and Object-Relational Mapping (ORM) library for Python.\n", 23 | "- **Functionality**: It allows developers to interact with the database using Python objects, abstracting the complexity of raw SQL queries.\n", 24 | "\n", 25 | "## Flask-SQLAlchemy\n", 26 | "- **Integration**: Flask-SQLAlchemy is an extension that integrates SQLAlchemy with Flask, providing a convenient way to manage database operations within Flask applications.\n", 27 | "\n", 28 | "## Installation\n", 29 | "1. **Installing Flask-SQLAlchemy**:\n", 30 | " - Use pip to install the Flask-SQLAlchemy extension:\n", 31 | " \n", 32 | " ```bash\n", 33 | " pip install flask-sqlalchemy\n", 34 | " ```\n", 35 | "\n", 36 | "## Configuring the Database\n", 37 | "2. **Database Configuration**:\n", 38 | " - Configure your Flask app to connect to the database by setting the `SQLALCHEMY_DATABASE_URI` configuration variable. For example, to use a SQLite database:\n", 39 | " \n", 40 | " ```python\n", 41 | " app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'\n", 42 | " app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\n", 43 | " ```\n", 44 | " -\n", 45 | " - `SQLALCHEMY_TRACK_MODIFICATIONS` is set to `False` to disable a feature that signals the application every time a change is about to be made in the database, which is unnecessary and can be resource-intensive.\n", 46 | "\n", 47 | "## Defining Models\n", 48 | "3. **Defining Database Models**:\n", 49 | " - Models in Flask-SQLAlchemy are Python classes that inherit from `db.Model`. Each class attribute represents a database column.\n", 50 | " - Example of defining a `User` model:\n", 51 | " \n", 52 | " ```python\n", 53 | " from flask_sqlalchemy import SQLAlchemy\n", 54 | "\n", 55 | " db = SQLAlchemy(app)\n", 56 | "\n", 57 | " class User(db.Model):\n", 58 | " id = db.Column(db.Integer, primary_key=True)\n", 59 | " username = db.Column(db.String(64), unique=True, nullable=False)\n", 60 | " email = db.Column(db.String(120), unique=True, nullable=False)\n", 61 | " ```\n", 62 | "
    \n", 63 | " \n", 64 | " - `db.Column` defines a column in the database. Common column types include `Integer`, `String`, `Float`, `Boolean`, and `DateTime`.\n", 65 | "\n", 66 | "## Creating the Database\n", 67 | "4. **Creating the Database**:\n", 68 | " - To create the database and its tables, run the following command in the Flask shell:\n", 69 | " \n", 70 | " ```python\n", 71 | " db.create_all()\n", 72 | " ```\n", 73 | "
    \n", 74 | " \n", 75 | " - This command generates the database file (e.g., `app.db`) and the necessary tables as defined in your models.\n", 76 | "\n", 77 | "## Performing Database Operations\n", 78 | "5. **Database Operations**:\n", 79 | " - **Adding Records**: To add a new record to the database, create an instance of the model and add it to the session:\n", 80 | " \n", 81 | " ```python\n", 82 | " user = User(username='john', email='john@example.com')\n", 83 | " db.session.add(user)\n", 84 | " db.session.commit()\n", 85 | " ```\n", 86 | "
    \n", 87 | " \n", 88 | " - **Querying Records**: To retrieve records from the database, use query methods:\n", 89 | " \n", 90 | " ```python\n", 91 | " user = User.query.filter_by(username='john').first()\n", 92 | " ```\n", 93 | "
    \n", 94 | " \n", 95 | " - **Updating Records**: Modify the attributes of a retrieved object and commit the changes:\n", 96 | " \n", 97 | " ```python\n", 98 | " user.email = 'john.doe@example.com'\n", 99 | " db.session.commit()\n", 100 | " ```\n", 101 | "
    \n", 102 | " \n", 103 | " - **Deleting Records**: To delete a record, use the `delete` method and commit the change:\n", 104 | " \n", 105 | " ```python\n", 106 | " db.session.delete(user)\n", 107 | " db.session.commit()\n", 108 | " ```\n", 109 | "\n", 110 | "## Migrations\n", 111 | "6. **Database Migrations**:\n", 112 | " - **Flask-Migrate**: This extension manages database migrations for Flask-SQLAlchemy, allowing you to track changes to your models over time.\n", 113 | " - **Installation**:\n", 114 | " \n", 115 | " ```bash\n", 116 | " pip install flask-migrate\n", 117 | " ```\n", 118 | "
    \n", 119 | " \n", 120 | " - **Setup**: Initialize Flask-Migrate in your Flask app:\n", 121 | " \n", 122 | " ```python\n", 123 | " from flask_migrate import Migrate\n", 124 | "\n", 125 | " migrate = Migrate(app, db)\n", 126 | " ```\n", 127 | "
    \n", 128 | " \n", 129 | " - **Using Migration Commands**:\n", 130 | " - **Initialize the migration repository**:\n", 131 | " \n", 132 | " ```bash\n", 133 | " flask db init\n", 134 | " ```\n", 135 | "
    \n", 136 | " \n", 137 | " - **Create a new migration script**:\n", 138 | " \n", 139 | " ```bash\n", 140 | " flask db migrate -m \"Initial migration.\"\n", 141 | " ```\n", 142 | "
    \n", 143 | " \n", 144 | " - **Apply the migration to the database**:\n", 145 | " \n", 146 | " ```bash\n", 147 | " flask db upgrade\n", 148 | " ```\n", 149 | "\n", 150 | "## Example Application\n", 151 | "7. **Complete Example**:\n", 152 | " - Below is a simple Flask application that demonstrates the integration of Flask-SQLAlchemy and Flask-Migrate:\n", 153 | " \n", 154 | " ```python\n", 155 | " from flask import Flask, render_template\n", 156 | " from flask_sqlalchemy import SQLAlchemy\n", 157 | " from flask_migrate import Migrate\n", 158 | "\n", 159 | " app = Flask(__name__)\n", 160 | " app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'\n", 161 | " app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\n", 162 | "\n", 163 | " db = SQLAlchemy(app)\n", 164 | " migrate = Migrate(app, db)\n", 165 | "\n", 166 | " class User(db.Model):\n", 167 | " id = db.Column(db.Integer, primary_key=True)\n", 168 | " username = db.Column(db.String(64), unique=True, nullable=False)\n", 169 | " email = db.Column(db.String(120), unique=True, nullable=False)\n", 170 | "\n", 171 | " @app.route('/')\n", 172 | " def index():\n", 173 | " users = User.query.all()\n", 174 | " return render_template('index.html', users=users)\n", 175 | "\n", 176 | " if __name__ == '__main__':\n", 177 | " app.run(debug=True)\n", 178 | " ```\n", 179 | "
    \n", 180 | " \n", 181 | " - **Explanation**:\n", 182 | " - **Configuration**: The database is configured to use SQLite with `app.db` as the database file.\n", 183 | " - **Model Definition**: The `User` model defines the schema for the `users` table.\n", 184 | " - **Database Operations**: The root route (`/`) queries all users and renders them in a template.\n", 185 | " - **Migrations**: Flask-Migrate is set up to handle any changes in the database schema." 186 | ] 187 | } 188 | ], 189 | "metadata": { 190 | "kernelspec": { 191 | "display_name": "Python 3 (ipykernel)", 192 | "language": "python", 193 | "name": "python3" 194 | }, 195 | "language_info": { 196 | "codemirror_mode": { 197 | "name": "ipython", 198 | "version": 3 199 | }, 200 | "file_extension": ".py", 201 | "mimetype": "text/x-python", 202 | "name": "python", 203 | "nbconvert_exporter": "python", 204 | "pygments_lexer": "ipython3", 205 | "version": "3.10.3" 206 | } 207 | }, 208 | "nbformat": 4, 209 | "nbformat_minor": 5 210 | } 211 | -------------------------------------------------------------------------------- /Day_48/data_integrate/data.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_48/data_integrate/data.sqlite -------------------------------------------------------------------------------- /Day_48/data_integrate/data_integration.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | import os 3 | from flask_sqlalchemy import SQLAlchemy 4 | 5 | basedir = os.path.abspath(os.path.dirname(__file__)) 6 | 7 | app = Flask(__name__) 8 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+os.path.join(basedir,'data.sqlite') 9 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 10 | 11 | db = SQLAlchemy(app) 12 | 13 | class Role(db.Model): 14 | __tablename__ = "roles" 15 | id = db.Column(db.Integer, primary_key=True) 16 | name = db.Column(db.String(64), unique=True) 17 | users = db.relationship('User', backref='Role') 18 | 19 | def __repr__(self): 20 | return '' % self.name 21 | 22 | class User(db.Model): 23 | __tablename__='users' 24 | id = db.Column(db.Integer, primary_key=True) 25 | username = db.Column(db.String(64), unique=True, index=True) 26 | role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) 27 | 28 | def __repr__(self): 29 | return '' % self.username -------------------------------------------------------------------------------- /Day_48/forms_database/data.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeyBuddy-NSK/100DayOfPython/39c95070fbfcd64cf8bd791550f2c92e23187c9f/Day_48/forms_database/data.sqlite -------------------------------------------------------------------------------- /Day_48/forms_database/forms.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, redirect, url_for,session,flash 2 | from flask_bootstrap import Bootstrap 3 | from flask_sqlalchemy import SQLAlchemy 4 | import os 5 | 6 | app = Flask(__name__) 7 | basedir = os.path.abspath(os.path.dirname(__file__)) 8 | 9 | # Config for web forms 10 | app.config['SECRET_KEY'] = 'ALIEURIFJKZDOIRHQWOIO' 11 | bootstrap = Bootstrap(app) 12 | 13 | # Config for database 14 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+os.path.join(basedir,'data.sqlite') 15 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 16 | db = SQLAlchemy(app) 17 | 18 | class User(db.Model): 19 | __tablename__ = 'users' 20 | id = db.Column(db.Integer,primary_key=True) 21 | username = db.Column(db.String(64),unique=True, index=True) 22 | 23 | def __repr__(self): 24 | return '' % self.username 25 | 26 | with app.app_context(): 27 | db.create_all() 28 | 29 | # forms 30 | from flask_wtf import FlaskForm 31 | from wtforms import StringField, SubmitField 32 | from wtforms.validators import DataRequired 33 | 34 | class NameForm(FlaskForm): 35 | name = StringField('What is your name?',validators=[DataRequired()]) 36 | submit = SubmitField('Submit') 37 | 38 | # Index 39 | @app.route('/',methods=['GET','POST']) 40 | def index(): 41 | form = NameForm() 42 | if form.validate_on_submit(): 43 | user = User.query.filter_by(username=form.name.data).first() 44 | if user is None: 45 | user = User(username=form.name.data) 46 | db.session.add(user) 47 | db.session.commit() 48 | session['known'] = False 49 | 50 | else: 51 | session['known'] = True 52 | session['name'] = form.name.data 53 | form.name.data = '' 54 | return redirect(url_for('index')) 55 | return render_template('index.html',name=session.get('name'),form=form,known=session.get('known')) 56 | 57 | 58 | if __name__=="__main__": 59 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_48/forms_database/templates/base.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | {% block title %} Database Integration - nkblog {% endblock %} 4 | 5 | {% block navbar %} 6 | 7 | 25 | 26 | {% endblock %} -------------------------------------------------------------------------------- /Day_48/forms_database/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% import 'bootstrap/wtf.html' as wtf %} 4 | 5 | {% block content %} 6 | 7 |
    8 | 20 | {% block page_content %} 21 |
    22 | {{ wtf.quick_form(form) }} 23 |
    24 | 25 | {% endblock %} 26 |
    27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /Day_49/Python Flask - Email Integration.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "ad93866c", 6 | "metadata": {}, 7 | "source": [ 8 | "# Learning Python (Day 49)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "255e614c", 14 | "metadata": {}, 15 | "source": [ 16 | "# Python Flask - Email Integration\n", 17 | "\n", 18 | "## Introduction\n", 19 | "- **Purpose**: Email support is essential for web applications to handle tasks like user registration, password resets, notifications, and more.\n", 20 | "- **Flask-Mail**: Flask-Mail is an extension for Flask that simplifies sending emails.\n", 21 | "\n", 22 | "## Installation\n", 23 | "1. **Installing Flask-Mail**:\n", 24 | " - Install the extension using pip:\n", 25 | " ```bash\n", 26 | " pip install Flask-Mail\n", 27 | " ```\n", 28 | "\n", 29 | "## Configuration\n", 30 | "2. **Configuring Flask-Mail**:\n", 31 | " - Configure your Flask app to connect to an email server by setting several configuration variables:\n", 32 | " ```python\n", 33 | " app.config['MAIL_SERVER'] = 'smtp.example.com'\n", 34 | " app.config['MAIL_PORT'] = 587\n", 35 | " app.config['MAIL_USE_TLS'] = True\n", 36 | " app.config['MAIL_USERNAME'] = 'your-username'\n", 37 | " app.config['MAIL_PASSWORD'] = 'your-password'\n", 38 | " ```\n", 39 | "\n", 40 | "## Setting Up Flask-Mail\n", 41 | "3. **Initializing Flask-Mail**:\n", 42 | " - Initialize Flask-Mail in your Flask app:\n", 43 | " ```python\n", 44 | " from flask_mail import Mail\n", 45 | "\n", 46 | " mail = Mail(app)\n", 47 | " ```\n", 48 | "\n", 49 | "## Sending Emails\n", 50 | "4. **Sending Emails**:\n", 51 | " - Create an instance of the `Message` class, set its attributes, and send it using the `send` method:\n", 52 | " ```python\n", 53 | " from flask_mail import Message\n", 54 | "\n", 55 | " msg = Message('Hello', sender='you@example.com', recipients=['someone@example.com'])\n", 56 | " msg.body = 'This is the email body'\n", 57 | " mail.send(msg)\n", 58 | " ```\n", 59 | "\n", 60 | "## Email Templates\n", 61 | "5. **Using Email Templates**:\n", 62 | " - HTML emails can be created using templates for better formatting and structure.\n", 63 | " - Use Flask’s `render_template` function to render HTML email bodies:\n", 64 | " ```python\n", 65 | " from flask import render_template\n", 66 | "\n", 67 | " msg = Message('Hello', sender='you@example.com', recipients=['someone@example.com'])\n", 68 | " msg.body = render_template('email.txt', user=user)\n", 69 | " msg.html = render_template('email.html', user=user)\n", 70 | " mail.send(msg)\n", 71 | " ```\n", 72 | "\n", 73 | "## Asynchronous Email\n", 74 | "6. **Sending Asynchronous Emails**:\n", 75 | " - Sending emails can be time-consuming, so it's often done asynchronously to avoid blocking the main application thread.\n", 76 | " - Use a background thread or task queue (like Celery) to send emails:\n", 77 | " ```python\n", 78 | " from threading import Thread\n", 79 | "\n", 80 | " def send_async_email(app, msg):\n", 81 | " with app.app_context():\n", 82 | " mail.send(msg)\n", 83 | "\n", 84 | " def send_email(subject, sender, recipients, text_body, html_body):\n", 85 | " msg = Message(subject, sender=sender, recipients=recipients)\n", 86 | " msg.body = text_body\n", 87 | " msg.html = html_body\n", 88 | " Thread(target=send_async_email, args=(app, msg)).start()\n", 89 | " ```\n", 90 | "\n", 91 | "## Example Application\n", 92 | "7. **Complete Example**:\n", 93 | " - A complete example of setting up and sending emails in a Flask application:\n", 94 | " ```python\n", 95 | " from flask import Flask, render_template\n", 96 | " from flask_mail import Mail, Message\n", 97 | " from threading import Thread\n", 98 | "\n", 99 | " app = Flask(__name__)\n", 100 | " app.config['MAIL_SERVER'] = 'smtp.example.com'\n", 101 | " app.config['MAIL_PORT'] = 587\n", 102 | " app.config['MAIL_USE_TLS'] = True\n", 103 | " app.config['MAIL_USERNAME'] = 'your-username'\n", 104 | " app.config['MAIL_PASSWORD'] = 'your-password'\n", 105 | "\n", 106 | " mail = Mail(app)\n", 107 | "\n", 108 | " def send_async_email(app, msg):\n", 109 | " with app.app_context():\n", 110 | " mail.send(msg)\n", 111 | "\n", 112 | " def send_email(subject, sender, recipients, text_body, html_body):\n", 113 | " msg = Message(subject, sender=sender, recipients=recipients)\n", 114 | " msg.body = text_body\n", 115 | " msg.html = html_body\n", 116 | " Thread(target=send_async_email, args=(app, msg)).start()\n", 117 | "\n", 118 | " @app.route('/send-email')\n", 119 | " def index():\n", 120 | " user = {'name': 'John Doe', 'email': 'john@example.com'}\n", 121 | " send_email('Hello', sender='you@example.com', recipients=[user['email']],\n", 122 | " text_body=render_template('email.txt', user=user),\n", 123 | " html_body=render_template('email.html', user=user))\n", 124 | " return 'Email sent!'\n", 125 | "\n", 126 | " if __name__ == '__main__':\n", 127 | " app.run(debug=True)\n", 128 | " ```\n", 129 | "\n", 130 | "## Explanation\n", 131 | "- **Configuration**: The email server and authentication details are configured in the Flask app.\n", 132 | "- **Initialization**: Flask-Mail is initialized to set up email handling.\n", 133 | "- **Sending Emails**: Emails are created and sent using the `Message` class and `send` method.\n", 134 | "- **Email Templates**: Emails can include both plain text and HTML content, rendered from templates.\n", 135 | "- **Asynchronous Sending**: Emails are sent in a background thread to prevent blocking the main application thread." 136 | ] 137 | } 138 | ], 139 | "metadata": { 140 | "kernelspec": { 141 | "display_name": "Python 3 (ipykernel)", 142 | "language": "python", 143 | "name": "python3" 144 | }, 145 | "language_info": { 146 | "codemirror_mode": { 147 | "name": "ipython", 148 | "version": 3 149 | }, 150 | "file_extension": ".py", 151 | "mimetype": "text/x-python", 152 | "name": "python", 153 | "nbconvert_exporter": "python", 154 | "pygments_lexer": "ipython3", 155 | "version": "3.11.7" 156 | } 157 | }, 158 | "nbformat": 4, 159 | "nbformat_minor": 5 160 | } 161 | -------------------------------------------------------------------------------- /Day_49/check_mail_server.py: -------------------------------------------------------------------------------- 1 | import smtplib 2 | from email.mime.text import MIMEText 3 | import os 4 | 5 | smtp_server = 'smtp.gmail.com' 6 | smtp_port = 587 7 | smtp_username = os.environ.get('MAIL_USERNAME') 8 | smtp_password = os.environ.get('MAIL_PASSWORD') 9 | 10 | msg = MIMEText('This is a test email') 11 | msg['Subject'] = 'Test Email' 12 | msg['From'] = smtp_username 13 | msg['To'] = '' 14 | 15 | try: 16 | server = smtplib.SMTP(smtp_server, smtp_port) 17 | server.starttls() 18 | server.login(smtp_username, smtp_password) 19 | server.sendmail(smtp_username, ['example@example.com'], msg.as_string()) 20 | server.quit() 21 | print('Mail sent successfully') 22 | except Exception as e: 23 | print(f'Failed to send mail: {e}') 24 | -------------------------------------------------------------------------------- /Day_49/flask_mail_int.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, redirect, url_for,session,flash 2 | from flask_bootstrap import Bootstrap 3 | from flask_sqlalchemy import SQLAlchemy 4 | import os 5 | 6 | app = Flask(__name__) 7 | basedir = os.path.abspath(os.path.dirname(__file__)) 8 | 9 | # Config for web forms 10 | app.config['SECRET_KEY'] = 'ALIEURIFJKZDOIRHQWOIO' 11 | bootstrap = Bootstrap(app) 12 | 13 | # Config for database 14 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+os.path.join(basedir,'data.sqlite') 15 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 16 | db = SQLAlchemy(app) 17 | 18 | class User(db.Model): 19 | __tablename__ = 'users' 20 | id = db.Column(db.Integer,primary_key=True) 21 | username = db.Column(db.String(64),unique=True, index=True) 22 | 23 | def __repr__(self): 24 | return '' % self.username 25 | 26 | with app.app_context(): 27 | db.create_all() 28 | 29 | # forms 30 | from flask_wtf import FlaskForm 31 | from wtforms import StringField, SubmitField 32 | from wtforms.validators import DataRequired 33 | 34 | class NameForm(FlaskForm): 35 | name = StringField('What is your name?',validators=[DataRequired()]) 36 | submit = SubmitField('Submit') 37 | 38 | 39 | # configuring mail 40 | from flask_mail import Mail, Message 41 | 42 | app.config['MAIL_SERVER'] = 'smtp.googlemail.com' 43 | app.config['MAIL_PORT'] = 465 44 | # app.config['MAIL_USE_TLS'] = True 45 | app.config['MAIL_USE_SSL'] = True 46 | app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME') 47 | app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD') 48 | app.config['NKBLOG_MAIL_SENDER'] = 'Nkblog Admin admin@nkblog.com' 49 | app.config['NKBLOG_MAIL_SUB_PREFIX'] = '[Nkblog]' 50 | app.config['NKBLOG_ADMIN'] = os.environ.get('NKBLOG_ADMIN') 51 | mail = Mail(app) 52 | 53 | # sending mail 54 | # def send_mail(to,subject,template,**kwargs): 55 | # msg = Message(app.config['NKBLOG_MAIL_SUB_PREFIX']+subject,sender=app.config['NKBLOG_MAIL_SENDER'], 56 | # recipients=[to]) 57 | # # msg.body = render_template(template+'.txt',**kwargs) 58 | # msg.html = render_template(template+'.html',**kwargs) 59 | # mail.send(msg) 60 | 61 | 62 | # sending Asynchronous Email 63 | 64 | """ 65 | If you sent a few test emails, you likely noticed that the mail.send() function blocks 66 | for a few seconds while the email is sent, making the browser look unresponsive dur‐ 67 | ing that time. To avoid unnecessary delays during request handling, the email send 68 | function can be moved to a background thread. E 69 | """ 70 | from threading import Thread 71 | def send_async_mail(app,msg): 72 | with app.app_context(): 73 | mail.send(msg) 74 | 75 | def send_mail(to,subject,template,**kwargs): 76 | msg = Message(app.config['NKBLOG_MAIL_SUB_PREFIX']+subject,sender=app.config['NKBLOG_MAIL_SENDER'], 77 | recipients=[to]) 78 | msg.body = render_template(template+'.txt',**kwargs) 79 | msg.html = render_template(template+'.html',**kwargs) 80 | thr = Thread(target=send_async_mail,args=[app,msg]) 81 | thr.start() 82 | print(thr) 83 | return thr 84 | # mail.send(msg) 85 | 86 | # Index 87 | @app.route('/',methods=['GET','POST']) 88 | def index(): 89 | form = NameForm() 90 | if form.validate_on_submit(): 91 | user = User.query.filter_by(username=form.name.data).first() 92 | if user is None: 93 | user = User(username=form.name.data) 94 | db.session.add(user) 95 | db.session.commit() 96 | session['known'] = False 97 | if app.config['NKBLOG_ADMIN']: 98 | send_mail(app.config['NKBLOG_ADMIN'],'New User', 'Mail/new_user',user=user) 99 | print("mail sent successfully.") 100 | else: 101 | print("--no admin mail--") 102 | 103 | else: 104 | session['known'] = True 105 | session['name'] = form.name.data 106 | form.name.data = '' 107 | return redirect(url_for('index')) 108 | return render_template('index.html',name=session.get('name'),form=form,known=session.get('known',False)) 109 | 110 | 111 | if __name__=="__main__": 112 | app.run(debug=True) -------------------------------------------------------------------------------- /Day_49/templates/Mail/new_user.html: -------------------------------------------------------------------------------- 1 | 2 |

    New user {{ user['username'] }} added successfully

    3 | 4 | -------------------------------------------------------------------------------- /Day_49/templates/Mail/new_user.txt: -------------------------------------------------------------------------------- 1 | New User added successfully. -------------------------------------------------------------------------------- /Day_49/templates/base.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | {% block title %} Email Integration - nkblog {% endblock %} 4 | 5 | {% block navbar %} 6 | 7 | 25 | 26 | {% endblock %} -------------------------------------------------------------------------------- /Day_49/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% import 'bootstrap/wtf.html' as wtf %} 4 | 5 | {% block content %} 6 | 7 |
    8 | 20 | {% block page_content %} 21 |
    22 | {{ wtf.quick_form(form) }} 23 |
    24 | 25 | {% endblock %} 26 |
    27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /Day_50/Python Flask - Large Application Structure.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "3d7ec46d", 6 | "metadata": {}, 7 | "source": [ 8 | "# Learning Python (Day 50)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "e41b95e6", 14 | "metadata": {}, 15 | "source": [ 16 | "# Python Flask - Large Application Structure\n", 17 | "## Introduction\n", 18 | "- **Purpose**: As applications grow, a more organized and modular structure is essential for maintainability and scalability.\n", 19 | "- **Goal**: Refactor a small Flask application into a larger, more organized structure.\n", 20 | "\n", 21 | "## Application Package\n", 22 | "- **Package Creation**: Instead of a single module, the application is split into a package with multiple modules.\n", 23 | " - Create a directory named `app`.\n", 24 | " - Add an `__init__.py` file to mark it as a package.\n", 25 | "\n", 26 | "## Initializing the Application\n", 27 | "- **Factory Function**: Use a factory function to create the application instance.\n", 28 | " - Allows for configuration and initialization of the app at runtime.\n", 29 | " - Example:\n", 30 | " ```python\n", 31 | " from flask import Flask\n", 32 | "\n", 33 | " def create_app(config_name):\n", 34 | " app = Flask(__name__)\n", 35 | " app.config.from_object(config[config_name])\n", 36 | " return app\n", 37 | " ```\n", 38 | "\n", 39 | "## Application Configuration\n", 40 | "- **Configuration Management**:\n", 41 | " - Separate configuration classes for different environments (development, testing, production).\n", 42 | " - Example configuration setup:\n", 43 | " ```python\n", 44 | " class Config:\n", 45 | " SECRET_KEY = 'your-secret-key'\n", 46 | " SQLALCHEMY_DATABASE_URI = 'sqlite:///app.db'\n", 47 | " \n", 48 | " class DevelopmentConfig(Config):\n", 49 | " DEBUG = True\n", 50 | "\n", 51 | " class TestingConfig(Config):\n", 52 | " TESTING = True\n", 53 | "\n", 54 | " class ProductionConfig(Config):\n", 55 | " pass\n", 56 | "\n", 57 | " config = {\n", 58 | " 'development': DevelopmentConfig,\n", 59 | " 'testing': TestingConfig,\n", 60 | " 'production': ProductionConfig,\n", 61 | " 'default': DevelopmentConfig\n", 62 | " }\n", 63 | " ```\n", 64 | "\n", 65 | "## Blueprints\n", 66 | "- **Purpose**: Blueprints help in organizing the application into smaller, reusable components.\n", 67 | "- **Creating Blueprints**:\n", 68 | " - Create a `main` blueprint for the core functionality.\n", 69 | " - Structure:\n", 70 | " ```\n", 71 | " app/\n", 72 | " main/\n", 73 | " __init__.py\n", 74 | " routes.py\n", 75 | " forms.py\n", 76 | " errors.py\n", 77 | " ```\n", 78 | " - Initialize the blueprint in `app/main/__init__.py`:\n", 79 | " ```python\n", 80 | " from flask import Blueprint\n", 81 | "\n", 82 | " main = Blueprint('main', __name__)\n", 83 | "\n", 84 | " from . import routes, errors\n", 85 | " ```\n", 86 | "\n", 87 | "## Registering Blueprints\n", 88 | "- **Integration**: Register blueprints in the factory function.\n", 89 | " - Ensures that the blueprint routes are recognized by the application.\n", 90 | " - Example:\n", 91 | " ```python\n", 92 | " def create_app(config_name):\n", 93 | " app = Flask(__name__)\n", 94 | " app.config.from_object(config[config_name])\n", 95 | " \n", 96 | " from .main import main as main_blueprint\n", 97 | " app.register_blueprint(main_blueprint)\n", 98 | "\n", 99 | " return app\n", 100 | " ```\n", 101 | "\n", 102 | "#### Error Handling\n", 103 | "- **Custom Error Pages**: Handle errors through blueprints for modular error management.\n", 104 | " - Example in `app/main/errors.py`:\n", 105 | " ```python\n", 106 | " from flask import render_template\n", 107 | " from . import main\n", 108 | "\n", 109 | " @main.app_errorhandler(404)\n", 110 | " def page_not_found(e):\n", 111 | " return render_template('404.html'), 404\n", 112 | "\n", 113 | " @main.app_errorhandler(500)\n", 114 | " def internal_server_error(e):\n", 115 | " return render_template('500.html'), 500\n", 116 | " ```\n", 117 | "\n", 118 | "## Extensions\n", 119 | "- **Initialization**: Initialize extensions in the factory function to ensure they are tied to the application instance.\n", 120 | " - Example:\n", 121 | " ```python\n", 122 | " from flask_sqlalchemy import SQLAlchemy\n", 123 | "\n", 124 | " db = SQLAlchemy()\n", 125 | "\n", 126 | " def create_app(config_name):\n", 127 | " app = Flask(__name__)\n", 128 | " app.config.from_object(config[config_name])\n", 129 | "\n", 130 | " db.init_app(app)\n", 131 | " \n", 132 | " from .main import main as main_blueprint\n", 133 | " app.register_blueprint(main_blueprint)\n", 134 | "\n", 135 | " return app\n", 136 | " ```\n", 137 | "\n", 138 | "## Larger Application Structure\n", 139 | "- **Comprehensive Structure**:\n", 140 | " ```\n", 141 | " myproject/\n", 142 | " app/\n", 143 | " __init__.py\n", 144 | " main/\n", 145 | " __init__.py\n", 146 | " routes.py\n", 147 | " forms.py\n", 148 | " errors.py\n", 149 | " templates/\n", 150 | " 404.html\n", 151 | " 500.html\n", 152 | " static/\n", 153 | " models.py\n", 154 | " email.py\n", 155 | " migrations/\n", 156 | " tests/\n", 157 | " venv/\n", 158 | " config.py\n", 159 | " requirements.txt\n", 160 | " manage.py\n", 161 | " ```\n", 162 | "\n", 163 | "## Explanation\n", 164 | "- **Modular Design**: Breaking down the application into blueprints and separate modules for routes, forms, and errors improves maintainability.\n", 165 | "- **Factory Function**: Allows for flexible application configuration and extension initialization.\n", 166 | "- **Configuration Classes**: Different settings for development, testing, and production environments.\n", 167 | "- **Blueprint Registration**: Ensures that all components are integrated and recognized by the application." 168 | ] 169 | } 170 | ], 171 | "metadata": { 172 | "kernelspec": { 173 | "display_name": "Python 3 (ipykernel)", 174 | "language": "python", 175 | "name": "python3" 176 | }, 177 | "language_info": { 178 | "codemirror_mode": { 179 | "name": "ipython", 180 | "version": 3 181 | }, 182 | "file_extension": ".py", 183 | "mimetype": "text/x-python", 184 | "name": "python", 185 | "nbconvert_exporter": "python", 186 | "pygments_lexer": "ipython3", 187 | "version": "3.11.7" 188 | } 189 | }, 190 | "nbformat": 4, 191 | "nbformat_minor": 5 192 | } 193 | -------------------------------------------------------------------------------- /Day_50/nkblog/app/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | from flask_bootstrap import Bootstrap 3 | from flask_moment import Moment 4 | from flask_mail import Mail 5 | from flask_sqlalchemy import SQLAlchemy 6 | from config import config 7 | 8 | bootstrap = Bootstrap() 9 | moment = Moment() 10 | mail = Mail() 11 | db = SQLAlchemy() 12 | 13 | def create_app(config_name): 14 | app = Flask(__name__) 15 | app.config.from_object(config[config_name]) 16 | config[config_name].init_app(app) 17 | 18 | bootstrap.init_app(app) 19 | mail.init_app(app) 20 | moment.init_app(app) 21 | db.init_app(app) 22 | 23 | from .main import main as main_blueprint 24 | app.register_blueprint(main_blueprint) 25 | 26 | return app -------------------------------------------------------------------------------- /Day_50/nkblog/app/email.py: -------------------------------------------------------------------------------- 1 | from flask_mail import Message 2 | from flask import render_template 3 | from flask import current_app 4 | from app import mail 5 | 6 | # sending Asynchronous Email 7 | 8 | """ 9 | If you sent a few test emails, you likely noticed that the mail.send() function blocks 10 | for a few seconds while the email is sent, making the browser look unresponsive dur‐ 11 | ing that time. To avoid unnecessary delays during request handling, the email send 12 | function can be moved to a background thread. E 13 | """ 14 | from threading import Thread 15 | def send_async_mail(app,msg): 16 | 17 | with app.app_context(): 18 | mail.send(msg) 19 | 20 | def send_mail(to,subject,template,**kwargs): 21 | app = current_app._get_current_object() 22 | msg = Message(app.config['NKBLOG_MAIL_SUBJECT_PREFIX']+subject,sender=app.config['NKBLOG_MAIL_SENDER'], 23 | recipients=[to]) 24 | msg.body = render_template(template+'.txt',**kwargs) 25 | msg.html = render_template(template+'.html',**kwargs) 26 | thr = Thread(target=send_async_mail,args=[app,msg]) 27 | thr.start() 28 | print(thr) 29 | return thr 30 | # mail.send(msg) -------------------------------------------------------------------------------- /Day_50/nkblog/app/main/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | main = Blueprint('main',__name__) 4 | 5 | from . import views, errors 6 | 7 | 8 | -------------------------------------------------------------------------------- /Day_50/nkblog/app/main/errors.py: -------------------------------------------------------------------------------- 1 | from flask import render_template 2 | from . import main 3 | 4 | @main.app_errorhandler(404) 5 | def page_not_found(e): 6 | return render_template('404.html'), 404 7 | 8 | @main.app_errorhandler(500) 9 | def internal_server_error(e): 10 | return render_template('500.html'), 500 11 | 12 | -------------------------------------------------------------------------------- /Day_50/nkblog/app/main/forms.py: -------------------------------------------------------------------------------- 1 | # forms 2 | from flask_wtf import FlaskForm 3 | from wtforms import StringField, SubmitField 4 | from wtforms.validators import DataRequired 5 | 6 | class NameForm(FlaskForm): 7 | name = StringField('What is your name?',validators=[DataRequired()]) 8 | submit = SubmitField('Submit') 9 | -------------------------------------------------------------------------------- /Day_50/nkblog/app/main/views.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from flask import render_template, session, redirect, url_for 3 | from . import main 4 | from .. import db 5 | from .forms import NameForm 6 | from ..models import User 7 | from ..email import send_mail 8 | from flask import current_app as app 9 | 10 | @main.route('/',methods=['GET','POST']) 11 | def index(): 12 | form = NameForm() 13 | if form.validate_on_submit(): 14 | user = User.query.filter_by(username=form.name.data).first() 15 | if user is None: 16 | user = User(username=form.name.data) 17 | db.session.add(user) 18 | db.session.commit() 19 | session['known'] = False 20 | if app.config['NKBLOG_ADMIN']: 21 | send_mail(app.config['NKBLOG_ADMIN'],'New User', 'Mail/new_user',user=user) 22 | print("mail sent successfully.") 23 | else: 24 | print("--no admin mail--") 25 | 26 | else: 27 | session['known'] = True 28 | session['name'] = form.name.data 29 | form.name.data = '' 30 | 31 | return redirect(url_for('.index')) 32 | 33 | return render_template('index.html',form=form,name=session.get('name'), 34 | known=session.get('known',False),current_time=datetime.utcnow()) -------------------------------------------------------------------------------- /Day_50/nkblog/app/models.py: -------------------------------------------------------------------------------- 1 | from app import db 2 | class User(db.Model): 3 | __tablename__ = 'users' 4 | id = db.Column(db.Integer,primary_key=True) 5 | username = db.Column(db.String(64),unique=True, index=True) 6 | 7 | def __repr__(self): 8 | return '' % self.username 9 | -------------------------------------------------------------------------------- /Day_50/nkblog/app/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | {% block title %} Error - nkblog {% endblock %} 4 | 5 | {% block navbar %} 6 | 7 | 25 | 26 | {% endblock %} 27 | 28 | {% block content %} 29 |
    30 | {% block page_content %} 31 | 34 | {% endblock %} 35 |
    36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /Day_50/nkblog/app/templates/500.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | {% block title %} Error - nkblog {% endblock %} 4 | 5 | {% block navbar %} 6 | 7 | 25 | 26 | {% endblock %} 27 | 28 | {% block content %} 29 |
    30 | {% block page_content %} 31 | 34 | {% endblock %} 35 |
    36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /Day_50/nkblog/app/templates/Mail/new_user.html: -------------------------------------------------------------------------------- 1 | 2 |

    New user {{ user['username'] }} added successfully

    3 | 4 | -------------------------------------------------------------------------------- /Day_50/nkblog/app/templates/Mail/new_user.txt: -------------------------------------------------------------------------------- 1 | New User added successfully. -------------------------------------------------------------------------------- /Day_50/nkblog/app/templates/base.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap/base.html' %} 2 | 3 | {% block title %} Large application - nkblog {% endblock %} 4 | 5 | {% block navbar %} 6 | 7 | 25 | 26 | {% endblock %} -------------------------------------------------------------------------------- /Day_50/nkblog/app/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% import 'bootstrap/wtf.html' as wtf %} 4 | 5 | {% block content %} 6 | 7 |
    8 | 20 | {% block page_content %} 21 |
    22 | {{ wtf.quick_form(form) }} 23 |
    24 | 25 | {% endblock %} 26 |
    27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /Day_50/nkblog/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | basedir = os.path.abspath(os.path.dirname(__file__)) 3 | 4 | class Config: 5 | SECRET_KEY = os.environ.get('SECRET_KEY','jsdfioisjthslkamcnfjrisl') 6 | MAIL_SERVER = os.environ.get('MAIL_SERVER','smtp.googlemail.com') 7 | MAIL_PORT = int(os.environ.get('MAIL_PORT','587')) 8 | MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS','true').lower() in ['true','on','1','True','TRUE'] 9 | MAIL_USERNAME = os.environ.get('MAIL_USERNAME') 10 | MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD') 11 | 12 | NKBLOG_MAIL_SUBJECT_PREFIX = '[Nkblog]' 13 | NKBLOG_MAIL_SENDER = 'Nkblog Admin nk@nkblog.com' 14 | NKBLOG_ADMIN = os.environ.get('NKBLOG_ADMIN') 15 | SQLALCHEMY_TRACK_MODIFICATIONS = False 16 | # DEBUG = os.environ.get('DEBUG','1').lower() in ['true','on','1','True','TRUE'] 17 | 18 | @staticmethod 19 | def init_app(app): 20 | pass 21 | 22 | 23 | class DevelopmentConfig(Config): 24 | DEBUG = True 25 | SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or 'sqlite:///'+os.path.join(basedir,'data-dev.sqlite') 26 | 27 | class TestingConfig(Config): 28 | TESTING = True 29 | SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or 'sqlite://' 30 | 31 | class ProductionConfig(Config): 32 | SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///'+os.path.join(basedir,'data.sqlite') 33 | 34 | 35 | config = { 36 | 37 | 'development' : DevelopmentConfig, 38 | 'testing' : TestingConfig, 39 | 'production' : ProductionConfig, 40 | 'default' : DevelopmentConfig 41 | } -------------------------------------------------------------------------------- /Day_50/nkblog/nkblog.py: -------------------------------------------------------------------------------- 1 | import os 2 | from app import create_app, db 3 | from app.models import User 4 | from flask_migrate import Migrate 5 | app = create_app(os.getenv('FLASK_CONFIG') or 'default') 6 | migrate = Migrate(app,db) 7 | 8 | with app.app_context(): 9 | db.create_all() 10 | 11 | @app.shell_context_processor 12 | def make_shell_context(): 13 | return dict(db=db, User=User) -------------------------------------------------------------------------------- /Day_52/Python Flask - User Roles.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "2aa54b95", 6 | "metadata": {}, 7 | "source": [ 8 | "# Learning Python (Day 52)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "565b2045", 14 | "metadata": {}, 15 | "source": [ 16 | "# Python Flask - User Roles\n", 17 | "\n", 18 | "## **1. User Roles and Permissions**\n", 19 | "\n", 20 | "**User Roles:** Roles represent different levels of access and permissions within the application. Common roles include:\n", 21 | "\n", 22 | "- **Admin:** Full access to all functionalities.\n", 23 | "\n", 24 | "- **Moderator:** Limited administrative capabilities.\n", 25 | "\n", 26 | "- **User:** Basic access, typically for regular users.\n", 27 | "\n", 28 | "**Permissions:** These define what actions each role can perform. For example:\n", 29 | "\n", 30 | "- **READ:** Ability to view content.\n", 31 | "\n", 32 | "- **WRITE:** Ability to create or modify content.\n", 33 | "\n", 34 | "- **ADMIN:** Ability to manage users and settings.\n", 35 | "\n", 36 | "\n", 37 | "## **2. Database Models for Roles and Permissions**\n", 38 | "\n", 39 | "To manage roles and permissions, additional database models are necessary:\n", 40 | "\n", 41 | "**Role Model:**\n", 42 | "```python\n", 43 | "class Role(db.Model):\n", 44 | " __tablename__ = 'roles'\n", 45 | " id = db.Column(db.Integer, primary_key=True)\n", 46 | " name = db.Column(db.String(64), unique=True)\n", 47 | " default = db.Column(db.Boolean, default=False, index=True)\n", 48 | " permissions = db.Column(db.Integer)\n", 49 | " users = db.relationship('User', backref='role', lazy='dynamic')\n", 50 | "\n", 51 | " def __repr__(self):\n", 52 | " return '' % self.name\n", 53 | "```\n", 54 | "\n", 55 | "**User Model:**\n", 56 | "Modify the `User` model to include a reference to the role.\n", 57 | "```python\n", 58 | "class User(db.Model):\n", 59 | " __tablename__ = 'users'\n", 60 | " id = db.Column(db.Integer, primary_key=True)\n", 61 | " username = db.Column(db.String(64), unique=True, index=True)\n", 62 | " role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))\n", 63 | "\n", 64 | " def __repr__(self):\n", 65 | " return '' % self.username\n", 66 | "```\n", 67 | "\n", 68 | "## **3. Assigning Roles to Users**\n", 69 | "\n", 70 | "When creating a new user, assign a default role. This can be done by extending the `User` model with additional methods.\n", 71 | "\n", 72 | "**Assign Default Role:**\n", 73 | "```python\n", 74 | "class User(db.Model):\n", 75 | " # existing fields...\n", 76 | " role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))\n", 77 | "\n", 78 | " def __init__(self, **kwargs):\n", 79 | " super(User, self).__init__(**kwargs)\n", 80 | " if self.role is None:\n", 81 | " if self.email == current_app.config['FLASKY_ADMIN']:\n", 82 | " self.role = Role.query.filter_by(permissions=0xff).first()\n", 83 | " if self.role is None:\n", 84 | " self.role = Role.query.filter_by(default=True).first()\n", 85 | "```\n", 86 | "\n", 87 | "## **4. Managing Role Permissions**\n", 88 | "\n", 89 | "Define permissions using bitmasks, which allow combining multiple permissions using bitwise operations.\n", 90 | "\n", 91 | "**Permission Constants:**\n", 92 | "```python\n", 93 | "class Permission:\n", 94 | " FOLLOW = 0x01\n", 95 | " COMMENT = 0x02\n", 96 | " WRITE_ARTICLES = 0x04\n", 97 | " MODERATE_COMMENTS = 0x08\n", 98 | " ADMINISTER = 0x80\n", 99 | "```\n", 100 | "\n", 101 | "Assign permissions to roles using these constants:\n", 102 | "```python\n", 103 | "class Role(db.Model):\n", 104 | " # existing fields...\n", 105 | " permissions = db.Column(db.Integer)\n", 106 | "\n", 107 | " def add_permission(self, perm):\n", 108 | " if not self.has_permission(perm):\n", 109 | " self.permissions += perm\n", 110 | "\n", 111 | " def remove_permission(self, perm):\n", 112 | " if self.has_permission(perm):\n", 113 | " self.permissions -= perm\n", 114 | "\n", 115 | " def reset_permissions(self):\n", 116 | " self.permissions = 0\n", 117 | "\n", 118 | " def has_permission(self, perm):\n", 119 | " return self.permissions & perm == perm\n", 120 | "```\n", 121 | "\n", 122 | "## **5. Role-Based Access Control (RBAC)**\n", 123 | "\n", 124 | "Implement role-based access control to restrict certain views or actions to users with specific roles.\n", 125 | "\n", 126 | "**Decorator for Permissions:**\n", 127 | "```python\n", 128 | "from functools import wraps\n", 129 | "from flask import abort\n", 130 | "from flask_login import current_user\n", 131 | "\n", 132 | "def permission_required(permission):\n", 133 | " def decorator(f):\n", 134 | " @wraps(f)\n", 135 | " def decorated_function(*args, **kwargs):\n", 136 | " if not current_user.can(permission):\n", 137 | " abort(403)\n", 138 | " return f(*args, **kwargs)\n", 139 | " return decorated_function\n", 140 | " return decorator\n", 141 | "```\n", 142 | "\n", 143 | "**Using the Decorator:**\n", 144 | "```python\n", 145 | "@app.route('/admin')\n", 146 | "@login_required\n", 147 | "@permission_required(Permission.ADMINISTER)\n", 148 | "def for_admins_only():\n", 149 | " return \"For administrators!\"\n", 150 | "```\n", 151 | "\n", 152 | "## **6. Extending the User Model**\n", 153 | "\n", 154 | "Extend the `User` model to include methods that check permissions and roles.\n", 155 | "\n", 156 | "**Check Permissions:**\n", 157 | "```python\n", 158 | "class User(UserMixin, db.Model):\n", 159 | " # existing fields...\n", 160 | " def can(self, permissions):\n", 161 | " return self.role is not None and \\\n", 162 | " (self.role.permissions & permissions) == permissions\n", 163 | "\n", 164 | " def is_administrator(self):\n", 165 | " return self.can(Permission.ADMINISTER)\n", 166 | "```\n", 167 | "\n", 168 | "## **Summary**\n", 169 | "\n", 170 | "- **User Roles:** Define and manage different user roles in the application.\n", 171 | "- **Permissions:** Use bitmasks to manage permissions efficiently.\n", 172 | "- **Role Assignment:** Automatically assign roles to new users.\n", 173 | "- **RBAC:** Implement role-based access control using decorators.\n", 174 | "- **Model Extensions:** Extend user and role models to handle permissions and roles.\n", 175 | "\n", 176 | "By implementing these concepts, you can create a secure and well-structured application with clear role-based access controls, ensuring that users have appropriate permissions based on their roles." 177 | ] 178 | } 179 | ], 180 | "metadata": { 181 | "kernelspec": { 182 | "display_name": "Python 3 (ipykernel)", 183 | "language": "python", 184 | "name": "python3" 185 | }, 186 | "language_info": { 187 | "codemirror_mode": { 188 | "name": "ipython", 189 | "version": 3 190 | }, 191 | "file_extension": ".py", 192 | "mimetype": "text/x-python", 193 | "name": "python", 194 | "nbconvert_exporter": "python", 195 | "pygments_lexer": "ipython3", 196 | "version": "3.11.7" 197 | } 198 | }, 199 | "nbformat": 4, 200 | "nbformat_minor": 5 201 | } 202 | -------------------------------------------------------------------------------- /Day_53/Python Flask - User Profiles.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "1e2de994-365f-4a28-82b1-8d738cb86568", 6 | "metadata": {}, 7 | "source": [ 8 | "# Learning Python (Day 53)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "750eebd2-0f43-47ef-b7e1-158bc37e2f2b", 14 | "metadata": {}, 15 | "source": [ 16 | "# Python Flask: User Profiles\n", 17 | "\n", 18 | "In this, the focus is on creating user profiles within a Flask application. This involves extending the `User` model to include additional profile information, setting up profile pages, and handling profile updates. Here’s a detailed breakdown:\n", 19 | "\n", 20 | "## Extending the User Model\n", 21 | "\n", 22 | "The `User` model is extended to include more fields related to the user's profile. This could include fields like name, location, about_me, and member_since.\n", 23 | "\n", 24 | "```python\n", 25 | "class User(db.Model):\n", 26 | " __tablename__ = 'users'\n", 27 | " id = db.Column(db.Integer, primary_key=True)\n", 28 | " username = db.Column(db.String(64), unique=True, index=True)\n", 29 | " email = db.Column(db.String(64), unique=True, index=True)\n", 30 | " password_hash = db.Column(db.String(128))\n", 31 | " name = db.Column(db.String(64))\n", 32 | " location = db.Column(db.String(64))\n", 33 | " about_me = db.Column(db.Text())\n", 34 | " member_since = db.Column(db.DateTime(), default=datetime.utcnow)\n", 35 | " last_seen = db.Column(db.DateTime(), default=datetime.utcnow)\n", 36 | "\n", 37 | " def __repr__(self):\n", 38 | " return ''.format(self.username)\n", 39 | "```\n", 40 | "\n", 41 | "## User Loader\n", 42 | "\n", 43 | "To load a user from the database by ID, the `user_loader` callback is used. This allows Flask-Login to retrieve the user details.\n", 44 | "\n", 45 | "```python\n", 46 | "@login.user_loader\n", 47 | "def load_user(user_id):\n", 48 | " return User.query.get(int(user_id))\n", 49 | "```\n", 50 | "\n", 51 | "## Profile Page\n", 52 | "\n", 53 | "The profile page displays the user’s information. A route is created to handle requests for a user’s profile.\n", 54 | "\n", 55 | "```python\n", 56 | "@main.route('/user/')\n", 57 | "def user(username):\n", 58 | " user = User.query.filter_by(username=username).first_or_404()\n", 59 | " return render_template('user.html', user=user)\n", 60 | "```\n", 61 | "\n", 62 | "## Last Seen\n", 63 | "\n", 64 | "To keep track of the last time a user was seen, a timestamp is updated every time a user makes a request.\n", 65 | "\n", 66 | "```python\n", 67 | "@app.before_request\n", 68 | "def before_request():\n", 69 | " if current_user.is_authenticated:\n", 70 | " current_user.ping()\n", 71 | "```\n", 72 | "\n", 73 | "In the `User` model, the `ping` method is defined to update the last_seen field.\n", 74 | "\n", 75 | "```python\n", 76 | "class User(db.Model):\n", 77 | " # ... other fields and methods ...\n", 78 | " \n", 79 | " def ping(self):\n", 80 | " self.last_seen = datetime.utcnow()\n", 81 | " db.session.add(self)\n", 82 | "```\n", 83 | "\n", 84 | "## Profile Edit Form\n", 85 | "\n", 86 | "A form is created to allow users to edit their profiles. Flask-WTF is used to handle form creation and validation.\n", 87 | "\n", 88 | "```python\n", 89 | "class EditProfileForm(FlaskForm):\n", 90 | " name = StringField('Real name', validators=[Length(0, 64)])\n", 91 | " location = StringField('Location', validators=[Length(0, 64)])\n", 92 | " about_me = TextAreaField('About me')\n", 93 | " submit = SubmitField('Submit')\n", 94 | "```\n", 95 | "\n", 96 | "## Edit Profile Route\n", 97 | "\n", 98 | "A route and corresponding view function are created to handle profile edits.\n", 99 | "\n", 100 | "```python\n", 101 | "@main.route('/edit-profile', methods=['GET', 'POST'])\n", 102 | "@login_required\n", 103 | "def edit_profile():\n", 104 | " form = EditProfileForm()\n", 105 | " if form.validate_on_submit():\n", 106 | " current_user.name = form.name.data\n", 107 | " current_user.location = form.location.data\n", 108 | " current_user.about_me = form.about_me.data\n", 109 | " db.session.add(current_user)\n", 110 | " flash('Your profile has been updated.')\n", 111 | " return redirect(url_for('.user', username=current_user.username))\n", 112 | " form.name.data = current_user.name\n", 113 | " form.location.data = current_user.location\n", 114 | " form.about_me.data = current_user.about_me\n", 115 | " return render_template('edit_profile.html', form=form)\n", 116 | "```\n", 117 | "\n", 118 | "## Templates\n", 119 | "\n", 120 | "Templates for displaying and editing the user profile are created. The `user.html` template shows the user’s profile, while the `edit_profile.html` template provides the form for editing the profile.\n", 121 | "\n", 122 | "```html\n", 123 | "\n", 124 | "{% extends \"base.html\" %}\n", 125 | "{% block content %}\n", 126 | "

    {{ user.username }}

    \n", 127 | "

    {{ user.name }}

    \n", 128 | "

    {{ user.location }}

    \n", 129 | "

    {{ user.about_me }}

    \n", 130 | "

    Member since: {{ user.member_since }}

    \n", 131 | "

    Last seen: {{ user.last_seen }}

    \n", 132 | "{% endblock %}\n", 133 | "\n", 134 | "\n", 135 | "{% extends \"base.html\" %}\n", 136 | "{% block content %}\n", 137 | "

    Edit Profile

    \n", 138 | "
    \n", 139 | " {{ form.hidden_tag() }}\n", 140 | " {{ form.name.label }} {{ form.name(size=32) }}
    \n", 141 | " {{ form.location.label }} {{ form.location(size=32) }}
    \n", 142 | " {{ form.about_me.label }} {{ form.about_me(rows=4) }}
    \n", 143 | " {{ form.submit() }}\n", 144 | "
    \n", 145 | "{% endblock %}\n", 146 | "```\n", 147 | "\n", 148 | "## Summary\n", 149 | "\n", 150 | "This covers how to enhance user profiles in a Flask application by extending the user model, creating profile pages, and enabling profile edits. By following these steps, users can have a richer and more personalized experience within the application. \n", 151 | "\n", 152 | "The focus on extending the user model, updating profile data, and ensuring the information is displayed and editable through user-friendly forms and templates is crucial for developing interactive and engaging web applications." 153 | ] 154 | } 155 | ], 156 | "metadata": { 157 | "kernelspec": { 158 | "display_name": "Python 3 (ipykernel)", 159 | "language": "python", 160 | "name": "python3" 161 | }, 162 | "language_info": { 163 | "codemirror_mode": { 164 | "name": "ipython", 165 | "version": 3 166 | }, 167 | "file_extension": ".py", 168 | "mimetype": "text/x-python", 169 | "name": "python", 170 | "nbconvert_exporter": "python", 171 | "pygments_lexer": "ipython3", 172 | "version": "3.10.3" 173 | } 174 | }, 175 | "nbformat": 4, 176 | "nbformat_minor": 5 177 | } 178 | -------------------------------------------------------------------------------- /Day_64-65/Python - API and REST APIs.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "ff7a42cc-0816-4e9d-ab93-658d3ce18e8a", 6 | "metadata": {}, 7 | "source": [ 8 | "# Python (Day 64 and Day 65)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "bd7f49a8-a460-4621-80dc-bb37b88865be", 14 | "metadata": {}, 15 | "source": [ 16 | "# API and REST APIs\n", 17 | "## Introduction to APIs\n", 18 | "\n", 19 | "**API (Application Programming Interface)** is a set of rules and protocols enabling different software applications to communicate. It acts as an intermediary for applications to interact and exchange data seamlessly.\n", 20 | "\n", 21 | "### Key Concepts of APIs\n", 22 | "\n", 23 | "1. **Endpoints**: Specific URLs provided by an API for requests to retrieve or send data.\n", 24 | "2. **Requests and Responses**: \n", 25 | " - **Request**: An action performed by asking the API (e.g., retrieving or sending data).\n", 26 | " - **Response**: The outcome or data sent back by the API after processing the request.\n", 27 | "3. **Methods/Verbs**:\n", 28 | " - **GET**: Retrieve data.\n", 29 | " - **POST**: Send data to create a resource.\n", 30 | " - **PUT**: Update an existing resource.\n", 31 | " - **DELETE**: Remove a resource.\n", 32 | "4. **Headers**: Metadata sent with requests/responses (e.g., authentication tokens, content type).\n", 33 | "5. **Status Codes**: Numerical codes indicating the outcome of a request (e.g., 200 for success, 404 for not found, 500 for server error).\n", 34 | "\n", 35 | "## What is a REST API?\n", 36 | "\n", 37 | "**REST (Representational State Transfer)** is an architectural style for designing networked applications, focusing on scalable, reliable, and efficient web services.\n", 38 | "\n", 39 | "### Principles of REST APIs\n", 40 | "\n", 41 | "1. **Stateless**: Each request must contain all necessary information; the server does not store client context.\n", 42 | "2. **Client-Server Architecture**: Clients and servers interact through requests and responses independently.\n", 43 | "3. **Uniform Interface**: Standardized interaction methods (typically using HTTP).\n", 44 | "4. **Resource-Based**: Focus on resources identified by URLs (e.g., users, posts).\n", 45 | "5. **Representation**: Resources represented in formats like JSON or XML.\n", 46 | "6. **Stateless Communication**: Each request from client to server must contain all the information needed to process it.\n", 47 | "\n", 48 | "### Common Use Cases for REST APIs\n", 49 | "\n", 50 | "- **Web Services**: Allow web applications to share data.\n", 51 | "- **Mobile Applications**: Enable mobile apps to communicate with servers.\n", 52 | "- **Microservices**: Facilitate communication between different services in a microservices architecture.\n", 53 | "\n", 54 | "### Example of a REST API Request and Response\n", 55 | "\n", 56 | "**Request**:\n", 57 | "- URL: `https://api.example.com/users`\n", 58 | "- Method: `GET`\n", 59 | "- Headers: `Authorization: Bearer `\n", 60 | "\n", 61 | "**Response**:\n", 62 | "- Status Code: `200 OK`\n", 63 | "- Body: \n", 64 | " ```json\n", 65 | " [\n", 66 | " {\n", 67 | " \"id\": 1,\n", 68 | " \"name\": \"NSK\",\n", 69 | " \"email\": \"nsk@example.com\"\n", 70 | " },\n", 71 | " {\n", 72 | " \"id\": 2,\n", 73 | " \"name\": \"nk\",\n", 74 | " \"email\": \"nk@example.com\"\n", 75 | " }\n", 76 | " ]\n", 77 | " ```\n", 78 | "\n", 79 | "### Advantages of REST APIs\n", 80 | "\n", 81 | "- **Scalability**: Easy to scale by adding more endpoints or services.\n", 82 | "- **Flexibility**: Can handle multiple types of calls and return various data formats.\n", 83 | "- **Interoperability**: Allows different systems to communicate, regardless of their underlying technology.\n", 84 | "\n", 85 | "- \n", 86 | "\n", 87 | "## Dissertation Overview: \"Architectural Styles and the Design of Network-based Software Architectures\" by Roy Thomas Fielding\n", 88 | "\n", 89 | "**Network-based Software**: Importance of software architecture in network-based applications.\n", 90 | "\n", 91 | "**Architectural Styles**: Fundamental patterns for organizing systems, including client-server and layered systems, evaluated based on performance, scalability, simplicity, and modifiability.\n", 92 | "\n", 93 | "### REST (Representational State Transfer) in Detail\n", 94 | "\n", 95 | "**Principles**:\n", 96 | "- **Resource Identification**: Use URLs to uniquely identify resources.\n", 97 | "- **Stateless Interactions**: Each request must contain all necessary information.\n", 98 | "- **Representations**: Resources can have multiple representations (e.g., XML, JSON).\n", 99 | "- **Self-descriptive Messages**: Each message includes enough information to describe how to process it.\n", 100 | "- **Hypermedia as the Engine of Application State (HATEOAS)**: Clients interact with the application entirely through hypermedia provided dynamically by servers.\n", 101 | "\n", 102 | "**Evaluation**:\n", 103 | "- **Advantages**: Scalability, simplicity, performance, and modifiability.\n", 104 | "- **Challenges**: Security, complexity in designing proper resource models, and adherence to constraints.\n", 105 | "\n", 106 | "### Practical Application and Impact\n", 107 | "\n", 108 | "**HTTP and REST**: HTTP is a concrete implementation of REST. Many modern web services use REST principles for design and operation, making REST crucial for scalable and reliable web services.\n", 109 | "\n", 110 | "**Future of REST**: Continues to evolve with new technologies and practices, maintaining relevance in network-based application architectures.\n", 111 | "\n", 112 | "## Summary\n", 113 | "\n", 114 | "APIs, particularly REST APIs, are essential in modern software development. Understanding APIs and REST is crucial for building scalable, reliable, and efficient applications, allowing seamless communication and data exchange between different systems." 115 | ] 116 | } 117 | ], 118 | "metadata": { 119 | "kernelspec": { 120 | "display_name": "Python 3 (ipykernel)", 121 | "language": "python", 122 | "name": "python3" 123 | }, 124 | "language_info": { 125 | "codemirror_mode": { 126 | "name": "ipython", 127 | "version": 3 128 | }, 129 | "file_extension": ".py", 130 | "mimetype": "text/x-python", 131 | "name": "python", 132 | "nbconvert_exporter": "python", 133 | "pygments_lexer": "ipython3", 134 | "version": "3.10.3" 135 | } 136 | }, 137 | "nbformat": 4, 138 | "nbformat_minor": 5 139 | } 140 | -------------------------------------------------------------------------------- /Day_7.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Day 7\n", 8 | "\n", 9 | "## Practicing Python from Basics" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "### Exception Handling" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "vscode": { 23 | "languageId": "plaintext" 24 | } 25 | }, 26 | "source": [ 27 | "**Handling Exceptions with try-except Blocks:**\n", 28 | "\n", 29 | "1. Write a Python program that prompts the user to enter two numbers, divides the first number by the second number, and handles the `ZeroDivisionError` exception.\n" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 4, 35 | "metadata": {}, 36 | "outputs": [ 37 | { 38 | "name": "stdout", 39 | "output_type": "stream", 40 | "text": [ 41 | "Number can't be divide by zero.\n" 42 | ] 43 | } 44 | ], 45 | "source": [ 46 | "num1 = eval(input(\"Enter number 1 :: \"))\n", 47 | "num2 = eval(input(\"Enter number 2 :: \"))\n", 48 | "\n", 49 | "try:\n", 50 | " div = num1/num2\n", 51 | " print(div)\n", 52 | "except ZeroDivisionError:\n", 53 | " print(\"Number can't be divide by zero.\")" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "2. Write a Python program that asks the user to enter a number and calculates the square root of that number using the `math.sqrt()` function. Handle the `ValueError` exception that might occur if the user enters a negative number.\n" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 7, 66 | "metadata": {}, 67 | "outputs": [ 68 | { 69 | "name": "stdout", 70 | "output_type": "stream", 71 | "text": [ 72 | "Please enter positive Number!.\n" 73 | ] 74 | } 75 | ], 76 | "source": [ 77 | "import math\n", 78 | "num = eval(input(\"Enter a number :: \"))\n", 79 | "\n", 80 | "try:\n", 81 | " sqrt = math.sqrt(num)\n", 82 | " print(f\"Square root of given number :: {sqrt}\")\n", 83 | "\n", 84 | "except ValueError:\n", 85 | " print(\"Please enter positive Number!.\")" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "3. Write a Python program that reads a list of numbers from a file (whose name is provided by the user), calculates the average, and handles any exceptions that might occur during the file reading or calculation process." 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 21, 98 | "metadata": {}, 99 | "outputs": [ 100 | { 101 | "name": "stdout", 102 | "output_type": "stream", 103 | "text": [ 104 | "Average :: 15.846153846153847\n" 105 | ] 106 | } 107 | ], 108 | "source": [ 109 | "def calculate_avg(numbers):\n", 110 | " try:\n", 111 | " avg = sum(numbers) / len(numbers)\n", 112 | " return avg\n", 113 | " except ZeroDivisionError:\n", 114 | " return \"Can not calculate average of an empty list.\"\n", 115 | " except Exception as e:\n", 116 | " return f\"Error : {e}\"\n", 117 | " \n", 118 | "if __name__ == \"__main__\":\n", 119 | " file_name = input(\"Enter a file name containing numbers :: \")\n", 120 | "\n", 121 | " try:\n", 122 | " with open(file_name,'r') as num_file:\n", 123 | " numbers = [eval(line.strip()) for line in num_file.readlines()]\n", 124 | " average = calculate_avg(numbers)\n", 125 | " print(f\"Average :: {average}\")\n", 126 | "\n", 127 | " except FileNotFoundError:\n", 128 | " print(f\"Error : file {file_name} not found\")\n", 129 | " \n", 130 | " except ValueError:\n", 131 | " print(f\"File contains invalid Data. Please provide file name containing numbers.\")\n", 132 | " \n", 133 | " except Exception as e:\n", 134 | " print(f\"Unexpected error occured :: {e}\")" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "**Handling Specific Exceptions:**\n", 142 | "\n", 143 | "4. Write a Python program that prompts the user to enter a file name and then attempts to open the file for reading. Handle the `FileNotFoundError` exception with a custom error message." 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": 22, 149 | "metadata": {}, 150 | "outputs": [ 151 | { 152 | "name": "stdout", 153 | "output_type": "stream", 154 | "text": [ 155 | "Please provide valid file name\n" 156 | ] 157 | } 158 | ], 159 | "source": [ 160 | "new_file = input(\"Enter a file name :: \")\n", 161 | "\n", 162 | "try:\n", 163 | " nfile = open(new_file,'r')\n", 164 | " nfile.close()\n", 165 | "\n", 166 | "except FileNotFoundError:\n", 167 | " print(\"Please provide valid file name\")" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "5. Write a Python program that asks the user to enter a string and converts it to an integer using the `int()` function. Handle the `ValueError` exception with a custom error message." 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 25, 180 | "metadata": {}, 181 | "outputs": [ 182 | { 183 | "name": "stdout", 184 | "output_type": "stream", 185 | "text": [ 186 | "Error : Cannot convert String value to integer.\n" 187 | ] 188 | } 189 | ], 190 | "source": [ 191 | "st = input(\"Enter a string :: \")\n", 192 | "\n", 193 | "try:\n", 194 | " # trying to convert string to int\n", 195 | " int_st = int(st)\n", 196 | " print(int_st)\n", 197 | "except ValueError:\n", 198 | " print(\"Error : Cannot convert String value to integer.\")" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "**Using finally Block:**\n", 206 | "\n", 207 | "6. Write a Python program that prompts the user to enter a file name and then attempts to open the file for reading. Use a `finally` block to ensure that the file is closed regardless of whether an exception occurs." 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": 32, 213 | "metadata": {}, 214 | "outputs": [ 215 | { 216 | "name": "stdout", 217 | "output_type": "stream", 218 | "text": [ 219 | "file closed!.\n" 220 | ] 221 | } 222 | ], 223 | "source": [ 224 | "last_file = input(\"Enter a file name :: \")\n", 225 | "\n", 226 | "lfile = None\n", 227 | "\n", 228 | "try:\n", 229 | " lfile = open(last_file,'r')\n", 230 | " content = lfile.read()\n", 231 | "except FileNotFoundError:\n", 232 | " print(\"Error : please enter valid file name.\")\n", 233 | "\n", 234 | "except Exception as e:\n", 235 | " print(\"Error : An unexcepted error occured.\")\n", 236 | "finally:\n", 237 | " if lfile is not None:\n", 238 | " lfile.close()\n", 239 | " print('file closed!.')\n" 240 | ] 241 | }, 242 | { 243 | "cell_type": "markdown", 244 | "metadata": {}, 245 | "source": [ 246 | "7. Write a Python program that asks the user to enter two numbers and divides the first number by the second number. Use a `finally` block to print a message indicating the end of the program." 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "execution_count": 33, 252 | "metadata": {}, 253 | "outputs": [ 254 | { 255 | "name": "stdout", 256 | "output_type": "stream", 257 | "text": [ 258 | "Division is :: 0.2857142857142857\n", 259 | "Program Complete.\n" 260 | ] 261 | } 262 | ], 263 | "source": [ 264 | "n1 = eval(input(\"Enter number 1 :: \"))\n", 265 | "n2 = eval(input(\"Enter number 2 :: \"))\n", 266 | "\n", 267 | "try:\n", 268 | " div = n1/n2\n", 269 | " print(f\"Division is :: {div}\")\n", 270 | "\n", 271 | "except ZeroDivisionError:\n", 272 | " print(\"Number can't be divide by zero.\")\n", 273 | "\n", 274 | "except ValueError:\n", 275 | " print(\"Please enter valid numbers\")\n", 276 | "\n", 277 | "finally:\n", 278 | " print(\"Program Complete.\")" 279 | ] 280 | } 281 | ], 282 | "metadata": { 283 | "kernelspec": { 284 | "display_name": "Python 3", 285 | "language": "python", 286 | "name": "python3" 287 | }, 288 | "language_info": { 289 | "codemirror_mode": { 290 | "name": "ipython", 291 | "version": 3 292 | }, 293 | "file_extension": ".py", 294 | "mimetype": "text/x-python", 295 | "name": "python", 296 | "nbconvert_exporter": "python", 297 | "pygments_lexer": "ipython3", 298 | "version": "3.10.3" 299 | } 300 | }, 301 | "nbformat": 4, 302 | "nbformat_minor": 2 303 | } 304 | -------------------------------------------------------------------------------- /Day_75-79/Selenium with python.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "a827ef23", 6 | "metadata": {}, 7 | "source": [ 8 | "# Day 75-79 (Learning Python From Basics)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "ba3eba68", 14 | "metadata": {}, 15 | "source": [ 16 | "# Basics of Selenium with Python\n", 17 | "\n", 18 | "## Installation\n", 19 | "To use Selenium with Python, you need to install the Selenium library using pip:\n", 20 | "\n", 21 | "```sh\n", 22 | "pip install selenium\n", 23 | "```\n", 24 | "\n", 25 | "Additionally, you need to download the WebDriver for the browser you want to use (e.g., ChromeDriver for Chrome).\n", 26 | "\n", 27 | "## Setting Up WebDriver\n", 28 | "To start using Selenium, you need to set up the WebDriver for the browser. Here’s an example using ChromeDriver:\n", 29 | "\n", 30 | "```python\n", 31 | "from selenium import webdriver\n", 32 | "from selenium.webdriver.chrome.service import Service\n", 33 | "from selenium.webdriver.chrome.options import Options\n", 34 | "\n", 35 | "# Setup Chrome options and service\n", 36 | "chrome_options = Options()\n", 37 | "chrome_options.add_argument(\"--headless\") # Run in headless mode (no GUI)\n", 38 | "\n", 39 | "service = Service('path/to/chromedriver')\n", 40 | "\n", 41 | "# Initialize the driver\n", 42 | "driver = webdriver.Chrome(service=service, options=chrome_options)\n", 43 | "```\n", 44 | "\n", 45 | "Replace `path/to/chromedriver` with the actual path to your downloaded ChromeDriver.\n", 46 | "\n", 47 | "## Opening a Webpage\n", 48 | "To open a webpage, you can use the `get` method:\n", 49 | "\n", 50 | "```python\n", 51 | "driver.get('https://www.example.com')\n", 52 | "```\n", 53 | "\n", 54 | "## Finding Elements\n", 55 | "Selenium provides several methods to locate elements on a web page:\n", 56 | "\n", 57 | "- `find_element(By.ID, 'element_id')`\n", 58 | "- `find_element(By.NAME, 'element_name')`\n", 59 | "- `find_element(By.CLASS_NAME, 'class_name')`\n", 60 | "- `find_element(By.TAG_NAME, 'tag_name')`\n", 61 | "- `find_element(By.CSS_SELECTOR, 'css_selector')`\n", 62 | "- `find_element(By.XPATH, 'xpath')`\n", 63 | "\n", 64 | "Example:\n", 65 | "\n", 66 | "```python\n", 67 | "element = driver.find_element(By.ID, 'element_id')\n", 68 | "```\n", 69 | "\n", 70 | "## Interacting with Elements\n", 71 | "You can interact with web elements using various methods like `click`, `send_keys`, etc.\n", 72 | "\n", 73 | "```python\n", 74 | "# Click a button\n", 75 | "button = driver.find_element(By.ID, 'submit_button')\n", 76 | "button.click()\n", 77 | "\n", 78 | "# Enter text into a text box\n", 79 | "text_box = driver.find_element(By.NAME, 'text_field')\n", 80 | "text_box.send_keys('Sample text')\n", 81 | "```\n", 82 | "\n", 83 | "## Handling Browser Actions\n", 84 | "Selenium can perform a variety of browser actions like navigating back and forth, refreshing the page, etc.\n", 85 | "\n", 86 | "```python\n", 87 | "# Navigate to a new page\n", 88 | "driver.get('https://www.anotherexample.com')\n", 89 | "\n", 90 | "# Navigate back\n", 91 | "driver.back()\n", 92 | "\n", 93 | "# Navigate forward\n", 94 | "driver.forward()\n", 95 | "\n", 96 | "# Refresh the page\n", 97 | "driver.refresh()\n", 98 | "```\n", 99 | "\n", 100 | "## Waiting for Elements\n", 101 | "Selenium provides implicit and explicit waits to wait for elements to appear on the web page.\n", 102 | "\n", 103 | "- **Implicit Wait:** Sets a default wait time for the entire session.\n", 104 | "\n", 105 | "```python\n", 106 | "driver.implicitly_wait(10) # seconds\n", 107 | "```\n", 108 | "\n", 109 | "- **Explicit Wait:** Waits for a specific condition to be met before continuing.\n", 110 | "\n", 111 | "```python\n", 112 | "from selenium.webdriver.common.by import By\n", 113 | "from selenium.webdriver.support.ui import WebDriverWait\n", 114 | "from selenium.webdriver.support import expected_conditions as EC\n", 115 | "\n", 116 | "wait = WebDriverWait(driver, 10)\n", 117 | "element = wait.until(EC.presence_of_element_located((By.ID, 'element_id')))\n", 118 | "```\n", 119 | "\n", 120 | "## Closing the Browser\n", 121 | "You can close the browser using the `close` or `quit` methods:\n", 122 | "\n", 123 | "```python\n", 124 | "# Close the current window\n", 125 | "driver.close()\n", 126 | "\n", 127 | "# Quit the WebDriver session and close all associated windows\n", 128 | "driver.quit()\n", 129 | "```\n", 130 | "\n", 131 | "# Code Example: Google Search Automation\n", 132 | "\n", 133 | "Here is a complete example that opens Google, searches for \"Selenium Python,\" and prints the titles of the search results:\n", 134 | "\n", 135 | "```python\n", 136 | "from selenium import webdriver\n", 137 | "from selenium.webdriver.common.by import By\n", 138 | "from selenium.webdriver.common.keys import Keys\n", 139 | "from selenium.webdriver.chrome.service import Service\n", 140 | "from selenium.webdriver.chrome.options import Options\n", 141 | "\n", 142 | "# Setup Chrome options and service\n", 143 | "chrome_options = Options()\n", 144 | "chrome_options.add_argument(\"--headless\") # Run in headless mode (no GUI)\n", 145 | "\n", 146 | "service = Service('path/to/chromedriver')\n", 147 | "\n", 148 | "# Initialize the driver\n", 149 | "driver = webdriver.Chrome(service=service, options=chrome_options)\n", 150 | "\n", 151 | "# Open Google\n", 152 | "driver.get('https://www.google.com')\n", 153 | "\n", 154 | "# Find the search box\n", 155 | "search_box = driver.find_element(By.NAME, 'q')\n", 156 | "\n", 157 | "# Enter search query and hit Enter\n", 158 | "search_box.send_keys('Selenium Python')\n", 159 | "search_box.send_keys(Keys.RETURN)\n", 160 | "\n", 161 | "# Wait for search results to appear\n", 162 | "driver.implicitly_wait(10)\n", 163 | "\n", 164 | "# Print titles of search results\n", 165 | "titles = driver.find_elements(By.XPATH, '//h3')\n", 166 | "for title in titles:\n", 167 | " print(title.text)\n", 168 | "\n", 169 | "# Close the browser\n", 170 | "driver.quit()\n", 171 | "```\n", 172 | "\n", 173 | "# Tips and Best Practices\n", 174 | "- **Use Explicit Waits**: Prefer explicit waits over implicit waits for better control and reliability.\n", 175 | "- **Handle Exceptions**: Properly handle exceptions to make your script more robust.\n", 176 | "- **Page Object Model (POM)**: Consider using the Page Object Model design pattern to organize your test code better.\n", 177 | "- **Headless Mode**: Use headless mode for running tests without opening a browser window, which is useful for continuous integration setups.\n", 178 | "\n", 179 | "By following these basics, you can start automating web interactions using Selenium with Python." 180 | ] 181 | } 182 | ], 183 | "metadata": { 184 | "kernelspec": { 185 | "display_name": "Python 3 (ipykernel)", 186 | "language": "python", 187 | "name": "python3" 188 | }, 189 | "language_info": { 190 | "codemirror_mode": { 191 | "name": "ipython", 192 | "version": 3 193 | }, 194 | "file_extension": ".py", 195 | "mimetype": "text/x-python", 196 | "name": "python", 197 | "nbconvert_exporter": "python", 198 | "pygments_lexer": "ipython3", 199 | "version": "3.11.7" 200 | } 201 | }, 202 | "nbformat": 4, 203 | "nbformat_minor": 5 204 | } 205 | -------------------------------------------------------------------------------- /Day_80-81/code_profiling_python_flask.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "59cd8334-1dec-4ef1-8139-ccf95af99c87", 6 | "metadata": {}, 7 | "source": [ 8 | "# Day 80 - 81 (Practicing pythong from basics)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "c6aa6d11-ee80-4ce5-a2eb-63bf63aea96b", 14 | "metadata": {}, 15 | "source": [ 16 | "# Basics of Code Profiling with Flask in Python\n", 17 | "\n", 18 | "Profiling is a crucial part of optimizing your application by identifying performance bottlenecks. In a Flask application, profiling can help you understand which parts of your code are consuming the most resources, allowing you to make informed decisions about optimizations.\n", 19 | "\n", 20 | "## Setting Up a Flask Application\n", 21 | "\n", 22 | "First, let’s set up a simple Flask application:\n", 23 | "\n", 24 | "```python\n", 25 | "from flask import Flask\n", 26 | "\n", 27 | "app = Flask(__name__)\n", 28 | "\n", 29 | "@app.route('/')\n", 30 | "def home():\n", 31 | " return \"Hello, Flask!\"\n", 32 | "\n", 33 | "@app.route('/slow')\n", 34 | "def slow():\n", 35 | " import time\n", 36 | " time.sleep(2)\n", 37 | " return \"This is a slow route!\"\n", 38 | "\n", 39 | "if __name__ == '__main__':\n", 40 | " app.run(debug=True)\n", 41 | "```\n", 42 | "\n", 43 | "## Profiling with `Werkzeug` Middleware\n", 44 | "\n", 45 | "Werkzeug, the underlying WSGI library used by Flask, provides a middleware called `ProfilerMiddleware` for profiling applications.\n", 46 | "\n", 47 | "## Setting Up the Profiler Middleware\n", 48 | "\n", 49 | "You can integrate `ProfilerMiddleware` into your Flask application as follows:\n", 50 | "\n", 51 | "1. **Install Flask and Click**:\n", 52 | " ```sh\n", 53 | " pip install flask click\n", 54 | " ```\n", 55 | "\n", 56 | "2. **Add the Profiler Middleware to Your Flask App**:\n", 57 | " ```python\n", 58 | " from flask import Flask\n", 59 | " import click\n", 60 | " from werkzeug.middleware.profiler import ProfilerMiddleware\n", 61 | "\n", 62 | " app = Flask(__name__)\n", 63 | "\n", 64 | " @app.route('/')\n", 65 | " def home():\n", 66 | " return \"Hello, Flask!\"\n", 67 | " @app.route('/slow')\n", 68 | " def slow():\n", 69 | " import time\n", 70 | " time.sleep(2)\n", 71 | " return \"This is a slow route!\"\n", 72 | "\n", 73 | " @app.cli.command()\n", 74 | " @click.option('--length', default=25, help='Number of functions to include in the profiler report.')\n", 75 | " @click.option('--profile-dir', default=None, help=\"Directory where profiler data files are saved.\")\n", 76 | " def profile(length, profile_dir):\n", 77 | " \"\"\"\n", 78 | " Start the application under the code profiler.\n", 79 | " \"\"\"\n", 80 | " app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[length], profile_dir=profile_dir)\n", 81 | " app.run(debug=True)\n", 82 | " \n", 83 | " if __name__ == '__main__':\n", 84 | " app.run(debug=True)\n", 85 | " \n", 86 | " ```\n", 87 | "\n", 88 | "3. **Run the Profiling Command**:\n", 89 | "\n", 90 | " ```sh\n", 91 | " flask profile --length=25 --profile-dir=./profile\n", 92 | " ```\n", 93 | "\n", 94 | " This command starts the Flask application with profiling enabled. The `length` option specifies the number of functions to include in the profiler report, and the `profile-dir` option specifies the directory where the profiling data files are saved.\n", 95 | "\n", 96 | "## Analyzing the Profile Data\n", 97 | "\n", 98 | "Once you have run the application with profiling, you will get detailed reports on the performance of your functions. The `ProfilerMiddleware` will generate files in the specified directory (`profile-dir`). These files can be analyzed using tools like `pstats`.\n", 99 | "\n", 100 | "## Example Analysis with `pstats`\n", 101 | "\n", 102 | "Here is an example script to analyze the profile data:\n", 103 | "\n", 104 | "```python\n", 105 | "import pstats\n", 106 | "\n", 107 | "p = pstats.Stats('profile_dir/profile_output_file')\n", 108 | "p.strip_dirs().sort_stats('cumulative').print_stats(10)\n", 109 | "```\n", 110 | "\n", 111 | "This script reads the profiling data from the specified file, sorts it by cumulative time, and prints the top 10 functions.\n", 112 | "\n", 113 | "# Summary\n", 114 | "\n", 115 | "By integrating profiling into your Flask application, you can gain valuable insights into the performance characteristics of your code. Using `Werkzeug`'s `ProfilerMiddleware` along with `pstats` for analysis, you can identify and address performance bottlenecks effectively.\n", 116 | "\n", 117 | "# Complete Example with `ProfilerMiddleware`\n", 118 | "\n", 119 | "Below is a complete example demonstrating how to profile a Flask application using `ProfilerMiddleware`:\n", 120 | "\n", 121 | "```python\n", 122 | "from flask import Flask\n", 123 | "import click\n", 124 | "from werkzeug.middleware.profiler import ProfilerMiddleware\n", 125 | "\n", 126 | "app = Flask(__name__)\n", 127 | "\n", 128 | "@app.route('/')\n", 129 | "def home():\n", 130 | " return \"Hello, Flask!\"\n", 131 | "\n", 132 | "@app.route('/slow')\n", 133 | "def slow():\n", 134 | " import time\n", 135 | " time.sleep(2)\n", 136 | " return \"This is a slow route!\"\n", 137 | "\n", 138 | "@app.cli.command()\n", 139 | "@click.option('--length', default=25, help='Number of functions to include in the profiler report.')\n", 140 | "@click.option('--profile-dir', default=None, help=\"Directory where profiler data files are saved.\")\n", 141 | "def profile(length, profile_dir):\n", 142 | " \"\"\"\n", 143 | " Start the application under the code profiler.\n", 144 | " \"\"\"\n", 145 | " app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[length], profile_dir=profile_dir)\n", 146 | " app.run(debug=True)\n", 147 | "\n", 148 | "if __name__ == '__main__':\n", 149 | " app.run(debug=True)\n", 150 | "```\n", 151 | "\n", 152 | "This setup allows you to profile specific parts of your Flask application, providing detailed insights into its performance and helping you optimize critical paths." 153 | ] 154 | } 155 | ], 156 | "metadata": { 157 | "kernelspec": { 158 | "display_name": "Python 3 (ipykernel)", 159 | "language": "python", 160 | "name": "python3" 161 | }, 162 | "language_info": { 163 | "codemirror_mode": { 164 | "name": "ipython", 165 | "version": 3 166 | }, 167 | "file_extension": ".py", 168 | "mimetype": "text/x-python", 169 | "name": "python", 170 | "nbconvert_exporter": "python", 171 | "pygments_lexer": "ipython3", 172 | "version": "3.10.3" 173 | } 174 | }, 175 | "nbformat": 4, 176 | "nbformat_minor": 5 177 | } 178 | --------------------------------------------------------------------------------