diff --git a/flask-sqlite/.coverage.keploy b/flask-sqlite/.coverage.keploy new file mode 100644 index 0000000..cf259d2 Binary files /dev/null and b/flask-sqlite/.coverage.keploy differ diff --git a/flask-sqlite/.coveragerc b/flask-sqlite/.coveragerc new file mode 100644 index 0000000..152922e --- /dev/null +++ b/flask-sqlite/.coveragerc @@ -0,0 +1,4 @@ +[run] +omit = + /usr/* +sigterm = true diff --git a/flask-sqlite/.gitignore b/flask-sqlite/.gitignore new file mode 100644 index 0000000..eff16dd --- /dev/null +++ b/flask-sqlite/.gitignore @@ -0,0 +1,35 @@ +# Python bytecode +__pycache__/ +*.py[cod] +*.pyo + +# SQLite DB file (do not commit local dev DB) +*.db +instance/ + +# Keploy reports (tests are OK, reports are not needed) +keploy/reports/ + +# Coverage reports +coverage.* +*.cover +.hypothesis/ + +# Keploy traces/cache +*.log +keploy/test-set-*/coverage.* +keploy/test-set-*/mocks/ + +# Environment files +.env +.venv/ +env/ +venv/ + +# IDE files +.vscode/ +.idea/ + +# macOS/Linux system files +.DS_Store +Thumbs.db diff --git a/flask-sqlite/README.md b/flask-sqlite/README.md new file mode 100644 index 0000000..8532cad --- /dev/null +++ b/flask-sqlite/README.md @@ -0,0 +1,126 @@ +# Flask + SQLite Sample App with Keploy Integration + +This is a simple **Student Management REST API** built using Python's Flask framework and SQLite for storage. It demonstrates basic **CRUD operations** (Create, Read, Update, Delete) and showcases how to write **API tests with [Keploy](https://keploy.io)** by auto-capturing HTTP calls as test cases. + +--- + +## 🚀 Features + +- 🧑 Add, retrieve, update, and delete students +- 💾 Uses SQLite — no external DB setup required +- 🔌 RESTful API with JSON input/output +- ✅ Auto-generate test cases using [Keploy CLI](https://docs.keploy.io) +- 🔄 Replay & validate API responses with Keploy + +--- + +## 📦 Tech Stack + +- **Flask** — Lightweight web framework +- **Flask-SQLAlchemy** — ORM for SQLite +- **SQLite** — Built-in relational DB +- **Keploy** — Testing toolkit for API auto-mocking and regression testing + +--- + +## 🛠 Installation + +1. **Clone the repository** +```bash +git clone https://github.com//samples-python.git +cd samples-python/flask-sqlite +``` + +2. Set up virtual environment (optional) +```bash +python3 -m venv venv +source venv/bin/activate +``` + +3. Install Dependencies + +```bash +pip install -r requirements.txt +``` +4. Run the Flask app + +```bash +python app.py +``` +--- + +## API Endpoints + +```bash + +| Method | Endpoint | Description | +| ------ | ---------------- | -------------------- | +| GET | `/students` | Get all students | +| POST | `/students` | Add a new student | +| PUT | `/students/` | Update student by ID | +| DELETE | `/students/` | Delete student by ID | + +``` +--- + +## Sample Curl Commands + +### Add a student + +```bash +curl -X POST http://localhost:5000/students \ + -H "Content-Type: application/json" \ + -d '{"name": "Alice", "age": 21}' + +# Get all students +curl http://localhost:5000/students + +# Update student +curl -X PUT http://localhost:5000/students/1 \ + -H "Content-Type: application/json" \ + -d '{"name": "Alice Updated", "age": 22}' + +# Delete student +curl -X DELETE http://localhost:5000/students/1 + +``` +--- + +## Running Keploy Tests + +Step 1: Record Tests +Start Keploy in record mode: + +```bash +keploy record --command "python app.py" +``` +Send some API requests via curl or Postman to generate test cases. + +Step 2: Replay Tests +After recording, stop the app and run: + +```bash +keploy test --command "python app.py" +``` +> Keploy will replay the previously captured requests and validate responses. + +## Folder Structure + +```bash +flask-sqlite/ +├── app.py # Flask app entry point +├── models.py # Student model +├── requirements.txt # Python dependencies +├── keploy.yml # Keploy config file +├── keploy/ # Auto-generated test cases +└── README.md # You are here! +``` +--- + +## Contributing +> Want to improve or add another example (e.g. FastAPI, SQLModel, etc.)? Contributions are welcome! Fork this repo, create your example folder, and submit a PR. + +## About Keploy +Keploy is a developer-friendly open-source testing toolkit that auto-generates test cases from API calls in real-time and replays them to catch regressions — without writing any test code. + +> Built with ❤️ for the Open Source Community. \ No newline at end of file diff --git a/flask-sqlite/app.py b/flask-sqlite/app.py new file mode 100644 index 0000000..b66f92f --- /dev/null +++ b/flask-sqlite/app.py @@ -0,0 +1,80 @@ +from flask import Flask, request, jsonify +from models import db, Student + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + +db.init_app(app) + +# 🔧 Validation Helper Function +def validate_student_data(data, partial=False): + if not data: + return "Missing JSON body" + + if not partial: + if 'name' not in data: + return "Missing 'name'" + if 'age' not in data: + return "Missing 'age'" + + if 'name' in data: + if not isinstance(data['name'], str) or not data['name'].strip(): + return "Invalid 'name'" + + if 'age' in data: + if not isinstance(data['age'], int): + return "Invalid 'age'" + + return None # No error + +@app.route('/') +def home(): + return jsonify({"message": "Flask Student API"}), 200 + +@app.route('/students', methods=['GET']) +def get_students(): + students = Student.query.all() + return jsonify([ + {"id": s.id, "name": s.name, "age": s.age} for s in students + ]) + +@app.route('/students', methods=['POST']) +def add_student(): + data = request.get_json() + error = validate_student_data(data) + if error: + return jsonify({"error": error}), 400 + + student = Student(name=data['name'].strip(), age=data['age']) + db.session.add(student) + db.session.commit() + return jsonify({"id": student.id}), 201 + +@app.route('/students/', methods=['PUT']) +def update_student(id): + student = Student.query.get_or_404(id) + data = request.get_json() + error = validate_student_data(data, partial=True) + if error: + return jsonify({"error": error}), 400 + + if 'name' in data: + student.name = data['name'].strip() + if 'age' in data: + student.age = data['age'] + + db.session.commit() + return jsonify({"message": "Updated"}), 200 + +@app.route('/students/', methods=['DELETE']) +def delete_student(id): + student = Student.query.get_or_404(id) + db.session.delete(student) + db.session.commit() + return jsonify({"message": "Deleted"}), 200 + +if __name__ == '__main__': + with app.app_context(): + db.create_all() + app.run(debug=True) diff --git a/flask-sqlite/keploy.yml b/flask-sqlite/keploy.yml new file mode 100755 index 0000000..aa33808 --- /dev/null +++ b/flask-sqlite/keploy.yml @@ -0,0 +1,67 @@ +# Generated by Keploy (2.6.11) +path: "" +appId: 0 +appName: flask-sqlite +command: .venv/bin/python app.py +templatize: + testSets: [] +port: 0 +e2e: false +dnsPort: 26789 +proxyPort: 16789 +debug: false +disableTele: false +disableANSI: false +containerName: "" +networkName: "" +buildDelay: 30 +test: + selectedTests: {} + globalNoise: + global: {} + test-sets: {} + delay: 5 + host: "" + port: 0 + apiTimeout: 5 + skipCoverage: false + coverageReportPath: "" + ignoreOrdering: true + mongoPassword: default@123 + language: "" + removeUnusedMocks: false + fallBackOnMiss: false + jacocoAgentPath: "" + basePath: "" + mocking: true + ignoredTests: {} + disableLineCoverage: false + disableMockUpload: true + useLocalMock: false + updateTemplate: false + mustPass: false + maxFailAttempts: 5 + maxFlakyChecks: 1 +record: + filters: [] + basePath: "" + recordTimer: 0s +configPath: "" +bypassRules: [] +generateGithubActions: false +keployContainer: keploy-v2 +keployNetwork: keploy-network +cmdType: native +contract: + services: [] + tests: [] + path: "" + download: false + generate: false + driven: consumer + mappings: + servicesMapping: {} + self: s1 +inCi: false + +# Visit [https://keploy.io/docs/running-keploy/configuration-file/] to learn about using keploy through configration file. diff --git a/flask-sqlite/keploy/.gitignore b/flask-sqlite/keploy/.gitignore new file mode 100644 index 0000000..5137843 --- /dev/null +++ b/flask-sqlite/keploy/.gitignore @@ -0,0 +1,2 @@ + +/reports/ diff --git a/flask-sqlite/keploy/test-set-0/tests/test-1.yaml b/flask-sqlite/keploy/test-set-0/tests/test-1.yaml new file mode 100755 index 0000000..5e3e160 --- /dev/null +++ b/flask-sqlite/keploy/test-set-0/tests/test-1.yaml @@ -0,0 +1,61 @@ +# Generated by Keploy (2.6.11) +version: api.keploy.io/v1beta1 +kind: Http +name: test-1 +spec: + metadata: {} + req: + method: GET + proto_major: 1 + proto_minor: 1 + url: http://localhost:5000/students + header: + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 + Accept-Encoding: gzip, deflate, br, zstd + Accept-Language: en-US,en;q=0.5 + Connection: keep-alive + Cookie: _ga_9C3YK4FNWZ=GS2.1.s1746835762$o1$g1$t1746835798$j0$l0$h0; _ga=GA1.1.370021656.1746835763; _clck=1e6823p%7C2%7Cfww%7C0%7C1996; __hstc=181257784.e3804237d83ad93b9ef5fdbdd48354d1.1750295949745.1750295949745.1750295949745.1; hubspotutk=e3804237d83ad93b9ef5fdbdd48354d1; __hssrc=1; _clsk=dk2mvr%7C1750295950556%7C1%7C1%7Cl.clarity.ms%2Fcollect; messagesUtk=a1a71bf707fd412b8e4bf788336568d9 + Host: localhost:5000 + Priority: u=0, i + Sec-Fetch-Dest: document + Sec-Fetch-Mode: navigate + Sec-Fetch-Site: none + Sec-Fetch-User: ?1 + Upgrade-Insecure-Requests: "1" + User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0 + body: "" + timestamp: 2025-06-19T09:36:00.825424089+05:30 + resp: + status_code: 200 + header: + Content-Length: "3" + Content-Type: application/json + Date: Thu, 19 Jun 2025 04:06:00 GMT + Server: Werkzeug/3.1.3 Python/3.12.3 + body: | + [] + status_message: OK + proto_major: 0 + proto_minor: 0 + timestamp: 2025-06-19T09:36:02.898108619+05:30 + objects: [] + assertions: + noise: + header.Date: [] + created: 1750305962 +curl: | + curl --request GET \ + --url http://localhost:5000/students \ + --header 'Sec-Fetch-User: ?1' \ + --header 'Cookie: _ga_9C3YK4FNWZ=GS2.1.s1746835762$o1$g1$t1746835798$j0$l0$h0; _ga=GA1.1.370021656.1746835763; _clck=1e6823p%7C2%7Cfww%7C0%7C1996; __hstc=181257784.e3804237d83ad93b9ef5fdbdd48354d1.1750295949745.1750295949745.1750295949745.1; hubspotutk=e3804237d83ad93b9ef5fdbdd48354d1; __hssrc=1; _clsk=dk2mvr%7C1750295950556%7C1%7C1%7Cl.clarity.ms%2Fcollect; messagesUtk=a1a71bf707fd412b8e4bf788336568d9' \ + --header 'Accept-Language: en-US,en;q=0.5' \ + --header 'Sec-Fetch-Dest: document' \ + --header 'Sec-Fetch-Mode: navigate' \ + --header 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \ + --header 'Priority: u=0, i' \ + --header 'Accept-Encoding: gzip, deflate, br, zstd' \ + --header 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0' \ + --header 'Upgrade-Insecure-Requests: 1' \ + --header 'Sec-Fetch-Site: none' \ + --header 'Host: localhost:5000' \ + --header 'Connection: keep-alive' \ diff --git a/flask-sqlite/keploy/test-set-0/tests/test-2.yaml b/flask-sqlite/keploy/test-set-0/tests/test-2.yaml new file mode 100755 index 0000000..adc5362 --- /dev/null +++ b/flask-sqlite/keploy/test-set-0/tests/test-2.yaml @@ -0,0 +1,61 @@ +# Generated by Keploy (2.6.11) +version: api.keploy.io/v1beta1 +kind: Http +name: test-2 +spec: + metadata: {} + req: + method: GET + proto_major: 1 + proto_minor: 1 + url: http://localhost:5000/favicon.ico + header: + Accept: image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5 + Accept-Encoding: gzip, deflate, br, zstd + Accept-Language: en-US,en;q=0.5 + Connection: keep-alive + Host: localhost:5000 + Priority: u=6 + Referer: http://localhost:5000/students + Sec-Fetch-Dest: image + Sec-Fetch-Mode: no-cors + Sec-Fetch-Site: cross-site + User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0 + body: "" + timestamp: 2025-06-19T09:36:00.905501417+05:30 + resp: + status_code: 404 + header: + Content-Length: "207" + Content-Type: text/html; charset=utf-8 + Date: Thu, 19 Jun 2025 04:06:00 GMT + Server: Werkzeug/3.1.3 Python/3.12.3 + body: | + + + 404 Not Found +

Not Found

+

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

+ status_message: Not Found + proto_major: 0 + proto_minor: 0 + timestamp: 2025-06-19T09:36:02.999325414+05:30 + objects: [] + assertions: + noise: + header.Date: [] + created: 1750305962 +curl: | + curl --request GET \ + --url http://localhost:5000/favicon.ico \ + --header 'Accept: image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5' \ + --header 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0' \ + --header 'Sec-Fetch-Mode: no-cors' \ + --header 'Host: localhost:5000' \ + --header 'Connection: keep-alive' \ + --header 'Referer: http://localhost:5000/students' \ + --header 'Sec-Fetch-Site: cross-site' \ + --header 'Sec-Fetch-Dest: image' \ + --header 'Accept-Language: en-US,en;q=0.5' \ + --header 'Priority: u=6' \ + --header 'Accept-Encoding: gzip, deflate, br, zstd' \ diff --git a/flask-sqlite/keploy/test-set-0/tests/test-3.yaml b/flask-sqlite/keploy/test-set-0/tests/test-3.yaml new file mode 100755 index 0000000..be4b920 --- /dev/null +++ b/flask-sqlite/keploy/test-set-0/tests/test-3.yaml @@ -0,0 +1,47 @@ +# Generated by Keploy (2.6.11) +version: api.keploy.io/v1beta1 +kind: Http +name: test-3 +spec: + metadata: {} + req: + method: POST + proto_major: 1 + proto_minor: 1 + url: http://localhost:5000/students + header: + Accept: '*/*' + Content-Length: "31" + Content-Type: application/json + Host: localhost:5000 + User-Agent: curl/8.5.0 + body: '{"name": "TestUser", "age": 20}' + timestamp: 2025-06-19T09:36:20.274605472+05:30 + resp: + status_code: 201 + header: + Content-Length: "14" + Content-Type: application/json + Date: Thu, 19 Jun 2025 04:06:20 GMT + Server: Werkzeug/3.1.3 Python/3.12.3 + body: | + { + "id": 1 + } + status_message: Created + proto_major: 0 + proto_minor: 0 + timestamp: 2025-06-19T09:36:22.355090014+05:30 + objects: [] + assertions: + noise: + header.Date: [] + created: 1750305982 +curl: |- + curl --request POST \ + --url http://localhost:5000/students \ + --header 'User-Agent: curl/8.5.0' \ + --header 'Accept: */*' \ + --header 'Content-Type: application/json' \ + --header 'Host: localhost:5000' \ + --data "{\"name\": \"TestUser\", \"age\": 20}" diff --git a/flask-sqlite/keploy/test-set-0/tests/test-4.yaml b/flask-sqlite/keploy/test-set-0/tests/test-4.yaml new file mode 100755 index 0000000..67f5090 --- /dev/null +++ b/flask-sqlite/keploy/test-set-0/tests/test-4.yaml @@ -0,0 +1,47 @@ +# Generated by Keploy (2.6.11) +version: api.keploy.io/v1beta1 +kind: Http +name: test-4 +spec: + metadata: {} + req: + method: POST + proto_major: 1 + proto_minor: 1 + url: http://localhost:5000/students + header: + Accept: '*/*' + Content-Length: "34" + Content-Type: application/json + Host: localhost:5000 + User-Agent: curl/8.5.0 + body: '{"name": "TestStudent", "age": 22}' + timestamp: 2025-06-19T09:36:23.422507862+05:30 + resp: + status_code: 201 + header: + Content-Length: "14" + Content-Type: application/json + Date: Thu, 19 Jun 2025 04:06:23 GMT + Server: Werkzeug/3.1.3 Python/3.12.3 + body: | + { + "id": 2 + } + status_message: Created + proto_major: 0 + proto_minor: 0 + timestamp: 2025-06-19T09:36:25.466032323+05:30 + objects: [] + assertions: + noise: + header.Date: [] + created: 1750305985 +curl: |- + curl --request POST \ + --url http://localhost:5000/students \ + --header 'Content-Type: application/json' \ + --header 'Host: localhost:5000' \ + --header 'User-Agent: curl/8.5.0' \ + --header 'Accept: */*' \ + --data "{\"name\": \"TestStudent\", \"age\": 22}" diff --git a/flask-sqlite/keploy/test-set-0/tests/test-5.yaml b/flask-sqlite/keploy/test-set-0/tests/test-5.yaml new file mode 100755 index 0000000..e47d732 --- /dev/null +++ b/flask-sqlite/keploy/test-set-0/tests/test-5.yaml @@ -0,0 +1,72 @@ +# Generated by Keploy (2.6.11) +version: api.keploy.io/v1beta1 +kind: Http +name: test-5 +spec: + metadata: {} + req: + method: GET + proto_major: 1 + proto_minor: 1 + url: http://localhost:5000/students + header: + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 + Accept-Encoding: gzip, deflate, br, zstd + Accept-Language: en-US,en;q=0.5 + Connection: keep-alive + Cookie: _ga_9C3YK4FNWZ=GS2.1.s1746835762$o1$g1$t1746835798$j0$l0$h0; _ga=GA1.1.370021656.1746835763; _clck=1e6823p%7C2%7Cfww%7C0%7C1996; __hstc=181257784.e3804237d83ad93b9ef5fdbdd48354d1.1750295949745.1750295949745.1750295949745.1; hubspotutk=e3804237d83ad93b9ef5fdbdd48354d1; __hssrc=1; _clsk=dk2mvr%7C1750295950556%7C1%7C1%7Cl.clarity.ms%2Fcollect; messagesUtk=a1a71bf707fd412b8e4bf788336568d9 + Host: localhost:5000 + Priority: u=0, i + Sec-Fetch-Dest: document + Sec-Fetch-Mode: navigate + Sec-Fetch-Site: none + Sec-Fetch-User: ?1 + Upgrade-Insecure-Requests: "1" + User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0 + body: "" + timestamp: 2025-06-19T09:36:26.714533+05:30 + resp: + status_code: 200 + header: + Content-Length: "126" + Content-Type: application/json + Date: Thu, 19 Jun 2025 04:06:26 GMT + Server: Werkzeug/3.1.3 Python/3.12.3 + body: | + [ + { + "age": 20, + "id": 1, + "name": "TestUser" + }, + { + "age": 22, + "id": 2, + "name": "TestStudent" + } + ] + status_message: OK + proto_major: 0 + proto_minor: 0 + timestamp: 2025-06-19T09:36:28.780097142+05:30 + objects: [] + assertions: + noise: + header.Date: [] + created: 1750305988 +curl: | + curl --request GET \ + --url http://localhost:5000/students \ + --header 'Cookie: _ga_9C3YK4FNWZ=GS2.1.s1746835762$o1$g1$t1746835798$j0$l0$h0; _ga=GA1.1.370021656.1746835763; _clck=1e6823p%7C2%7Cfww%7C0%7C1996; __hstc=181257784.e3804237d83ad93b9ef5fdbdd48354d1.1750295949745.1750295949745.1750295949745.1; hubspotutk=e3804237d83ad93b9ef5fdbdd48354d1; __hssrc=1; _clsk=dk2mvr%7C1750295950556%7C1%7C1%7Cl.clarity.ms%2Fcollect; messagesUtk=a1a71bf707fd412b8e4bf788336568d9' \ + --header 'Sec-Fetch-Dest: document' \ + --header 'Accept-Encoding: gzip, deflate, br, zstd' \ + --header 'Sec-Fetch-Mode: navigate' \ + --header 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \ + --header 'Host: localhost:5000' \ + --header 'Connection: keep-alive' \ + --header 'Accept-Language: en-US,en;q=0.5' \ + --header 'Upgrade-Insecure-Requests: 1' \ + --header 'Sec-Fetch-Site: none' \ + --header 'Sec-Fetch-User: ?1' \ + --header 'Priority: u=0, i' \ + --header 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0' \ diff --git a/flask-sqlite/keploy/test-set-0/tests/test-6.yaml b/flask-sqlite/keploy/test-set-0/tests/test-6.yaml new file mode 100755 index 0000000..ebb18a5 --- /dev/null +++ b/flask-sqlite/keploy/test-set-0/tests/test-6.yaml @@ -0,0 +1,61 @@ +# Generated by Keploy (2.6.11) +version: api.keploy.io/v1beta1 +kind: Http +name: test-6 +spec: + metadata: {} + req: + method: GET + proto_major: 1 + proto_minor: 1 + url: http://localhost:5000/favicon.ico + header: + Accept: image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5 + Accept-Encoding: gzip, deflate, br, zstd + Accept-Language: en-US,en;q=0.5 + Connection: keep-alive + Host: localhost:5000 + Priority: u=6 + Referer: http://localhost:5000/students + Sec-Fetch-Dest: image + Sec-Fetch-Mode: no-cors + Sec-Fetch-Site: cross-site + User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0 + body: "" + timestamp: 2025-06-19T09:36:26.773273264+05:30 + resp: + status_code: 404 + header: + Content-Length: "207" + Content-Type: text/html; charset=utf-8 + Date: Thu, 19 Jun 2025 04:06:26 GMT + Server: Werkzeug/3.1.3 Python/3.12.3 + body: | + + + 404 Not Found +

Not Found

+

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

+ status_message: Not Found + proto_major: 0 + proto_minor: 0 + timestamp: 2025-06-19T09:36:28.780258492+05:30 + objects: [] + assertions: + noise: + header.Date: [] + created: 1750305988 +curl: | + curl --request GET \ + --url http://localhost:5000/favicon.ico \ + --header 'Host: localhost:5000' \ + --header 'Accept-Language: en-US,en;q=0.5' \ + --header 'Connection: keep-alive' \ + --header 'Referer: http://localhost:5000/students' \ + --header 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0' \ + --header 'Accept-Encoding: gzip, deflate, br, zstd' \ + --header 'Accept: image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5' \ + --header 'Sec-Fetch-Site: cross-site' \ + --header 'Priority: u=6' \ + --header 'Sec-Fetch-Dest: image' \ + --header 'Sec-Fetch-Mode: no-cors' \ diff --git a/flask-sqlite/models.py b/flask-sqlite/models.py new file mode 100644 index 0000000..99e387e --- /dev/null +++ b/flask-sqlite/models.py @@ -0,0 +1,8 @@ +from flask_sqlalchemy import SQLAlchemy + +db = SQLAlchemy() + +class Student(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(100), nullable=False) + age = db.Column(db.Integer, nullable=False) diff --git a/flask-sqlite/requirements.txt b/flask-sqlite/requirements.txt new file mode 100644 index 0000000..41fbe74 --- /dev/null +++ b/flask-sqlite/requirements.txt @@ -0,0 +1,2 @@ +Flask==3.0.2 +Flask_SQLAlchemy==3.1.1