├── django_breeze ├── core │ ├── utils.py │ ├── __init__.py │ ├── handlers │ │ ├── __init__.py │ │ └── files.py │ └── management │ │ ├── commands │ │ ├── startapp.py │ │ ├── startproject.py │ │ ├── create-app.py │ │ └── _remove-app.py │ │ └── __init__.py ├── templatetags │ ├── __init__.py │ └── django_vite.py ├── __init__.py ├── templates │ ├── react_typescript │ │ ├── src │ │ │ ├── vite-env.d.ts │ │ │ ├── index.css │ │ │ ├── Layout │ │ │ │ └── SiteLayout.tsx │ │ │ ├── index.html │ │ │ ├── main.tsx │ │ │ ├── pages │ │ │ │ └── index.tsx │ │ │ └── assets │ │ │ │ └── react.svg │ │ ├── postcss.config.js │ │ ├── tailwind.config.js │ │ ├── tsconfig.node.json │ │ ├── .gitignore │ │ ├── tsconfig.json │ │ ├── package.json │ │ ├── vite.config.ts │ │ └── public │ │ │ └── vite.svg │ ├── vue3_typescript │ │ ├── src │ │ │ ├── vite-env.d.ts │ │ │ ├── index.css │ │ │ ├── components │ │ │ │ └── Framwork.vue │ │ │ ├── assets │ │ │ │ └── vue.svg │ │ │ ├── main.tsx │ │ │ ├── index.html │ │ │ ├── pages │ │ │ │ └── index.vue │ │ │ └── public │ │ │ │ └── vite.svg │ │ ├── postcss.config.js │ │ ├── tailwind.config.js │ │ ├── tsconfig.node.json │ │ ├── .gitignore │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── vite.config.ts │ ├── vue3 │ │ ├── src │ │ │ ├── index.css │ │ │ ├── components │ │ │ │ └── Framwork.vue │ │ │ ├── assets │ │ │ │ └── vue.svg │ │ │ ├── index.html │ │ │ ├── main.jsx │ │ │ ├── pages │ │ │ │ └── index.vue │ │ │ └── public │ │ │ │ └── vite.svg │ │ ├── postcss.config.js │ │ ├── tailwind.config.js │ │ ├── .gitignore │ │ ├── package.json │ │ └── vite.config.js │ ├── react │ │ ├── src │ │ │ ├── index.css │ │ │ ├── Layout │ │ │ │ └── SiteLayout.jsx │ │ │ ├── index.html │ │ │ ├── main.jsx │ │ │ ├── pages │ │ │ │ └── index.jsx │ │ │ └── assets │ │ │ │ └── react.svg │ │ ├── postcss.config.js │ │ ├── tailwind.config.js │ │ ├── .gitignore │ │ ├── package.json │ │ └── vite.config.js │ ├── svelte4 │ │ ├── src │ │ │ ├── index.css │ │ │ ├── components │ │ │ │ └── PackageCard.svelte │ │ │ ├── main.js │ │ │ ├── index.html │ │ │ └── pages │ │ │ │ └── index.svelte │ │ ├── postcss.config.js │ │ ├── tailwind.config.js │ │ ├── package.json │ │ └── vite.config.js │ └── svelte4_typescript │ │ ├── src │ │ ├── index.css │ │ ├── components │ │ │ └── PackageCard.svelte │ │ ├── main.ts │ │ ├── index.html │ │ └── pages │ │ │ └── index.svelte │ │ ├── postcss.config.js │ │ ├── tailwind.config.js │ │ ├── tsconfig.node.json │ │ ├── vite.config.ts │ │ ├── package.json │ │ └── tsconfig.json ├── urls.py ├── static │ └── django_breeze │ │ ├── django-breeze-logo.jpg │ │ └── django-breeze-logo.png ├── __main__.py ├── scripts │ └── django_breeze.py ├── views.py ├── middleware.py ├── apps.py └── settings.py ├── tests └── README.md ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── publish_package.yml ├── pyproject.toml ├── LICENSE.md ├── CODE_OF_CONDUCT.md ├── README.md └── poetry.lock /django_breeze/core/utils.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_breeze/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_breeze/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Tests Directory 2 | -------------------------------------------------------------------------------- /django_breeze/core/handlers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_breeze/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = "django_breeze.apps.DjangoBreezeConfig" 2 | -------------------------------------------------------------------------------- /django_breeze/templatetags/django_vite.py: -------------------------------------------------------------------------------- 1 | from django_vite.templatetags.django_vite import * 2 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /django_breeze/templates/react/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /django_breeze/templates/svelte4/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /django_breeze/templates/react/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /django_breeze/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from django_breeze.views import welcome_page 3 | 4 | urlpatterns = [path("", welcome_page, name="welcome")] 5 | -------------------------------------------------------------------------------- /django_breeze/static/django_breeze/django-breeze-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louxsdon/django-breeze/HEAD/django_breeze/static/django_breeze/django-breeze-logo.jpg -------------------------------------------------------------------------------- /django_breeze/static/django_breeze/django-breeze-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louxsdon/django-breeze/HEAD/django_breeze/static/django_breeze/django-breeze-logo.png -------------------------------------------------------------------------------- /django_breeze/templates/react/src/Layout/SiteLayout.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function SiteLayout({ children }) { 4 | return
{children}
; 5 | } 6 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/src/Layout/SiteLayout.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function SiteLayout({ children }) { 4 | return
{children}
; 5 | } 6 | -------------------------------------------------------------------------------- /django_breeze/templates/react/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ["./src/index.html", "./src/**/*.{js,ts,jsx,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ["./src/index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ["./src/index.html", "./src/**/*.{js,ts,jsx,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ["./src/index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /django_breeze/__main__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Invokes django-breeze when the django_breeze module is run as a script. 3 | Example: python -m django_breeze react 4 | """ 5 | from django_breeze.core import management 6 | 7 | if __name__ == "__main__": 8 | management.execute_command() 9 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4/src/components/PackageCard.svelte: -------------------------------------------------------------------------------- 1 | 4 |
5 |

{framework}

6 |
-------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | 3 | module.exports = { 4 | content: [ 5 | "./src/index.html", 6 | "./src/**/*.{js,svelte}" 7 | ], 8 | darkMode: 'selector', 9 | theme: { 10 | extend: {}, 11 | }, 12 | plugins: [], 13 | } 14 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/src/components/PackageCard.svelte: -------------------------------------------------------------------------------- 1 | 4 |
5 |

{framework}

6 |
-------------------------------------------------------------------------------- /django_breeze/scripts/django_breeze.py: -------------------------------------------------------------------------------- 1 | import re 2 | import sys 3 | from django_breeze.core.management import execute_command 4 | 5 | 6 | def run(): 7 | sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0]) 8 | sys.exit(execute_command()) 9 | 10 | 11 | if __name__ == "__main__": 12 | run() 13 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | 3 | module.exports = { 4 | content: [ 5 | "./src/index.html", 6 | "./src/**/*.{js,svelte}" 7 | ], 8 | darkMode: 'selector', 9 | theme: { 10 | extend: {}, 11 | }, 12 | plugins: [], 13 | } 14 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/src/components/Framwork.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/src/components/Framwork.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 5 | "skipLibCheck": true, 6 | "module": "ESNext", 7 | "moduleResolution": "bundler", 8 | "strict": true, 9 | "noEmit": true 10 | }, 11 | "include": ["vite.config.ts"] 12 | } -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4/src/main.js: -------------------------------------------------------------------------------- 1 | import { createInertiaApp } from "@inertiajs/svelte"; 2 | import "./index.css"; 3 | 4 | createInertiaApp({ 5 | resolve: (name) => { 6 | const pages = import.meta.glob("./pages/**/*.svelte", { eager: true }); 7 | return pages[`./pages/${name}.svelte`]; 8 | }, 9 | setup({ el, App, props }) { 10 | new App({ target: el, props }); 11 | }, 12 | }); 13 | 14 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createInertiaApp } from "@inertiajs/svelte"; 2 | import "./index.css"; 3 | 4 | createInertiaApp({ 5 | resolve: (name) => { 6 | const pages = import.meta.glob("./pages/**/*.svelte", { eager: true }); 7 | return pages[`./pages/${name}.svelte`]; 8 | }, 9 | setup({ el, App, props }) { 10 | new App({ target: el, props }); 11 | }, 12 | }); 13 | 14 | -------------------------------------------------------------------------------- /django_breeze/views.py: -------------------------------------------------------------------------------- 1 | from inertia import render 2 | 3 | 4 | def welcome_page(request): 5 | """A welcome page for a successful project setup 6 | 7 | Args: 8 | request (HttpRequest): A valid http request 9 | 10 | Returns: 11 | httpResponse: An inertia render response 12 | """ 13 | packages = ["Django", "Inertia.js", "Vite.js"] 14 | return render(request, "index", {"packages": packages}) 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | /__pycache__/ 27 | **/__pycache__/ 28 | 29 | # virtual environments 30 | venv 31 | env 32 | 33 | .env -------------------------------------------------------------------------------- /django_breeze/templates/react/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | /__pycache__/ 27 | **/__pycache__/ 28 | 29 | # virtual environments 30 | venv 31 | env 32 | 33 | .env -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | /__pycache__/ 27 | **/__pycache__/ 28 | 29 | # virtual environments 30 | venv 31 | env 32 | 33 | .env -------------------------------------------------------------------------------- /django_breeze/templates/vue3/src/assets/vue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_breeze/templates/react/src/index.html: -------------------------------------------------------------------------------- 1 | {% load django_vite %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% vite_hmr_client %} {% vite_asset 'main.jsx' %} 12 | 13 | Django Breeze 14 | 15 | 16 | 17 | {% block inertia %}{% endblock %} 18 | 19 | 20 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4/src/index.html: -------------------------------------------------------------------------------- 1 | {% load django_vite %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% vite_hmr_client %} {% vite_asset 'main.js' %} 12 | 13 | Django Breeze 14 | 15 | 16 | 17 | {% block inertia %}{% endblock %} 18 | 19 | 20 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/src/assets/vue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/src/index.html: -------------------------------------------------------------------------------- 1 | {% load django_vite %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% vite_hmr_client %} {% vite_asset 'main.jsx' %} 12 | 13 | Django Breeze | Vue 14 | 15 | 16 | 17 | {% block inertia %}{% endblock %} 18 | 19 | 20 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/src/main.jsx: -------------------------------------------------------------------------------- 1 | import { createApp, h } from "vue"; 2 | import { createInertiaApp } from "@inertiajs/vue3"; 3 | import "vite/modulepreload-polyfill"; 4 | import "./index.css"; 5 | 6 | createInertiaApp({ 7 | resolve: (name) => { 8 | const pages = import.meta.glob("./pages/**/*.vue", { eager: true }); 9 | return pages[`./pages/${name}.vue`]; 10 | }, 11 | setup({ el, App, props, plugin }) { 12 | createApp({ render: () => h(App, props) }) 13 | .use(plugin) 14 | .mount(el); 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/src/index.html: -------------------------------------------------------------------------------- 1 | {% load django_vite %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% vite_hmr_client %} {% vite_asset 'main.tsx' %} 12 | 13 | Django Breeze 14 | 15 | 16 | 17 | {% block inertia %}{% endblock %} 18 | 19 | 20 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/src/index.html: -------------------------------------------------------------------------------- 1 | {% load django_vite %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% vite_hmr_client %} {% vite_asset 'main.ts' %} 12 | 13 | Django Breeze 14 | 15 | 16 | 17 | {% block inertia %}{% endblock %} 18 | 19 | 20 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { createApp, h } from "vue"; 2 | import { createInertiaApp } from "@inertiajs/vue3"; 3 | import "vite/modulepreload-polyfill"; 4 | import "./index.css"; 5 | 6 | createInertiaApp({ 7 | resolve: (name) => { 8 | const pages = import.meta.glob("./pages/**/*.vue", { eager: true }); 9 | return pages[`./pages/${name}.vue`]; 10 | }, 11 | setup({ el, App, props, plugin }) { 12 | createApp({ render: () => h(App, props) }) 13 | .use(plugin) 14 | .mount(el); 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@inertiajs/vue3": "^1.0.6", 13 | "vue": "^3.2.47" 14 | }, 15 | "devDependencies": { 16 | "@vitejs/plugin-vue": "^4.1.0", 17 | "autoprefixer": "^10.4.14", 18 | "postcss": "^8.4.23", 19 | "tailwindcss": "^3.3.1", 20 | "vite": "^4.3.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/src/index.html: -------------------------------------------------------------------------------- 1 | {% load django_vite %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% vite_hmr_client %} {% vite_asset 'main.tsx' %} 12 | 13 | Django Breeze | Vue TypeScript 14 | 15 | 16 | 17 | {% block inertia %}{% endblock %} 18 | 19 | 20 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte4", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@sveltejs/vite-plugin-svelte": "^3.1.2", 13 | "@inertiajs/svelte": "^1.2.0", 14 | "autoprefixer": "^10.4.20", 15 | "postcss": "^8.4.44", 16 | "tailwindcss": "^3.4.10" 17 | }, 18 | "devDependencies": { 19 | "vite": "^5.4.3", 20 | "svelte": "^4.2.19" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3_typescript", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vue-tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@inertiajs/vue3": "^1.0.6", 13 | "vue": "^3.2.47" 14 | }, 15 | "devDependencies": { 16 | "@vitejs/plugin-vue": "^4.1.0", 17 | "autoprefixer": "^10.4.14", 18 | "postcss": "^8.4.23", 19 | "tailwindcss": "^3.3.1", 20 | "typescript": "^5.0.2", 21 | "vite": "^4.3.0", 22 | "vue-tsc": "^1.2.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /django_breeze/templates/react/src/main.jsx: -------------------------------------------------------------------------------- 1 | import { createInertiaApp } from "@inertiajs/react"; 2 | import { createRoot } from "react-dom/client"; 3 | import "vite/modulepreload-polyfill"; 4 | import "./index.css"; 5 | 6 | const pages = import.meta.glob("./pages/**/*.jsx"); 7 | 8 | document.addEventListener("DOMContentLoaded", () => { 9 | createInertiaApp({ 10 | resolve: async (name) => { 11 | const page = (await pages[`./pages/${name}.jsx`]()).default; 12 | page.layout = page.layout; 13 | return page; 14 | }, 15 | setup({ el, App, props }) { 16 | createRoot(el).render(); 17 | }, 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { createInertiaApp } from "@inertiajs/react"; 2 | import { createRoot } from "react-dom/client"; 3 | import "vite/modulepreload-polyfill"; 4 | import "./index.css"; 5 | 6 | const pages = import.meta.glob("./pages/**/*.tsx"); 7 | 8 | document.addEventListener("DOMContentLoaded", () => { 9 | createInertiaApp({ 10 | resolve: async (name) => { 11 | const page = (await pages[`./pages/${name}.tsx`]()).default; 12 | page.layout = page.layout; 13 | return page; 14 | }, 15 | setup({ el, App, props }) { 16 | createRoot(el).render(); 17 | }, 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /django_breeze/templates/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-project", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@inertiajs/react": "^1.0.3", 13 | "axios": "^1.3.5", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0" 16 | }, 17 | "devDependencies": { 18 | "@types/react": "^18.0.28", 19 | "@types/react-dom": "^18.0.11", 20 | "@vitejs/plugin-react": "^3.1.0", 21 | "autoprefixer": "^10.4.14", 22 | "postcss": "^8.4.22", 23 | "tailwindcss": "^3.3.1", 24 | "vite": "^4.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { svelte } from "@sveltejs/vite-plugin-svelte"; 3 | import { resolve } from "path"; 4 | 5 | export default defineConfig({ 6 | plugins: [svelte()], 7 | root: resolve("./src"), 8 | base: "/static/", 9 | server: { 10 | host: "localhost", 11 | port: 5173, 12 | open: false, 13 | watch: { 14 | usePolling: true, 15 | disableGlobbing: false, 16 | }, 17 | }, 18 | build: { 19 | outDir: resolve("./static/dist"), 20 | manifest: true, 21 | emptyOutDir: true, 22 | target: "es2015", 23 | rollupOptions: { 24 | input: { 25 | main: resolve("./src/main.js"), 26 | }, 27 | }, 28 | }, 29 | }); -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-react-typescript", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@inertiajs/react": "^1.0.3", 13 | "axios": "^1.3.5", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0" 16 | }, 17 | "devDependencies": { 18 | "@types/react": "^18.0.28", 19 | "@types/react-dom": "^18.0.11", 20 | "@vitejs/plugin-react": "^3.1.0", 21 | "autoprefixer": "^10.4.14", 22 | "postcss": "^8.4.22", 23 | "tailwindcss": "^3.3.1", 24 | "typescript": "^5.8.2", 25 | "vite": "^4.2.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4/src/pages/index.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 | 12 |

Welcome, Django Breeze

13 |

Your project is setup successfully!

14 |

Powered by:

15 |
16 | {#each $page.props.packages as framework} 17 | 18 | {/each} 19 |
20 |
-------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { svelte, vitePreprocess } from "@sveltejs/vite-plugin-svelte"; 3 | import { resolve } from "path"; 4 | 5 | export default defineConfig({ 6 | plugins: [svelte({ preprocess: vitePreprocess() })], 7 | root: resolve("./src"), 8 | base: "/static/", 9 | server: { 10 | host: "localhost", 11 | port: 5173, 12 | open: false, 13 | watch: { 14 | usePolling: true, 15 | disableGlobbing: false, 16 | }, 17 | }, 18 | build: { 19 | outDir: resolve("./static/dist"), 20 | manifest: true, 21 | emptyOutDir: true, 22 | target: "es2015", 23 | rollupOptions: { 24 | input: { 25 | main: resolve("./src/main.js"), 26 | }, 27 | }, 28 | }, 29 | }); -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "preserve", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte4_typescript", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "check": "svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json" 11 | }, 12 | "dependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.1.2", 14 | "@inertiajs/svelte": "^1.2.0", 15 | "autoprefixer": "^10.4.20", 16 | "postcss": "^8.4.44", 17 | "tailwindcss": "^3.4.10" 18 | }, 19 | "devDependencies": { 20 | "vite": "^5.4.3", 21 | "@tsconfig/svelte": "^5.0.4", 22 | "svelte": "^4.2.19", 23 | "svelte-check": "^3.8.5", 24 | "tslib": "^2.6.3", 25 | "typescript": "^5.5.3" 26 | } 27 | } -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/svelte/tsconfig.json", 3 | "compilerOptions": { 4 | "target": "ESNext", 5 | "useDefineForClassFields": true, 6 | "module": "ESNext", 7 | "resolveJsonModule": true, 8 | /** 9 | * Typecheck JS in `.svelte` and `.js` files by default. 10 | * Disable checkJs if you'd like to use dynamic types in JS. 11 | * Note that setting allowJs false does not prevent the use 12 | * of JS in `.svelte` files. 13 | */ 14 | "allowJs": true, 15 | "checkJs": true, 16 | "isolatedModules": true, 17 | "moduleDetection": "force" 18 | }, 19 | "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } -------------------------------------------------------------------------------- /django_breeze/core/management/commands/startapp.py: -------------------------------------------------------------------------------- 1 | from django_breeze.core.management import BaseCommand 2 | import argparse 3 | import sys 4 | 5 | 6 | class StartAppCommand(BaseCommand): 7 | """ 8 | A command that delegates to the Django admin startapp command. 9 | """ 10 | 11 | name = "startapp" 12 | description = "A command that delegates to the Django admin startapp command" 13 | 14 | def add_arguments(self, parser): 15 | parser.add_argument( 16 | "app_args", 17 | help="Django admin startapp command arguments.", 18 | nargs=argparse.REMAINDER, 19 | ) 20 | 21 | def handle(self, args): 22 | from django.core.management import execute_from_command_line 23 | 24 | execute_from_command_line(["django-admin"] + [args.command] + args.app_args) 25 | -------------------------------------------------------------------------------- /django_breeze/middleware.py: -------------------------------------------------------------------------------- 1 | from inertia import share 2 | from django.conf import settings 3 | from django.contrib.messages import get_messages 4 | import json 5 | 6 | 7 | def inertia_share(get_response): 8 | def middleware(request): 9 | message = None 10 | for message in get_messages(request): 11 | message = { 12 | "message": message.message, 13 | "level": message.level, 14 | "tags": message.tags, 15 | "extra_tags": message.extra_tags, 16 | "level_tag": message.level_tag, 17 | } 18 | share( 19 | request, 20 | flash=message, 21 | user=lambda: request.user, # evaluated lazily at render time 22 | ) 23 | 24 | return get_response(request) 25 | 26 | return middleware 27 | -------------------------------------------------------------------------------- /django_breeze/core/management/commands/startproject.py: -------------------------------------------------------------------------------- 1 | from django_breeze.core.management import BaseCommand 2 | import argparse 3 | import sys 4 | 5 | 6 | class StartProjectCommand(BaseCommand): 7 | """ 8 | A command that delegates to the Django admin startproject command. 9 | """ 10 | 11 | name = "startproject" 12 | description = "A command that delegates to the Django admin startproject command" 13 | 14 | def add_arguments(self, parser): 15 | parser.add_argument( 16 | "project_args", 17 | help="Django admin startproject command arguments.", 18 | nargs=argparse.REMAINDER, 19 | ) 20 | 21 | def handle(self, args): 22 | from django.core.management import execute_from_command_line 23 | 24 | execute_from_command_line(["django-admin"] + [args.command] + args.project_args) 25 | -------------------------------------------------------------------------------- /django_breeze/templates/svelte4_typescript/src/pages/index.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 | 16 |

Welcome, Django Breeze

17 |

Your project is setup successfully!

18 |

Powered by:

19 |
20 | {#each packages as framework} 21 | 22 | {/each} 23 |
24 |
-------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "django-breeze" 3 | version = "1.1.0" 4 | description = "Django Breeze provides a minimal and simple starting point for building a Django application with Inertia and Vite with minimal or no configuration. Styled with Tailwind CSS." 5 | keywords = ["react", "django", "vue", "inertia", "vite"] 6 | authors = ["louxsdon "] 7 | license = "MIT" 8 | readme = "README.md" 9 | repository = "https://github.com/Louxsdon/django-breeze" 10 | packages = [{ include = "django_breeze" }] 11 | 12 | [tool.poetry.dependencies] 13 | python = "^3.10" 14 | django-vite = "3.0.5" 15 | inertia-django = "0.6.0" 16 | 17 | 18 | [tool.poetry.group.dev.dependencies] 19 | mypy = "^1.2.0" 20 | 21 | [tool.poetry.scripts] 22 | django-breeze = 'django_breeze.scripts.django_breeze:run' 23 | 24 | [build-system] 25 | requires = ["poetry-core"] 26 | build-backend = "poetry.core.masonry.api" 27 | -------------------------------------------------------------------------------- /django_breeze/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | from django_breeze.settings import initialize 3 | 4 | 5 | class DjangoBreezeConfig(AppConfig): 6 | default_auto_field = "django.db.models.BigAutoField" 7 | name = "django_breeze" 8 | 9 | def ready(self): 10 | initialize() 11 | from django_breeze import urls 12 | 13 | # Import the project's URL patterns 14 | from django.conf import settings 15 | from importlib import import_module 16 | 17 | # Get the current urlpatterns from the root URL configuration 18 | root_urlconf = import_module(settings.ROOT_URLCONF) 19 | urlpatterns = getattr(root_urlconf, "urlpatterns", []) 20 | 21 | # append django-breeze url patterns 22 | urlpatterns += urls.urlpatterns 23 | 24 | # Set the modified urlpatterns back to the ROOT_URLCONF setting 25 | root_urlconf.urlpatterns = urlpatterns 26 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 29 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import vue from "@vitejs/plugin-vue"; 3 | import { resolve } from "path"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [vue()], 8 | root: resolve("./src"), 9 | base: "/static/", 10 | server: { 11 | host: "localhost", 12 | port: 5173, 13 | open: false, 14 | watch: { 15 | usePolling: true, 16 | disableGlobbing: false, 17 | }, 18 | }, 19 | resolve: { 20 | resolve: { 21 | extensions: [".vue", ".js", ".jsx", ".json"], 22 | }, 23 | }, 24 | build: { 25 | outDir: resolve("./static/dist"), 26 | assetsDir: "", 27 | manifest: true, 28 | emptyOutDir: true, 29 | target: "es2015", 30 | rollupOptions: { 31 | input: { 32 | main: resolve("./src/main.jsx"), 33 | }, 34 | output: { 35 | chunkFileNames: undefined, 36 | }, 37 | }, 38 | }, 39 | }); 40 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 29 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import vue from "@vitejs/plugin-vue"; 3 | import { resolve } from "path"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [vue()], 8 | root: resolve("./src"), 9 | base: "/static/", 10 | server: { 11 | host: "localhost", 12 | port: 5173, 13 | open: false, 14 | watch: { 15 | usePolling: true, 16 | disableGlobbing: false, 17 | }, 18 | }, 19 | resolve: { 20 | resolve: { 21 | extensions: [".vue", ".ts", ".tsx", ".json"], 22 | }, 23 | }, 24 | build: { 25 | outDir: resolve("./static/dist"), 26 | assetsDir: "", 27 | manifest: true, 28 | emptyOutDir: true, 29 | target: "es2015", 30 | rollupOptions: { 31 | input: { 32 | main: resolve("./src/main.tsx"), 33 | }, 34 | output: { 35 | chunkFileNames: undefined, 36 | }, 37 | }, 38 | }, 39 | }); 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /django_breeze/templates/react/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | import { resolve } from "path"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [ 8 | react({ 9 | include: "**/*.disabled", 10 | }), 11 | ], 12 | root: resolve("./src"), 13 | base: "/static/", 14 | server: { 15 | host: "localhost", 16 | port: 5173, 17 | open: false, 18 | watch: { 19 | usePolling: true, 20 | disableGlobbing: false, 21 | }, 22 | }, 23 | resolve: { 24 | resolve: { 25 | extensions: [".js", ".jsx", ".json"], 26 | }, 27 | }, 28 | build: { 29 | outDir: resolve("./static/dist"), 30 | assetsDir: "", 31 | manifest: true, 32 | emptyOutDir: true, 33 | target: "es2015", 34 | rollupOptions: { 35 | input: { 36 | main: resolve("./src/main.jsx"), 37 | }, 38 | output: { 39 | chunkFileNames: undefined, 40 | }, 41 | }, 42 | }, 43 | }); 44 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | import { resolve } from "path"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [ 8 | react({ 9 | include: "**/*.disabled", 10 | }), 11 | ], 12 | root: resolve("./src"), 13 | base: "/static/", 14 | server: { 15 | host: "localhost", 16 | port: 5173, 17 | open: false, 18 | watch: { 19 | usePolling: true, 20 | disableGlobbing: false, 21 | }, 22 | }, 23 | resolve: { 24 | resolve: { 25 | extensions: [".ts", ".tsx", ".json"], 26 | }, 27 | }, 28 | build: { 29 | outDir: resolve("./static/dist"), 30 | assetsDir: "", 31 | manifest: true, 32 | emptyOutDir: true, 33 | target: "es2015", 34 | rollupOptions: { 35 | input: { 36 | main: resolve("./src/main.tsx"), 37 | }, 38 | output: { 39 | chunkFileNames: undefined, 40 | }, 41 | }, 42 | }, 43 | }); 44 | -------------------------------------------------------------------------------- /django_breeze/templates/react/src/pages/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function IndexPage(props) { 4 | return ( 5 |
6 | 11 |

Welcome, Django Breeze

12 |

Your project is setup successfully!

13 |

Powered by:

14 |
15 | {props.packages.map((framework, i) => ( 16 | 17 | ))} 18 |
19 |
20 | ); 21 | } 22 | 23 | function PackageCard({ framework }) { 24 | return ( 25 |
26 |

{framework}

27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Louxs Don 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function IndexPage(props: string[]): string { 4 | return ( 5 |
6 | 11 |

Welcome, Django Breeze

12 |

Your project is setup successfully!

13 |

Powered by:

14 |
15 | {props.packages.map((framework, i) => ( 16 | 17 | ))} 18 |
19 |
20 | ); 21 | } 22 | 23 | function PackageCard({ framework }: { framework: string }) { 24 | return ( 25 |
26 |

{framework}

27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /django_breeze/core/management/commands/create-app.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from django_breeze.core.management import BaseCommand 3 | from django_breeze.core.handlers.files import TemplateFilesHandler 4 | 5 | BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent 6 | TEMPLATE_DIR = BASE_DIR / "templates" 7 | 8 | 9 | class CreateAppCommand(BaseCommand): 10 | name = "create-app" 11 | description = "Create a new app" 12 | usage = "create-app [ react|vue3|svelte4 ] [ --typescript ]" 13 | 14 | def add_arguments(self, parser): 15 | parser.add_argument( 16 | "framework", 17 | choices=["react", "vue3", "svelte4"], 18 | help="Framework of the app to create", 19 | ) 20 | parser.add_argument("--typescript", action="store_true", help="use TypeScript") 21 | 22 | def handle(self, args): 23 | template_handler = TemplateFilesHandler() 24 | template_handler.create_project_files(args) 25 | 26 | def _verbose(self, message: str): 27 | """Display brief message of a process(es) 28 | 29 | Args: 30 | message (str): message to display 31 | """ 32 | print(message) 33 | 34 | def _verbose(self, message: str): 35 | """Display brief message of a process(es) 36 | 37 | Args: 38 | message (str): message to display 39 | """ 40 | print(message) 41 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3/src/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_breeze/templates/vue3_typescript/src/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_breeze/core/management/commands/_remove-app.py: -------------------------------------------------------------------------------- 1 | import shutil 2 | import os 3 | from pathlib import Path 4 | 5 | from django_breeze.core.management import BaseCommand 6 | from django_breeze.core.handlers.files import TemplateFilesHandler 7 | 8 | DESTINATION_DIR = os.getcwd() 9 | 10 | 11 | class RemoveAppCommand(BaseCommand): 12 | name = "remove-app" 13 | description = "Remove a previously created app" 14 | usage = "remove-app" 15 | 16 | def add_arguments(self, parser): 17 | parser.add_argument("framwork", help="Name of the app to remove") 18 | parser.add_argument( 19 | "--type", help="Name of the template to remove the app from" 20 | ) 21 | 22 | def handle(self, args): 23 | answer = input( 24 | "This will remove all files and directories generated by 'create-app' command. Continue? [y/n]: " 25 | ).lower() 26 | 27 | if answer != "y": 28 | return 29 | 30 | src_dir = TemplateFilesHandler().get_template_dir(args.framework) 31 | 32 | print(src_dir) 33 | 34 | if args.typescript: 35 | src_dir = str(src_dir) + "_typescript" 36 | 37 | files = get_generated_files(src_dir) 38 | 39 | print("Done.") 40 | 41 | 42 | def get_generated_files(src_dir): 43 | existing_files = [] 44 | for name in os.listdir(src_dir): 45 | if name == ".gitignore": 46 | continue 47 | dest = os.path.join(DESTINATION_DIR, name) 48 | 49 | if os.path.exists(dest): 50 | existing_files.append(dest) 51 | 52 | return existing_files 53 | 54 | 55 | def remove_files(item, dest): 56 | """Copy files and directories from template directory to destination directory 57 | 58 | Args: 59 | src (Path): Source directory 60 | dest (Path): Destination directory 61 | """ 62 | dest_dir = os.path.join(dest, item) 63 | if os.path.isdir(item): 64 | shutil.rmtree(dest_dir) 65 | else: 66 | os.remove(dest_dir) 67 | -------------------------------------------------------------------------------- /django_breeze/core/handlers/files.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import os 3 | import shutil 4 | from typing import List 5 | 6 | 7 | BASE_DIR = Path(__file__).resolve().parent.parent.parent 8 | TEMPLATE_DIR = BASE_DIR / "templates" 9 | 10 | 11 | class TemplateFilesHandler: 12 | """Responsible for handling template files""" 13 | 14 | def get_templates(self) -> List: 15 | """Get list of all available templates 16 | 17 | Returns: 18 | List: List of template files 19 | """ 20 | templates = os.listdir(TEMPLATE_DIR) 21 | return templates 22 | 23 | def get_template_dir(self, template_name: str) -> Path: 24 | """Get the template file's directory 25 | 26 | Args: 27 | template_name (str): Name of the template file 28 | 29 | Returns: 30 | Path: Returns the path to the template directory 31 | """ 32 | return TEMPLATE_DIR / template_name.lower() 33 | 34 | def create_project_files(self, args) -> None: 35 | """Create a new project fles base on the selected framework 36 | 37 | Args: 38 | args: Argparser arguments 39 | """ 40 | DESTINATION_DIR = os.getcwd() 41 | 42 | src_dir = self.get_template_dir(args.framework) 43 | 44 | print(src_dir) 45 | 46 | if args.typescript: 47 | src_dir = str(src_dir) + "_typescript" 48 | 49 | # Check if the source directory exists in the destination directory 50 | for name in os.listdir(src_dir): 51 | if name == ".gitignore": 52 | continue 53 | dest = os.path.join(DESTINATION_DIR, name) 54 | 55 | if os.path.exists(dest): 56 | print(f"File or directory '{dest}' already exists. Skipping.") 57 | return 58 | 59 | # copy template files 60 | copy_files(src_dir, DESTINATION_DIR) 61 | 62 | print("\nProject files generated successfully!\n") 63 | 64 | 65 | def copy_files(src, dest): 66 | """Copy files and directories from template directory to destination directory 67 | 68 | Args: 69 | src (Path): Source directory 70 | dest (Path): Destination directory 71 | """ 72 | 73 | for item in os.listdir(src): 74 | src_dir = os.path.join(src, item) 75 | dest_dir = os.path.join(dest, item) 76 | if os.path.isdir(src_dir): 77 | shutil.copytree(src_dir, dest_dir, dirs_exist_ok=True) 78 | else: 79 | shutil.copy2(src_dir, dest_dir) 80 | -------------------------------------------------------------------------------- /.github/workflows/publish_package.yml: -------------------------------------------------------------------------------- 1 | name: Poetry Publish to PyPi 2 | 3 | on: 4 | release: 5 | types: published 6 | 7 | jobs: 8 | deploy: 9 | runs-on: [ubuntu-latest] 10 | steps: 11 | #---------------------------------------------- 12 | # check-out repo and set-up python 13 | #---------------------------------------------- 14 | - name: Check out repository 15 | uses: actions/checkout@v3 16 | - name: Set up python 17 | id: setup-python 18 | uses: actions/setup-python@v4 19 | with: 20 | python-version: "3.11" 21 | #---------------------------------------------- 22 | # ----- install & configure poetry ----- 23 | #---------------------------------------------- 24 | - name: Install Poetry 25 | uses: snok/install-poetry@v1 26 | with: 27 | virtualenvs-create: true 28 | virtualenvs-in-project: true 29 | installer-parallel: true 30 | 31 | #---------------------------------------------- 32 | # load cached venv if cache exists 33 | #---------------------------------------------- 34 | - name: Load cached venv 35 | id: cached-poetry-dependencies 36 | uses: actions/cache@v3 37 | with: 38 | path: .venv 39 | key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }} 40 | #---------------------------------------------- 41 | # install dependencies if cache does not exist 42 | #---------------------------------------------- 43 | - name: Install dependencies 44 | if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' 45 | run: poetry install --no-interaction --no-root 46 | #---------------------------------------------- 47 | # install your root project, if required 48 | #---------------------------------------------- 49 | - name: Install project 50 | run: poetry install --no-interaction 51 | #---------------------------------------------- 52 | # configure poetry 53 | #---------------------------------------------- 54 | - name: Poetry config 55 | run: poetry config pypi-token.pypi "${{secrets.PYPI_API_TOKEN}}" 56 | #---------------------------------------------- 57 | # build and publish package 58 | #---------------------------------------------- 59 | - name: Build Package 60 | run: poetry build 61 | #---------------------------------------------- 62 | # build and publish package 63 | #---------------------------------------------- 64 | - name: Publish Build Package 65 | run: poetry publish 66 | -------------------------------------------------------------------------------- /django_breeze/core/management/__init__.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import importlib 3 | import os 4 | import pkgutil 5 | import sys 6 | import inspect 7 | 8 | 9 | class BaseCommand: 10 | help = "" 11 | name = None 12 | description = None 13 | usage = None 14 | 15 | def add_arguments(self, parser): 16 | pass 17 | 18 | def handle(self, args): 19 | pass 20 | 21 | def create_parser(self, subparsers): 22 | parser = subparsers.add_parser( 23 | name=self.name, 24 | description=self.description, 25 | usage=self.usage, 26 | ) 27 | parser.set_defaults(command=self.name) 28 | self.add_arguments(parser) 29 | return parser 30 | 31 | 32 | def find_commands(management_dir=__path__[0]): 33 | """ 34 | Given a path to a management directory, return a list of all the command 35 | names that are available. 36 | """ 37 | command_dir = os.path.join(management_dir, "commands") 38 | return [ 39 | name 40 | for _, name, is_pkg in pkgutil.iter_modules([command_dir]) 41 | if not is_pkg and not name.startswith("_") 42 | ] 43 | 44 | 45 | class ManagementUtility: 46 | def __init__(self, argv=None): 47 | self.argv = argv or sys.argv[:] 48 | 49 | def get_command_instance(self, command_name): 50 | """Iterates through the subclasses of BaseCommand and creates a list of command classes that have a matching name attribute. 51 | If there is at least one match, it creates an instance of the first matching command class and returns it. If there are no matches, it returns None. 52 | 53 | Args: 54 | command_name (string): name of the command 55 | 56 | Returns: 57 | instance | None: Return the BaseClass instance or None 58 | """ 59 | command_classes = [ 60 | cls for cls in BaseCommand.__subclasses__() if cls.name == command_name 61 | ] 62 | return command_classes[0]() if command_classes else None 63 | 64 | def create_subparser(self, subparsers, command_name): 65 | module = importlib.import_module( 66 | f".commands.{command_name}", package="django_breeze.core.management" 67 | ) 68 | 69 | for _, command_class in inspect.getmembers(module, inspect.isclass): 70 | if ( 71 | issubclass(command_class, BaseCommand) 72 | and command_class is not BaseCommand 73 | ): 74 | command_class().create_parser(subparsers) 75 | 76 | def execute(self): 77 | """Execute the utility command""" 78 | parser = argparse.ArgumentParser( 79 | description="Django Breeze Management Utility", 80 | usage="django-breeze [options]", 81 | ) 82 | subparsers = parser.add_subparsers(title="Commands", dest="command") 83 | 84 | for command_name in find_commands(): 85 | self.create_subparser(subparsers, command_name) 86 | 87 | args = parser.parse_args(self.argv[1:]) 88 | 89 | if not args.command: 90 | print(parser.print_help(), end="\n\n") 91 | parser.exit() 92 | 93 | command = self.get_command_instance(args.command) 94 | command.handle(args) 95 | 96 | 97 | def execute_command(): 98 | manager = ManagementUtility() 99 | manager.execute() 100 | -------------------------------------------------------------------------------- /django_breeze/settings.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings as django_settings 2 | from inertia.settings import settings as inertia_settings 3 | from pathlib import Path 4 | import inertia 5 | 6 | 7 | def initialize() -> None: 8 | """Initialize all neccessary django, inertia and django-vite settings""" 9 | BASE_DIR = getattr(django_settings, "BASE_DIR") 10 | 11 | MIDDLEWARES = [ 12 | "inertia.middleware.InertiaMiddleware", 13 | # "django-breeze.django_breeze.middleware.inertia_share", 14 | ] 15 | 16 | # Django Breeze Default Settings 17 | DJANGO_BREEZE: dict = { 18 | "TEMPLATE_DIR_PATH": Path(BASE_DIR) / "src/", # path to frontend files 19 | "INERTIA": { 20 | "LAYOUT": "index.html", 21 | "SSR_URL": inertia_settings.INERTIA_SSR_URL, 22 | "SSR_ENABLED": inertia_settings.INERTIA_SSR_ENABLED, 23 | "JSON_ENCODER": inertia_settings.INERTIA_JSON_ENCODER, 24 | }, 25 | "DJANGO_VITE": { 26 | "DEV_MODE": getattr(django_settings, "DEBUG", True), 27 | "SERVER_PROTOCOL": "http", 28 | "DEV_SERVER_HOST": "localhost", 29 | "DEV_SERVER_PORT": 5173, 30 | "WS_CLIENT_URL": "@vite/client", 31 | "ASSETS_PATH": Path(getattr(django_settings, "STATIC_PATH", "static")) 32 | / "dist", 33 | "STATIC_URL_PREFIX": "", 34 | "LEGACY_POLYFILLS_MOTIF": "legacy-polyfills", 35 | }, 36 | "STATIC_ROOT": "static", 37 | "CSRF_HEADER_NAME": "HTTP_X_XSRF_TOKEN", 38 | "CSRF_COOKIE_NAME": "XSRF-TOKEN", 39 | } 40 | 41 | # Get user defined django breeze settings 42 | user_settings = getattr(django_settings, "DJANGO_BREEZE", {}) 43 | 44 | def merge_dicts(*dicts): 45 | """ 46 | Recursively merges dictionaries. 47 | """ 48 | result = {} 49 | for d in dicts: 50 | for k, v in d.items(): 51 | if isinstance(v, dict): 52 | result[k] = merge_dicts(result.get(k, {}), v) 53 | else: 54 | result[k] = v 55 | return result 56 | 57 | # Merge DJANGO_BREEZE and user-defined settings 58 | merged_settings = merge_dicts(DJANGO_BREEZE, user_settings) 59 | 60 | def key_exist(key) -> bool: 61 | return ( 62 | hasattr(django_settings, key) and getattr(django_settings, key) is not None 63 | ) 64 | 65 | settings = {} 66 | 67 | for key, value in merged_settings.items(): 68 | if isinstance(value, dict): 69 | for sub_key, sub_value in value.items(): 70 | sub_key = f"{key}_{sub_key}" 71 | if not key_exist(sub_key): 72 | settings[sub_key] = sub_value 73 | else: 74 | if not key_exist(key): 75 | settings[key] = value 76 | 77 | for key, value in settings.items(): 78 | setattr(django_settings, key, value) 79 | 80 | TEMPLATE_DIR = Path(getattr(django_settings, "TEMPLATE_DIR_PATH")) 81 | 82 | django_settings.TEMPLATES[0]["DIRS"].extend( 83 | [TEMPLATE_DIR, Path(inertia.__file__).resolve().parent / "templates/"] 84 | ) 85 | 86 | django_settings.STATICFILES_DIRS.extend( 87 | [ 88 | django_settings.DJANGO_VITE_ASSETS_PATH, 89 | TEMPLATE_DIR / "assets", 90 | TEMPLATE_DIR / "public", 91 | ] 92 | ) 93 | for middleware in MIDDLEWARES: 94 | django_settings.MIDDLEWARE.append(middleware) 95 | -------------------------------------------------------------------------------- /django_breeze/templates/react/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_breeze/templates/react_typescript/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![django-breeze-logo](https://user-images.githubusercontent.com/60859741/233969758-939d1091-f04c-4625-8e2a-23697bca58d8.jpg) 2 | 3 | # Django Breeze 4 | 5 | ## Introduction 6 | 7 | Django Breeze provides a minimal and simple starting point for building a Django application with `Inertia` and `Vite.js` with minimal or no configuration. Styled with Tailwind CSS. 8 | 9 | Inertia helps build single-page apps, without building an API. Create modern single-page React, Vue, and Svelte apps using classic server-side routing. Works with any backend. Documentation for Inertia can be found on the [Intertia website](https://inertiajs.com/). 10 | 11 | ## Setup and Installation 12 | 13 | Before installing the packages, ensure you are in your project's virtual environment. 14 | 15 | 1. Install the django-breeze package. 16 | 17 | ```bash 18 | pip install django-breeze 19 | ``` 20 | 21 | 2. Create a new django project if you haven't created one already. 22 | 23 | ```bash 24 | django-breeze startproject myproject 25 | ``` 26 | 27 | Add the django_breeze to your `INSTALLED_APPS` in `settings.py` 28 | 29 | ```python 30 | INSTALLED_APPS = [ 31 | #.............. 32 | 'django_breeze', 33 | #.............. 34 | ] 35 | ``` 36 | 37 | ### Generate Project Files 38 | 39 | Generate your frontend project files with django-breeze, use `--typescript` option for usage with TypeScript. 40 | 41 | React 42 | 43 | ```bash 44 | django-breeze create-app react 45 | 46 | ``` 47 | 48 | React With TypeScript 49 | 50 | ```bash 51 | django-breeze create-app react --typescript 52 | 53 | ``` 54 | 55 | Vue 3 56 | 57 | ```bash 58 | django-breeze create-app vue3 59 | ``` 60 | 61 | Vue 3 With TypeScript 62 | 63 | ```bash 64 | django-breeze create-app vue3 --typescript 65 | ``` 66 | 67 | After generating your frontend project files, you should see `src` directory with other relevant files in the root of your django project. 68 | 69 | ### Install the frontend packages 70 | 71 | Run this command to install packages for the frontend. 72 | 73 | ```bash 74 | npm install 75 | 76 | # or 77 | 78 | yarn 79 | ``` 80 | 81 | ### Start the Servers 82 | 83 | Run the following commands to start your development servers. 84 | 85 | 1. Vite server 86 | 87 | ```bash 88 | npm run dev 89 | ``` 90 | 91 | 2. Django server 92 | 93 | ```bash 94 | python manage.py runserver 95 | ``` 96 | 97 | Now visit your django host address at e.g 98 | 99 | ![django-breeze-success-setup screen](https://user-images.githubusercontent.com/60859741/233971714-3729c1d9-6f9e-4a39-ae38-4d76f14419ef.png) 100 | 101 | Now you're all set! 102 | 103 | ## Usage 104 | 105 | ### Responses 106 | 107 | Render Inertia responses is simple, you can either use the provided inertia render function or, for the most common use case, the inertia decorator. The render function accepts four arguments, the first is your request object. The second is the name of the component you want to render from within your pages directory (without extension). The third argument is a dict of `props` that should be provided to your components. The final argument is `template_data`, for any variables you want to provide to your template, but this is much less common. 108 | 109 | ```python 110 | # views.py 111 | 112 | from inertia import render 113 | from .models import Event 114 | 115 | def index(request): 116 | return render(request, 'Event/Index', props={ 117 | 'events': Event.objects.all() 118 | }) 119 | ``` 120 | 121 | Or use the simpler decorator for the most common use cases 122 | 123 | ```python 124 | # views.py 125 | 126 | from inertia import inertia 127 | from .models import Event 128 | 129 | @inertia('Event/Index') 130 | def index(request): 131 | return { 132 | 'events': Event.objects.all(), 133 | } 134 | ``` 135 | 136 | For more information on the usage, refer to [inertia-django Docs.](https://github.com/inertiajs/inertia-django#usage) 137 | 138 | ## Production 139 | 140 | In production, you must do the following: 141 | 142 | 1. In the `settings.py` 143 | 144 | ```python 145 | DEBUG = FALSE 146 | ``` 147 | 148 | 2. Run below command to build your frontend files 149 | 150 | ```bash 151 | npm run build 152 | # or 153 | yarn build 154 | ``` 155 | 156 | 3. Run below django command to collect static files. 157 | 158 | ```bash 159 | python -m manage.py collectstatic 160 | ``` 161 | 162 | ## Settings 163 | 164 | Although, djang breeze comes with minimal or no configuration but here are some of the default settings it comes with out of the box. 165 | 166 | ### Django Settings 167 | 168 | ```python 169 | # settings.py 170 | 171 | STATIC_ROOT = "static" 172 | 173 | DJANGO_BREEZE = { 174 | "INERTIA": { 175 | "LAYOUT": "index.html", 176 | "SSR_URL": "http://localhost:13714", 177 | "SSR_ENABLED": False, 178 | }, 179 | "DJANGO_VITE": { 180 | "DEV_MODE": True, # vite dev mode, default based on django DEBUG 181 | "SERVER_PROTOCOL": "http", 182 | "DEV_SERVER_HOST": "localhost", 183 | "DEV_SERVER_PORT": 5173, 184 | "WS_CLIENT_URL": "@vite/client", 185 | "ASSETS_PATH": "static/dist", # vite build asset path 186 | "STATIC_URL_PREFIX": "", 187 | } 188 | } 189 | ``` 190 | 191 | Settings for [Inertia Django](https://github.com/inertiajs/inertia-django) is under `INERTIA` and [Django Vite](https://github.com/MrBin99/django-vite) is `DJANGO_VITE`. You can find more explaination of the settings on their repos 192 | 193 | `Note:` All settings are joined with underscore to match how their developers defined them e.g inertia settings is `INERTIA_LAYOUT` and django vite is `DJANGO_VITE_DEV_MODE` which has been done automatically by django breeze so you just use the `DJANGO_BREEZE` settings format in your `settings.py` file. 194 | 195 | ## Thank you 196 | 197 | A very big thanks to the following people for their work done: 198 | 199 | - [Inertia.js Team](https://github.com/inertiajs) for Inertia Django Adaptor. 200 | - [MrBin99](https://github.com/MrBin99) for Django Vite. 201 | 202 | ## License 203 | 204 | Django Breeze is open-sourced software licensed under the [MIT license](LICENSE.md). 205 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "asgiref" 5 | version = "3.8.1" 6 | description = "ASGI specs, helper code, and adapters" 7 | optional = false 8 | python-versions = ">=3.8" 9 | files = [ 10 | {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, 11 | {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, 12 | ] 13 | 14 | [package.dependencies] 15 | typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} 16 | 17 | [package.extras] 18 | tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] 19 | 20 | [[package]] 21 | name = "certifi" 22 | version = "2024.8.30" 23 | description = "Python package for providing Mozilla's CA Bundle." 24 | optional = false 25 | python-versions = ">=3.6" 26 | files = [ 27 | {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, 28 | {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, 29 | ] 30 | 31 | [[package]] 32 | name = "charset-normalizer" 33 | version = "3.3.2" 34 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 35 | optional = false 36 | python-versions = ">=3.7.0" 37 | files = [ 38 | {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, 39 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, 40 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, 41 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, 42 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, 43 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, 44 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, 45 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, 46 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, 47 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, 48 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, 49 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, 50 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, 51 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, 52 | {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, 53 | {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, 54 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, 55 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, 56 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, 57 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, 58 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, 59 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, 60 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, 61 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, 62 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, 63 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, 64 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, 65 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, 66 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, 67 | {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, 68 | {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, 69 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, 70 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, 71 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, 72 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, 73 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, 74 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, 75 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, 76 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, 77 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, 78 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, 79 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, 80 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, 81 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, 82 | {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, 83 | {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, 84 | {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, 85 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, 86 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, 87 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, 88 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, 89 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, 90 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, 91 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, 92 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, 93 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, 94 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, 95 | {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, 96 | {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, 97 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, 98 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, 99 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, 100 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, 101 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, 102 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, 103 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, 104 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, 105 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, 106 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, 107 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, 108 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, 109 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, 110 | {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, 111 | {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, 112 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, 113 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, 114 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, 115 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, 116 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, 117 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, 118 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, 119 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, 120 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, 121 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, 122 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, 123 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, 124 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, 125 | {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, 126 | {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, 127 | {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, 128 | ] 129 | 130 | [[package]] 131 | name = "django" 132 | version = "5.1.1" 133 | description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." 134 | optional = false 135 | python-versions = ">=3.10" 136 | files = [ 137 | {file = "Django-5.1.1-py3-none-any.whl", hash = "sha256:71603f27dac22a6533fb38d83072eea9ddb4017fead6f67f2562a40402d61c3f"}, 138 | {file = "Django-5.1.1.tar.gz", hash = "sha256:021ffb7fdab3d2d388bc8c7c2434eb9c1f6f4d09e6119010bbb1694dda286bc2"}, 139 | ] 140 | 141 | [package.dependencies] 142 | asgiref = ">=3.8.1,<4" 143 | sqlparse = ">=0.3.1" 144 | tzdata = {version = "*", markers = "sys_platform == \"win32\""} 145 | 146 | [package.extras] 147 | argon2 = ["argon2-cffi (>=19.1.0)"] 148 | bcrypt = ["bcrypt"] 149 | 150 | [[package]] 151 | name = "django-vite" 152 | version = "3.0.5" 153 | description = "Integration of Vite in a Django project." 154 | optional = false 155 | python-versions = "*" 156 | files = [ 157 | {file = "django_vite-3.0.5-py3-none-any.whl", hash = "sha256:049b74f38c999cbfcf0e2c21b254c2e059bb97bfd7e4049caf2d0f9fba0b482f"}, 158 | {file = "django_vite-3.0.5.tar.gz", hash = "sha256:431c1212e7627adc20666d150578f1a8983f043e90f3905778fb3c5c0ffe6963"}, 159 | ] 160 | 161 | [package.dependencies] 162 | Django = ">=3.2" 163 | 164 | [package.extras] 165 | dev = ["black"] 166 | 167 | [[package]] 168 | name = "idna" 169 | version = "3.10" 170 | description = "Internationalized Domain Names in Applications (IDNA)" 171 | optional = false 172 | python-versions = ">=3.6" 173 | files = [ 174 | {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, 175 | {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, 176 | ] 177 | 178 | [package.extras] 179 | all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] 180 | 181 | [[package]] 182 | name = "inertia-django" 183 | version = "0.6.0" 184 | description = "Django adapter for the InertiaJS framework" 185 | optional = false 186 | python-versions = ">=3.8,<4.0" 187 | files = [ 188 | {file = "inertia_django-0.6.0-py3-none-any.whl", hash = "sha256:362b02c20cbbb7eebe0a55c7ea4819831810ea42fc481f0611913ace91df531c"}, 189 | {file = "inertia_django-0.6.0.tar.gz", hash = "sha256:fdaf2557d357b755d7762b3fc0f39864b59071326f6524487ad0af173b4f8ec6"}, 190 | ] 191 | 192 | [package.dependencies] 193 | django = ">=4" 194 | requests = ">=2,<3" 195 | 196 | [[package]] 197 | name = "mypy" 198 | version = "1.11.2" 199 | description = "Optional static typing for Python" 200 | optional = false 201 | python-versions = ">=3.8" 202 | files = [ 203 | {file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"}, 204 | {file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"}, 205 | {file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"}, 206 | {file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"}, 207 | {file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"}, 208 | {file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"}, 209 | {file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"}, 210 | {file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"}, 211 | {file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"}, 212 | {file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"}, 213 | {file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"}, 214 | {file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"}, 215 | {file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"}, 216 | {file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"}, 217 | {file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"}, 218 | {file = "mypy-1.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:37c7fa6121c1cdfcaac97ce3d3b5588e847aa79b580c1e922bb5d5d2902df19b"}, 219 | {file = "mypy-1.11.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a8a53bc3ffbd161b5b2a4fff2f0f1e23a33b0168f1c0778ec70e1a3d66deb86"}, 220 | {file = "mypy-1.11.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ff93107f01968ed834f4256bc1fc4475e2fecf6c661260066a985b52741ddce"}, 221 | {file = "mypy-1.11.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:edb91dded4df17eae4537668b23f0ff6baf3707683734b6a818d5b9d0c0c31a1"}, 222 | {file = "mypy-1.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:ee23de8530d99b6db0573c4ef4bd8f39a2a6f9b60655bf7a1357e585a3486f2b"}, 223 | {file = "mypy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6"}, 224 | {file = "mypy-1.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70"}, 225 | {file = "mypy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d"}, 226 | {file = "mypy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d"}, 227 | {file = "mypy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24"}, 228 | {file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"}, 229 | {file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"}, 230 | ] 231 | 232 | [package.dependencies] 233 | mypy-extensions = ">=1.0.0" 234 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 235 | typing-extensions = ">=4.6.0" 236 | 237 | [package.extras] 238 | dmypy = ["psutil (>=4.0)"] 239 | install-types = ["pip"] 240 | mypyc = ["setuptools (>=50)"] 241 | reports = ["lxml"] 242 | 243 | [[package]] 244 | name = "mypy-extensions" 245 | version = "1.0.0" 246 | description = "Type system extensions for programs checked with the mypy type checker." 247 | optional = false 248 | python-versions = ">=3.5" 249 | files = [ 250 | {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, 251 | {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, 252 | ] 253 | 254 | [[package]] 255 | name = "requests" 256 | version = "2.32.3" 257 | description = "Python HTTP for Humans." 258 | optional = false 259 | python-versions = ">=3.8" 260 | files = [ 261 | {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, 262 | {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, 263 | ] 264 | 265 | [package.dependencies] 266 | certifi = ">=2017.4.17" 267 | charset-normalizer = ">=2,<4" 268 | idna = ">=2.5,<4" 269 | urllib3 = ">=1.21.1,<3" 270 | 271 | [package.extras] 272 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 273 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] 274 | 275 | [[package]] 276 | name = "sqlparse" 277 | version = "0.5.1" 278 | description = "A non-validating SQL parser." 279 | optional = false 280 | python-versions = ">=3.8" 281 | files = [ 282 | {file = "sqlparse-0.5.1-py3-none-any.whl", hash = "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4"}, 283 | {file = "sqlparse-0.5.1.tar.gz", hash = "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e"}, 284 | ] 285 | 286 | [package.extras] 287 | dev = ["build", "hatch"] 288 | doc = ["sphinx"] 289 | 290 | [[package]] 291 | name = "tomli" 292 | version = "2.0.1" 293 | description = "A lil' TOML parser" 294 | optional = false 295 | python-versions = ">=3.7" 296 | files = [ 297 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 298 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 299 | ] 300 | 301 | [[package]] 302 | name = "typing-extensions" 303 | version = "4.12.2" 304 | description = "Backported and Experimental Type Hints for Python 3.8+" 305 | optional = false 306 | python-versions = ">=3.8" 307 | files = [ 308 | {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, 309 | {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, 310 | ] 311 | 312 | [[package]] 313 | name = "tzdata" 314 | version = "2024.2" 315 | description = "Provider of IANA time zone data" 316 | optional = false 317 | python-versions = ">=2" 318 | files = [ 319 | {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"}, 320 | {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, 321 | ] 322 | 323 | [[package]] 324 | name = "urllib3" 325 | version = "2.2.3" 326 | description = "HTTP library with thread-safe connection pooling, file post, and more." 327 | optional = false 328 | python-versions = ">=3.8" 329 | files = [ 330 | {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, 331 | {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, 332 | ] 333 | 334 | [package.extras] 335 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] 336 | h2 = ["h2 (>=4,<5)"] 337 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] 338 | zstd = ["zstandard (>=0.18.0)"] 339 | 340 | [metadata] 341 | lock-version = "2.0" 342 | python-versions = "^3.10" 343 | content-hash = "4bac7bd1306e428bcfdf25a9767f5e193f24ce5715bec86cb2c67134f42f77fc" 344 | --------------------------------------------------------------------------------