django-db-chat-widget 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_db_chat_widget-0.1.0/.github/workflows/ci.yml +35 -0
- django_db_chat_widget-0.1.0/.gitignore +18 -0
- django_db_chat_widget-0.1.0/LICENSE +21 -0
- django_db_chat_widget-0.1.0/PKG-INFO +156 -0
- django_db_chat_widget-0.1.0/README.md +124 -0
- django_db_chat_widget-0.1.0/example_project/example_project/__init__.py +0 -0
- django_db_chat_widget-0.1.0/example_project/example_project/settings.py +61 -0
- django_db_chat_widget-0.1.0/example_project/example_project/urls.py +7 -0
- django_db_chat_widget-0.1.0/example_project/example_project/wsgi.py +7 -0
- django_db_chat_widget-0.1.0/example_project/manage.py +19 -0
- django_db_chat_widget-0.1.0/example_project/seed_db.py +49 -0
- django_db_chat_widget-0.1.0/example_project/templates/home.html +32 -0
- django_db_chat_widget-0.1.0/pyproject.toml +61 -0
- django_db_chat_widget-0.1.0/src/django_db_chat_widget/__init__.py +1 -0
- django_db_chat_widget-0.1.0/src/django_db_chat_widget/apps.py +7 -0
- django_db_chat_widget-0.1.0/src/django_db_chat_widget/conf.py +106 -0
- django_db_chat_widget-0.1.0/src/django_db_chat_widget/static/django_db_chat_widget/widget.css +253 -0
- django_db_chat_widget-0.1.0/src/django_db_chat_widget/static/django_db_chat_widget/widget.js +233 -0
- django_db_chat_widget-0.1.0/src/django_db_chat_widget/templatetags/__init__.py +0 -0
- django_db_chat_widget-0.1.0/src/django_db_chat_widget/templatetags/db_chat_widget.py +64 -0
- django_db_chat_widget-0.1.0/src/django_db_chat_widget/urls.py +10 -0
- django_db_chat_widget-0.1.0/src/django_db_chat_widget/views.py +35 -0
- django_db_chat_widget-0.1.0/tests/__init__.py +0 -0
- django_db_chat_widget-0.1.0/tests/conftest.py +30 -0
- django_db_chat_widget-0.1.0/tests/settings.py +50 -0
- django_db_chat_widget-0.1.0/tests/test_conf.py +70 -0
- django_db_chat_widget-0.1.0/tests/test_templatetags.py +37 -0
- django_db_chat_widget-0.1.0/tests/test_views.py +81 -0
- django_db_chat_widget-0.1.0/tests/urls.py +5 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
|
14
|
+
django-version: ["4.2", "5.0"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
|
|
22
|
+
- name: Install db-chat-widget (core) from GitHub
|
|
23
|
+
run: pip install "db-chat-widget @ git+https://github.com/krak225/db-chat-widget.git"
|
|
24
|
+
|
|
25
|
+
- name: Install package with dev extras
|
|
26
|
+
run: pip install -e ".[dev]"
|
|
27
|
+
|
|
28
|
+
- name: Install pinned Django version
|
|
29
|
+
run: pip install "django~=${{ matrix.django-version }}.0"
|
|
30
|
+
|
|
31
|
+
- name: Lint
|
|
32
|
+
run: ruff check .
|
|
33
|
+
|
|
34
|
+
- name: Test
|
|
35
|
+
run: pytest -v
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Armand Kouassi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-db-chat-widget
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Django integration for db-chat-widget: a natural-language database chatbot widget for Django templates.
|
|
5
|
+
Project-URL: Homepage, https://github.com/krak225/django-db-chat-widget
|
|
6
|
+
Project-URL: Issues, https://github.com/krak225/django-db-chat-widget/issues
|
|
7
|
+
Author: Armand Kouassi
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: chatbot,database,django,llm,nl2sql,sql,widget
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Framework :: Django
|
|
13
|
+
Classifier: Framework :: Django :: 4.2
|
|
14
|
+
Classifier: Framework :: Django :: 5.0
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Database
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Requires-Dist: db-chat-widget>=0.1.0
|
|
26
|
+
Requires-Dist: django>=4.2
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest-django>=4.8; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# django-db-chat-widget
|
|
34
|
+
|
|
35
|
+
Django integration for [db-chat-widget](https://github.com/krak225/db-chat-widget):
|
|
36
|
+
drop a natural-language database chatbot into any Django template as a
|
|
37
|
+
floating popup (or inline panel), backed by your existing Django database
|
|
38
|
+
connection.
|
|
39
|
+
|
|
40
|
+
- **Reuses your existing Django database connection** — no separate
|
|
41
|
+
credentials to configure; the SQLAlchemy URL is derived automatically from
|
|
42
|
+
`settings.DATABASES` (PostgreSQL, MySQL, SQLite).
|
|
43
|
+
- **Pluggable LLM backend**: Anthropic Claude, OpenAI, Groq, or a local
|
|
44
|
+
Ollama model (via [db-chat-widget](https://github.com/krak225/db-chat-widget)).
|
|
45
|
+
- **Read-only by default**: generated SQL is parsed and only `SELECT`
|
|
46
|
+
statements are allowed unless you explicitly opt into write access.
|
|
47
|
+
- **One template tag**: `{% db_chat_widget %}` renders a floating chat
|
|
48
|
+
bubble (or an inline panel) — no extra views or URLs to wire up yourself.
|
|
49
|
+
- **Proper CSRF handling**: works with Django's CSRF protection out of the
|
|
50
|
+
box, no `csrf_exempt` required.
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install django-db-chat-widget
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This pulls in [`db-chat-widget`](https://github.com/krak225/db-chat-widget)
|
|
59
|
+
(the framework-agnostic core: LLM providers, SQL safety checks, query
|
|
60
|
+
execution) as a dependency.
|
|
61
|
+
|
|
62
|
+
Add the app and its URLs:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
# settings.py
|
|
66
|
+
INSTALLED_APPS = [
|
|
67
|
+
...,
|
|
68
|
+
"django.contrib.staticfiles",
|
|
69
|
+
"django_db_chat_widget",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
TEMPLATES = [
|
|
73
|
+
{
|
|
74
|
+
...,
|
|
75
|
+
"OPTIONS": {
|
|
76
|
+
"context_processors": [
|
|
77
|
+
...,
|
|
78
|
+
"django.template.context_processors.request", # required
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
DB_CHAT_WIDGET = {
|
|
85
|
+
"DB_ALIAS": "default", # which DATABASES entry to query
|
|
86
|
+
"LLM_PROVIDER": "groq", # "anthropic" | "openai" | "groq" | "ollama"
|
|
87
|
+
"LLM_API_KEY": "gsk_...", # or read from os.environ
|
|
88
|
+
"READ_ONLY": True, # default: only SELECT statements allowed
|
|
89
|
+
"MAX_ROWS": 200,
|
|
90
|
+
"ALLOWED_TABLES": None, # e.g. ["orders", "customers"] to scope access
|
|
91
|
+
"TITLE": "Ask your database",
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
# urls.py
|
|
97
|
+
from django.urls import include, path
|
|
98
|
+
|
|
99
|
+
urlpatterns = [
|
|
100
|
+
...,
|
|
101
|
+
path("db-chat/", include("django_db_chat_widget.urls")),
|
|
102
|
+
]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Then drop the tag into any template:
|
|
106
|
+
|
|
107
|
+
```html
|
|
108
|
+
{% load db_chat_widget %}
|
|
109
|
+
{% db_chat_widget %}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
That's it — a floating chat bubble now appears in the bottom-right corner of
|
|
113
|
+
that page. See [`example_project/`](example_project) for a complete, runnable
|
|
114
|
+
Django project demonstrating this end to end.
|
|
115
|
+
|
|
116
|
+
## Template tag options
|
|
117
|
+
|
|
118
|
+
```html
|
|
119
|
+
{% db_chat_widget %} {# popup, bottom-right #}
|
|
120
|
+
{% db_chat_widget position="bottom-left" %} {# popup, bottom-left #}
|
|
121
|
+
{% db_chat_widget target="#my-chat-div" %} {# inline instead of popup #}
|
|
122
|
+
{% db_chat_widget title="Ask HR" placeholder="..." %}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Multiple databases / explicit connection
|
|
126
|
+
|
|
127
|
+
If your Django project has several `DATABASES` entries, point
|
|
128
|
+
`DB_CHAT_WIDGET["DB_ALIAS"]` at the one to query. To bypass Django's
|
|
129
|
+
`DATABASES` entirely (e.g. a read replica not declared there), set
|
|
130
|
+
`DB_CHAT_WIDGET["DB_URL"]` to an explicit SQLAlchemy URL instead — it takes
|
|
131
|
+
precedence over `DB_ALIAS`.
|
|
132
|
+
|
|
133
|
+
## Safety notes
|
|
134
|
+
|
|
135
|
+
- `READ_ONLY=True` (the default) is enforced by parsing the generated SQL
|
|
136
|
+
with `sqlglot`, not just by prompting the model — treat it as the actual
|
|
137
|
+
security boundary. See
|
|
138
|
+
[db-chat-widget's safety notes](https://github.com/krak225/db-chat-widget#safety-notes)
|
|
139
|
+
for details.
|
|
140
|
+
- Use `ALLOWED_TABLES` to scope the chatbot away from sensitive tables (e.g.
|
|
141
|
+
Django's own `auth_user` / session tables).
|
|
142
|
+
- The `/db-chat/chat/` endpoint is a normal Django view protected by Django's
|
|
143
|
+
CSRF middleware; the template tag ensures the CSRF cookie is set on any
|
|
144
|
+
page that renders it.
|
|
145
|
+
|
|
146
|
+
## Development
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
pip install -e ".[dev]"
|
|
150
|
+
pytest
|
|
151
|
+
ruff check .
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
MIT
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# django-db-chat-widget
|
|
2
|
+
|
|
3
|
+
Django integration for [db-chat-widget](https://github.com/krak225/db-chat-widget):
|
|
4
|
+
drop a natural-language database chatbot into any Django template as a
|
|
5
|
+
floating popup (or inline panel), backed by your existing Django database
|
|
6
|
+
connection.
|
|
7
|
+
|
|
8
|
+
- **Reuses your existing Django database connection** — no separate
|
|
9
|
+
credentials to configure; the SQLAlchemy URL is derived automatically from
|
|
10
|
+
`settings.DATABASES` (PostgreSQL, MySQL, SQLite).
|
|
11
|
+
- **Pluggable LLM backend**: Anthropic Claude, OpenAI, Groq, or a local
|
|
12
|
+
Ollama model (via [db-chat-widget](https://github.com/krak225/db-chat-widget)).
|
|
13
|
+
- **Read-only by default**: generated SQL is parsed and only `SELECT`
|
|
14
|
+
statements are allowed unless you explicitly opt into write access.
|
|
15
|
+
- **One template tag**: `{% db_chat_widget %}` renders a floating chat
|
|
16
|
+
bubble (or an inline panel) — no extra views or URLs to wire up yourself.
|
|
17
|
+
- **Proper CSRF handling**: works with Django's CSRF protection out of the
|
|
18
|
+
box, no `csrf_exempt` required.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install django-db-chat-widget
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This pulls in [`db-chat-widget`](https://github.com/krak225/db-chat-widget)
|
|
27
|
+
(the framework-agnostic core: LLM providers, SQL safety checks, query
|
|
28
|
+
execution) as a dependency.
|
|
29
|
+
|
|
30
|
+
Add the app and its URLs:
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
# settings.py
|
|
34
|
+
INSTALLED_APPS = [
|
|
35
|
+
...,
|
|
36
|
+
"django.contrib.staticfiles",
|
|
37
|
+
"django_db_chat_widget",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
TEMPLATES = [
|
|
41
|
+
{
|
|
42
|
+
...,
|
|
43
|
+
"OPTIONS": {
|
|
44
|
+
"context_processors": [
|
|
45
|
+
...,
|
|
46
|
+
"django.template.context_processors.request", # required
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
DB_CHAT_WIDGET = {
|
|
53
|
+
"DB_ALIAS": "default", # which DATABASES entry to query
|
|
54
|
+
"LLM_PROVIDER": "groq", # "anthropic" | "openai" | "groq" | "ollama"
|
|
55
|
+
"LLM_API_KEY": "gsk_...", # or read from os.environ
|
|
56
|
+
"READ_ONLY": True, # default: only SELECT statements allowed
|
|
57
|
+
"MAX_ROWS": 200,
|
|
58
|
+
"ALLOWED_TABLES": None, # e.g. ["orders", "customers"] to scope access
|
|
59
|
+
"TITLE": "Ask your database",
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
# urls.py
|
|
65
|
+
from django.urls import include, path
|
|
66
|
+
|
|
67
|
+
urlpatterns = [
|
|
68
|
+
...,
|
|
69
|
+
path("db-chat/", include("django_db_chat_widget.urls")),
|
|
70
|
+
]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Then drop the tag into any template:
|
|
74
|
+
|
|
75
|
+
```html
|
|
76
|
+
{% load db_chat_widget %}
|
|
77
|
+
{% db_chat_widget %}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
That's it — a floating chat bubble now appears in the bottom-right corner of
|
|
81
|
+
that page. See [`example_project/`](example_project) for a complete, runnable
|
|
82
|
+
Django project demonstrating this end to end.
|
|
83
|
+
|
|
84
|
+
## Template tag options
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
{% db_chat_widget %} {# popup, bottom-right #}
|
|
88
|
+
{% db_chat_widget position="bottom-left" %} {# popup, bottom-left #}
|
|
89
|
+
{% db_chat_widget target="#my-chat-div" %} {# inline instead of popup #}
|
|
90
|
+
{% db_chat_widget title="Ask HR" placeholder="..." %}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Multiple databases / explicit connection
|
|
94
|
+
|
|
95
|
+
If your Django project has several `DATABASES` entries, point
|
|
96
|
+
`DB_CHAT_WIDGET["DB_ALIAS"]` at the one to query. To bypass Django's
|
|
97
|
+
`DATABASES` entirely (e.g. a read replica not declared there), set
|
|
98
|
+
`DB_CHAT_WIDGET["DB_URL"]` to an explicit SQLAlchemy URL instead — it takes
|
|
99
|
+
precedence over `DB_ALIAS`.
|
|
100
|
+
|
|
101
|
+
## Safety notes
|
|
102
|
+
|
|
103
|
+
- `READ_ONLY=True` (the default) is enforced by parsing the generated SQL
|
|
104
|
+
with `sqlglot`, not just by prompting the model — treat it as the actual
|
|
105
|
+
security boundary. See
|
|
106
|
+
[db-chat-widget's safety notes](https://github.com/krak225/db-chat-widget#safety-notes)
|
|
107
|
+
for details.
|
|
108
|
+
- Use `ALLOWED_TABLES` to scope the chatbot away from sensitive tables (e.g.
|
|
109
|
+
Django's own `auth_user` / session tables).
|
|
110
|
+
- The `/db-chat/chat/` endpoint is a normal Django view protected by Django's
|
|
111
|
+
CSRF middleware; the template tag ensures the CSRF cookie is set on any
|
|
112
|
+
page that renders it.
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pip install -e ".[dev]"
|
|
118
|
+
pytest
|
|
119
|
+
ruff check .
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MIT
|
|
File without changes
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
5
|
+
|
|
6
|
+
SECRET_KEY = "example-secret-key-not-for-production"
|
|
7
|
+
DEBUG = True
|
|
8
|
+
ALLOWED_HOSTS = ["*"]
|
|
9
|
+
|
|
10
|
+
INSTALLED_APPS = [
|
|
11
|
+
"django.contrib.contenttypes",
|
|
12
|
+
"django.contrib.auth",
|
|
13
|
+
"django.contrib.sessions",
|
|
14
|
+
"django.contrib.staticfiles",
|
|
15
|
+
"django_db_chat_widget",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
MIDDLEWARE = [
|
|
19
|
+
"django.middleware.security.SecurityMiddleware",
|
|
20
|
+
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
21
|
+
"django.middleware.common.CommonMiddleware",
|
|
22
|
+
"django.middleware.csrf.CsrfViewMiddleware",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
ROOT_URLCONF = "example_project.urls"
|
|
26
|
+
|
|
27
|
+
TEMPLATES = [
|
|
28
|
+
{
|
|
29
|
+
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
30
|
+
"DIRS": [BASE_DIR / "templates"],
|
|
31
|
+
"APP_DIRS": True,
|
|
32
|
+
"OPTIONS": {
|
|
33
|
+
"context_processors": [
|
|
34
|
+
"django.template.context_processors.request",
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
WSGI_APPLICATION = "example_project.wsgi.application"
|
|
41
|
+
|
|
42
|
+
# This is also the database that the chatbot answers questions about — see
|
|
43
|
+
# DB_CHAT_WIDGET below, which reuses this same connection by default.
|
|
44
|
+
DATABASES = {
|
|
45
|
+
"default": {
|
|
46
|
+
"ENGINE": "django.db.backends.sqlite3",
|
|
47
|
+
"NAME": BASE_DIR / "db.sqlite3",
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
STATIC_URL = "/static/"
|
|
52
|
+
|
|
53
|
+
USE_TZ = True
|
|
54
|
+
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|
55
|
+
|
|
56
|
+
DB_CHAT_WIDGET = {
|
|
57
|
+
"DB_ALIAS": "default",
|
|
58
|
+
"LLM_PROVIDER": os.environ.get("DB_CHAT_LLM_PROVIDER", "groq"),
|
|
59
|
+
"LLM_API_KEY": os.environ.get("DB_CHAT_LLM_API_KEY"),
|
|
60
|
+
"TITLE": "Ask about our data",
|
|
61
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example_project.settings")
|
|
8
|
+
try:
|
|
9
|
+
from django.core.management import execute_from_command_line
|
|
10
|
+
except ImportError as exc:
|
|
11
|
+
raise ImportError(
|
|
12
|
+
"Couldn't import Django. Make sure it's installed and available on "
|
|
13
|
+
"your PYTHONPATH environment variable."
|
|
14
|
+
) from exc
|
|
15
|
+
execute_from_command_line(sys.argv)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
main()
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Seed example_project/db.sqlite3 with a couple of demo tables.
|
|
2
|
+
|
|
3
|
+
Run once before `python manage.py runserver`:
|
|
4
|
+
|
|
5
|
+
python seed_db.py
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sqlite3
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
DB_PATH = Path(__file__).parent / "db.sqlite3"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main() -> None:
|
|
15
|
+
conn = sqlite3.connect(DB_PATH)
|
|
16
|
+
try:
|
|
17
|
+
conn.execute("DROP TABLE IF EXISTS customers")
|
|
18
|
+
conn.execute("DROP TABLE IF EXISTS orders")
|
|
19
|
+
conn.execute(
|
|
20
|
+
"CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT, country TEXT)"
|
|
21
|
+
)
|
|
22
|
+
conn.execute(
|
|
23
|
+
"CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, "
|
|
24
|
+
"amount REAL, status TEXT)"
|
|
25
|
+
)
|
|
26
|
+
conn.executemany(
|
|
27
|
+
"INSERT INTO customers (id, name, country) VALUES (?, ?, ?)",
|
|
28
|
+
[
|
|
29
|
+
(1, "Awa Diallo", "Senegal"),
|
|
30
|
+
(2, "Kofi Mensah", "Ghana"),
|
|
31
|
+
(3, "Amina Traore", "Cote d'Ivoire"),
|
|
32
|
+
],
|
|
33
|
+
)
|
|
34
|
+
conn.executemany(
|
|
35
|
+
"INSERT INTO orders (id, customer_id, amount, status) VALUES (?, ?, ?, ?)",
|
|
36
|
+
[
|
|
37
|
+
(1, 1, 120.0, "paid"),
|
|
38
|
+
(2, 1, 45.5, "pending"),
|
|
39
|
+
(3, 2, 300.0, "paid"),
|
|
40
|
+
],
|
|
41
|
+
)
|
|
42
|
+
conn.commit()
|
|
43
|
+
finally:
|
|
44
|
+
conn.close()
|
|
45
|
+
print(f"Seeded {DB_PATH}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
main()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>My Django site</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
margin: 0;
|
|
10
|
+
min-height: 100vh;
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
justify-content: center;
|
|
14
|
+
background: #f5f5f7;
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
16
|
+
}
|
|
17
|
+
.card { max-width: 480px; text-align: center; padding: 0 16px; color: #374151; }
|
|
18
|
+
</style>
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
<div class="card">
|
|
22
|
+
<h1>My existing Django site</h1>
|
|
23
|
+
<p>
|
|
24
|
+
This template is otherwise unchanged — only the two lines at the bottom
|
|
25
|
+
were added to get a floating chat bubble in the corner.
|
|
26
|
+
</p>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
{% load db_chat_widget %}
|
|
30
|
+
{% db_chat_widget %}
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "django-db-chat-widget"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Django integration for db-chat-widget: a natural-language database chatbot widget for Django templates."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Armand Kouassi" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["django", "chatbot", "sql", "database", "llm", "nl2sql", "widget"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Framework :: Django",
|
|
19
|
+
"Framework :: Django :: 4.2",
|
|
20
|
+
"Framework :: Django :: 5.0",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.9",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Topic :: Database",
|
|
29
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
dependencies = [
|
|
33
|
+
"django>=4.2",
|
|
34
|
+
"db-chat-widget>=0.1.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
dev = [
|
|
39
|
+
"pytest>=8.0",
|
|
40
|
+
"pytest-django>=4.8",
|
|
41
|
+
"ruff>=0.4",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[project.urls]
|
|
45
|
+
Homepage = "https://github.com/krak225/django-db-chat-widget"
|
|
46
|
+
Issues = "https://github.com/krak225/django-db-chat-widget/issues"
|
|
47
|
+
|
|
48
|
+
[tool.hatch.build.targets.wheel]
|
|
49
|
+
packages = ["src/django_db_chat_widget"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
DJANGO_SETTINGS_MODULE = "tests.settings"
|
|
53
|
+
testpaths = ["tests"]
|
|
54
|
+
python_files = ["test_*.py"]
|
|
55
|
+
|
|
56
|
+
[tool.ruff]
|
|
57
|
+
line-length = 100
|
|
58
|
+
target-version = "py39"
|
|
59
|
+
|
|
60
|
+
[tool.ruff.lint]
|
|
61
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|