├── 10 ├── README.md └── rabbitmq-web │ ├── api │ ├── __init__.py │ ├── api_models.py │ ├── api_router.py │ └── backend │ │ ├── __init__.py │ │ ├── rpc_client.py │ │ └── rpc_server.py │ ├── endpoint.py │ └── requirements.txt ├── 11 ├── README.md └── celery-web │ ├── boston_housing │ ├── __init__.py │ ├── ml │ │ ├── __init__.py │ │ ├── datahelper.py │ │ └── trainingservice.py │ ├── tasks.py │ └── worker.py │ ├── endpoint.py │ ├── models.py │ ├── requirements.txt │ └── router.py ├── 12 └── tf-decision-forests │ ├── README.MD │ ├── TF_Decision_Forests.ipynb │ └── data │ ├── test.csv │ └── train.csv ├── 13 ├── README.MD └── sentiment_fine_tuning_huggingface_v2.ipynb ├── 14 └── hr-app │ ├── .idea │ └── .gitignore │ ├── README.MD │ └── hr_app │ ├── base │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ └── base │ │ │ ├── employee.html │ │ │ ├── employee_confirm_delete.html │ │ │ ├── employee_form.html │ │ │ ├── employee_list.html │ │ │ ├── login.html │ │ │ ├── main.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ └── views.py │ ├── hr_app │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py │ └── manage.py ├── 15 └── pyscript-web │ ├── chart.py │ ├── index.html │ ├── index2.html │ └── taxables.csv ├── 16 └── annotation-box │ ├── 1014-receipt.jpg │ └── index.html ├── 17 └── django-react │ ├── .idea │ └── .gitignore │ └── mysite │ ├── README.MD │ ├── assets │ └── index.js │ ├── manage.py │ ├── myapp │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py │ ├── mysite │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py │ ├── package-lock.json │ ├── package.json │ ├── static │ └── index-bundle.js │ ├── templates │ └── myapp │ │ └── hello_webpack.html │ └── webpack.config.js ├── 19 └── django-htmx-simple │ ├── .idea │ └── .gitignore │ └── simple_app │ ├── README.MD │ ├── base │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── display_tasks.html │ │ └── tasks_list.html │ ├── tests.py │ ├── urls.py │ └── views.py │ ├── manage.py │ └── simple_app │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── 20 └── django-htmx-sandbox │ ├── .idea │ └── .gitignore │ ├── README.MD │ ├── base │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py │ ├── db.json │ ├── manage.py │ └── uiapp │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ └── 0011_alter_employeemodel_first_name.py │ ├── models.py │ ├── templates │ ├── base.html │ ├── edit-form-htmx.html │ ├── employees-htmx.html │ ├── index.html │ ├── partials │ │ └── info.html │ └── view-table-htmx.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── 21 └── django-jet-htmx-sandbox │ ├── .idea │ └── .gitignore │ ├── README.MD │ ├── base │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py │ ├── db.json │ ├── manage.py │ └── uiapp │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ ├── 0001_initial.py │ ├── 0002_alter_employeemodel_department_id_and_more.py │ ├── 0003_alter_employeemodel_department_id_and_more.py │ ├── 0004_alter_employeemodel_hire_date.py │ ├── 0005_alter_employeemodel_job_id.py │ ├── 0006_jobmodel.py │ ├── 0007_alter_employeemodel_job_id.py │ ├── 0008_alter_employeemodel_manager_id_and_more.py │ ├── 0009_remove_employeemodel_department_id_departmentsmodel.py │ ├── 0010_employeemodel_department_id.py │ ├── 0011_alter_employeemodel_first_name.py │ └── __init__.py │ ├── models.py │ ├── static │ └── scripts │ │ └── index-page.js │ ├── templates │ ├── base.html │ └── index.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── .github └── FUNDING.yml ├── .gitignore ├── 01 └── zero-shot-pipeline-sentiment.ipynb ├── 02 └── sentiment-fine-tuning-huggingface.ipynb ├── 03 ├── data-extractor.py └── requirements.txt ├── 04 └── multi-output-model.ipynb ├── 05 └── invoiceservice │ ├── app │ ├── api │ │ ├── db.py │ │ ├── db_config.py │ │ ├── db_manager.py │ │ ├── invoices.py │ │ └── models.py │ └── main.py │ └── requirements.txt ├── 06 ├── README.md ├── react-tensorflowjs-app │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── index.css │ │ ├── index.js │ │ ├── logo.svg │ │ ├── reportWebVitals.js │ │ └── setupTests.js │ └── yarn.lock └── steps.txt ├── 07 └── rabbitmq-app │ ├── app │ ├── receive.py │ └── send.py │ └── rabbitmq │ ├── Dockerfile │ ├── docker-compose.yml │ └── init.sh ├── 08 ├── README.md ├── data_chart.jpg └── react-tensorflowjs-app │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── dataHelper.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── modelTraining.js │ ├── reportWebVitals.js │ └── setupTests.js │ └── yarn.lock ├── 09 └── backend-app │ ├── README.MD │ ├── docker-compose.yml │ └── invoiceservice │ ├── Dockerfile │ ├── app │ ├── api │ │ ├── db.py │ │ ├── db_config.py │ │ ├── db_manager.py │ │ ├── invoices.py │ │ └── models.py │ └── main.py │ ├── python38.module │ └── requirements.txt ├── LICENSE └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [abaranovskis-redsamurai] 4 | -------------------------------------------------------------------------------- /.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 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | .DS_Store 131 | 14/hr-app/.idea/hr-app.iml 132 | 14/hr-app/.idea/inspectionProfiles/profiles_settings.xml 133 | 14/hr-app/.idea/inspectionProfiles/Project_Default.xml 134 | 14/hr-app/.idea/misc.xml 135 | 14/hr-app/.idea/modules.xml 136 | 14/hr-app/.idea/vcs.xml 137 | 17/django-react/.idea/django-react.iml 138 | 17/django-react/.idea/inspectionProfiles/profiles_settings.xml 139 | 17/django-react/.idea/inspectionProfiles/Project_Default.xml 140 | 17/django-react/.idea/misc.xml 141 | 17/django-react/.idea/modules.xml 142 | 17/django-react/.idea/vcs.xml 143 | 17/django-react/mysite/node_modules/ 144 | 19/django-htmx-simple/.idea/django-htmx-simple.iml 145 | 19/django-htmx-simple/.idea/inspectionProfiles/profiles_settings.xml 146 | 19/django-htmx-simple/.idea/inspectionProfiles/Project_Default.xml 147 | 19/django-htmx-simple/.idea/misc.xml 148 | 19/django-htmx-simple/.idea/modules.xml 149 | 19/django-htmx-simple/simple_app/base/migrations/0001_initial.py 150 | 19/django-htmx-simple/simple_app/base/migrations/0002_taskmodel_delete_task.py 151 | 19/django-htmx-simple/simple_app/base/migrations/__init__.py 152 | 20/django-htmx-sandbox/.idea/dataSources.xml 153 | 20/django-htmx-sandbox/.idea/django-htmx-sandbox.iml 154 | 20/django-htmx-sandbox/.idea/inspectionProfiles/profiles_settings.xml 155 | 20/django-htmx-sandbox/.idea/inspectionProfiles/Project_Default.xml 156 | 20/django-htmx-sandbox/.idea/misc.xml 157 | 20/django-htmx-sandbox/.idea/modules.xml 158 | 20/django-htmx-sandbox/.idea/vcs.xml 159 | 20/django-htmx-sandbox/uiapp/migrations/0001_initial.py 160 | 20/django-htmx-sandbox/uiapp/migrations/0002_alter_employeemodel_department_id_and_more.py 161 | 20/django-htmx-sandbox/uiapp/migrations/0003_alter_employeemodel_department_id_and_more.py 162 | 20/django-htmx-sandbox/uiapp/migrations/0004_alter_employeemodel_hire_date.py 163 | 20/django-htmx-sandbox/uiapp/migrations/0005_alter_employeemodel_job_id.py 164 | 20/django-htmx-sandbox/uiapp/migrations/0006_jobmodel.py 165 | 20/django-htmx-sandbox/uiapp/migrations/0007_alter_employeemodel_job_id.py 166 | 20/django-htmx-sandbox/uiapp/migrations/0008_alter_employeemodel_manager_id_and_more.py 167 | 20/django-htmx-sandbox/uiapp/migrations/0009_remove_employeemodel_department_id_departmentsmodel.py 168 | 20/django-htmx-sandbox/uiapp/migrations/0010_employeemodel_department_id.py 169 | 20/django-htmx-sandbox/uiapp/migrations/__init__.py 170 | 21/django-jet-htmx-sandbox/.idea/dataSources.xml 171 | 21/django-jet-htmx-sandbox/.idea/django-jet-htmx-sandbox.iml 172 | 21/django-jet-htmx-sandbox/.idea/inspectionProfiles/profiles_settings.xml 173 | 21/django-jet-htmx-sandbox/.idea/inspectionProfiles/Project_Default.xml 174 | 21/django-jet-htmx-sandbox/.idea/misc.xml 175 | 21/django-jet-htmx-sandbox/.idea/modules.xml 176 | 21/django-jet-htmx-sandbox/.idea/vcs.xml 177 | -------------------------------------------------------------------------------- /03/data-extractor.py: -------------------------------------------------------------------------------- 1 | import dateparser 2 | from price_parser import Price 3 | from schwifty import IBAN 4 | 5 | # https://pypi.org/project/dateparser/ 6 | # https://pypi.org/project/price-parser/ 7 | # https://pypi.org/project/schwifty/ 8 | 9 | def main(): 10 | d = dateparser.parse('2.Mai 2020', languages=['de']) 11 | print(d) 12 | d = dateparser.parse('2.Abc 2020', languages=['de']) 13 | print(d) 14 | d = dateparser.parse('2020.12.8') 15 | print(d) 16 | print() 17 | 18 | p = Price.fromstring("-114,47 €") 19 | print(p) 20 | p = Price.fromstring("3 500 руб") 21 | print(p) 22 | p = Price.fromstring("Rs. 11,499") 23 | print(p) 24 | p = Price.fromstring("$1499.99") 25 | print(p) 26 | p = Price.fromstring("199,999.00") 27 | print(p) 28 | p = Price.fromstring("199.999,00") 29 | print(p) 30 | print() 31 | 32 | i = IBAN('LT12 1000 0111 0100 1000') 33 | print(i.country) 34 | i = IBAN('DE89 3704 0044 0532 0130 00') 35 | print(i.country) 36 | try: 37 | i = IBAN('DE89 3704') 38 | print(i.country) 39 | except Exception as e: 40 | print(e) 41 | 42 | if __name__ == "__main__": 43 | main() -------------------------------------------------------------------------------- /03/requirements.txt: -------------------------------------------------------------------------------- 1 | dateparser~=1.0.0 2 | schwifty~=2020.11.0 3 | price-parser~=0.3.4 -------------------------------------------------------------------------------- /05/invoiceservice/app/api/db.py: -------------------------------------------------------------------------------- 1 | # Based on: https://blogs.oracle.com/opal/how-to-use-python-flask-with-oracle-database 2 | 3 | import cx_Oracle 4 | from invoiceservice.app.api import db_config 5 | 6 | pool = None 7 | 8 | def init_db(): 9 | cx_Oracle.init_oracle_client(lib_dir=db_config.oracle_client) 10 | 11 | def init_session(connection, requestedTag_ignored): 12 | cursor = connection.cursor() 13 | cursor.execute(""" 14 | ALTER SESSION SET 15 | TIME_ZONE = 'UTC' 16 | NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI'""") 17 | 18 | def start_pool(): 19 | 20 | # Generally a fixed-size pool is recommended, i.e. pool_min=pool_max. 21 | # Here the pool contains 4 connections, which is fine for 4 conncurrent 22 | # users. 23 | # 24 | # The "get mode" is chosen so that if all connections are already in use, any 25 | # subsequent acquire() will wait for one to become available. 26 | # 27 | # Note there is no explicit 'close cursor' or 'close connection'. At the 28 | # end-of-scope when init_session() finishes, the cursor and connection will be 29 | # closed automatically. In real apps with a bigger code base, you will want to 30 | # close each connection as early as possible so another web request can use it. 31 | 32 | pool_min = 4 33 | pool_max = 4 34 | pool_inc = 0 35 | pool_gmd = cx_Oracle.SPOOL_ATTRVAL_WAIT 36 | 37 | username = db_config.user 38 | password = db_config.pw 39 | connect_string = db_config.connect_string 40 | 41 | print("Connecting to", connect_string) 42 | 43 | global pool 44 | pool = cx_Oracle.SessionPool(user=username, 45 | password=password, 46 | dsn=connect_string, 47 | min=pool_min, 48 | max=pool_max, 49 | increment=pool_inc, 50 | threaded=True, 51 | getmode=pool_gmd, 52 | sessionCallback=init_session) 53 | 54 | def fetch_all_invoices(): 55 | connection = pool.acquire() 56 | cursor = connection.cursor() 57 | sql = "select to_char(invoice_date, 'yyyy-mm-dd') as invoice_date, invoice_number, total from invoices where " \ 58 | "total > :total_var order by total" 59 | total_var = 200 60 | cursor.execute(sql, [total_var]) 61 | 62 | cursor.rowfactory = lambda *args: dict(zip([d[0] for d in cursor.description], args)) 63 | data = cursor.fetchall() 64 | 65 | return data -------------------------------------------------------------------------------- /05/invoiceservice/app/api/db_config.py: -------------------------------------------------------------------------------- 1 | user = "username" 2 | pw = "password" 3 | oracle_client = "/Users/andrejb/mywork/cloud/db/instantclient_19_8" 4 | connect_string = "tcps://adb.eu-frankfurt-1.oraclecloud.com:1522/n3irgbwjvjxwqfk_katanadb_medium.adb.oraclecloud.com?" \ 5 | "wallet_location=/Users/andrejb/infra/shared/wallets/Wallet_katanaDB&retry_delay=3" -------------------------------------------------------------------------------- /05/invoiceservice/app/api/db_manager.py: -------------------------------------------------------------------------------- 1 | import invoiceservice.app.api.db as db 2 | 3 | def get_all_invoices(): 4 | data = db.fetch_all_invoices() 5 | 6 | return data -------------------------------------------------------------------------------- /05/invoiceservice/app/api/invoices.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from fastapi import APIRouter 3 | 4 | from invoiceservice.app.api import db_manager 5 | from invoiceservice.app.api.models import Invoice 6 | 7 | invoices = APIRouter() 8 | 9 | @invoices.get('/') 10 | def test(): 11 | return 'API is running' 12 | 13 | @invoices.get('/all', response_model=List[Invoice]) 14 | def get_all_invoices(): 15 | return db_manager.get_all_invoices() -------------------------------------------------------------------------------- /05/invoiceservice/app/api/models.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class Invoice(BaseModel): 4 | INVOICE_DATE: str 5 | INVOICE_NUMBER: str 6 | TOTAL: float 7 | -------------------------------------------------------------------------------- /05/invoiceservice/app/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi.middleware.cors import CORSMiddleware 3 | from invoiceservice.app.api.invoices import invoices 4 | import invoiceservice.app.api.db as db 5 | 6 | app = FastAPI(openapi_url='/api/v1/invoices/openapi.json', docs_url='/api/v1/invoices/docs') 7 | 8 | app.add_middleware( 9 | CORSMiddleware, 10 | allow_origins=["*"], 11 | allow_methods=["*"], 12 | allow_headers=["*"], 13 | allow_credentials=True, 14 | ) 15 | 16 | @app.on_event("startup") 17 | def startup(): 18 | db.init_db() 19 | db.start_pool() 20 | 21 | app.include_router(invoices, prefix='/api/v1/invoices') -------------------------------------------------------------------------------- /05/invoiceservice/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.63.0 2 | uvicorn==0.13.3 -------------------------------------------------------------------------------- /06/README.md: -------------------------------------------------------------------------------- 1 | Instructions: 2 | 3 | 1. yarn install 4 | 2. yarn start 5 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `yarn build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-tensorflowjs-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@tensorflow/tfjs": "^2.8.6", 7 | "@testing-library/jest-dom": "^5.11.4", 8 | "@testing-library/react": "^11.1.0", 9 | "@testing-library/user-event": "^12.1.10", 10 | "react": "^17.0.1", 11 | "react-dom": "^17.0.1", 12 | "react-scripts": "4.0.2", 13 | "web-vitals": "^1.0.1" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": [ 23 | "react-app", 24 | "react-app/jest" 25 | ] 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/06/react-tensorflowjs-app/public/favicon.ico -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/06/react-tensorflowjs-app/public/logo192.png -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/06/react-tensorflowjs-app/public/logo512.png -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/src/App.js: -------------------------------------------------------------------------------- 1 | import logo from './logo.svg'; 2 | import './App.css'; 3 | import * as tf from '@tensorflow/tfjs'; 4 | 5 | const handleRunTraining = (event) => { 6 | const model = tf.sequential(); 7 | model.add(tf.layers.dense({ units: 1, inputShape: [1] })); 8 | 9 | model.compile({ optimizer: tf.train.sgd(0.1), loss: 'meanSquaredError' }); 10 | model.summary(); 11 | 12 | // y = 2x - 1 13 | const xs = tf.tensor2d([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], [6, 1]); 14 | const ys = tf.tensor2d([-3.0, -1.0, 2.0, 3.0, 5.0, 7.0], [6, 1]); 15 | doTraining(model, xs, ys).then(() => { 16 | const prediction = model.predict(tf.tensor2d([10], [1, 1])); 17 | var res = prediction.dataSync()[0]; 18 | prediction.dispose(); 19 | 20 | console.log('Result: ' + res); 21 | }); 22 | }; 23 | 24 | async function doTraining(model, xs, ys) { 25 | const history = 26 | await model.fit(xs, ys, 27 | { 28 | epochs: 200, 29 | callbacks: { 30 | onEpochEnd: async (epoch, logs) => { 31 | console.log("Epoch:" 32 | + epoch 33 | + " Loss:" 34 | + logs.loss); 35 | 36 | } 37 | } 38 | }); 39 | console.log(history.params); 40 | } 41 | 42 | function App() { 43 | return ( 44 |
45 |
46 | logo 47 |

48 | Edit src/App.js and save to reload. 49 |

50 | 56 | Learn React 57 | 58 |
59 | 60 |
61 |
62 | ); 63 | } 64 | 65 | export default App; 66 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /06/react-tensorflowjs-app/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /06/steps.txt: -------------------------------------------------------------------------------- 1 | 1. yarn create react-app react-tensorflowjs-app 2 | 3 | 2. cd react-tensorflowjs-app 4 | 5 | 3. yarn add @tensorflow/tfjs 6 | 7 | 4. yarn start 8 | 9 | 5. Button and listener 10 | 11 | 12 | 13 | const handleRunTraining = (event) => { 14 | 15 | }; 16 | 17 | 6. Training function 18 | 19 | import * as tf from '@tensorflow/tfjs'; 20 | 21 | async function doTraining(model, xs, ys) { 22 | const history = 23 | await model.fit(xs, ys, 24 | { 25 | epochs: 200, 26 | callbacks: { 27 | onEpochEnd: async (epoch, logs) => { 28 | console.log("Epoch:" 29 | + epoch 30 | + " Loss:" 31 | + logs.loss); 32 | 33 | } 34 | } 35 | }); 36 | console.log(history.params); 37 | } 38 | 39 | 7. Model construction 40 | 41 | const model = tf.sequential(); 42 | model.add(tf.layers.dense({ units: 1, inputShape: [1] })); 43 | 44 | model.compile({ optimizer: tf.train.sgd(0.1), loss: 'meanSquaredError' }); 45 | model.summary(); 46 | 47 | // y = 2x - 1 48 | const xs = tf.tensor2d([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], [6, 1]); 49 | const ys = tf.tensor2d([-3.0, -1.0, 2.0, 3.0, 5.0, 7.0], [6, 1]); 50 | doTraining(model, xs, ys).then(() => { 51 | const prediction = model.predict(tf.tensor2d([10], [1, 1])); 52 | var res = prediction.dataSync()[0]; 53 | prediction.dispose(); 54 | 55 | console.log('Result: ' + res); 56 | }); -------------------------------------------------------------------------------- /07/rabbitmq-app/app/receive.py: -------------------------------------------------------------------------------- 1 | import pika, sys, os 2 | 3 | def main(): 4 | connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) 5 | channel = connection.channel() 6 | 7 | channel.queue_declare(queue='hello') 8 | 9 | def callback(ch, method, properties, body): 10 | print(" [x] Received %r" % body) 11 | 12 | channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=True) 13 | 14 | print(' [*] Waiting for messages. To exit press CTRL+C') 15 | channel.start_consuming() 16 | 17 | if __name__ == '__main__': 18 | try: 19 | main() 20 | except KeyboardInterrupt: 21 | print('Interrupted') 22 | try: 23 | sys.exit(0) 24 | except SystemExit: 25 | os._exit(0) -------------------------------------------------------------------------------- /07/rabbitmq-app/app/send.py: -------------------------------------------------------------------------------- 1 | import pika 2 | 3 | connection = pika.BlockingConnection( 4 | pika.ConnectionParameters(host='localhost')) 5 | channel = connection.channel() 6 | 7 | channel.queue_declare(queue='hello') 8 | 9 | channel.basic_publish(exchange='', routing_key='hello', body='Hello World!') 10 | print(" [x] Sent 'Hello World!'") 11 | connection.close() -------------------------------------------------------------------------------- /07/rabbitmq-app/rabbitmq/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rabbitmq:3.8 2 | 3 | WORKDIR /usr/local/bin/ 4 | ADD ./init.sh . 5 | RUN chmod +x ./init.sh 6 | 7 | CMD ["./init.sh"] 8 | -------------------------------------------------------------------------------- /07/rabbitmq-app/rabbitmq/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | rabbitmq: 4 | build: 5 | context: . 6 | dockerfile: Dockerfile 7 | container_name: "rabbitmq-3.8" 8 | restart: always 9 | ports: 10 | - 5672:5672 11 | - 15672:15672 12 | volumes: 13 | - ./rabbitmq/etc/:/etc/rabbitmq/ 14 | - ./rabbitmq/data/:/var/lib/rabbitmq/ 15 | - ./rabbitmq/logs/:/var/log/rabbitmq/ 16 | environment: 17 | - RABBITMQ_DEFAULT_USER=guest 18 | - RABBITMQ_DEFAULT_PASS=guest 19 | - RABBITMQ_NODENAME=rabbitnode@localhost 20 | - RABBITMQ_USER=rabbit 21 | - RABBITMQ_PASSWORD=rabbit 22 | volumes: 23 | rabbitmq: 24 | -------------------------------------------------------------------------------- /07/rabbitmq-app/rabbitmq/init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # docker-compose up 4 | # http://localhost:15672/ 5 | # docker-compose down 6 | 7 | set -e 8 | ( 9 | count=0; 10 | # Execute list_users until service is up and running 11 | until timeout 5 rabbitmqctl list_users >/dev/null 2>/dev/null || (( count++ >= 60 )); do sleep 1; done; 12 | 13 | # Enable plugins 14 | rabbitmq-plugins enable rabbitmq_management 15 | 16 | # Register user 17 | if rabbitmqctl list_users | grep $RABBITMQ_USER > /dev/null 18 | then 19 | echo "User '$RABBITMQ_USER' already exist, skipping user creation" 20 | else 21 | echo "Creating user '$RABBITMQ_USER'..." 22 | rabbitmqctl add_user $RABBITMQ_USER $RABBITMQ_PASSWORD 23 | rabbitmqctl set_user_tags $RABBITMQ_USER administrator 24 | rabbitmqctl set_permissions -p / $RABBITMQ_USER ".*" ".*" ".*" 25 | echo "User '$RABBITMQ_USER' creation completed" 26 | fi 27 | ) & 28 | 29 | # Call original entrypoint 30 | exec docker-entrypoint.sh rabbitmq-server $@ 31 | -------------------------------------------------------------------------------- /08/README.md: -------------------------------------------------------------------------------- 1 | Instructions: 2 | 3 | 1. yarn install 4 | 2. yarn start 5 | -------------------------------------------------------------------------------- /08/data_chart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/08/data_chart.jpg -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `yarn build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-tensorflowjs-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@tensorflow/tfjs": "^2.8.6", 7 | "@testing-library/jest-dom": "^5.11.4", 8 | "@testing-library/react": "^11.1.0", 9 | "@testing-library/user-event": "^12.1.10", 10 | "react": "^17.0.1", 11 | "react-dom": "^17.0.1", 12 | "react-scripts": "4.0.2", 13 | "web-vitals": "^1.0.1" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": [ 23 | "react-app", 24 | "react-app/jest" 25 | ] 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/08/react-tensorflowjs-app/public/favicon.ico -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/08/react-tensorflowjs-app/public/logo192.png -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/08/react-tensorflowjs-app/public/logo512.png -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/App.js: -------------------------------------------------------------------------------- 1 | import logo from './logo.svg'; 2 | import './App.css'; 3 | import * as tf from '@tensorflow/tfjs'; 4 | import { prepareData } from "./dataHelper"; 5 | import { runTraining } from "./modelTraining"; 6 | 7 | const handleRunTraining = async (event) => { 8 | const [numOfFeatures, convertedDataTraining, convertedDataValidation] = prepareData(); 9 | 10 | console.log('Training data:'); 11 | await convertedDataTraining.forEachAsync(e => console.log(e)); 12 | 13 | await runTraining(numOfFeatures, convertedDataTraining, convertedDataValidation); 14 | }; 15 | 16 | const handleRunInference = async (event) => { 17 | const model = await tf.loadLayersModel('indexeddb://basic-model'); 18 | 19 | let data = [500, 850]; 20 | data[0] = (data[0] / (1000 / 2)) - 1; 21 | data[1] = (data[1] / (1000 / 2)) - 1; 22 | 23 | const input = tf.tensor2d(data, [1, data.length]); 24 | const prediction = model.predict(input); 25 | 26 | const pIndex = tf.argMax(prediction, 1).dataSync(); 27 | const classNames = ["Red", "Green", "Blue"]; 28 | const probability = prediction.dataSync()[pIndex]; 29 | const result = classNames[pIndex]; 30 | 31 | prediction.dispose(); 32 | 33 | console.log(result + ' : ' + probability); 34 | } 35 | 36 | function App() { 37 | return ( 38 |
39 |
40 | logo 41 |

42 | Edit src/App.js and save to reload. 43 |

44 | 50 | Learn React 51 | 52 |
53 | 54 | 55 | 56 | 59 | 62 | 63 | 64 |
57 | 58 | 60 | 61 |
65 |
66 |
67 | ); 68 | } 69 | 70 | export default App; 71 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/dataHelper.js: -------------------------------------------------------------------------------- 1 | import * as tf from "@tensorflow/tfjs"; 2 | 3 | export function prepareData() { 4 | let data = []; 5 | 6 | const redData1 = { xs: [150, 200], ys: 'Red' }; 7 | const redData2 = { xs: [150, 400], ys: 'Red' }; 8 | const redData3 = { xs: [200, 250], ys: 'Red' }; 9 | const redData4 = { xs: [250, 150], ys: 'Red' }; 10 | const redData5 = { xs: [250, 350], ys: 'Red' }; 11 | const redData6 = { xs: [300, 300], ys: 'Red' }; 12 | 13 | const greenData1 = { xs: [500, 700], ys: 'Green' }; 14 | const greenData2 = { xs: [550, 800], ys: 'Green' }; 15 | const greenData3 = { xs: [550, 900], ys: 'Green' }; 16 | const greenData4 = { xs: [600, 700], ys: 'Green' }; 17 | const greenData5 = { xs: [600, 750], ys: 'Green' }; 18 | const greenData6 = { xs: [650, 850], ys: 'Green' }; 19 | 20 | const blueData1 = { xs: [800, 200], ys: 'Blue' }; 21 | const blueData2 = { xs: [850, 100], ys: 'Blue' }; 22 | const blueData3 = { xs: [850, 400], ys: 'Blue' }; 23 | const blueData4 = { xs: [900, 200], ys: 'Blue' }; 24 | const blueData5 = { xs: [900, 250], ys: 'Blue' }; 25 | const blueData6 = { xs: [950, 200], ys: 'Blue' }; 26 | 27 | data.push(redData1); 28 | data.push(redData2); 29 | data.push(redData3); 30 | data.push(redData4); 31 | data.push(redData5); 32 | data.push(redData6); 33 | 34 | data.push(greenData1); 35 | data.push(greenData2); 36 | data.push(greenData3); 37 | data.push(greenData4); 38 | data.push(greenData5); 39 | data.push(greenData6); 40 | 41 | data.push(blueData1); 42 | data.push(blueData2); 43 | data.push(blueData3); 44 | data.push(blueData4); 45 | data.push(blueData5); 46 | data.push(blueData6); 47 | 48 | data.forEach(function (item, index) { 49 | item.xs[0] = (item.xs[0] / (1000 / 2)) - 1; 50 | item.xs[1] = (item.xs[1] / (1000 / 2)) - 1; 51 | }) 52 | 53 | console.log('Data size: ' + data.length); 54 | console.log(data); 55 | const training_size = Math.round((data.length * 80) / 100); 56 | 57 | const dataShuffled = tf.data.array(data).shuffle(3); 58 | 59 | const dataTraining = dataShuffled.take(training_size); 60 | const dataValidation = dataShuffled.skip(training_size); 61 | 62 | const convertedDataTraining = 63 | dataTraining.map(({ xs, ys }) => { 64 | const labels = [ 65 | ys == "Red" ? 1 : 0, 66 | ys == "Green" ? 1 : 0, 67 | ys == "Blue" ? 1 : 0 68 | ] 69 | return { xs: Object.values(xs), ys: Object.values(labels) }; 70 | }).batch(1); 71 | 72 | const convertedDataValidation = 73 | dataValidation.map(({ xs, ys }) => { 74 | const labels = [ 75 | ys == "Red" ? 1 : 0, 76 | ys == "Green" ? 1 : 0, 77 | ys == "Blue" ? 1 : 0 78 | ] 79 | return { xs: Object.values(xs), ys: Object.values(labels) }; 80 | }).batch(1); 81 | 82 | const numOfFeatures = 2; 83 | 84 | return [numOfFeatures, convertedDataTraining, convertedDataValidation]; 85 | } -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/modelTraining.js: -------------------------------------------------------------------------------- 1 | import * as tf from "@tensorflow/tfjs"; 2 | 3 | function buildModel(numOfFeatures) { 4 | const model = tf.sequential(); 5 | 6 | model.add(tf.layers.dense({ 7 | inputShape: [numOfFeatures], 8 | units: 12, 9 | activation: 'relu' 10 | })); 11 | model.add(tf.layers.dense({ 12 | units: 3, 13 | activation: 'softmax' 14 | })); 15 | 16 | model.compile({ optimizer: tf.train.adam(0.01), loss: 'categoricalCrossentropy', metrics: 'accuracy' }); 17 | 18 | return model; 19 | } 20 | 21 | export async function runTraining(numOfFeatures, convertedDataTraining, convertedDataValidation) { 22 | const model = buildModel(numOfFeatures); 23 | 24 | const history = await model.fitDataset( 25 | convertedDataTraining, 26 | { 27 | epochs: 100, 28 | validationData: convertedDataValidation, 29 | callbacks: {onEpochEnd: (epoch, logs) => { 30 | console.log("Epoch: " + epoch + " Loss: " + logs.loss + " Accuracy: " + logs.acc + " Validation loss: " 31 | + logs.val_loss + " Validation accuracy: " + logs.val_acc); 32 | } 33 | }}); 34 | 35 | await model.save('indexeddb://basic-model'); 36 | console.log('Model saved'); 37 | 38 | return history; 39 | } -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /08/react-tensorflowjs-app/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /09/backend-app/README.MD: -------------------------------------------------------------------------------- 1 | ## FastAPI and Oracle DB Client in Docker 2 | 3 | # Commands 4 | 5 | * docker-compose up --build 6 | * docker-compose up --build -d (in detached mode) 7 | 8 | * docker images 9 | 10 | * docker ps -a 11 | 12 | * docker exec -it invoice-service /bin/bash 13 | 14 | * docker-compose down 15 | 16 | # API 17 | 18 | * http://127.0.0.1:8001/api/v1/invoices/docs 19 | 20 | # Environment variables in docker-compose.yml 21 | 22 | * USERNAME=user 23 | * PASSWORD=pass 24 | * CONNECT_STRING=tcps://adb.eu-frankfurt-1.oraclecloud.com:1522/aaa_db_medium.adb.oraclecloud.com 25 | -------------------------------------------------------------------------------- /09/backend-app/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | 3 | services: 4 | invoice-service: 5 | image: katanaml/invoice-service 6 | build: 7 | context: ./invoiceservice 8 | dockerfile: Dockerfile 9 | container_name: invoice-service 10 | ports: 11 | - 8001:8000 12 | command: uvicorn invoiceservice.app.main:app --reload --host 0.0.0.0 13 | volumes: 14 | - /Users/andrejb/infra/shared/wallets/Wallet_katanaDB:/usr/lib/oracle/21/client64/lib/network/admin:Z,ro 15 | environment: 16 | - USERNAME=user 17 | - PASSWORD=pass 18 | - CONNECT_STRING=tcps://adb.eu-frankfurt-1.oraclecloud.com:1522/abc_db_medium.adb.oraclecloud.com 19 | networks: 20 | - network1 21 | restart: 'no' 22 | 23 | networks: 24 | network1: 25 | name: katana-network -------------------------------------------------------------------------------- /09/backend-app/invoiceservice/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM oraclelinux:8-slim 2 | 3 | COPY python38.module /etc/dnf/modules.d/python38.module 4 | 5 | COPY ./requirements.txt /invoiceservice/requirements.txt 6 | 7 | RUN microdnf install oracle-instantclient-release-el8 && \ 8 | microdnf install oracle-instantclient-basic oracle-instantclient-devel oracle-instantclient-sqlplus && \ 9 | microdnf clean all 10 | 11 | RUN microdnf install python38 \ 12 | python38-libs \ 13 | python38-pip \ 14 | python38-setuptools && \ 15 | microdnf clean all 16 | 17 | RUN python3 -m pip install cx_Oracle 18 | 19 | RUN python3 -m pip install -r /invoiceservice/requirements.txt \ 20 | && rm -rf /root/.cache/pip 21 | 22 | COPY ./app /invoiceservice/app/ -------------------------------------------------------------------------------- /09/backend-app/invoiceservice/app/api/db.py: -------------------------------------------------------------------------------- 1 | # Based on: https://blogs.oracle.com/opal/how-to-use-python-flask-with-oracle-database 2 | 3 | import cx_Oracle 4 | from invoiceservice.app.api import db_config 5 | 6 | pool = None 7 | 8 | def init_db(): 9 | cx_Oracle.init_oracle_client(lib_dir=db_config.oracle_client) 10 | 11 | def init_session(connection, requestedTag_ignored): 12 | cursor = connection.cursor() 13 | cursor.execute(""" 14 | ALTER SESSION SET 15 | TIME_ZONE = 'UTC' 16 | NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI'""") 17 | 18 | def start_pool(): 19 | 20 | # Generally a fixed-size pool is recommended, i.e. pool_min=pool_max. 21 | # Here the pool contains 4 connections, which is fine for 4 conncurrent 22 | # users. 23 | # 24 | # The "get mode" is chosen so that if all connections are already in use, any 25 | # subsequent acquire() will wait for one to become available. 26 | # 27 | # Note there is no explicit 'close cursor' or 'close connection'. At the 28 | # end-of-scope when init_session() finishes, the cursor and connection will be 29 | # closed automatically. In real apps with a bigger code base, you will want to 30 | # close each connection as early as possible so another web request can use it. 31 | 32 | pool_min = 4 33 | pool_max = 4 34 | pool_inc = 0 35 | pool_gmd = cx_Oracle.SPOOL_ATTRVAL_WAIT 36 | 37 | username = db_config.user 38 | password = db_config.pw 39 | connect_string = db_config.connect_string 40 | 41 | print("Connecting to", connect_string) 42 | 43 | global pool 44 | pool = cx_Oracle.SessionPool(user=username, 45 | password=password, 46 | dsn=connect_string, 47 | min=pool_min, 48 | max=pool_max, 49 | increment=pool_inc, 50 | threaded=True, 51 | getmode=pool_gmd, 52 | sessionCallback=init_session) 53 | 54 | def fetch_all_invoices(): 55 | connection = pool.acquire() 56 | cursor = connection.cursor() 57 | sql = "select to_char(invoice_date, 'yyyy-mm-dd') as invoice_date, invoice_number, total from invoices where " \ 58 | "total > :total_var order by total" 59 | total_var = 200 60 | cursor.execute(sql, [total_var]) 61 | 62 | cursor.rowfactory = lambda *args: dict(zip([d[0] for d in cursor.description], args)) 63 | data = cursor.fetchall() 64 | 65 | return data -------------------------------------------------------------------------------- /09/backend-app/invoiceservice/app/api/db_config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | user = os.environ.get('USERNAME'); 4 | pw = os.environ.get('PASSWORD'); 5 | oracle_client = '/usr/lib/oracle/21/client64/lib'; 6 | connect_string = os.environ.get('CONNECT_STRING') + '?' \ 7 | 'wallet_location=/usr/lib/oracle/21/client64/lib/network/admin&retry_delay=3'; -------------------------------------------------------------------------------- /09/backend-app/invoiceservice/app/api/db_manager.py: -------------------------------------------------------------------------------- 1 | import invoiceservice.app.api.db as db 2 | 3 | def get_all_invoices(): 4 | data = db.fetch_all_invoices() 5 | 6 | return data -------------------------------------------------------------------------------- /09/backend-app/invoiceservice/app/api/invoices.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from fastapi import APIRouter 3 | 4 | from invoiceservice.app.api import db_manager 5 | from invoiceservice.app.api.models import Invoice 6 | 7 | invoices = APIRouter() 8 | 9 | @invoices.get('/') 10 | def test(): 11 | return 'API is running' 12 | 13 | @invoices.get('/all', response_model=List[Invoice]) 14 | def get_all_invoices(): 15 | return db_manager.get_all_invoices() -------------------------------------------------------------------------------- /09/backend-app/invoiceservice/app/api/models.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class Invoice(BaseModel): 4 | INVOICE_DATE: str 5 | INVOICE_NUMBER: str 6 | TOTAL: float 7 | -------------------------------------------------------------------------------- /09/backend-app/invoiceservice/app/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi.middleware.cors import CORSMiddleware 3 | from invoiceservice.app.api.invoices import invoices 4 | import invoiceservice.app.api.db as db 5 | 6 | app = FastAPI(openapi_url='/api/v1/invoices/openapi.json', docs_url='/api/v1/invoices/docs') 7 | 8 | app.add_middleware( 9 | CORSMiddleware, 10 | allow_origins=["*"], 11 | allow_methods=["*"], 12 | allow_headers=["*"], 13 | allow_credentials=True, 14 | ) 15 | 16 | @app.on_event("startup") 17 | def startup(): 18 | db.init_db() 19 | db.start_pool() 20 | 21 | app.include_router(invoices, prefix='/api/v1/invoices') -------------------------------------------------------------------------------- /09/backend-app/invoiceservice/python38.module: -------------------------------------------------------------------------------- 1 | [python38] 2 | name=python38 3 | stream=3.8 4 | profiles=common 5 | state=enabled -------------------------------------------------------------------------------- /09/backend-app/invoiceservice/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.63.0 2 | uvicorn==0.13.3 -------------------------------------------------------------------------------- /10/README.md: -------------------------------------------------------------------------------- 1 | # RabbitMQ RPC with FastAPI 2 | 3 | Sample app with FastAPI endpoint. RabbitMQ is used as a postman to deliver and return message between endpoint API and backend. Backend code could run on different microservice. Multiple backends can be started for scalability. 4 | 5 | RabbitMQ logic is based on official example [Remote procedure call (RPC)](https://www.rabbitmq.com/tutorials/tutorial-six-python.html) 6 | 7 | ## Commands 8 | 9 | * Start backend (you can start multiple instances) 10 | * **python rpc_server.py** 11 | * Start FastAPI endpoint (from rabbitmq-web folder) 12 | * **uvicorn endpoint:app --reload** 13 | 14 | 15 | API url: http://127.0.0.1:8000/api/v1/fibonacci/docs 16 | -------------------------------------------------------------------------------- /10/rabbitmq-web/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/10/rabbitmq-web/api/__init__.py -------------------------------------------------------------------------------- /10/rabbitmq-web/api/api_models.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class Data(BaseModel): 4 | fibNumber: int -------------------------------------------------------------------------------- /10/rabbitmq-web/api/api_router.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | from api.api_models import Data 3 | from api.backend.rpc_client import FibonacciRpcClient 4 | 5 | router = APIRouter() 6 | 7 | @router.get('/') 8 | def test(): 9 | return 'API is running' 10 | 11 | @router.post('/calculate') 12 | def calculate_fibonacci(inputData:Data): 13 | fibonacci_rpc = FibonacciRpcClient() 14 | 15 | print(" [x] Requesting fib(%s)" % inputData.fibNumber) 16 | response = fibonacci_rpc.call(inputData.fibNumber) 17 | print(" [.] Got %r" % response) 18 | 19 | return response -------------------------------------------------------------------------------- /10/rabbitmq-web/api/backend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/10/rabbitmq-web/api/backend/__init__.py -------------------------------------------------------------------------------- /10/rabbitmq-web/api/backend/rpc_client.py: -------------------------------------------------------------------------------- 1 | import pika 2 | import uuid 3 | 4 | class FibonacciRpcClient(object): 5 | 6 | def __init__(self): 7 | self.connection = pika.BlockingConnection( 8 | pika.ConnectionParameters(host='localhost')) 9 | 10 | self.channel = self.connection.channel() 11 | 12 | result = self.channel.queue_declare(queue='', exclusive=True) 13 | self.callback_queue = result.method.queue 14 | 15 | self.channel.basic_consume( 16 | queue=self.callback_queue, 17 | on_message_callback=self.on_response, 18 | auto_ack=True) 19 | 20 | def on_response(self, ch, method, props, body): 21 | if self.corr_id == props.correlation_id: 22 | self.response = body 23 | 24 | def call(self, n): 25 | self.response = None 26 | self.corr_id = str(uuid.uuid4()) 27 | self.channel.basic_publish( 28 | exchange='', 29 | routing_key='rpc_queue', 30 | properties=pika.BasicProperties( 31 | reply_to=self.callback_queue, 32 | correlation_id=self.corr_id, 33 | ), 34 | body=str(n)) 35 | while self.response is None: 36 | self.connection.process_data_events() 37 | return int(self.response) -------------------------------------------------------------------------------- /10/rabbitmq-web/api/backend/rpc_server.py: -------------------------------------------------------------------------------- 1 | import pika 2 | 3 | connection = pika.BlockingConnection( 4 | pika.ConnectionParameters(host='localhost')) 5 | 6 | channel = connection.channel() 7 | 8 | channel.queue_declare(queue='rpc_queue') 9 | 10 | def fib(n): 11 | if n < 3: 12 | return 1 13 | i = 3 14 | last1 = 1 15 | last2 = 1 16 | while i <= n: 17 | result = last1 + last2 18 | last2 = last1 19 | last1 = result 20 | i += 1 21 | return result 22 | 23 | def on_request(ch, method, props, body): 24 | n = int(body) 25 | 26 | print(" [.] fib(%s)" % n) 27 | response = fib(n) 28 | 29 | ch.basic_publish(exchange='', 30 | routing_key=props.reply_to, 31 | properties=pika.BasicProperties(correlation_id = \ 32 | props.correlation_id), 33 | body=str(response)) 34 | ch.basic_ack(delivery_tag=method.delivery_tag) 35 | 36 | channel.basic_qos(prefetch_count=1) 37 | channel.basic_consume(queue='rpc_queue', on_message_callback=on_request) 38 | 39 | print(" [x] Awaiting RPC requests") 40 | channel.start_consuming() -------------------------------------------------------------------------------- /10/rabbitmq-web/endpoint.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi.middleware.cors import CORSMiddleware 3 | from api.api_router import router 4 | 5 | app = FastAPI(openapi_url='/api/v1/fibonacci/openapi.json', docs_url='/api/v1/fibonacci/docs') 6 | 7 | app.add_middleware( 8 | CORSMiddleware, 9 | allow_origins=["*"], 10 | allow_methods=["*"], 11 | allow_headers=["*"], 12 | allow_credentials=True, 13 | ) 14 | 15 | app.include_router(router, prefix='/api/v1/fibonacci') -------------------------------------------------------------------------------- /10/rabbitmq-web/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.63.0 2 | uvicorn==0.13.4 3 | pydantic==1.8.1 4 | pika==1.2.0 -------------------------------------------------------------------------------- /11/README.md: -------------------------------------------------------------------------------- 1 | # Celery Distributed Task Queue with FastAPI for Machine Learning 2 | 3 | This sample app demonstrates how to implement Celery distributed task queues on top of RabbitMQ broker for Machine Learning model training and data processing. We are using TensorFlow in this example to train the model. API request comes through FastAPI and it is being processed asynchronously by Celery. There is a separate API endpoint to check task status. Multiple requests can be initiated and processed at the same time in parallel. Celery tasks can be monitored using Flower monitoring tool. 4 | 5 | * Celery [documentation](https://docs.celeryproject.org/en/stable/index.html) 6 | * Machine Learning model [description](https://towardsdatascience.com/multi-output-model-with-tensorflow-keras-functional-api-875dd89aa7c6) 7 | * [Flower](https://flower.readthedocs.io/en/latest/) - Celery monitoring tool 8 | 9 | ## Commands (executed from celery-web folder) 10 | 11 | * Start FastAPI endpoint 12 | * **uvicorn endpoint:app --reload** 13 | * Start Celery worker 14 | * **celery -A boston_housing.worker worker --loglevel=INFO** 15 | * Start Flower monitoring dashboard 16 | * **celery -A boston_housing.worker --broker=pyamqp://guest@localhost// flower** 17 | 18 | ## URL's 19 | 20 | * API url: http://127.0.0.1:8000/api/v1/bostonhousing/docs 21 | * Flower url: http://127.0.0.1:5555/tasks 22 | -------------------------------------------------------------------------------- /11/celery-web/boston_housing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/11/celery-web/boston_housing/__init__.py -------------------------------------------------------------------------------- /11/celery-web/boston_housing/ml/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/11/celery-web/boston_housing/ml/__init__.py -------------------------------------------------------------------------------- /11/celery-web/boston_housing/ml/datahelper.py: -------------------------------------------------------------------------------- 1 | # Importing the libraries 2 | import pandas as pd 3 | import numpy as np 4 | 5 | # Importing the Boston Housing dataset 6 | from sklearn.datasets import load_boston 7 | from sklearn.model_selection import train_test_split 8 | 9 | def prepare_datasets(test_size): 10 | # Loading the Boston Housing dataset 11 | boston = load_boston() 12 | 13 | # Initializing the dataframe 14 | data = pd.DataFrame(boston.data) 15 | 16 | # Adding the feature names to the dataframe 17 | data.columns = boston.feature_names 18 | 19 | # Adding target variable to dataframe 20 | data['PRICE'] = boston.target 21 | 22 | # Split the data into train and test with 80 train / 20 test 23 | train, test = train_test_split(data, test_size=test_size, random_state=1) 24 | train, val = train_test_split(train, test_size=test_size, random_state=1) 25 | 26 | train_Y = format_output(train) 27 | test_Y = format_output(test) 28 | val_Y = format_output(val) 29 | 30 | # Normalize the training and test data 31 | norm_train_X = np.array(norm(train, train)) 32 | norm_test_X = np.array(norm(test, train)) 33 | norm_val_X = np.array(norm(val, train)) 34 | 35 | return norm_train_X, norm_test_X, norm_val_X, train_Y, test_Y, val_Y 36 | 37 | # Helper functions 38 | def norm(x, train): 39 | # Get PRICE and PTRATIO as the 2 outputs and format them as np arrays 40 | # PTRATIO - pupil-teacher ratio by town 41 | train_stats = train.describe() 42 | train_stats = train_stats.transpose() 43 | 44 | return (x - train_stats['mean']) / train_stats['std'] 45 | 46 | def format_output(data): 47 | y1 = data.pop('PRICE') 48 | y1 = np.array(y1) 49 | y2 = data.pop('PTRATIO') 50 | y2 = np.array(y2) 51 | return y1, y2 -------------------------------------------------------------------------------- /11/celery-web/boston_housing/ml/trainingservice.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | from tensorflow.keras.models import Model 3 | from tensorflow.keras.layers import Dense, Input 4 | from .datahelper import prepare_datasets 5 | from celery.utils.log import get_task_logger 6 | 7 | # Create logger - enable to display messages on task logger 8 | celery_log = get_task_logger(__name__) 9 | 10 | def build_model(columns_len): 11 | # Define model layers. 12 | input_layer = Input(shape=(columns_len,)) 13 | first_dense = Dense(units='128', activation='relu')(input_layer) 14 | # Y1 output will be fed from the first dense 15 | y1_output = Dense(units='1', name='price_output')(first_dense) 16 | 17 | second_dense = Dense(units='128', activation='relu')(first_dense) 18 | # Y2 output will be fed from the second dense 19 | y2_output = Dense(units='1', name='ptratio_output')(second_dense) 20 | 21 | # Define the model with the input layer and a list of output layers 22 | model = Model(inputs=input_layer, outputs=[y1_output, y2_output]) 23 | 24 | return model 25 | 26 | def run_training(dataset_split): 27 | norm_train_X, norm_test_X, norm_val_X, train_Y, test_Y, val_Y = prepare_datasets(dataset_split) 28 | celery_log.info(f"Data prepared") 29 | 30 | model = build_model(len(norm_train_X[0])) 31 | 32 | # Specify the optimizer, and compile the model with loss functions for both outputs 33 | optimizer = tf.keras.optimizers.SGD(lr=0.001) 34 | model.compile(optimizer=optimizer, 35 | loss={'price_output': 'mse', 'ptratio_output': 'mse'}, 36 | metrics={'price_output': tf.keras.metrics.RootMeanSquaredError(), 37 | 'ptratio_output': tf.keras.metrics.RootMeanSquaredError()}) 38 | 39 | # Train the model for 100 epochs 40 | model.fit(norm_train_X, train_Y, 41 | epochs=1000, batch_size=10, 42 | validation_data=(norm_test_X, test_Y), 43 | verbose=0) 44 | 45 | # Test the model and print loss and rmse for both outputs 46 | loss, Y1_loss, Y2_loss, Y1_rmse, Y2_rmse = model.evaluate(x=norm_val_X, y=val_Y) 47 | 48 | celery_log.info(f'loss: {loss}') 49 | celery_log.info(f'price_loss: {Y1_loss}') 50 | celery_log.info(f'ptratio_loss: {Y2_loss}') 51 | celery_log.info(f'price_rmse: {Y1_rmse}') 52 | celery_log.info(f'ptratio_rmse: {Y2_rmse}') 53 | 54 | celery_log.info('Training task completed') 55 | # Run predict 56 | Y_pred = model.predict(norm_test_X) 57 | price_pred = Y_pred[0] 58 | ptratio_pred = Y_pred[1] 59 | celery_log.info('Predict task completed') -------------------------------------------------------------------------------- /11/celery-web/boston_housing/tasks.py: -------------------------------------------------------------------------------- 1 | from .worker import app 2 | from celery.utils.log import get_task_logger 3 | from .ml.trainingservice import run_training 4 | 5 | # Create logger - enable to display messages on task logger 6 | celery_log = get_task_logger(__name__) 7 | 8 | @app.task(name='boston_housing.train_model') 9 | def train_model(dataset_split): 10 | run_training(dataset_split) 11 | celery_log.info(f"Celery task completed!") 12 | return 'OK' -------------------------------------------------------------------------------- /11/celery-web/boston_housing/worker.py: -------------------------------------------------------------------------------- 1 | from celery import Celery 2 | 3 | app = Celery( 4 | 'celery_web', 5 | broker='pyamqp://guest@localhost//', 6 | backend='rpc://', 7 | include=['boston_housing.tasks'] 8 | ) -------------------------------------------------------------------------------- /11/celery-web/endpoint.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi.middleware.cors import CORSMiddleware 3 | from router import router 4 | 5 | app = FastAPI(openapi_url='/api/v1/bostonhousing/openapi.json', docs_url='/api/v1/bostonhousing/docs') 6 | 7 | app.add_middleware( 8 | CORSMiddleware, 9 | allow_origins=["*"], 10 | allow_methods=["*"], 11 | allow_headers=["*"], 12 | allow_credentials=True, 13 | ) 14 | 15 | app.include_router(router, prefix='/api/v1/bostonhousing') -------------------------------------------------------------------------------- /11/celery-web/models.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class RequestData(BaseModel): 4 | dataset_split: float 5 | 6 | class Task(BaseModel): 7 | # Celery task representation 8 | task_id: str 9 | status: str 10 | 11 | 12 | class Result(BaseModel): 13 | # Celery task result 14 | task_id: str 15 | status: str -------------------------------------------------------------------------------- /11/celery-web/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.63.0 2 | uvicorn==0.13.4 3 | pydantic==1.8.1 4 | pandas==1.2.4 5 | numpy==1.19.5 6 | scikit-learn==0.24.1 7 | tensorflow==2.4.1 8 | celery==4.4.7 9 | flower==0.9.7 -------------------------------------------------------------------------------- /11/celery-web/router.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | from models import RequestData, Task, Result 3 | from boston_housing.tasks import train_model 4 | from celery.result import AsyncResult 5 | from fastapi.responses import JSONResponse 6 | 7 | router = APIRouter() 8 | 9 | @router.get('/') 10 | def touch(): 11 | return 'API is running' 12 | 13 | @router.post('/train', response_model=Task, status_code=202) 14 | async def run_training(requestData:RequestData): 15 | task_id = train_model.delay(requestData.dataset_split) 16 | return {'task_id': str(task_id), 'status': 'Processing'} 17 | 18 | @router.get('/result/{task_id}', response_model=Result, status_code=200, 19 | responses={202: {'model': Task, 'description': 'Accepted: Not Ready'}}) 20 | async def fetch_result(task_id): 21 | # Fetch result for task_id 22 | task = AsyncResult(task_id) 23 | if not task.ready(): 24 | return JSONResponse(status_code=202, content={'task_id': str(task_id), 'status': 'Processing'}) 25 | result = task.get() 26 | return {'task_id': task_id, 'status': str(result)} -------------------------------------------------------------------------------- /12/tf-decision-forests/README.MD: -------------------------------------------------------------------------------- 1 | This sample is using TensorFlow Decision Forests to build ML model for Titanic dataset. 2 | 3 | - TensorFlow Decision Forests: https://www.tensorflow.org/decision_forests 4 | - Titanic dataset on Kaggle: https://www.kaggle.com/c/titanic 5 | -------------------------------------------------------------------------------- /13/README.MD: -------------------------------------------------------------------------------- 1 | Hugging Face team recently released online course about transformers, pretrained model fine-tuning, and sharing models on the Hugging Face hub. I went through the first part of the course related to model fine-tuning. I explain what changes I did for my previous sample related to Hugging Face model fine-tuning, based on knowledge learned from this course. 2 | -------------------------------------------------------------------------------- /14/hr-app/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /14/hr-app/README.MD: -------------------------------------------------------------------------------- 1 | ## Based on YouTube tutorial 2 | 3 | [Django To Do List App With User Registration & Login](https://www.youtube.com/watch?v=llbtoQTt4qw) 4 | 5 | ## Install Django 6 | 7 | ``` 8 | pip install django 9 | ``` 10 | 11 | ## Create project 12 | 13 | ``` 14 | django-admin startproject hr_app 15 | ``` 16 | 17 | ## Create application 18 | 19 | ``` 20 | python manage.py startapp base 21 | ``` 22 | 23 | ## Run application 24 | 25 | ``` 26 | python manage.py runserver 27 | ``` 28 | 29 | ## Run Django migrations (build Django ORM) 30 | 31 | ``` 32 | python manage.py makemigrations 33 | ``` 34 | 35 | ## Create Django ORM 36 | 37 | ``` 38 | python manage.py migrate 39 | ``` 40 | 41 | ## Create Django superuser 42 | 43 | ``` 44 | python manage.py createsuperuser 45 | ``` 46 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/14/hr-app/hr_app/base/__init__.py -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import Employee 3 | 4 | 5 | admin.site.register(Employee) 6 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BaseConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'base' 7 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.4 on 2022-04-23 19:53 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Employee', 19 | fields=[ 20 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('firstName', models.CharField(max_length=200)), 22 | ('lastName', models.CharField(max_length=200)), 23 | ('approved', models.BooleanField(default=False)), 24 | ('created', models.DateTimeField(auto_now_add=True)), 25 | ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 26 | ], 27 | options={ 28 | 'ordering': ['approved'], 29 | }, 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/14/hr-app/hr_app/base/migrations/__init__.py -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import User 3 | 4 | 5 | # Create your models here. 6 | 7 | class Employee(models.Model): 8 | user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) 9 | firstName = models.CharField(max_length=200) 10 | lastName = models.CharField(max_length=200) 11 | approved = models.BooleanField(default=False) 12 | created = models.DateTimeField(auto_now_add=True) 13 | 14 | def __str__(self): 15 | return self.lastName 16 | 17 | class Meta: 18 | ordering = ['approved'] -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/templates/base/employee.html: -------------------------------------------------------------------------------- 1 |

Employee: {{employee}}

-------------------------------------------------------------------------------- /14/hr-app/hr_app/base/templates/base/employee_confirm_delete.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/main.html' %} 2 | {% block content %} 3 | 4 |
5 | ← Back 6 |
7 | 8 |
9 |
10 | {% csrf_token %} 11 |

Are you sure you want to delete this employee entry? "{{employee}}"

12 | 13 |
14 |
15 | 16 | {% endblock content %} -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/templates/base/employee_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/main.html' %} 2 | {% block content %} 3 | 4 |
5 | ← Back 6 |
7 | 8 |
9 |
10 | {% csrf_token %} 11 | {{form.as_p}} 12 | 13 |
14 |
15 | 16 | {% endblock content %} -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/templates/base/employee_list.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/main.html' %} 2 | {% block content %} 3 | 4 |
5 |
6 |

Hello {{request.user|title}}

7 |

You have {{count}} not approved employee{{count|pluralize:"s"}}

8 |
9 | 10 | {% if request.user.is_authenticated %} 11 | Logout 12 | {% else %} 13 | Login 14 | {% endif %} 15 |
16 | 17 |
18 |
19 | 20 | 21 |
22 | + 23 |
24 | 25 |
26 | {% for employee in employees %} 27 |
28 | {% if employee.approved %} 29 |
30 |
31 | {{employee}} 32 |
33 | × 34 | {% else %} 35 |
36 |
37 | {{employee}} 38 |
39 | × 40 | {% endif %} 41 |
42 | {% empty %} 43 |

No employees

44 | {% endfor %} 45 |
46 | 47 | {% endblock content %} -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/templates/base/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/main.html' %} 2 | {% block content %} 3 | 4 |
5 |

Login

6 |
7 | 8 |
9 |
10 | {% csrf_token %} 11 | {{form.as_p}} 12 | 13 |
14 |

Don't have an account? Register

15 |
16 | 17 | {% endblock content %} -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/templates/base/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | Employees List 11 | 12 | 13 | 14 | 15 | 16 | 17 | 199 | 200 | 201 | 202 | 203 |
204 | {% block content %} 205 | 206 | {% endblock content %} 207 |
208 | 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/templates/base/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/main.html' %} 2 | {% block content %} 3 | 4 |
5 |

Register

6 |
7 | 8 |
9 |
10 | {% csrf_token %} 11 | 12 | {{form.username}} 13 | 14 | 15 | {{form.password1}} 16 | 17 | 18 | {{form.password1}} 19 | 20 |
21 |

Already have an account? Login

22 |
23 | 24 | {% endblock content %} -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from .views import EmployeeList, EmployeeDetail, EmployeeCreate, EmployeeUpdate, EmployeeDelete, CustomLoginView 3 | from .views import RegisterPage 4 | from django.contrib.auth.views import LogoutView 5 | 6 | 7 | urlpatterns = [ 8 | path('login/', CustomLoginView.as_view(), name='login'), 9 | path('logout/', LogoutView.as_view(next_page='login'), name='logout'), 10 | path('register/', RegisterPage.as_view(), name='register'), 11 | 12 | path('', EmployeeList.as_view(), name='employees'), 13 | path('employee//', EmployeeDetail.as_view(), name='employee'), 14 | path('employee-create/', EmployeeCreate.as_view(), name='employee-create'), 15 | path('employee-update//', EmployeeUpdate.as_view(), name='employee-update'), 16 | path('employee-delete//', EmployeeDelete.as_view(), name='employee-delete'), 17 | ] -------------------------------------------------------------------------------- /14/hr-app/hr_app/base/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.views.generic.list import ListView 3 | from django.views.generic.detail import DetailView 4 | from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView 5 | from django.urls import reverse_lazy 6 | 7 | from django.contrib.auth.views import LoginView 8 | from django.contrib.auth.mixins import LoginRequiredMixin 9 | from django.contrib.auth.forms import UserCreationForm 10 | from django.contrib.auth import login 11 | 12 | from .models import Employee 13 | 14 | 15 | class CustomLoginView(LoginView): 16 | template_name = 'base/login.html' 17 | fields = '__all__' 18 | redirect_authenticated_user = True 19 | 20 | def get_success_url(self): 21 | return reverse_lazy('employees') 22 | 23 | 24 | class RegisterPage(FormView): 25 | template_name = 'base/register.html' 26 | form_class = UserCreationForm 27 | redirect_authenticated_user = True 28 | success_url = reverse_lazy('employees') 29 | 30 | def form_valid(self, form): 31 | user = form.save() 32 | if user is not None: 33 | login(self.request, user) 34 | return super(RegisterPage, self).form_valid(form) 35 | 36 | def get(self, *args, **kwargs): 37 | if self.request.user.is_authenticated: 38 | return redirect('employees') 39 | return super(RegisterPage, self).get(*args, **kwargs) 40 | 41 | 42 | class EmployeeList(LoginRequiredMixin, ListView): 43 | model = Employee 44 | context_object_name = 'employees' 45 | 46 | def get_context_data(self, **kwargs): 47 | context = super().get_context_data(**kwargs) 48 | context['employees'] = context['employees'].filter(user=self.request.user) 49 | context['count'] = context['employees'].filter(approved=False).count() 50 | 51 | search_input = self.request.GET.get('search-area') or '' 52 | if search_input: 53 | context['employees'] = context['employees'].filter(lastName__istartswith=search_input) 54 | 55 | context['search_input'] = search_input 56 | 57 | return context 58 | 59 | 60 | class EmployeeDetail(LoginRequiredMixin, DetailView): 61 | model = Employee 62 | context_object_name = 'employee' 63 | template_name = 'base/employee.html' 64 | 65 | 66 | class EmployeeCreate(LoginRequiredMixin, CreateView): 67 | model = Employee 68 | fields = ['firstName', 'lastName', 'approved'] 69 | success_url = reverse_lazy('employees') 70 | 71 | def form_valid(self, form): 72 | form.instance.user = self.request.user 73 | return super(EmployeeCreate, self).form_valid(form) 74 | 75 | 76 | class EmployeeUpdate(LoginRequiredMixin, UpdateView): 77 | model = Employee 78 | fields = ['firstName', 'lastName', 'approved'] 79 | success_url = reverse_lazy('employees') 80 | 81 | 82 | class EmployeeDelete(LoginRequiredMixin, DeleteView): 83 | model = Employee 84 | context_object_name = 'employee' 85 | success_url = reverse_lazy('employees') 86 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/hr_app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/14/hr-app/hr_app/hr_app/__init__.py -------------------------------------------------------------------------------- /14/hr-app/hr_app/hr_app/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for hr_app project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hr_app.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/hr_app/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for hr_app project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.0.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.0/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'django-insecure-@sdamb)y#zcnh_idn9dup2zo#5a!72mqyggaozy+=4b$@zi8og' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'base.apps.BaseConfig' 41 | ] 42 | 43 | MIDDLEWARE = [ 44 | 'django.middleware.security.SecurityMiddleware', 45 | 'django.contrib.sessions.middleware.SessionMiddleware', 46 | 'django.middleware.common.CommonMiddleware', 47 | 'django.middleware.csrf.CsrfViewMiddleware', 48 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 49 | 'django.contrib.messages.middleware.MessageMiddleware', 50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 51 | ] 52 | 53 | ROOT_URLCONF = 'hr_app.urls' 54 | 55 | TEMPLATES = [ 56 | { 57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 58 | 'DIRS': [], 59 | 'APP_DIRS': True, 60 | 'OPTIONS': { 61 | 'context_processors': [ 62 | 'django.template.context_processors.debug', 63 | 'django.template.context_processors.request', 64 | 'django.contrib.auth.context_processors.auth', 65 | 'django.contrib.messages.context_processors.messages', 66 | ], 67 | }, 68 | }, 69 | ] 70 | 71 | WSGI_APPLICATION = 'hr_app.wsgi.application' 72 | 73 | 74 | # Database 75 | # https://docs.djangoproject.com/en/4.0/ref/settings/#databases 76 | 77 | DATABASES = { 78 | 'default': { 79 | 'ENGINE': 'django.db.backends.sqlite3', 80 | 'NAME': BASE_DIR / 'db.sqlite3', 81 | } 82 | } 83 | 84 | 85 | # Password validation 86 | # https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators 87 | 88 | AUTH_PASSWORD_VALIDATORS = [ 89 | { 90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 91 | }, 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 100 | }, 101 | ] 102 | 103 | 104 | # Internationalization 105 | # https://docs.djangoproject.com/en/4.0/topics/i18n/ 106 | 107 | LANGUAGE_CODE = 'en-us' 108 | 109 | TIME_ZONE = 'UTC' 110 | 111 | USE_I18N = True 112 | 113 | USE_TZ = True 114 | 115 | LOGIN_URL = 'login' 116 | 117 | # Static files (CSS, JavaScript, Images) 118 | # https://docs.djangoproject.com/en/4.0/howto/static-files/ 119 | 120 | STATIC_URL = 'static/' 121 | 122 | # Default primary key field type 123 | # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field 124 | 125 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 126 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/hr_app/urls.py: -------------------------------------------------------------------------------- 1 | """hr_app URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('', include('base.urls')), 22 | ] 23 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/hr_app/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for hr_app project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hr_app.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /14/hr-app/hr_app/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hr_app.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /15/pyscript-web/chart.py: -------------------------------------------------------------------------------- 1 | # data.py 2 | import altair as alt 3 | 4 | def get_chart(cars): 5 | return (alt.Chart(cars).mark_circle(size=60).encode( 6 | x='Horsepower', 7 | y='Miles_per_Gallon', 8 | color='Origin', 9 | tooltip=['Name', 'Origin', 'Horsepower', 'Miles_per_Gallon'] 10 | )) -------------------------------------------------------------------------------- /15/pyscript-web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | - altair 23 | - vega_datasets 24 | - numpy 25 | - pandas 26 | - panel==0.13.1a2 27 | - paths: 28 | - /chart.py 29 | 30 | 31 | 32 | 33 |
34 | 40 | 41 |
42 |
43 | 44 |
45 |
46 |
47 |
48 |
49 | 50 | import asyncio 51 | import panel as pn 52 | import altair as alt 53 | from vega_datasets import data 54 | from panel.io.pyodide import show 55 | from chart import get_chart 56 | 57 | horse_power = pn.widgets.IntInput(value=230, step=1, start=0, end=230) 58 | search = pn.Column('# Filter by Horsepower', horse_power, background='White') 59 | 60 | cars = data.cars() 61 | table = pn.widgets.Tabulator(pagination='remote', page_size=10) 62 | table.value = cars 63 | 64 | chart = pn.pane.Vega() 65 | chart.object = get_chart(cars) 66 | 67 | @pn.depends(horse_power, watch=True) 68 | def update_ui(*events): 69 | chart.object = get_chart(cars[cars['Horsepower'] < horse_power.value]) 70 | table.value = cars[cars['Horsepower'] < horse_power.value] 71 | 72 | await show(search, 'search') 73 | await show(chart, 'chart') 74 | await show(table, 'table') 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /15/pyscript-web/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | - numpy 23 | - pandas 24 | - panel==0.13.1a2 25 | 26 | 27 | 28 | 29 |
30 | 36 | 37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | 45 | import asyncio 46 | import panel as pn 47 | import pandas as pd 48 | from panel.io.pyodide import show 49 | 50 | file_input = pn.widgets.FileInput(accept='.csv', width=180) 51 | button_upload = pn.widgets.Button(name='Upload', button_type='primary', width=100) 52 | row = pn.Row(file_input, button_upload, height=75) 53 | 54 | table = pn.widgets.Tabulator(pagination='remote', page_size=10) 55 | document.getElementById('table').style.display = 'none' 56 | 57 | def process_file(event): 58 | if file_input.value is not None: 59 | df = pd.read_csv(io.BytesIO(file_input.value)) 60 | table.value = df 61 | document.getElementById('table').style.display = 'block' 62 | 63 | button_upload.on_click(process_file) 64 | 65 | await show(row, 'fileinput') 66 | await show(table, 'table') 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /15/pyscript-web/taxables.csv: -------------------------------------------------------------------------------- 1 | "Item","Cost","Tax","Total" 2 | "Fruit of the Loom Girl's Socks",7.97,0.60,8.57 3 | "Rawlings Little League Baseball",2.97,0.22,3.19 4 | "Secret Antiperspirant",1.29,0.10,1.39 5 | "Deadpool DVD",14.96,1.12,16.08 6 | "Maxwell House Coffee 28 oz",7.28,0.55,7.83 7 | "Banana Boat Sunscreen, 8 oz",6.68,0.50,7.18 8 | "Wrench Set, 18 pieces",10.00,0.75,10.75 9 | "M and M, 42 oz",8.98,0.67,9.65 10 | "Bertoli Alfredo Sauce",2.12,0.16,2.28 11 | "Large Paperclips, 10 boxes",6.19,0.46,6.65 -------------------------------------------------------------------------------- /16/annotation-box/1014-receipt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/16/annotation-box/1014-receipt.jpg -------------------------------------------------------------------------------- /16/annotation-box/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 |
34 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /17/django-react/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /17/django-react/mysite/README.MD: -------------------------------------------------------------------------------- 1 | ## Based on this tutorial 2 | 3 | [Integrating a Modern JavaScript Pipeline into a Django Application](https://www.saaspegasus.com/guides/modern-javascript-for-django-developers/integrating-javascript-pipeline/) 4 | 5 | ## Django setup 6 | 7 | ``` 8 | pip install django 9 | ``` 10 | 11 | ``` 12 | django-admin startproject mysite 13 | ``` 14 | 15 | ``` 16 | python manage.py startapp myapp 17 | ``` 18 | 19 | ``` 20 | python manage.py migrate 21 | ``` 22 | 23 | ``` 24 | python manage.py runserver 25 | ``` 26 | 27 | ## Webpack setup 28 | 29 | ``` 30 | npm init -y 31 | npm install webpack webpack-cli --save-dev 32 | ``` 33 | 34 | ``` 35 | npm run dev 36 | ``` 37 | 38 | ## Connecting webpack bundles to Django 39 | 40 | Run Django server 41 | 42 | ``` 43 | http://localhost:8000/hello-webpack/ 44 | ``` 45 | 46 | ## Setting up React with Babel 47 | 48 | ``` 49 | npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/preset-react 50 | ``` 51 | 52 | ``` 53 | npm install --save react react-dom 54 | ``` 55 | 56 | ``` 57 | npm run dev 58 | ``` -------------------------------------------------------------------------------- /17/django-react/mysite/assets/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from "react-dom"; 3 | 4 | ReactDOM.render( 5 |

Hello, react!

, 6 | document.getElementById('root') 7 | ); -------------------------------------------------------------------------------- /17/django-react/mysite/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /17/django-react/mysite/myapp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/17/django-react/mysite/myapp/__init__.py -------------------------------------------------------------------------------- /17/django-react/mysite/myapp/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /17/django-react/mysite/myapp/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class MyappConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'myapp' 7 | -------------------------------------------------------------------------------- /17/django-react/mysite/myapp/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/17/django-react/mysite/myapp/migrations/__init__.py -------------------------------------------------------------------------------- /17/django-react/mysite/myapp/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /17/django-react/mysite/myapp/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /17/django-react/mysite/myapp/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /17/django-react/mysite/mysite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/17/django-react/mysite/mysite/__init__.py -------------------------------------------------------------------------------- /17/django-react/mysite/mysite/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for mysite project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /17/django-react/mysite/mysite/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for mysite project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.0.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.0/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | import os 15 | 16 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 17 | BASE_DIR = Path(__file__).resolve().parent.parent 18 | 19 | 20 | # Quick-start development settings - unsuitable for production 21 | # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ 22 | 23 | # SECURITY WARNING: keep the secret key used in production secret! 24 | SECRET_KEY = 'django-insecure-gnmwr)to838s(3%r1%^sp9g*!nn=-c1)%d1^1^y1x+oc$kr-m3' 25 | 26 | # SECURITY WARNING: don't run with debug turned on in production! 27 | DEBUG = True 28 | 29 | ALLOWED_HOSTS = [] 30 | 31 | 32 | # Application definition 33 | 34 | INSTALLED_APPS = [ 35 | 'django.contrib.admin', 36 | 'django.contrib.auth', 37 | 'django.contrib.contenttypes', 38 | 'django.contrib.sessions', 39 | 'django.contrib.messages', 40 | 'django.contrib.staticfiles', 41 | 'myapp.apps.MyappConfig' 42 | ] 43 | 44 | MIDDLEWARE = [ 45 | 'django.middleware.security.SecurityMiddleware', 46 | 'django.contrib.sessions.middleware.SessionMiddleware', 47 | 'django.middleware.common.CommonMiddleware', 48 | 'django.middleware.csrf.CsrfViewMiddleware', 49 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 50 | 'django.contrib.messages.middleware.MessageMiddleware', 51 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 52 | ] 53 | 54 | ROOT_URLCONF = 'mysite.urls' 55 | 56 | TEMPLATES = [ 57 | { 58 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 59 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 60 | 'APP_DIRS': True, 61 | 'OPTIONS': { 62 | 'context_processors': [ 63 | 'django.template.context_processors.debug', 64 | 'django.template.context_processors.request', 65 | 'django.contrib.auth.context_processors.auth', 66 | 'django.contrib.messages.context_processors.messages', 67 | ], 68 | }, 69 | }, 70 | ] 71 | 72 | WSGI_APPLICATION = 'mysite.wsgi.application' 73 | 74 | 75 | # Database 76 | # https://docs.djangoproject.com/en/4.0/ref/settings/#databases 77 | 78 | DATABASES = { 79 | 'default': { 80 | 'ENGINE': 'django.db.backends.sqlite3', 81 | 'NAME': BASE_DIR / 'db.sqlite3', 82 | } 83 | } 84 | 85 | 86 | # Password validation 87 | # https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators 88 | 89 | AUTH_PASSWORD_VALIDATORS = [ 90 | { 91 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 92 | }, 93 | { 94 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 95 | }, 96 | { 97 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 98 | }, 99 | { 100 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 101 | }, 102 | ] 103 | 104 | 105 | # Internationalization 106 | # https://docs.djangoproject.com/en/4.0/topics/i18n/ 107 | 108 | LANGUAGE_CODE = 'en-us' 109 | 110 | TIME_ZONE = 'UTC' 111 | 112 | USE_I18N = True 113 | 114 | USE_TZ = True 115 | 116 | 117 | # Static files (CSS, JavaScript, Images) 118 | # https://docs.djangoproject.com/en/4.0/howto/static-files/ 119 | 120 | STATIC_URL = 'static/' 121 | 122 | STATICFILES_DIRS = [ 123 | os.path.join(BASE_DIR, 'static'), 124 | ] 125 | 126 | # Default primary key field type 127 | # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field 128 | 129 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 130 | -------------------------------------------------------------------------------- /17/django-react/mysite/mysite/urls.py: -------------------------------------------------------------------------------- 1 | """mysite URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from django.views.generic import TemplateView 19 | 20 | urlpatterns = [ 21 | path('admin/', admin.site.urls), 22 | path('hello-webpack/', TemplateView.as_view(template_name='myapp/hello_webpack.html')) 23 | ] 24 | -------------------------------------------------------------------------------- /17/django-react/mysite/mysite/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for mysite project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /17/django-react/mysite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mysite", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "webpack --mode development --watch" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@babel/core": "^7.17.10", 15 | "@babel/preset-env": "^7.17.10", 16 | "@babel/preset-react": "^7.16.7", 17 | "babel-loader": "^8.2.5", 18 | "webpack": "^5.72.1", 19 | "webpack-cli": "^4.9.2" 20 | }, 21 | "dependencies": { 22 | "lodash": "^4.17.21", 23 | "react": "^18.1.0", 24 | "react-dom": "^18.1.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /17/django-react/mysite/templates/myapp/hello_webpack.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | Getting Started with Django and Webpack 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /17/django-react/mysite/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './assets/index.js', // path to our input file 5 | output: { 6 | filename: 'index-bundle.js', // output bundle file name 7 | path: path.resolve(__dirname, './static'), // path to our Django static directory 8 | }, 9 | module: { 10 | rules: [ 11 | { 12 | test: /\.(js|jsx)$/, 13 | exclude: /node_modules/, 14 | loader: "babel-loader", 15 | options: { presets: ["@babel/preset-env", "@babel/preset-react"] } 16 | }, 17 | ] 18 | } 19 | }; -------------------------------------------------------------------------------- /19/django-htmx-simple/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/README.MD: -------------------------------------------------------------------------------- 1 | ## Based on tutorial 2 | 3 | [How To Use Htmx In Django, by Matt Layman](https://www.mattlayman.com/blog/2021/how-to-htmx-django/) 4 | 5 | ## Install Django 6 | 7 | ``` 8 | pip install django 9 | ``` 10 | 11 | ## Create project 12 | 13 | ``` 14 | django-admin startproject simple_app 15 | ``` 16 | 17 | ## Create application 18 | 19 | ``` 20 | python manage.py startapp base 21 | ``` 22 | 23 | ## Run application 24 | 25 | ``` 26 | python manage.py runserver 27 | ``` 28 | 29 | ## Run Django migrations (build Django ORM) 30 | 31 | ``` 32 | python manage.py makemigrations 33 | ``` 34 | 35 | ``` 36 | python manage.py migrate 37 | ``` 38 | 39 | ## Create Django superuser 40 | 41 | ``` 42 | python manage.py createsuperuser 43 | ``` 44 | 45 | Add new task entries through Django Admin console 46 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/19/django-htmx-simple/simple_app/base/__init__.py -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from base.models import TaskModel 4 | 5 | admin.site.register(TaskModel) -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BaseConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'base' 7 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class TaskModel(models.Model): 5 | title = models.CharField(max_length=200) 6 | description = models.TextField() 7 | created_at = models.DateTimeField(auto_now_add=True) 8 | updated_at = models.DateTimeField(auto_now=True) 9 | 10 | def __str__(self): 11 | return self.title 12 | 13 | class Meta: 14 | verbose_name = 'Task' 15 | verbose_name_plural = 'Tasks' 16 | ordering = ['-created_at'] -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | Htmx Demo! 3 | 4 | {% block main %}{% endblock %} 5 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/templates/display_tasks.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main %} 4 |

Tasks

5 | {% include "tasks_list.html" %} 6 | {% endblock %} -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/templates/tasks_list.html: -------------------------------------------------------------------------------- 1 |
5 | {% for task in tasks %} 6 |
{{ forloop.counter }} {{ task.description }} 7 | 9 | Delete? 10 | 11 |
12 | {% endfor %} 13 |
-------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from .views import display_tasks, delete_task 3 | 4 | urlpatterns = [ 5 | path('tasks/', display_tasks, name='display_tasks'), 6 | path('tasks//delete/', delete_task, name='delete_task'), 7 | ] -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/base/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from .models import TaskModel 3 | from django.views.decorators.http import require_http_methods 4 | 5 | 6 | def display_tasks(request): 7 | tasks = TaskModel.objects.all() 8 | return render(request, 'display_tasks.html', {'tasks': tasks}) 9 | 10 | 11 | @require_http_methods(['DELETE']) 12 | def delete_task(request, task_id): 13 | TaskModel.objects.filter(id=task_id).delete() 14 | tasks = TaskModel.objects.all() 15 | return render(request, 'tasks_list.html', {'tasks': tasks}) 16 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'simple_app.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/simple_app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/19/django-htmx-simple/simple_app/simple_app/__init__.py -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/simple_app/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for simple_app project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'simple_app.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/simple_app/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for simple_app project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.0.6. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.0/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'django-insecure-_c(%^rvhsx2i$bpn4gwzk2cr1a^%h%2fsx75@nreub%s*wvt2o' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'base.apps.BaseConfig', 41 | ] 42 | 43 | MIDDLEWARE = [ 44 | 'django.middleware.security.SecurityMiddleware', 45 | 'django.contrib.sessions.middleware.SessionMiddleware', 46 | 'django.middleware.common.CommonMiddleware', 47 | 'django.middleware.csrf.CsrfViewMiddleware', 48 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 49 | 'django.contrib.messages.middleware.MessageMiddleware', 50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 51 | ] 52 | 53 | ROOT_URLCONF = 'simple_app.urls' 54 | 55 | TEMPLATES = [ 56 | { 57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 58 | 'DIRS': [], 59 | 'APP_DIRS': True, 60 | 'OPTIONS': { 61 | 'context_processors': [ 62 | 'django.template.context_processors.debug', 63 | 'django.template.context_processors.request', 64 | 'django.contrib.auth.context_processors.auth', 65 | 'django.contrib.messages.context_processors.messages', 66 | ], 67 | }, 68 | }, 69 | ] 70 | 71 | WSGI_APPLICATION = 'simple_app.wsgi.application' 72 | 73 | 74 | # Database 75 | # https://docs.djangoproject.com/en/4.0/ref/settings/#databases 76 | 77 | DATABASES = { 78 | 'default': { 79 | 'ENGINE': 'django.db.backends.sqlite3', 80 | 'NAME': BASE_DIR / 'db.sqlite3', 81 | } 82 | } 83 | 84 | 85 | # Password validation 86 | # https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators 87 | 88 | AUTH_PASSWORD_VALIDATORS = [ 89 | { 90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 91 | }, 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 100 | }, 101 | ] 102 | 103 | 104 | # Internationalization 105 | # https://docs.djangoproject.com/en/4.0/topics/i18n/ 106 | 107 | LANGUAGE_CODE = 'en-us' 108 | 109 | TIME_ZONE = 'UTC' 110 | 111 | USE_I18N = True 112 | 113 | USE_TZ = True 114 | 115 | 116 | # Static files (CSS, JavaScript, Images) 117 | # https://docs.djangoproject.com/en/4.0/howto/static-files/ 118 | 119 | STATIC_URL = 'static/' 120 | 121 | # Default primary key field type 122 | # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field 123 | 124 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 125 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/simple_app/urls.py: -------------------------------------------------------------------------------- 1 | """simple_app URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('', include('base.urls')), 22 | ] 23 | -------------------------------------------------------------------------------- /19/django-htmx-simple/simple_app/simple_app/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for simple_app project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'simple_app.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/README.MD: -------------------------------------------------------------------------------- 1 | ## 1. Install Django 2 | 3 | ``` 4 | pip install django 5 | ``` 6 | 7 | Install dependencies: 8 | 9 | ``` 10 | pip install django-widget-tweaks 11 | ``` 12 | 13 | ``` 14 | pip install django-browser-reload 15 | ``` 16 | 17 | #### Steps 2 - 5 are not required. These steps are needed if you would create app from scratch. Run application in Step 6 18 | 19 | ## 2. Create project 20 | 21 | ``` 22 | django-admin startproject base . 23 | ``` 24 | 25 | ## 3. Create application 26 | 27 | ``` 28 | python manage.py startapp uiapp 29 | ``` 30 | 31 | ## 4. Run Django migrations (build Django ORM) 32 | 33 | ``` 34 | python manage.py makemigrations 35 | ``` 36 | 37 | ``` 38 | python manage.py migrate 39 | ``` 40 | 41 | ## 5. Create Django superuser (not required, DB file is provided) 42 | 43 | ``` 44 | python manage.py createsuperuser 45 | ``` 46 | 47 | Add new employee entries through Django Admin console 48 | 49 | ## 6. Run application 50 | 51 | ``` 52 | python manage.py runserver 53 | ``` 54 | 55 | ## 7. Dump/load data (not required) 56 | 57 | ``` 58 | python manage.py dumpdata uiapp > db.json --indent 4 59 | ``` 60 | 61 | ``` 62 | python manage.py loaddata db.json 63 | ``` 64 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/20/django-htmx-sandbox/base/__init__.py -------------------------------------------------------------------------------- /20/django-htmx-sandbox/base/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for base project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'base.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/base/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for base project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.1. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'django-insecure-n8$7w6zmcj)rz2rbmefz*b124!@qv6_421q2o(dshfb&7mroc)' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'uiapp.apps.UiappConfig', 41 | 'widget_tweaks', 42 | 'django_browser_reload', 43 | ] 44 | 45 | MIDDLEWARE = [ 46 | 'django.middleware.security.SecurityMiddleware', 47 | 'django.contrib.sessions.middleware.SessionMiddleware', 48 | 'django.middleware.common.CommonMiddleware', 49 | 'django.middleware.csrf.CsrfViewMiddleware', 50 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 51 | 'django.contrib.messages.middleware.MessageMiddleware', 52 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 53 | 'django_browser_reload.middleware.BrowserReloadMiddleware', 54 | ] 55 | 56 | ROOT_URLCONF = 'base.urls' 57 | 58 | TEMPLATES = [ 59 | { 60 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 61 | 'DIRS': [], 62 | 'APP_DIRS': True, 63 | 'OPTIONS': { 64 | 'context_processors': [ 65 | 'django.template.context_processors.debug', 66 | 'django.template.context_processors.request', 67 | 'django.contrib.auth.context_processors.auth', 68 | 'django.contrib.messages.context_processors.messages', 69 | ], 70 | }, 71 | }, 72 | ] 73 | 74 | WSGI_APPLICATION = 'base.wsgi.application' 75 | 76 | 77 | # Database 78 | # https://docs.djangoproject.com/en/4.1/ref/settings/#databases 79 | 80 | DATABASES = { 81 | 'default': { 82 | 'ENGINE': 'django.db.backends.sqlite3', 83 | 'NAME': BASE_DIR / 'db.sqlite3', 84 | } 85 | } 86 | 87 | 88 | # Password validation 89 | # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators 90 | 91 | AUTH_PASSWORD_VALIDATORS = [ 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 100 | }, 101 | { 102 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 103 | }, 104 | ] 105 | 106 | 107 | # Internationalization 108 | # https://docs.djangoproject.com/en/4.1/topics/i18n/ 109 | 110 | LANGUAGE_CODE = 'en-us' 111 | 112 | TIME_ZONE = 'UTC' 113 | 114 | USE_I18N = True 115 | 116 | USE_TZ = True 117 | 118 | 119 | # Static files (CSS, JavaScript, Images) 120 | # https://docs.djangoproject.com/en/4.1/howto/static-files/ 121 | 122 | STATIC_URL = 'static/' 123 | 124 | # Default primary key field type 125 | # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field 126 | 127 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 128 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/base/urls.py: -------------------------------------------------------------------------------- 1 | """base URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('', include('uiapp.urls')) 22 | ] 23 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/base/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for base project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'base.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/db.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "model": "uiapp.jobmodel", 4 | "pk": "AD_PRES", 5 | "fields": { 6 | "job_title": "President", 7 | "min_salary": "20080.00", 8 | "max_salary": "40000.00", 9 | "created_at": "2022-08-04T17:12:50.181Z", 10 | "updated_at": "2022-08-04T17:12:50.181Z" 11 | } 12 | }, 13 | { 14 | "model": "uiapp.jobmodel", 15 | "pk": "AD_VP", 16 | "fields": { 17 | "job_title": "Administration Vice President", 18 | "min_salary": "15000.00", 19 | "max_salary": "30000.00", 20 | "created_at": "2022-08-04T17:11:55.525Z", 21 | "updated_at": "2022-08-04T17:11:55.525Z" 22 | } 23 | }, 24 | { 25 | "model": "uiapp.jobmodel", 26 | "pk": "FI_ACCOUNT", 27 | "fields": { 28 | "job_title": "Accountant", 29 | "min_salary": "4200.00", 30 | "max_salary": "9000.00", 31 | "created_at": "2022-08-04T17:13:19.952Z", 32 | "updated_at": "2022-08-04T17:13:19.952Z" 33 | } 34 | }, 35 | { 36 | "model": "uiapp.jobmodel", 37 | "pk": "IT_PROG", 38 | "fields": { 39 | "job_title": "Programmer", 40 | "min_salary": "4000.00", 41 | "max_salary": "10000.00", 42 | "created_at": "2022-08-04T17:11:10.265Z", 43 | "updated_at": "2022-08-04T17:11:10.265Z" 44 | } 45 | }, 46 | { 47 | "model": "uiapp.jobmodel", 48 | "pk": "PU_MAN", 49 | "fields": { 50 | "job_title": "Purchasing Manager", 51 | "min_salary": "8000.00", 52 | "max_salary": "15000.00", 53 | "created_at": "2022-08-04T17:13:49.099Z", 54 | "updated_at": "2022-08-04T17:13:49.099Z" 55 | } 56 | }, 57 | { 58 | "model": "uiapp.departmentsmodel", 59 | "pk": 60, 60 | "fields": { 61 | "department_name": "IT", 62 | "manager_id": 1, 63 | "location_id": 1700, 64 | "created_at": "2022-08-04T19:27:12.768Z", 65 | "updated_at": "2022-08-04T19:29:25.783Z" 66 | } 67 | }, 68 | { 69 | "model": "uiapp.departmentsmodel", 70 | "pk": 90, 71 | "fields": { 72 | "department_name": "Executive", 73 | "manager_id": 1, 74 | "location_id": 1700, 75 | "created_at": "2022-08-04T19:26:22.023Z", 76 | "updated_at": "2022-08-04T19:29:19.970Z" 77 | } 78 | }, 79 | { 80 | "model": "uiapp.departmentsmodel", 81 | "pk": 170, 82 | "fields": { 83 | "department_name": "Manufacturing", 84 | "manager_id": null, 85 | "location_id": 1700, 86 | "created_at": "2022-08-05T04:04:06.458Z", 87 | "updated_at": "2022-08-05T04:04:06.458Z" 88 | } 89 | }, 90 | { 91 | "model": "uiapp.employeemodel", 92 | "pk": 1, 93 | "fields": { 94 | "first_name": "Steven", 95 | "last_name": "King", 96 | "email": "sking@my.org", 97 | "phone_number": "515.123.4567", 98 | "hire_date": "2003-06-17", 99 | "job_id": "AD_PRES", 100 | "salary": "25000.01", 101 | "commission_pct": "0.10", 102 | "manager_id": null, 103 | "department_id": 90, 104 | "created_at": "2022-08-04T19:28:55.526Z", 105 | "updated_at": "2022-08-15T08:23:08.631Z" 106 | } 107 | }, 108 | { 109 | "model": "uiapp.employeemodel", 110 | "pk": 2, 111 | "fields": { 112 | "first_name": "Neena", 113 | "last_name": "Kochhar", 114 | "email": "nkochhar@my.org", 115 | "phone_number": "515.123.4568", 116 | "hire_date": "2005-09-21", 117 | "job_id": "AD_VP", 118 | "salary": "17000.00", 119 | "commission_pct": "0.20", 120 | "manager_id": 1, 121 | "department_id": 90, 122 | "created_at": "2022-08-04T19:30:51.233Z", 123 | "updated_at": "2022-08-15T08:01:00.986Z" 124 | } 125 | }, 126 | { 127 | "model": "uiapp.employeemodel", 128 | "pk": 3, 129 | "fields": { 130 | "first_name": "Lex", 131 | "last_name": "De Haan", 132 | "email": "ldehaan@my.org", 133 | "phone_number": "515.123.4569", 134 | "hire_date": "2001-01-13", 135 | "job_id": "AD_VP", 136 | "salary": "17010.00", 137 | "commission_pct": null, 138 | "manager_id": 1, 139 | "department_id": 90, 140 | "created_at": "2022-08-05T04:00:41.026Z", 141 | "updated_at": "2022-08-14T12:54:50.381Z" 142 | } 143 | }, 144 | { 145 | "model": "uiapp.employeemodel", 146 | "pk": 4, 147 | "fields": { 148 | "first_name": "Alexander", 149 | "last_name": "Hunold", 150 | "email": "anuhold@my.org", 151 | "phone_number": "590.423.4567", 152 | "hire_date": "2006-01-03", 153 | "job_id": "IT_PROG", 154 | "salary": "9000.00", 155 | "commission_pct": null, 156 | "manager_id": 3, 157 | "department_id": 60, 158 | "created_at": "2022-08-05T04:01:52.292Z", 159 | "updated_at": "2022-08-05T04:01:52.292Z" 160 | } 161 | }, 162 | { 163 | "model": "uiapp.employeemodel", 164 | "pk": 5, 165 | "fields": { 166 | "first_name": "Bruce", 167 | "last_name": "Ernst", 168 | "email": "bernst@my.org", 169 | "phone_number": "590.423.4568", 170 | "hire_date": "2007-05-25", 171 | "job_id": "IT_PROG", 172 | "salary": "6000.00", 173 | "commission_pct": null, 174 | "manager_id": 3, 175 | "department_id": 60, 176 | "created_at": "2022-08-05T04:03:15.885Z", 177 | "updated_at": "2022-08-15T03:33:09.445Z" 178 | } 179 | } 180 | ] 181 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'base.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/20/django-htmx-sandbox/uiapp/__init__.py -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import EmployeeModel, JobModel, DepartmentsModel 3 | 4 | 5 | admin.site.register(EmployeeModel) 6 | admin.site.register(JobModel) 7 | admin.site.register(DepartmentsModel) -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UiappConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'uiapp' 7 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from .models import EmployeeModel 3 | 4 | 5 | class DateInput(forms.DateInput): 6 | input_type = 'date' 7 | 8 | 9 | class EmployeeForm(forms.ModelForm): 10 | 11 | def clean_email(self): 12 | email = self.cleaned_data['email'] 13 | if '@' not in email: 14 | raise forms.ValidationError('Invalid email') 15 | return email 16 | 17 | def clean_salary(self): 18 | salary = self.cleaned_data['salary'] 19 | if salary < self.cleaned_data['job_id'].min_salary or salary > self.cleaned_data['job_id'].max_salary: 20 | raise forms.ValidationError( 21 | 'Invalid salary, must be in range [{}, {}]'.format(self.cleaned_data['job_id'].min_salary, 22 | self.cleaned_data['job_id'].max_salary)) 23 | return salary 24 | 25 | class Meta: 26 | model = EmployeeModel 27 | fields = ['employee_id', 28 | 'first_name', 29 | 'last_name', 30 | 'email', 31 | 'phone_number', 32 | 'hire_date', 33 | 'job_id', 34 | 'salary', 35 | 'commission_pct', 36 | 'manager_id', 37 | 'department_id'] 38 | widgets = { 39 | 'hire_date': DateInput() 40 | } 41 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/migrations/0011_alter_employeemodel_first_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-13 18:23 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('uiapp', '0010_employeemodel_department_id'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='employeemodel', 15 | name='first_name', 16 | field=models.CharField(max_length=20), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class JobModel(models.Model): 5 | job_id = models.CharField(primary_key=True, max_length=10) 6 | job_title = models.CharField(max_length=35) 7 | min_salary = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True) 8 | max_salary = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True) 9 | created_at = models.DateTimeField(auto_now_add=True) 10 | updated_at = models.DateTimeField(auto_now=True) 11 | 12 | def __str__(self): 13 | return self.job_title 14 | 15 | class Meta: 16 | verbose_name = 'Job' 17 | verbose_name_plural = 'Jobs' 18 | ordering = ['-job_id'] 19 | 20 | 21 | class DepartmentsModel(models.Model): 22 | department_id = models.SmallIntegerField(primary_key=True) 23 | department_name = models.CharField(max_length=30) 24 | manager_id = models.ForeignKey('EmployeeModel', on_delete=models.CASCADE, blank=True, null=True) 25 | location_id = models.SmallIntegerField(blank=True, null=True) 26 | created_at = models.DateTimeField(auto_now_add=True) 27 | updated_at = models.DateTimeField(auto_now=True) 28 | 29 | def __str__(self): 30 | return self.department_name 31 | 32 | class Meta: 33 | verbose_name = 'Department' 34 | verbose_name_plural = 'Departments' 35 | ordering = ['-department_id'] 36 | 37 | 38 | class EmployeeModel(models.Model): 39 | employee_id = models.AutoField(primary_key=True) 40 | first_name = models.CharField(max_length=20) 41 | last_name = models.CharField(max_length=25) 42 | email = models.CharField(max_length=25) 43 | phone_number = models.CharField(max_length=20, blank=True, null=True) 44 | hire_date = models.DateField() 45 | job_id = models.ForeignKey(JobModel, on_delete=models.CASCADE) 46 | salary = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True) 47 | commission_pct = models.DecimalField(max_digits=2, decimal_places=2, blank=True, null=True) 48 | manager_id = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True) 49 | department_id = models.ForeignKey(DepartmentsModel, on_delete=models.CASCADE, blank=True, null=True) 50 | created_at = models.DateTimeField(auto_now_add=True) 51 | updated_at = models.DateTimeField(auto_now=True) 52 | 53 | def __str__(self): 54 | return self.first_name + ' ' + self.last_name 55 | 56 | class Meta: 57 | verbose_name = 'Employee' 58 | verbose_name_plural = 'Employees' 59 | ordering = ['-employee_id'] 60 | constraints = [ 61 | models.CheckConstraint(check=models.Q(salary__gte=0), name='salary_constraint', violation_error_message='Salary must be greater than 0'), 62 | models.UniqueConstraint(fields=['email'], name='Email must be unique'), 63 | ] -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Django, HTMX and Alpine.js 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | {% block content %} 17 | {% endblock %} 18 |
19 | 20 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/templates/edit-form-htmx.html: -------------------------------------------------------------------------------- 1 | {% load widget_tweaks %} 2 | 3 |
9 | 10 | 11 | {% csrf_token %} 12 | 13 |
14 |
15 |
16 | 19 | {% render_field form.first_name placeholder="Bonnie" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %} 20 |
21 |
22 | 25 | {% render_field form.phone_number placeholder="515.123.4567" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %} 26 |
27 |
28 | 30 | {% render_field form.salary class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %} 31 |
32 |
33 | 35 | {% render_field form.department_id class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %} 36 |
37 |
38 |
39 |
40 | 43 | {% render_field form.last_name placeholder="Green" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %} 44 |
45 |
46 | 49 | {% render_field form.hire_date class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %} 50 |
51 |
52 | 55 | {% render_field form.commission_pct placeholder="0" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %} 56 |
57 |
58 |
59 |
60 | 62 | {% render_field form.email class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %} 63 |
64 |
65 | 67 | {% render_field form.job_id class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" %} 68 |
69 |
70 | 72 | {% render_field form.manager_id class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" %} 73 |
74 |
75 |
76 | 80 | 84 | 85 | 86 |
87 | {% include "partials/info.html" %} 88 |
89 | 90 |
-------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/templates/employees-htmx.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |

Employees

6 | 7 | {% include "view-table-htmx.html" %} 8 | 9 |
10 |
11 | 12 |
13 |
14 |

Edit Employee

15 |
16 | 17 | {% include "edit-form-htmx.html" %} 18 | 19 |
20 | 21 |
22 |
23 | 24 |
-------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |

Django, HTMX and Alpine.js

8 |
9 | 10 |
11 | 12 | {% include "employees-htmx.html" %} 13 | 14 | {% endblock %} -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/templates/partials/info.html: -------------------------------------------------------------------------------- 1 | {% for error in errors %} 2 | 3 | 15 | 16 | {% endfor %} 17 | 18 | {% for msg in success %} 19 | 31 | {% endfor %} -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/templates/view-table-htmx.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 10 | 13 | 16 | 19 | 22 | 25 | 28 | 31 | 34 | 37 | 40 | 41 | 42 | 43 | {% for employee in employees %} 44 |
45 |
46 | 49 | 52 | 55 | 58 | 61 | 64 | 67 | 70 | 73 | 76 | 86 | 87 | 88 | {% endfor %} 89 | 90 |
8 | First name 9 | 11 | Last name 12 | 14 | Email 15 | 17 | Phone number 18 | 20 | Hire date 21 | 23 | Job 24 | 26 | Salary 27 | 29 | Commission Pct 30 | 32 | Manager 33 | 35 | Department 36 | 38 | Edit 39 |
47 | {{ employee.first_name }} 48 | 50 | {{ employee.last_name }} 51 | 53 | {{ employee.email }} 54 | 56 | {{ employee.phone_number }} 57 | 59 | {{ employee.hire_date }} 60 | 62 | {{ employee.job_id }} 63 | 65 | {{ employee.salary }} 66 | 68 | {{ employee.commission_pct }} 69 | 71 | {{ employee.manager_id }} 72 | 74 | {{ employee.department_id }} 75 | 77 | 85 |
-------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, include 2 | from .views import IndexView, EmployeeEditView, EmployeeTableView 3 | 4 | 5 | urlpatterns = [ 6 | path('', IndexView.as_view(), name='index'), 7 | path('employees/', EmployeeTableView.as_view(), name='employees'), 8 | path('edit_employee//', EmployeeEditView.as_view(), name='edit_employee'), 9 | path("__reload__/", include("django_browser_reload.urls")), 10 | ] -------------------------------------------------------------------------------- /20/django-htmx-sandbox/uiapp/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.shortcuts import render 3 | from django.views.generic import ListView 4 | from .models import EmployeeModel 5 | from .forms import EmployeeForm 6 | 7 | 8 | class IndexView(ListView): 9 | template_name = 'index.html' 10 | 11 | def get(self, request): 12 | employees = EmployeeModel.objects.all() 13 | context = {'employees': employees} 14 | return render(request, self.template_name, context) 15 | 16 | 17 | class EmployeeTableView(ListView): 18 | template_name = 'view-table-htmx.html' 19 | 20 | def get(self, request): 21 | employees = EmployeeModel.objects.all() 22 | context = {'employees': employees} 23 | return render(request, self.template_name, context) 24 | 25 | 26 | class EmployeeEditView(ListView): 27 | template_name = 'edit-form-htmx.html' 28 | 29 | def get(self, request, pk): 30 | employee = EmployeeModel.objects.get(pk=pk) 31 | form = EmployeeForm(instance=employee) 32 | context = {'form': form} 33 | return render(request, self.template_name, context) 34 | 35 | def post(self, request, pk): 36 | # handle save after edit 37 | if request.POST.get('id') is not None: 38 | pk = request.POST.get('id') 39 | 40 | employee = EmployeeModel.objects.get(pk=pk) 41 | form = EmployeeForm(request.POST, instance=employee) 42 | 43 | if form.is_valid(): 44 | print('Primary key:', pk) 45 | print(form.cleaned_data) 46 | 47 | form.save() 48 | 49 | success = {'Data saved successfully'} 50 | 51 | context = {'form': form, 'success': success} 52 | response = render(request, self.template_name, context) 53 | response['HX-Trigger'] = 'employeeChanged' 54 | return response 55 | else: 56 | context = {'form': form, 'errors': form.errors.values()} 57 | return render(request, self.template_name, context) 58 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/README.MD: -------------------------------------------------------------------------------- 1 | ## 1. Install Django 2 | 3 | ``` 4 | pip install django 5 | ``` 6 | 7 | Install dependencies: 8 | 9 | ``` 10 | pip install django-browser-reload 11 | ``` 12 | 13 | #### Steps 2 - 5 are not required. These steps are needed if you would create app from scratch. Run application in Step 6 14 | 15 | ## 2. Create project 16 | 17 | ``` 18 | django-admin startproject base . 19 | ``` 20 | 21 | ## 3. Create application 22 | 23 | ``` 24 | python manage.py startapp uiapp 25 | ``` 26 | 27 | ## 4. Run Django migrations (build Django ORM) 28 | 29 | ``` 30 | python manage.py makemigrations 31 | ``` 32 | 33 | ``` 34 | python manage.py migrate 35 | ``` 36 | 37 | ## 5. Create Django superuser (not required, DB file is provided) 38 | 39 | ``` 40 | python manage.py createsuperuser 41 | ``` 42 | 43 | Add new employee entries through Django Admin console 44 | 45 | ## 6. Run application 46 | 47 | ``` 48 | python manage.py runserver 49 | ``` 50 | 51 | ## 7. Dump/load data (not required) 52 | 53 | ``` 54 | python manage.py dumpdata uiapp > db.json --indent 4 55 | ``` 56 | 57 | ``` 58 | python manage.py loaddata db.json 59 | ``` 60 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/21/django-jet-htmx-sandbox/base/__init__.py -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/base/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for base project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'base.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/base/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for base project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.1. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'django-insecure-n8$7w6zmcj)rz2rbmefz*b124!@qv6_421q2o(dshfb&7mroc)' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'uiapp.apps.UiappConfig', 41 | 'django_browser_reload', 42 | ] 43 | 44 | MIDDLEWARE = [ 45 | 'django.middleware.security.SecurityMiddleware', 46 | 'django.contrib.sessions.middleware.SessionMiddleware', 47 | 'django.middleware.common.CommonMiddleware', 48 | 'django.middleware.csrf.CsrfViewMiddleware', 49 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 50 | 'django.contrib.messages.middleware.MessageMiddleware', 51 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 52 | 'django_browser_reload.middleware.BrowserReloadMiddleware', 53 | ] 54 | 55 | ROOT_URLCONF = 'base.urls' 56 | 57 | TEMPLATES = [ 58 | { 59 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 60 | 'DIRS': [], 61 | 'APP_DIRS': True, 62 | 'OPTIONS': { 63 | 'context_processors': [ 64 | 'django.template.context_processors.debug', 65 | 'django.template.context_processors.request', 66 | 'django.contrib.auth.context_processors.auth', 67 | 'django.contrib.messages.context_processors.messages', 68 | ], 69 | }, 70 | }, 71 | ] 72 | 73 | WSGI_APPLICATION = 'base.wsgi.application' 74 | 75 | 76 | # Database 77 | # https://docs.djangoproject.com/en/4.1/ref/settings/#databases 78 | 79 | DATABASES = { 80 | 'default': { 81 | 'ENGINE': 'django.db.backends.sqlite3', 82 | 'NAME': BASE_DIR / 'db.sqlite3', 83 | } 84 | } 85 | 86 | 87 | # Password validation 88 | # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators 89 | 90 | AUTH_PASSWORD_VALIDATORS = [ 91 | { 92 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 93 | }, 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 96 | }, 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 99 | }, 100 | { 101 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 102 | }, 103 | ] 104 | 105 | 106 | # Internationalization 107 | # https://docs.djangoproject.com/en/4.1/topics/i18n/ 108 | 109 | LANGUAGE_CODE = 'en-us' 110 | 111 | TIME_ZONE = 'UTC' 112 | 113 | USE_I18N = True 114 | 115 | USE_TZ = True 116 | 117 | 118 | # Static files (CSS, JavaScript, Images) 119 | # https://docs.djangoproject.com/en/4.1/howto/static-files/ 120 | 121 | STATIC_URL = 'uiapp/static/' 122 | 123 | # Default primary key field type 124 | # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field 125 | 126 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 127 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/base/urls.py: -------------------------------------------------------------------------------- 1 | """base URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('', include('uiapp.urls')) 22 | ] 23 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/base/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for base project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'base.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/db.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "model": "uiapp.jobmodel", 4 | "pk": "AD_PRES", 5 | "fields": { 6 | "job_title": "President", 7 | "min_salary": "20080.00", 8 | "max_salary": "40000.00", 9 | "created_at": "2022-08-04T17:12:50.181Z", 10 | "updated_at": "2022-08-04T17:12:50.181Z" 11 | } 12 | }, 13 | { 14 | "model": "uiapp.jobmodel", 15 | "pk": "AD_VP", 16 | "fields": { 17 | "job_title": "Administration Vice President", 18 | "min_salary": "15000.00", 19 | "max_salary": "30000.00", 20 | "created_at": "2022-08-04T17:11:55.525Z", 21 | "updated_at": "2022-08-04T17:11:55.525Z" 22 | } 23 | }, 24 | { 25 | "model": "uiapp.jobmodel", 26 | "pk": "FI_ACCOUNT", 27 | "fields": { 28 | "job_title": "Accountant", 29 | "min_salary": "4200.00", 30 | "max_salary": "9000.00", 31 | "created_at": "2022-08-04T17:13:19.952Z", 32 | "updated_at": "2022-08-04T17:13:19.952Z" 33 | } 34 | }, 35 | { 36 | "model": "uiapp.jobmodel", 37 | "pk": "IT_PROG", 38 | "fields": { 39 | "job_title": "Programmer", 40 | "min_salary": "4000.00", 41 | "max_salary": "10000.00", 42 | "created_at": "2022-08-04T17:11:10.265Z", 43 | "updated_at": "2022-08-04T17:11:10.265Z" 44 | } 45 | }, 46 | { 47 | "model": "uiapp.jobmodel", 48 | "pk": "PU_MAN", 49 | "fields": { 50 | "job_title": "Purchasing Manager", 51 | "min_salary": "8000.00", 52 | "max_salary": "15000.00", 53 | "created_at": "2022-08-04T17:13:49.099Z", 54 | "updated_at": "2022-08-04T17:13:49.099Z" 55 | } 56 | }, 57 | { 58 | "model": "uiapp.departmentsmodel", 59 | "pk": 60, 60 | "fields": { 61 | "department_name": "IT", 62 | "manager_id": 1, 63 | "location_id": 1700, 64 | "created_at": "2022-08-04T19:27:12.768Z", 65 | "updated_at": "2022-08-04T19:29:25.783Z" 66 | } 67 | }, 68 | { 69 | "model": "uiapp.departmentsmodel", 70 | "pk": 90, 71 | "fields": { 72 | "department_name": "Executive", 73 | "manager_id": 1, 74 | "location_id": 1700, 75 | "created_at": "2022-08-04T19:26:22.023Z", 76 | "updated_at": "2022-08-04T19:29:19.970Z" 77 | } 78 | }, 79 | { 80 | "model": "uiapp.departmentsmodel", 81 | "pk": 170, 82 | "fields": { 83 | "department_name": "Manufacturing", 84 | "manager_id": null, 85 | "location_id": 1700, 86 | "created_at": "2022-08-05T04:04:06.458Z", 87 | "updated_at": "2022-08-05T04:04:06.458Z" 88 | } 89 | }, 90 | { 91 | "model": "uiapp.employeemodel", 92 | "pk": 1, 93 | "fields": { 94 | "first_name": "Steven", 95 | "last_name": "King", 96 | "email": "sking@my.org", 97 | "phone_number": "515.123.4567", 98 | "hire_date": "2003-06-17", 99 | "job_id": "AD_PRES", 100 | "salary": "25000.01", 101 | "commission_pct": "0.10", 102 | "manager_id": null, 103 | "department_id": 90, 104 | "created_at": "2022-08-04T19:28:55.526Z", 105 | "updated_at": "2022-08-15T08:23:08.631Z" 106 | } 107 | }, 108 | { 109 | "model": "uiapp.employeemodel", 110 | "pk": 2, 111 | "fields": { 112 | "first_name": "Neena", 113 | "last_name": "Kochhar", 114 | "email": "nkochhar@my.org", 115 | "phone_number": "515.123.4568", 116 | "hire_date": "2005-09-21", 117 | "job_id": "AD_VP", 118 | "salary": "17000.00", 119 | "commission_pct": "0.20", 120 | "manager_id": 1, 121 | "department_id": 90, 122 | "created_at": "2022-08-04T19:30:51.233Z", 123 | "updated_at": "2022-08-15T08:01:00.986Z" 124 | } 125 | }, 126 | { 127 | "model": "uiapp.employeemodel", 128 | "pk": 3, 129 | "fields": { 130 | "first_name": "Lex", 131 | "last_name": "De Haan", 132 | "email": "ldehaan@my.org", 133 | "phone_number": "515.123.4569", 134 | "hire_date": "2001-01-13", 135 | "job_id": "AD_VP", 136 | "salary": "17010.00", 137 | "commission_pct": null, 138 | "manager_id": 1, 139 | "department_id": 90, 140 | "created_at": "2022-08-05T04:00:41.026Z", 141 | "updated_at": "2022-08-14T12:54:50.381Z" 142 | } 143 | }, 144 | { 145 | "model": "uiapp.employeemodel", 146 | "pk": 4, 147 | "fields": { 148 | "first_name": "Alexander", 149 | "last_name": "Hunold", 150 | "email": "anuhold@my.org", 151 | "phone_number": "590.423.4567", 152 | "hire_date": "2006-01-03", 153 | "job_id": "IT_PROG", 154 | "salary": "9000.00", 155 | "commission_pct": null, 156 | "manager_id": 3, 157 | "department_id": 60, 158 | "created_at": "2022-08-05T04:01:52.292Z", 159 | "updated_at": "2022-08-05T04:01:52.292Z" 160 | } 161 | }, 162 | { 163 | "model": "uiapp.employeemodel", 164 | "pk": 5, 165 | "fields": { 166 | "first_name": "Bruce", 167 | "last_name": "Ernst", 168 | "email": "bernst@my.org", 169 | "phone_number": "590.423.4568", 170 | "hire_date": "2007-05-25", 171 | "job_id": "IT_PROG", 172 | "salary": "6000.00", 173 | "commission_pct": null, 174 | "manager_id": 3, 175 | "department_id": 60, 176 | "created_at": "2022-08-05T04:03:15.885Z", 177 | "updated_at": "2022-08-15T03:33:09.445Z" 178 | } 179 | } 180 | ] 181 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'base.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/21/django-jet-htmx-sandbox/uiapp/__init__.py -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import EmployeeModel, JobModel, DepartmentsModel 3 | 4 | 5 | admin.site.register(EmployeeModel) 6 | admin.site.register(JobModel) 7 | admin.site.register(DepartmentsModel) -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UiappConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'uiapp' 7 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 13:05 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='EmployeeModel', 16 | fields=[ 17 | ('employee_id', models.AutoField(primary_key=True, serialize=False)), 18 | ('first_name', models.CharField(blank=True, max_length=20, null=True)), 19 | ('last_name', models.CharField(max_length=25)), 20 | ('email', models.CharField(max_length=25)), 21 | ('phone_number', models.CharField(blank=True, max_length=20, null=True)), 22 | ('hire_date', models.DateField(auto_now_add=True)), 23 | ('job_id', models.CharField(max_length=5)), 24 | ('salary', models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True)), 25 | ('commission_pct', models.DecimalField(blank=True, decimal_places=2, max_digits=2, null=True)), 26 | ('manager_id', models.IntegerField(blank=True, max_length=6, null=True)), 27 | ('department_id', models.IntegerField(blank=True, max_length=4, null=True)), 28 | ('created_at', models.DateTimeField(auto_now_add=True)), 29 | ('updated_at', models.DateTimeField(auto_now=True)), 30 | ], 31 | options={ 32 | 'verbose_name': 'Employee', 33 | 'verbose_name_plural': 'Employees', 34 | 'ordering': ['-employee_id'], 35 | }, 36 | ), 37 | ] 38 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0002_alter_employeemodel_department_id_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 13:06 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('uiapp', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='employeemodel', 15 | name='department_id', 16 | field=models.DecimalField(blank=True, decimal_places=0, max_digits=4, null=True), 17 | ), 18 | migrations.AlterField( 19 | model_name='employeemodel', 20 | name='manager_id', 21 | field=models.DecimalField(blank=True, decimal_places=0, max_digits=6, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0003_alter_employeemodel_department_id_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 13:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('uiapp', '0002_alter_employeemodel_department_id_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='employeemodel', 15 | name='department_id', 16 | field=models.SmallIntegerField(blank=True, null=True), 17 | ), 18 | migrations.AlterField( 19 | model_name='employeemodel', 20 | name='manager_id', 21 | field=models.SmallIntegerField(blank=True, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0004_alter_employeemodel_hire_date.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 13:13 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('uiapp', '0003_alter_employeemodel_department_id_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='employeemodel', 15 | name='hire_date', 16 | field=models.DateField(), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0005_alter_employeemodel_job_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 13:17 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('uiapp', '0004_alter_employeemodel_hire_date'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='employeemodel', 15 | name='job_id', 16 | field=models.CharField(max_length=10), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0006_jobmodel.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 17:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('uiapp', '0005_alter_employeemodel_job_id'), 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='JobModel', 15 | fields=[ 16 | ('job_id', models.CharField(max_length=10, primary_key=True, serialize=False)), 17 | ('job_title', models.CharField(max_length=35)), 18 | ('min_salary', models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True)), 19 | ('max_salary', models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True)), 20 | ('created_at', models.DateTimeField(auto_now_add=True)), 21 | ('updated_at', models.DateTimeField(auto_now=True)), 22 | ], 23 | options={ 24 | 'verbose_name': 'Job', 25 | 'verbose_name_plural': 'Jobs', 26 | 'ordering': ['-job_id'], 27 | }, 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0007_alter_employeemodel_job_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 17:19 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('uiapp', '0006_jobmodel'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='employeemodel', 16 | name='job_id', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='uiapp.jobmodel'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0008_alter_employeemodel_manager_id_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 19:19 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('uiapp', '0007_alter_employeemodel_job_id'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='employeemodel', 16 | name='manager_id', 17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='uiapp.employeemodel'), 18 | ), 19 | migrations.AddConstraint( 20 | model_name='employeemodel', 21 | constraint=models.CheckConstraint(check=models.Q(('salary__gte', 0)), name='salary_gt_0'), 22 | ), 23 | migrations.AddConstraint( 24 | model_name='employeemodel', 25 | constraint=models.UniqueConstraint(fields=('email',), name='email_unique'), 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0009_remove_employeemodel_department_id_departmentsmodel.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 19:24 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('uiapp', '0008_alter_employeemodel_manager_id_and_more'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='employeemodel', 16 | name='department_id', 17 | ), 18 | migrations.CreateModel( 19 | name='DepartmentsModel', 20 | fields=[ 21 | ('department_id', models.SmallIntegerField(primary_key=True, serialize=False)), 22 | ('department_name', models.CharField(max_length=30)), 23 | ('location_id', models.SmallIntegerField(blank=True, null=True)), 24 | ('created_at', models.DateTimeField(auto_now_add=True)), 25 | ('updated_at', models.DateTimeField(auto_now=True)), 26 | ('manager_id', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='uiapp.employeemodel')), 27 | ], 28 | options={ 29 | 'verbose_name': 'Department', 30 | 'verbose_name_plural': 'Departments', 31 | 'ordering': ['-department_id'], 32 | }, 33 | ), 34 | ] 35 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0010_employeemodel_department_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-04 19:24 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('uiapp', '0009_remove_employeemodel_department_id_departmentsmodel'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='employeemodel', 16 | name='department_id', 17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='uiapp.departmentsmodel'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/0011_alter_employeemodel_first_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-13 18:23 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('uiapp', '0010_employeemodel_department_id'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='employeemodel', 15 | name='first_name', 16 | field=models.CharField(max_length=20), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katanaml/sample-apps/05466acd5dbea82b31e2a32cc9777120cb7ebab3/21/django-jet-htmx-sandbox/uiapp/migrations/__init__.py -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class JobModel(models.Model): 5 | job_id = models.CharField(primary_key=True, max_length=10) 6 | job_title = models.CharField(max_length=35) 7 | min_salary = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True) 8 | max_salary = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True) 9 | created_at = models.DateTimeField(auto_now_add=True) 10 | updated_at = models.DateTimeField(auto_now=True) 11 | 12 | def natural_key(self): 13 | return self.job_title 14 | 15 | def __str__(self): 16 | return self.job_title 17 | 18 | class Meta: 19 | verbose_name = 'Job' 20 | verbose_name_plural = 'Jobs' 21 | ordering = ['-job_id'] 22 | 23 | 24 | class DepartmentsModel(models.Model): 25 | department_id = models.SmallIntegerField(primary_key=True) 26 | department_name = models.CharField(max_length=30) 27 | manager_id = models.ForeignKey('EmployeeModel', on_delete=models.CASCADE, blank=True, null=True) 28 | location_id = models.SmallIntegerField(blank=True, null=True) 29 | created_at = models.DateTimeField(auto_now_add=True) 30 | updated_at = models.DateTimeField(auto_now=True) 31 | 32 | def natural_key(self): 33 | return self.department_name 34 | 35 | def __str__(self): 36 | return self.department_name 37 | 38 | class Meta: 39 | verbose_name = 'Department' 40 | verbose_name_plural = 'Departments' 41 | ordering = ['-department_id'] 42 | 43 | 44 | class EmployeeModel(models.Model): 45 | employee_id = models.AutoField(primary_key=True) 46 | first_name = models.CharField(max_length=20) 47 | last_name = models.CharField(max_length=25) 48 | email = models.CharField(max_length=25) 49 | phone_number = models.CharField(max_length=20, blank=True, null=True) 50 | hire_date = models.DateField() 51 | job_id = models.ForeignKey(JobModel, on_delete=models.CASCADE) 52 | salary = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True) 53 | commission_pct = models.DecimalField(max_digits=2, decimal_places=2, blank=True, null=True) 54 | manager_id = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True) 55 | department_id = models.ForeignKey(DepartmentsModel, on_delete=models.CASCADE, blank=True, null=True) 56 | created_at = models.DateTimeField(auto_now_add=True) 57 | updated_at = models.DateTimeField(auto_now=True) 58 | 59 | def natural_key(self): 60 | return self.first_name + ' ' + self.last_name 61 | 62 | def __str__(self): 63 | return self.first_name + ' ' + self.last_name 64 | 65 | class Meta: 66 | verbose_name = 'Employee' 67 | verbose_name_plural = 'Employees' 68 | ordering = ['-employee_id'] 69 | constraints = [ 70 | models.CheckConstraint(check=models.Q(salary__gte=0), name='salary_constraint', violation_error_message='Salary must be greater than 0'), 71 | models.UniqueConstraint(fields=['email'], name='Email must be unique'), 72 | ] -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/static/scripts/index-page.js: -------------------------------------------------------------------------------- 1 | require(['knockout', 2 | 'ojs/ojarraydataprovider', 3 | 'ojs/ojvalidation-base', 4 | 'ojs/ojknockout', 5 | 'ojs/ojtable', 6 | 'ojs/ojvalidation-datetime', 7 | 'ojs/ojvalidation-number' 8 | ], function (ko, ArrayDataProvider, ValidationBase) { 9 | 'use strict'; 10 | 11 | let ViewModel = function () { 12 | 13 | // for salary fields 14 | const salOptions = { 15 | style: 'currency', 16 | currency: 'USD' 17 | }; 18 | const salaryConverter = ValidationBase.Validation.converterFactory("number").createConverter(salOptions); 19 | 20 | // for date fields 21 | const dateOptions = { 22 | formatStyle: 'date', 23 | dateFormat: 'medium' 24 | }; 25 | const dateConverter = ValidationBase.Validation.converterFactory("datetime").createConverter(dateOptions); 26 | 27 | // the use of arrow functions works just fine 28 | this.formatSal = data => salaryConverter.format(data); 29 | this.formatDate = data => dateConverter.format(data); 30 | 31 | var employeesArray = JSON.parse(JSON.parse(document.getElementById('employees').textContent)); 32 | var empsArray = []; 33 | employeesArray.forEach(function (employee) { 34 | var emp = {empno: employee.pk, 35 | fname: employee.fields.first_name, 36 | lname: employee.fields.last_name, 37 | email: employee.fields.email, 38 | phone: employee.fields.phone_number, 39 | job: employee.fields.job_id, 40 | hiredate: employee.fields.hire_date, 41 | sal: employee.fields.salary, 42 | comm: employee.fields.commission_pct, 43 | manager: employee.fields.manager_id, 44 | dept: employee.fields.department_id}; 45 | 46 | empsArray.push(emp); 47 | }); 48 | 49 | this.dataProvider = new ArrayDataProvider(empsArray, { 50 | keyAttributes: "empno" 51 | }); 52 | }; 53 | ko.applyBindings(new ViewModel(), document.getElementById('table')); 54 | }); -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Django, Oracle JET and HTMX 8 | 9 | 10 | 11 | 12 | 14 | 15 | 25 | 26 | 27 | 28 |
29 | {% block content %} 30 | {% endblock %} 31 |
32 | 33 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | 4 | {% block content %} 5 | 6 |
7 |
8 |

Django, Oracle JET and HTMX

9 |
10 |
11 | 12 |
13 |
14 |

Employees

15 | 16 | 30 | 31 | 34 | 37 | 40 | 41 | 42 | 43 |
44 |
45 | 46 |
47 |
48 |

Edit Employee

49 |
50 | 51 | 52 |
53 | 54 |
55 |
56 | 57 | {{ employees |json_script:"employees" }} 58 | 59 | 60 | 61 | {% endblock %} -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, include 2 | from .views import IndexView 3 | 4 | 5 | urlpatterns = [ 6 | path('', IndexView.as_view(), name='index'), 7 | path("__reload__/", include("django_browser_reload.urls")), 8 | ] -------------------------------------------------------------------------------- /21/django-jet-htmx-sandbox/uiapp/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.views.generic import ListView 3 | from django.core import serializers 4 | from uiapp.models import EmployeeModel 5 | 6 | 7 | class IndexView(ListView): 8 | template_name = 'index.html' 9 | 10 | def get(self, request): 11 | employees = EmployeeModel.objects.all() 12 | 13 | data = serializers.serialize('json', employees, use_natural_foreign_keys=True) 14 | 15 | context = {'employees': data} 16 | return render(request, self.template_name, context) 17 | --------------------------------------------------------------------------------