├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── app ├── __init__.py ├── config.py ├── models.py ├── routes.py └── templates │ ├── base.html │ ├── content.html │ ├── footer.html │ ├── header.html │ ├── index.html │ └── update.html ├── crudapp.py ├── requirements.txt └── screenshots.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Gürkan Akdeniz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Example Python Flask Crud 2 | 3 | Simple example python flask crud app for sqlite. 4 | 5 | ## Screenshots 6 | 7 | 8 | ![image](screenshots.png) 9 | 10 | 11 | ### Installing (for linux) 12 | 13 | open the terminal and follow the white rabbit. 14 | 15 | 16 | ``` 17 | git clone https://github.com/gurkanakdeniz/example-flask-crud.git 18 | ``` 19 | ``` 20 | cd example-flask-crud/ 21 | ``` 22 | ``` 23 | python3 -m venv venv 24 | ``` 25 | ``` 26 | source venv/bin/activate 27 | ``` 28 | ``` 29 | pip install --upgrade pip 30 | ``` 31 | ``` 32 | pip install -r requirements.txt 33 | ``` 34 | ``` 35 | export FLASK_APP=crudapp.py 36 | ``` 37 | ``` 38 | flask db init 39 | ``` 40 | ``` 41 | flask db migrate -m "entries table" 42 | ``` 43 | ``` 44 | flask db upgrade 45 | ``` 46 | ``` 47 | flask run 48 | ``` 49 | 50 | ## License 51 | 52 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details 53 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-dinky -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from app.config import Config 3 | from flask_sqlalchemy import SQLAlchemy 4 | from flask_migrate import Migrate 5 | 6 | app = Flask(__name__) 7 | app.config.from_object(Config) 8 | db = SQLAlchemy(app) 9 | migrate = Migrate(app, db) 10 | 11 | from app import routes, models 12 | -------------------------------------------------------------------------------- /app/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | basedir = os.path.abspath(os.path.dirname(__file__)) 3 | 4 | class Config(object): 5 | SECRET_KEY = 'do-or-do-not-there-is-no-try' 6 | # SECRET_KEY = os.environ.get('SECRET_KEY') or 'do-or-do-not-there-is-no-try' 7 | SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///' + os.path.join(basedir, 'app.db') 8 | SQLALCHEMY_TRACK_MODIFICATIONS = False -------------------------------------------------------------------------------- /app/models.py: -------------------------------------------------------------------------------- 1 | from app import db 2 | 3 | class Entry(db.Model): 4 | id = db.Column(db.Integer, primary_key=True) 5 | title = db.Column(db.String(64), index=True, nullable=False) 6 | description = db.Column(db.String(120), index=True, nullable=False) 7 | status = db.Column(db.Boolean, default=False) -------------------------------------------------------------------------------- /app/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request, redirect 2 | from app import app, db 3 | from app.models import Entry 4 | 5 | jedi = "of the jedi" 6 | 7 | @app.route('/') 8 | @app.route('/index') 9 | def index(): 10 | # entries = [ 11 | # { 12 | # 'id' : 1, 13 | # 'title': 'test title 1', 14 | # 'description' : 'test desc 1', 15 | # 'status' : True 16 | # }, 17 | # { 18 | # 'id': 2, 19 | # 'title': 'test title 2', 20 | # 'description': 'test desc 2', 21 | # 'status': False 22 | # } 23 | # ] 24 | entries = Entry.query.all() 25 | return render_template('index.html', entries=entries) 26 | 27 | @app.route('/add', methods=['POST']) 28 | def add(): 29 | if request.method == 'POST': 30 | form = request.form 31 | title = form.get('title') 32 | description = form.get('description') 33 | if not title or description: 34 | entry = Entry(title = title, description = description) 35 | db.session.add(entry) 36 | db.session.commit() 37 | return redirect('/') 38 | 39 | return "of the jedi" 40 | 41 | @app.route('/update/') 42 | def updateRoute(id): 43 | if not id or id != 0: 44 | entry = Entry.query.get(id) 45 | if entry: 46 | return render_template('update.html', entry=entry) 47 | 48 | return "of the jedi" 49 | 50 | @app.route('/update/', methods=['POST']) 51 | def update(id): 52 | if not id or id != 0: 53 | entry = Entry.query.get(id) 54 | if entry: 55 | form = request.form 56 | title = form.get('title') 57 | description = form.get('description') 58 | entry.title = title 59 | entry.description = description 60 | db.session.commit() 61 | return redirect('/') 62 | 63 | return "of the jedi" 64 | 65 | 66 | 67 | @app.route('/delete/') 68 | def delete(id): 69 | if not id or id != 0: 70 | entry = Entry.query.get(id) 71 | if entry: 72 | db.session.delete(entry) 73 | db.session.commit() 74 | return redirect('/') 75 | 76 | return "of the jedi" 77 | 78 | @app.route('/turn/') 79 | def turn(id): 80 | if not id or id != 0: 81 | entry = Entry.query.get(id) 82 | if entry: 83 | entry.status = not entry.status 84 | db.session.commit() 85 | return redirect('/') 86 | 87 | return "of the jedi" 88 | 89 | # @app.errorhandler(Exception) 90 | # def error_page(e): 91 | # return "of the jedi" -------------------------------------------------------------------------------- /app/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 9 | 10 | 11 | 12 | {% include "header.html" %} 13 | 14 |
15 | 16 | {% block content %}{% endblock %} 17 | 18 |
19 | 20 | {% include "footer.html" %} 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/templates/content.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 | 8 |
9 |
10 |
11 |
12 |
13 | 14 |
15 |
16 | 18 |
19 | 22 |
23 |
24 |
25 |
26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | {% for entry in entries %} 39 | 40 | 41 | 42 | 43 | 57 | 58 | {% endfor %} 59 | 60 | 61 |
IdTitleDescriptionOperations
{{ entry.id }}{{ entry.title }}{{ entry.description }} 44 | 46 | Turn Status 47 | 48 | 50 | Delete 51 | 52 | 54 | Edit 55 | 56 |
62 |
63 | 64 |
65 |
66 | 67 | {% endblock %} 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /app/templates/footer.html: -------------------------------------------------------------------------------- 1 |
footer
2 | -------------------------------------------------------------------------------- /app/templates/header.html: -------------------------------------------------------------------------------- 1 | Home 2 |
header
-------------------------------------------------------------------------------- /app/templates/index.html: -------------------------------------------------------------------------------- 1 | {% include "content.html" %} -------------------------------------------------------------------------------- /app/templates/update.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 | 8 |
9 |
10 |
11 |
12 |
13 | 14 |
15 |
16 | 18 |
19 | 22 |
23 |
24 |
25 |
26 |
27 |
28 | 29 | {% endblock %} 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /crudapp.py: -------------------------------------------------------------------------------- 1 | from app import app -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | alembic==1.7.7 2 | click==8.1.3 3 | Flask==2.1.2 4 | Flask-Migrate==3.1.0 5 | Flask-SQLAlchemy==2.5.1 6 | Flask-WTF==1.0.1 7 | itsdangerous==2.1.2 8 | Jinja2==3.1.2 9 | Mako==1.2.0 10 | MarkupSafe==2.1.1 11 | python-dateutil==2.8.2 12 | python-editor==1.0.4 13 | six==1.16.0 14 | SQLAlchemy==1.4.36 15 | Werkzeug==2.1.2 16 | WTForms==3.0.1 -------------------------------------------------------------------------------- /screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkanakdeniz/example-flask-crud/efcdf038a6a4a6442f5a2c77d8c3755021fea939/screenshots.png --------------------------------------------------------------------------------