django-drfkit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_drfkit-0.1.0.dist-info/METADATA +125 -0
- django_drfkit-0.1.0.dist-info/RECORD +32 -0
- django_drfkit-0.1.0.dist-info/WHEEL +5 -0
- django_drfkit-0.1.0.dist-info/entry_points.txt +2 -0
- django_drfkit-0.1.0.dist-info/top_level.txt +1 -0
- drfkit/__init__.py +0 -0
- drfkit/cli.py +10 -0
- drfkit/commands/__init__.py +0 -0
- drfkit/commands/app.py +7 -0
- drfkit/commands/new.py +102 -0
- drfkit/core/__init__.py +0 -0
- drfkit/core/renderer.py +21 -0
- drfkit/templates/app/__init__.py.j2 +1 -0
- drfkit/templates/app/admin.py.j2 +6 -0
- drfkit/templates/app/apps.py.j2 +5 -0
- drfkit/templates/app/models.py.j2 +3 -0
- drfkit/templates/app/serializers.py.j2 +3 -0
- drfkit/templates/app/tests.py.j2 +3 -0
- drfkit/templates/app/urls.py.j2 +10 -0
- drfkit/templates/app/views.py.j2 +7 -0
- drfkit/templates/project/asgi.py.j2 +6 -0
- drfkit/templates/project/env.j2 +3 -0
- drfkit/templates/project/manage.py.j2 +10 -0
- drfkit/templates/project/requirements/base.txt.j2 +3 -0
- drfkit/templates/project/settings/__init__.py.j2 +0 -0
- drfkit/templates/project/settings/base.py.j2 +66 -0
- drfkit/templates/project/settings/dev.py.j2 +4 -0
- drfkit/templates/project/settings/prod.py.j2 +4 -0
- drfkit/templates/project/urls.py.j2 +8 -0
- drfkit/templates/project/wsgi.py.j2 +6 -0
- drfkit/utils/__init__.py +0 -0
- drfkit/utils/template.py +14 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-drfkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A CLI tool for production-ready DRF scaffolding
|
|
5
|
+
Requires-Python: >=3.8
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: typer
|
|
8
|
+
Requires-Dist: jinja2
|
|
9
|
+
|
|
10
|
+
# DRFKit
|
|
11
|
+
|
|
12
|
+
A powerful CLI tool for scaffolding Django REST Framework projects with a clean, production-ready architecture.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
* **Instant Scaffolding:** Creates a scalable folder structure with `apps/` and `config/` directories.
|
|
19
|
+
* **Security First:** Auto-generates a cryptographically secure `SECRET_KEY` during creation.
|
|
20
|
+
* **Split Settings:** Pre-configured `base.py`, `dev.py`, and `prod.py` for better environment management.
|
|
21
|
+
* **DRF Ready:** Django REST Framework is installed and added to installed apps by default.
|
|
22
|
+
* **Clean Templates:** Generates `.env` and requirements files automatically.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
Install the package via pip:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install drfkit
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
*(Requires Python 3.8+)*
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
### 1. Create a New Project
|
|
37
|
+
|
|
38
|
+
Run the following command to scaffold your project:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
drfkit new project myproject
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This creates the following structure:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
myproject/
|
|
48
|
+
├── config/
|
|
49
|
+
│ ├── settings/
|
|
50
|
+
│ │ ├── base.py
|
|
51
|
+
│ │ ├── dev.py
|
|
52
|
+
│ │ └── prod.py
|
|
53
|
+
│ ├── urls.py
|
|
54
|
+
│ ├── wsgi.py
|
|
55
|
+
│ └── asgi.py
|
|
56
|
+
├── apps/ # Your apps go here
|
|
57
|
+
├── requirements/
|
|
58
|
+
│ └── base.txt
|
|
59
|
+
├── .env # Pre-filled with your secret key
|
|
60
|
+
└── manage.py
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2. Run the Server
|
|
64
|
+
|
|
65
|
+
Navigate to your project and start the development server:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cd myproject
|
|
69
|
+
python -m venv venv
|
|
70
|
+
source venv/bin/activate
|
|
71
|
+
pip install -r requirements/base.txt
|
|
72
|
+
python manage.py runserver
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
No extra configuration needed—it works out of the box!
|
|
76
|
+
|
|
77
|
+
## Usage
|
|
78
|
+
|
|
79
|
+
### Creating an App
|
|
80
|
+
|
|
81
|
+
DRFKit encourages a modular structure by placing apps inside the `apps/` directory.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
drfkit new app myapp
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
This generates:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
apps/myapp/
|
|
91
|
+
├── __init__.py
|
|
92
|
+
├── admin.py
|
|
93
|
+
├── apps.py
|
|
94
|
+
├── models.py
|
|
95
|
+
├── serializers.py # Ready for DRF
|
|
96
|
+
├── tests.py
|
|
97
|
+
├── urls.py
|
|
98
|
+
└── views.py
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
> **Note:** Remember to add `'apps.myapp'` to `INSTALLED_APPS` in `config/settings/base.py`.
|
|
102
|
+
|
|
103
|
+
## Configuration
|
|
104
|
+
|
|
105
|
+
### Environment Settings
|
|
106
|
+
|
|
107
|
+
* **Development:** By default, `manage.py` uses `config.settings.dev`. This is perfect for local coding.
|
|
108
|
+
* **Production:** To switch to production settings, set the environment variable:
|
|
109
|
+
```bash
|
|
110
|
+
export DJANGO_SETTINGS_MODULE=config.settings.prod
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Secret Key
|
|
114
|
+
|
|
115
|
+
A unique `SECRET_KEY` is generated and placed inside `settings/base.py` automatically when you create a project. This ensures your local development is secure from the start.
|
|
116
|
+
|
|
117
|
+
## Contributing
|
|
118
|
+
|
|
119
|
+
Contributions are welcome! If you have ideas for improvement or find a bug, feel free to open an issue or submit a pull request.
|
|
120
|
+
|
|
121
|
+
## 👤 Author
|
|
122
|
+
|
|
123
|
+
**[Your Name]**
|
|
124
|
+
* GitHub: [[Oviyan](https://github.com/Oviyan007/)]
|
|
125
|
+
* Linkedin: [[Oviyan](https://www.linkedin.com/in/oviyan-s/)]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
drfkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
drfkit/cli.py,sha256=INYFxTanTapYSwp-41yhZkpwYNp1K0i65RClXYA5_kM,284
|
|
3
|
+
drfkit/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
drfkit/commands/app.py,sha256=5nqTrEo584hvxm3y2ThnkF1xWCP9TLF0IKL0sBU6s2w,254
|
|
5
|
+
drfkit/commands/new.py,sha256=CnZewHBCXsZb-oAVGCF8vXeSP66bc0Y2p2FzCtzekCc,3942
|
|
6
|
+
drfkit/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
drfkit/core/renderer.py,sha256=s_7I1dkIPXz8nt8lbcKBgxy6QuPEp37-K5LE85Uep9k,648
|
|
8
|
+
drfkit/templates/app/__init__.py.j2,sha256=rQnHgFRsn-6y3yS_AXU5885xoQqB0TepUqCHnx4q9-g,79
|
|
9
|
+
drfkit/templates/app/admin.py.j2,sha256=yZDOS7tlghDMcAu6A4UJoLX-fRd04iV1hkmTjAj0yZI,240
|
|
10
|
+
drfkit/templates/app/apps.py.j2,sha256=xs3u_vhqyKcd5xU9u39JaWmL4tIzHd4J-NVCFDJXO0Y,178
|
|
11
|
+
drfkit/templates/app/models.py.j2,sha256=hPlMx-cG1oXfyB4ubH-nJOP_fp0wvtFN8_z8Vj8M8gw,58
|
|
12
|
+
drfkit/templates/app/serializers.py.j2,sha256=hQ4xI__4BqlrvcO3Pj2JQLd8oDcRD35WK3RRIIqbqYw,70
|
|
13
|
+
drfkit/templates/app/tests.py.j2,sha256=Fr0r-qWlGT2-ZiB69i1rFX1V-IPCPzLzRBA7z5u3xQY,61
|
|
14
|
+
drfkit/templates/app/urls.py.j2,sha256=BHvQjr0g_a6dHCpDprDlHSj_NZGS8_vPJjsbtAxdsj0,304
|
|
15
|
+
drfkit/templates/app/views.py.j2,sha256=Yn-dwHFEkxaRK-bVuKSsKeH9_PtVCloHiYxt4ycNuE0,326
|
|
16
|
+
drfkit/templates/project/asgi.py.j2,sha256=eq8XfXfI0ljsnU2tqiqGMLNzlw9HBeGpzS34cdfCb6s,175
|
|
17
|
+
drfkit/templates/project/env.j2,sha256=uLJjpnxs_1eTrE9882qAm24YjEPyGd2n2enJe25snaI,87
|
|
18
|
+
drfkit/templates/project/manage.py.j2,sha256=0AFA81IVWAUYaHex6OlWymjj1oZiFLXz7_46vst-9t4,261
|
|
19
|
+
drfkit/templates/project/urls.py.j2,sha256=VXKHD07dxVfNc6ahE8-hvwItsWeV22wpNJnr1gjnT2c,210
|
|
20
|
+
drfkit/templates/project/wsgi.py.j2,sha256=c9Vy6vYmL657Jso-qvd6TfJkXJOX4juIuhydt9w-vbc,175
|
|
21
|
+
drfkit/templates/project/requirements/base.txt.j2,sha256=sNq-iGbbaW-RnnWLDUtt17xZdcGmxvJLM2vDNT1t1-Q,53
|
|
22
|
+
drfkit/templates/project/settings/__init__.py.j2,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
drfkit/templates/project/settings/base.py.j2,sha256=perECpjwyI_okFCeHmGuJsZaoYB1KY8hItqxhTJTT6w,1985
|
|
24
|
+
drfkit/templates/project/settings/dev.py.j2,sha256=wVMV6nDmlWuQaKDoQRxgiEdOKrCtLpPUtsmYk1baDuI,55
|
|
25
|
+
drfkit/templates/project/settings/prod.py.j2,sha256=7th7ZgG_NV2NuZKCGYu9iZWjZH2h1I82twEXnxTfDgY,56
|
|
26
|
+
drfkit/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
drfkit/utils/template.py,sha256=Gz_yL72gu4ofec1H2yS8AQ28si1UobHndInKdUEBxwU,483
|
|
28
|
+
django_drfkit-0.1.0.dist-info/METADATA,sha256=14IRMz-Tfc-eOWmkoKe2pqWXzlOJLMZfTn6GLI1Vrjs,3190
|
|
29
|
+
django_drfkit-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
30
|
+
django_drfkit-0.1.0.dist-info/entry_points.txt,sha256=F0VpvMcgitF_-AXaMsiN2fq0JTDc51WlC__bmipV8TA,42
|
|
31
|
+
django_drfkit-0.1.0.dist-info/top_level.txt,sha256=KC8RxM3aOEmOemRFr04GNggBa8F-uMBfngJJgfIsqN8,7
|
|
32
|
+
django_drfkit-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
drfkit
|
drfkit/__init__.py
ADDED
|
File without changes
|
drfkit/cli.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from drfkit.commands import new
|
|
3
|
+
|
|
4
|
+
cli = typer.Typer(name="drfkit", help="A CLI tool for scaffolding DRF projects")
|
|
5
|
+
|
|
6
|
+
# Register the 'new' group which contains 'project' and 'app' commands
|
|
7
|
+
cli.add_typer(new.app_cmd, name="new")
|
|
8
|
+
|
|
9
|
+
if __name__ == "__main__":
|
|
10
|
+
cli()
|
|
File without changes
|
drfkit/commands/app.py
ADDED
drfkit/commands/new.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
import secrets
|
|
3
|
+
import string
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from drfkit.utils.template import render
|
|
6
|
+
|
|
7
|
+
app_cmd= typer.Typer(help="Create new DRF projects or apps")
|
|
8
|
+
|
|
9
|
+
def generate_secret_key(length=50):
|
|
10
|
+
"""Generate a cryptographically secure random string."""
|
|
11
|
+
chars = string.ascii_letters + string.digits + string.punctuation
|
|
12
|
+
# Ensure we don't use characters that might break .env files or Python strings easily (optional)
|
|
13
|
+
# For simplicity, we just pick from the standard set:
|
|
14
|
+
return ''.join(secrets.choice(chars) for _ in range(length))
|
|
15
|
+
@app_cmd.command()
|
|
16
|
+
def project(name: str):
|
|
17
|
+
"""
|
|
18
|
+
Scaffold a new DRF project with split settings and clean structure.
|
|
19
|
+
"""
|
|
20
|
+
root = Path(name)
|
|
21
|
+
|
|
22
|
+
if root.exists():
|
|
23
|
+
typer.secho(f"Error: Directory '{name}' already exists.", fg=typer.colors.RED)
|
|
24
|
+
raise typer.Exit(1)
|
|
25
|
+
# Generate the key here
|
|
26
|
+
secret_key = generate_secret_key()
|
|
27
|
+
context = {"project_name": name,"secret_key": secret_key}
|
|
28
|
+
|
|
29
|
+
# Define folder structure
|
|
30
|
+
dirs = [
|
|
31
|
+
root / "config" / "settings",
|
|
32
|
+
root / "apps",
|
|
33
|
+
root / "scripts",
|
|
34
|
+
root / "requirements"
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
for d in dirs:
|
|
38
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
|
|
40
|
+
# Create __init__.py for python packages
|
|
41
|
+
(root / "apps").joinpath("__init__.py").touch()
|
|
42
|
+
(root / "config").joinpath("__init__.py").touch()
|
|
43
|
+
|
|
44
|
+
# Define files to render
|
|
45
|
+
files = {
|
|
46
|
+
"project/manage.py.j2": root / "manage.py",
|
|
47
|
+
"project/urls.py.j2": root / "config" / "urls.py",
|
|
48
|
+
"project/wsgi.py.j2": root / "config" / "wsgi.py",
|
|
49
|
+
"project/asgi.py.j2": root / "config" / "asgi.py",
|
|
50
|
+
"project/settings/base.py.j2": root / "config" / "settings" / "base.py",
|
|
51
|
+
"project/settings/dev.py.j2": root / "config" / "settings" / "dev.py",
|
|
52
|
+
"project/settings/prod.py.j2": root / "config" / "settings" / "prod.py",
|
|
53
|
+
"project/settings/__init__.py.j2": root / "config" / "settings" / "__init__.py",
|
|
54
|
+
"project/env.j2": root / ".env",
|
|
55
|
+
"project/requirements/base.txt.j2": root / "requirements" / "base.txt",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
with typer.progressbar(files.items(), label="Generating files") as progress_bar:
|
|
59
|
+
for template, dest in progress_bar:
|
|
60
|
+
render(template, dest, context)
|
|
61
|
+
|
|
62
|
+
typer.secho(f"\n✔ Project '{name}' created successfully!", fg=typer.colors.GREEN)
|
|
63
|
+
typer.echo(f" cd {name}")
|
|
64
|
+
typer.echo(f" python -m venv venv && venv/bin/activate")
|
|
65
|
+
typer.echo(f" pip install -r requirements/base.txt")
|
|
66
|
+
|
|
67
|
+
@app_cmd.command()
|
|
68
|
+
def app(name: str):
|
|
69
|
+
"""
|
|
70
|
+
Scaffold a new DRF app inside the 'apps/' directory.
|
|
71
|
+
"""
|
|
72
|
+
# We assume this command is run inside a drfkit-generated project root
|
|
73
|
+
app_dir = Path("apps") / name
|
|
74
|
+
|
|
75
|
+
if app_dir.exists():
|
|
76
|
+
typer.secho(f"Error: App '{name}' already exists in apps/.", fg=typer.colors.RED)
|
|
77
|
+
raise typer.Exit(1)
|
|
78
|
+
|
|
79
|
+
if not Path("apps").exists():
|
|
80
|
+
typer.secho("Error: 'apps' directory not found. Are you in a drfkit project root?", fg=typer.colors.RED)
|
|
81
|
+
raise typer.Exit(1)
|
|
82
|
+
|
|
83
|
+
app_dir.mkdir(parents=True, exist_ok=True)
|
|
84
|
+
|
|
85
|
+
context = {"app_name": name}
|
|
86
|
+
|
|
87
|
+
files = {
|
|
88
|
+
"app/models.py.j2": app_dir / "models.py",
|
|
89
|
+
"app/serializers.py.j2": app_dir / "serializers.py",
|
|
90
|
+
"app/views.py.j2": app_dir / "views.py",
|
|
91
|
+
"app/urls.py.j2": app_dir / "urls.py",
|
|
92
|
+
"app/tests.py.j2": app_dir / "tests.py",
|
|
93
|
+
"app/admin.py.j2": app_dir / "admin.py",
|
|
94
|
+
"app/apps.py.j2": app_dir / "apps.py",
|
|
95
|
+
"app/__init__.py.j2": app_dir / "__init__.py",
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for template, dest in files.items():
|
|
99
|
+
render(template, dest, context)
|
|
100
|
+
|
|
101
|
+
typer.secho(f"✔ App '{name}' created at apps/{name}", fg=typer.colors.GREEN)
|
|
102
|
+
typer.echo(f" Don't forget to add 'apps.{name}' to INSTALLED_APPS in config/settings/base.py")
|
drfkit/core/__init__.py
ADDED
|
File without changes
|
drfkit/core/renderer.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from jinja2 import Environment, FileSystemLoader
|
|
3
|
+
|
|
4
|
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
5
|
+
TEMPLATE_DIR = os.path.join(BASE_DIR, "templates")
|
|
6
|
+
|
|
7
|
+
env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def render_project(project_name: str):
|
|
11
|
+
context = {"project_name": project_name}
|
|
12
|
+
|
|
13
|
+
os.makedirs(project_name, exist_ok=True)
|
|
14
|
+
|
|
15
|
+
template = env.get_template("project/manage.py.j2")
|
|
16
|
+
content = template.render(context)
|
|
17
|
+
|
|
18
|
+
with open(os.path.join(project_name, "manage.py"), "w") as f:
|
|
19
|
+
f.write(content)
|
|
20
|
+
|
|
21
|
+
print(f"✔ Project '{project_name}' created")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
default_app_config = 'apps.{{ app_name }}.apps.{{ app_name|capitalize }}Config'
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from django.urls import path, include
|
|
2
|
+
from rest_framework.routers import DefaultRouter
|
|
3
|
+
from .views import {{ app_name|capitalize }}ViewSet
|
|
4
|
+
|
|
5
|
+
router = DefaultRouter()
|
|
6
|
+
router.register(r'{{ app_name|lower }}s', {{ app_name|capitalize }}ViewSet)
|
|
7
|
+
|
|
8
|
+
urlpatterns = [
|
|
9
|
+
path('', include(router.urls)),
|
|
10
|
+
]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from rest_framework import viewsets
|
|
2
|
+
from .models import {{ app_name|capitalize }}
|
|
3
|
+
from .serializers import {{ app_name|capitalize }}Serializer
|
|
4
|
+
|
|
5
|
+
class {{ app_name|capitalize }}ViewSet(viewsets.ModelViewSet):
|
|
6
|
+
queryset = {{ app_name|capitalize }}.objects.all()
|
|
7
|
+
serializer_class = {{ app_name|capitalize }}Serializer
|
|
File without changes
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
|
4
|
+
|
|
5
|
+
SECRET_KEY = '{{secret_key}}'
|
|
6
|
+
|
|
7
|
+
INSTALLED_APPS = [
|
|
8
|
+
'django.contrib.admin',
|
|
9
|
+
'django.contrib.auth',
|
|
10
|
+
'django.contrib.contenttypes',
|
|
11
|
+
'django.contrib.sessions',
|
|
12
|
+
'django.contrib.messages',
|
|
13
|
+
'django.contrib.staticfiles',
|
|
14
|
+
|
|
15
|
+
# Third party
|
|
16
|
+
'rest_framework',
|
|
17
|
+
|
|
18
|
+
# Local apps
|
|
19
|
+
# Add your apps here, e.g., 'apps.users'
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
MIDDLEWARE = [
|
|
23
|
+
'django.middleware.security.SecurityMiddleware',
|
|
24
|
+
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
25
|
+
'django.middleware.common.CommonMiddleware',
|
|
26
|
+
'django.middleware.csrf.CsrfViewMiddleware',
|
|
27
|
+
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
28
|
+
'django.contrib.messages.middleware.MessageMiddleware',
|
|
29
|
+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
ROOT_URLCONF = 'config.urls'
|
|
33
|
+
|
|
34
|
+
TEMPLATES = [
|
|
35
|
+
{
|
|
36
|
+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
37
|
+
'DIRS': [],
|
|
38
|
+
'APP_DIRS': True,
|
|
39
|
+
'OPTIONS': {
|
|
40
|
+
'context_processors': [
|
|
41
|
+
'django.template.context_processors.debug',
|
|
42
|
+
'django.template.context_processors.request',
|
|
43
|
+
'django.contrib.auth.context_processors.auth',
|
|
44
|
+
'django.contrib.messages.context_processors.messages',
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
WSGI_APPLICATION = 'config.wsgi.application'
|
|
51
|
+
|
|
52
|
+
AUTH_PASSWORD_VALIDATORS = [
|
|
53
|
+
{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
|
|
54
|
+
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
|
|
55
|
+
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
|
|
56
|
+
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
LANGUAGE_CODE = 'en-us'
|
|
60
|
+
TIME_ZONE = 'UTC'
|
|
61
|
+
USE_I18N = True
|
|
62
|
+
USE_TZ = True
|
|
63
|
+
|
|
64
|
+
STATIC_URL = 'static/'
|
|
65
|
+
|
|
66
|
+
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
drfkit/utils/__init__.py
ADDED
|
File without changes
|
drfkit/utils/template.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from jinja2 import Environment, FileSystemLoader
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
5
|
+
TEMPLATE_DIR = BASE_DIR / "templates"
|
|
6
|
+
|
|
7
|
+
env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
|
|
8
|
+
|
|
9
|
+
def render(template_path: str, destination: Path, context: dict):
|
|
10
|
+
template = env.get_template(template_path)
|
|
11
|
+
content = template.render(**context)
|
|
12
|
+
|
|
13
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
14
|
+
destination.write_text(content)
|