├── 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 |
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 |
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 |
7 |
8 |
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 |
7 |
8 |
9 |
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 |
16 |
17 |
24 |
25 |
26 | {% for employee in employees %}
27 |
28 | {% if employee.approved %}
29 |
33 |
×
34 | {% else %}
35 |
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 |
7 |
8 |
9 |
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 |
7 |
8 |
9 |
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 |
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 |
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 |
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 |
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 |
--------------------------------------------------------------------------------
/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 |
4 |
10 |
Info
11 |
12 | {{ error }}
13 |
14 |
15 |
16 | {% endfor %}
17 |
18 | {% for msg in success %}
19 |
20 |
26 |
Info
27 |
28 | {{ msg }}
29 |
30 |
31 | {% endfor %}
--------------------------------------------------------------------------------
/20/django-htmx-sandbox/uiapp/templates/view-table-htmx.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | First name
9 | |
10 |
11 | Last name
12 | |
13 |
14 | Email
15 | |
16 |
17 | Phone number
18 | |
19 |
20 | Hire date
21 | |
22 |
23 | Job
24 | |
25 |
26 | Salary
27 | |
28 |
29 | Commission Pct
30 | |
31 |
32 | Manager
33 | |
34 |
35 | Department
36 | |
37 |
38 | Edit
39 | |
40 |
41 |
42 |
43 | {% for employee in employees %}
44 |
45 |
46 |
47 | {{ employee.first_name }}
48 | |
49 |
50 | {{ employee.last_name }}
51 | |
52 |
53 | {{ employee.email }}
54 | |
55 |
56 | {{ employee.phone_number }}
57 | |
58 |
59 | {{ employee.hire_date }}
60 | |
61 |
62 | {{ employee.job_id }}
63 | |
64 |
65 | {{ employee.salary }}
66 | |
67 |
68 | {{ employee.commission_pct }}
69 | |
70 |
71 | {{ employee.manager_id }}
72 | |
73 |
74 | {{ employee.department_id }}
75 | |
76 |
77 |
85 | |
86 |
87 |
88 | {% endfor %}
89 |
90 |
--------------------------------------------------------------------------------
/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 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
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 |
--------------------------------------------------------------------------------