├── djpro ├── utils │ ├── __init__.py │ ├── messages │ │ ├── __init__.py │ │ ├── run_prod.py │ │ └── run_dev.py │ ├── django_utils.py │ ├── logging.py │ └── write_and_config.py ├── commands │ ├── __init__.py │ ├── man.py │ ├── module.py │ ├── help.py │ └── project.py ├── __init__.py └── base.py ├── docs ├── changelog.rst ├── _build │ ├── html │ │ ├── _static │ │ │ ├── scripts │ │ │ │ ├── furo-extensions.js │ │ │ │ ├── furo.js.LICENSE.txt │ │ │ │ └── furo.js │ │ │ ├── file.png │ │ │ ├── minus.png │ │ │ ├── plus.png │ │ │ ├── documentation_options.js │ │ │ ├── debug.css │ │ │ ├── doctools.js │ │ │ ├── styles │ │ │ │ ├── furo-extensions.css │ │ │ │ └── furo-extensions.css.map │ │ │ ├── language_data.js │ │ │ ├── sphinx_highlight.js │ │ │ └── skeleton.css │ │ ├── _sources │ │ │ ├── changelog.rst.txt │ │ │ ├── contributing.rst.txt │ │ │ ├── modules.rst.txt │ │ │ ├── setup.rst.txt │ │ │ ├── license.rst.txt │ │ │ ├── djpro.rst.txt │ │ │ ├── unfold.rst.txt │ │ │ ├── djpro.utils.messages.rst.txt │ │ │ ├── man.rst.txt │ │ │ ├── djpro.commands.rst.txt │ │ │ ├── install.rst.txt │ │ │ ├── djpro.utils.rst.txt │ │ │ ├── index.rst.txt │ │ │ ├── api.rst.txt │ │ │ ├── docker.rst.txt │ │ │ ├── explanation.rst.txt │ │ │ └── quickstart.rst.txt │ │ ├── objects.inv │ │ ├── .buildinfo │ │ ├── .buildinfo.bak │ │ ├── search.html │ │ ├── _modules │ │ │ ├── index.html │ │ │ └── djpro │ │ │ │ └── utils │ │ │ │ └── django_utils.html │ │ └── unfold.html │ └── doctrees │ │ ├── api.doctree │ │ ├── man.doctree │ │ ├── djpro.doctree │ │ ├── index.doctree │ │ ├── setup.doctree │ │ ├── docker.doctree │ │ ├── install.doctree │ │ ├── license.doctree │ │ ├── modules.doctree │ │ ├── unfold.doctree │ │ ├── changelog.doctree │ │ ├── environment.pickle │ │ ├── quickstart.doctree │ │ ├── contributing.doctree │ │ ├── djpro.utils.doctree │ │ ├── explanation.doctree │ │ ├── djpro.commands.doctree │ │ └── djpro.utils.messages.doctree ├── contributing.rst ├── requirements.txt ├── modules.rst ├── setup.rst ├── license.rst ├── djpro.rst ├── unfold.rst ├── djpro.utils.messages.rst ├── Makefile ├── man.rst ├── djpro.commands.rst ├── install.rst ├── make.bat ├── djpro.utils.rst ├── index.rst ├── api.rst ├── docker.rst ├── conf.py ├── explanation.rst └── quickstart.rst ├── .gitignore ├── SECURITY.rst ├── AUTHORS.rst ├── readthedocs.yml ├── .github └── workflows │ └── publish.yml ├── LICENSE.txt ├── CHANGELOG.rst ├── README.rst ├── tests └── test_utils.py ├── CONTRIBUTING.rst └── setup.py /djpro/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /djpro/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /djpro/utils/messages/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CHANGELOG.rst -------------------------------------------------------------------------------- /docs/_build/html/_static/scripts/furo-extensions.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/contributing.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CONTRIBUTING.rst -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx==7.1.2 2 | furo>=2024.8.6 3 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/changelog.rst.txt: -------------------------------------------------------------------------------- 1 | .. include:: ../CHANGELOG.rst -------------------------------------------------------------------------------- /docs/_build/html/_sources/contributing.rst.txt: -------------------------------------------------------------------------------- 1 | .. include:: ../CONTRIBUTING.rst -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | __pycache__ 4 | *.egg-info 5 | env 6 | src 7 | .env 8 | local -------------------------------------------------------------------------------- /docs/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/html/objects.inv -------------------------------------------------------------------------------- /docs/_build/doctrees/api.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/api.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/man.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/man.doctree -------------------------------------------------------------------------------- /docs/modules.rst: -------------------------------------------------------------------------------- 1 | dj-pro 2 | ====== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | djpro 8 | setup 9 | -------------------------------------------------------------------------------- /docs/_build/doctrees/djpro.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/djpro.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/setup.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/setup.doctree -------------------------------------------------------------------------------- /docs/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/html/_static/plus.png -------------------------------------------------------------------------------- /docs/_build/doctrees/docker.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/docker.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/install.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/install.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/license.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/license.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/modules.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/modules.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/unfold.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/unfold.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/changelog.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/changelog.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/_build/doctrees/quickstart.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/quickstart.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/contributing.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/contributing.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/djpro.utils.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/djpro.utils.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/explanation.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/explanation.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/djpro.commands.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/djpro.commands.doctree -------------------------------------------------------------------------------- /docs/_build/html/_sources/modules.rst.txt: -------------------------------------------------------------------------------- 1 | dj-pro 2 | ====== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | djpro 8 | setup 9 | -------------------------------------------------------------------------------- /docs/_build/doctrees/djpro.utils.messages.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szew404/djpro/HEAD/docs/_build/doctrees/djpro.utils.messages.doctree -------------------------------------------------------------------------------- /docs/setup.rst: -------------------------------------------------------------------------------- 1 | setup module 2 | ============ 3 | 4 | .. automodule:: setup 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/setup.rst.txt: -------------------------------------------------------------------------------- 1 | setup module 2 | ============ 3 | 4 | .. automodule:: setup 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/_build/html/_static/scripts/furo.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * gumshoejs v5.1.2 (patched by @pradyunsg) 3 | * A simple, framework-agnostic scrollspy script. 4 | * (c) 2019 Chris Ferdinandi 5 | * MIT License 6 | * http://github.com/cferdinandi/gumshoe 7 | */ 8 | -------------------------------------------------------------------------------- /docs/_build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file records the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: e08d649af84175d2a8c68489301e13d6 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/_build/html/.buildinfo.bak: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file records the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: fd71f058329aed1d7b5f22ad16f2a595 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /djpro/utils/django_utils.py: -------------------------------------------------------------------------------- 1 | from django.core.management.utils import get_random_secret_key 2 | 3 | 4 | def generate_secret_key(): 5 | """Django predefined function to create the Django secret key. 6 | Return a 50 character random string usable as a SECRET_KEY setting value.""" 7 | return get_random_secret_key() 8 | -------------------------------------------------------------------------------- /SECURITY.rst: -------------------------------------------------------------------------------- 1 | Security Policy 2 | =============== 3 | 4 | 5 | Reporting a Vulnerability 6 | ------------------------- 7 | 8 | If you discover a security vulnerability within ``djpro``, please 9 | send an e-mail to Franco Gidaszewski via gidaszewskifranco@gmail.com. All security 10 | vulnerabilities will be promptly addressed. -------------------------------------------------------------------------------- /docs/license.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | License and Credits 3 | =================== 4 | 5 | djpro is open source software licensed under the 6 | `MIT / X11 License `_. 7 | The full license text can be also found in the `source code repository `_. 8 | 9 | .. include:: ../AUTHORS.rst -------------------------------------------------------------------------------- /docs/_build/html/_sources/license.rst.txt: -------------------------------------------------------------------------------- 1 | =================== 2 | License and Credits 3 | =================== 4 | 5 | djpro is open source software licensed under the 6 | `MIT / X11 License `_. 7 | The full license text can be also found in the `source code repository `_. 8 | 9 | .. include:: ../AUTHORS.rst -------------------------------------------------------------------------------- /docs/_build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | const DOCUMENTATION_OPTIONS = { 2 | VERSION: '0.0.6', 3 | LANGUAGE: 'en', 4 | COLLAPSE_INDEX: false, 5 | BUILDER: 'html', 6 | FILE_SUFFIX: '.html', 7 | LINK_SUFFIX: '.html', 8 | HAS_SOURCE: true, 9 | SOURCELINK_SUFFIX: '.txt', 10 | NAVIGATION_WITH_KEYS: false, 11 | SHOW_SEARCH_SUMMARY: true, 12 | ENABLE_SEARCH_SHORTCUTS: true, 13 | }; -------------------------------------------------------------------------------- /docs/djpro.rst: -------------------------------------------------------------------------------- 1 | djpro package 2 | ============= 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | djpro.commands 11 | djpro.utils 12 | 13 | Submodules 14 | ---------- 15 | 16 | djpro.base module 17 | ----------------- 18 | 19 | .. automodule:: djpro.base 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | 24 | Module contents 25 | --------------- 26 | 27 | .. automodule:: djpro 28 | :members: 29 | :undoc-members: 30 | :show-inheritance: 31 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/djpro.rst.txt: -------------------------------------------------------------------------------- 1 | djpro package 2 | ============= 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | djpro.commands 11 | djpro.utils 12 | 13 | Submodules 14 | ---------- 15 | 16 | djpro.base module 17 | ----------------- 18 | 19 | .. automodule:: djpro.base 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | 24 | Module contents 25 | --------------- 26 | 27 | .. automodule:: djpro 28 | :members: 29 | :undoc-members: 30 | :show-inheritance: 31 | -------------------------------------------------------------------------------- /AUTHORS.rst: -------------------------------------------------------------------------------- 1 | Credits 2 | ======= 3 | 4 | ``djpro`` was created by `Franco Gidaszewski `_. 5 | 6 | Acknowledgments 7 | =============== 8 | 9 | The existence of ``djpro`` would have been impossible without these 10 | projects: 11 | 12 | - `django `_ 13 | - `joke2k/django-environ `_ 14 | - `encode/django-rest-framework `_ 15 | - `unfoldadmin/django-unfold `_ -------------------------------------------------------------------------------- /docs/unfold.rst: -------------------------------------------------------------------------------- 1 | Unfold configuration 2 | -------------------- 3 | 4 | .. -unfold- 5 | 6 | To include the Unfold custom theme for Django Admin Site, adds the ``--unfold`` option 7 | to the general djpro project creation command: 8 | 9 | .. code-block:: shell 10 | 11 | djpro project YOUR-PROJECT-NAME --unfold 12 | 13 | .. note:: 14 | 15 | Change ``YOUR-PROJECT-NAME`` to your project name. 16 | Find your unfold configuration in ``settings_base``. 17 | 18 | * `Learn more about Unfold `_ 19 | 20 | .. -end-unfold- -------------------------------------------------------------------------------- /djpro/utils/messages/run_prod.py: -------------------------------------------------------------------------------- 1 | from ..logging import logging, log_with_color, Fore 2 | 3 | 4 | def run_prod_messages(): 5 | """Messages""" 6 | 7 | # Mensajes principales 8 | messages = [ 9 | "Your production environment is almost ready to run...", 10 | "Learn how to setup and run your production environment using Docker Compose:\n", 11 | "https://djpro.readthedocs.io/en/latest/quickstart.html#including-docker-configuration\n", 12 | ] 13 | 14 | for message in messages: 15 | log_with_color(logging.INFO, message, Fore.WHITE) 16 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/unfold.rst.txt: -------------------------------------------------------------------------------- 1 | Unfold configuration 2 | -------------------- 3 | 4 | .. -unfold- 5 | 6 | To include the Unfold custom theme for Django Admin Site, adds the ``--unfold`` option 7 | to the general djpro project creation command: 8 | 9 | .. code-block:: shell 10 | 11 | djpro project YOUR-PROJECT-NAME --unfold 12 | 13 | .. note:: 14 | 15 | Change ``YOUR-PROJECT-NAME`` to your project name. 16 | Find your unfold configuration in ``settings_base``. 17 | 18 | * `Learn more about Unfold `_ 19 | 20 | .. -end-unfold- -------------------------------------------------------------------------------- /djpro/utils/logging.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import time 3 | 4 | from colorama import Fore, Style, init 5 | 6 | logger = logging.getLogger(__name__) 7 | logger.setLevel(logging.DEBUG) 8 | 9 | stream_handler = logging.StreamHandler() 10 | stream_handler.setLevel(logging.DEBUG) 11 | 12 | formatter = logging.Formatter("%(message)s") 13 | stream_handler.setFormatter(formatter) 14 | 15 | logger.addHandler(stream_handler) 16 | 17 | init(autoreset=True) 18 | 19 | 20 | def log_with_color(level, message, color, delay=0): 21 | colored_message = f"{color}{message}{Style.RESET_ALL}" 22 | logger.log(level, colored_message) 23 | time.sleep(delay) 24 | -------------------------------------------------------------------------------- /docs/djpro.utils.messages.rst: -------------------------------------------------------------------------------- 1 | djpro.utils.messages package 2 | ============================ 3 | 4 | Submodules 5 | ---------- 6 | 7 | djpro.utils.messages.run\_dev module 8 | ------------------------------------ 9 | 10 | .. automodule:: djpro.utils.messages.run_dev 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | djpro.utils.messages.run\_prod module 16 | ------------------------------------- 17 | 18 | .. automodule:: djpro.utils.messages.run_prod 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | Module contents 24 | --------------- 25 | 26 | .. automodule:: djpro.utils.messages 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/djpro.utils.messages.rst.txt: -------------------------------------------------------------------------------- 1 | djpro.utils.messages package 2 | ============================ 3 | 4 | Submodules 5 | ---------- 6 | 7 | djpro.utils.messages.run\_dev module 8 | ------------------------------------ 9 | 10 | .. automodule:: djpro.utils.messages.run_dev 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | djpro.utils.messages.run\_prod module 16 | ------------------------------------- 17 | 18 | .. automodule:: djpro.utils.messages.run_prod 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | Module contents 24 | --------------- 25 | 26 | .. automodule:: djpro.utils.messages 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | -------------------------------------------------------------------------------- /djpro/utils/messages/run_dev.py: -------------------------------------------------------------------------------- 1 | from ..logging import logging, log_with_color, Fore 2 | 3 | 4 | def run_dev_messages(): 5 | """Messages""" 6 | 7 | # Mensaje principal 8 | log_with_color( 9 | logging.INFO, 10 | "Your development environment is almost ready to run...", 11 | Fore.WHITE, 12 | ) 13 | log_with_color( 14 | logging.INFO, 15 | "Run the following commands inside the folder 'src' of your project:\n", 16 | Fore.WHITE, 17 | ) 18 | 19 | commands = [ 20 | "pip install -r requirements.txt", 21 | "djpro man collectstatic", 22 | "djpro man runserver\n", 23 | ] 24 | 25 | for command in commands: 26 | log_with_color(logging.INFO, f" {command}", Fore.WHITE) 27 | -------------------------------------------------------------------------------- /docs/man.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | Man command 3 | =========== 4 | 5 | Usage 6 | ===== 7 | 8 | This command was created to make it faster and easier to run the ``manage.py`` commands in Django. 9 | 10 | .. note:: 11 | 12 | This command must be used from the root folder of your project. The command will search for the ``/src/bin`` directory. 13 | 14 | This command allows you to execute any command available in manage.py. 15 | View list of available manage.py commands: 16 | 17 | .. code-block:: shell 18 | 19 | djpro man help 20 | 21 | Examples 22 | ======== 23 | 24 | .. code-block:: shell 25 | 26 | djpro man runserver 27 | 28 | .. code-block:: shell 29 | 30 | djpro man migrate 31 | 32 | .. note:: 33 | 34 | Behind the scenes, the ``man`` command executes in the terminal ``python manage.py ``. -------------------------------------------------------------------------------- /docs/djpro.commands.rst: -------------------------------------------------------------------------------- 1 | djpro.commands package 2 | ====================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | djpro.commands.help module 8 | -------------------------- 9 | 10 | .. automodule:: djpro.commands.help 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | djpro.commands.module module 16 | ----------------------------- 17 | 18 | .. automodule:: djpro.commands.module 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | djpro.commands.project module 24 | ----------------------------- 25 | 26 | .. automodule:: djpro.commands.project 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | Module contents 32 | --------------- 33 | 34 | .. automodule:: djpro.commands 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/man.rst.txt: -------------------------------------------------------------------------------- 1 | =========== 2 | Man command 3 | =========== 4 | 5 | Usage 6 | ===== 7 | 8 | This command was created to make it faster and easier to run the ``manage.py`` commands in Django. 9 | 10 | .. note:: 11 | 12 | This command must be used from the root folder of your project. The command will search for the ``/src/bin`` directory. 13 | 14 | This command allows you to execute any command available in manage.py. 15 | View list of available manage.py commands: 16 | 17 | .. code-block:: shell 18 | 19 | djpro man help 20 | 21 | Examples 22 | ======== 23 | 24 | .. code-block:: shell 25 | 26 | djpro man runserver 27 | 28 | .. code-block:: shell 29 | 30 | djpro man migrate 31 | 32 | .. note:: 33 | 34 | Behind the scenes, the ``man`` command executes in the terminal ``python manage.py ``. -------------------------------------------------------------------------------- /docs/_build/html/_sources/djpro.commands.rst.txt: -------------------------------------------------------------------------------- 1 | djpro.commands package 2 | ====================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | djpro.commands.help module 8 | -------------------------- 9 | 10 | .. automodule:: djpro.commands.help 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | djpro.commands.module module 16 | ----------------------------- 17 | 18 | .. automodule:: djpro.commands.module 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | djpro.commands.project module 24 | ----------------------------- 25 | 26 | .. automodule:: djpro.commands.project 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | Module contents 32 | --------------- 33 | 34 | .. automodule:: djpro.commands 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | -------------------------------------------------------------------------------- /readthedocs.yml: -------------------------------------------------------------------------------- 1 | # This file is part of dj-pro. 2 | # 3 | # Copyright (c) 2024, Franco Gidaszewski 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE.txt file that was distributed with this source code. 7 | 8 | # Read the Docs configuration file 9 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 10 | 11 | --- 12 | # Required 13 | version: 2 14 | 15 | # Set the OS, Python version and other tools you might need 16 | build: 17 | os: ubuntu-22.04 18 | tools: 19 | python: "3.12" 20 | 21 | # Build documentation in the "docs/" directory with Sphinx 22 | sphinx: 23 | configuration: docs/conf.py 24 | 25 | python: 26 | install: 27 | - method: pip 28 | path: . 29 | extra_requirements: 30 | - docs 31 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /docs/install.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Installation 3 | ============ 4 | 5 | Requirements 6 | ============ 7 | 8 | * `Django `_ >= 5.0 9 | 10 | Installing djpro 11 | ================= 12 | 13 | djpro is a Python-only package `hosted_on_pypi`_. 14 | The recommended installation method is `pip`_-installing into a 15 | :mod:`virtualenv `: 16 | 17 | .. code-block:: console 18 | 19 | $ python -m pip install djpro 20 | 21 | .. note:: 22 | 23 | djpro will install ``the latest version of Django`` if is not installed yet. 24 | 25 | 26 | .. _hosted_on_pypi: https://pypi.org/project/djpro/ 27 | .. _pip: https://pip.pypa.io/en/stable/ 28 | 29 | More information about ``pip`` and PyPI can be found here: 30 | 31 | * `Install pip `_ 32 | * `Python Packaging User Guide `_ -------------------------------------------------------------------------------- /docs/_build/html/_sources/install.rst.txt: -------------------------------------------------------------------------------- 1 | ============ 2 | Installation 3 | ============ 4 | 5 | Requirements 6 | ============ 7 | 8 | * `Django `_ >= 5.0 9 | 10 | Installing djpro 11 | ================= 12 | 13 | djpro is a Python-only package `hosted_on_pypi`_. 14 | The recommended installation method is `pip`_-installing into a 15 | :mod:`virtualenv `: 16 | 17 | .. code-block:: console 18 | 19 | $ python -m pip install djpro 20 | 21 | .. note:: 22 | 23 | djpro will install ``the latest version of Django`` if is not installed yet. 24 | 25 | 26 | .. _hosted_on_pypi: https://pypi.org/project/djpro/ 27 | .. _pip: https://pip.pypa.io/en/stable/ 28 | 29 | More information about ``pip`` and PyPI can be found here: 30 | 31 | * `Install pip `_ 32 | * `Python Packaging User Guide `_ -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Upload to PyPI when a Release is Created 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | pypi-publish: 9 | name: Publish release to PyPI 10 | runs-on: ubuntu-latest 11 | environment: 12 | name: pypi 13 | url: https://pypi.org/p/ 14 | permissions: 15 | id-token: write 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Set up Python 19 | uses: actions/setup-python@v4 20 | with: 21 | python-version: "3.x" 22 | - name: Install dependencies 23 | run: | 24 | python -m pip install --upgrade pip 25 | pip install setuptools wheel 26 | - name: Build package 27 | run: | 28 | python setup.py sdist bdist_wheel # Could also be python -m build 29 | - name: Publish package distributions to PyPI 30 | uses: pypa/gh-action-pypi-publish@release/v1 -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024, Franco Gidaszewski 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /docs/djpro.utils.rst: -------------------------------------------------------------------------------- 1 | djpro.utils package 2 | =================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | djpro.utils.messages 11 | 12 | Submodules 13 | ---------- 14 | 15 | djpro.utils.django\_utils module 16 | -------------------------------- 17 | 18 | .. automodule:: djpro.utils.django_utils 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | djpro.utils.files\_content module 24 | --------------------------------- 25 | 26 | .. automodule:: djpro.utils.files_content 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | djpro.utils.logging module 32 | -------------------------- 33 | 34 | .. automodule:: djpro.utils.logging 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | djpro.utils.write\_and\_config module 40 | ------------------------------------- 41 | 42 | .. automodule:: djpro.utils.write_and_config 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | Module contents 48 | --------------- 49 | 50 | .. automodule:: djpro.utils 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/djpro.utils.rst.txt: -------------------------------------------------------------------------------- 1 | djpro.utils package 2 | =================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | djpro.utils.messages 11 | 12 | Submodules 13 | ---------- 14 | 15 | djpro.utils.django\_utils module 16 | -------------------------------- 17 | 18 | .. automodule:: djpro.utils.django_utils 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | djpro.utils.files\_content module 24 | --------------------------------- 25 | 26 | .. automodule:: djpro.utils.files_content 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | djpro.utils.logging module 32 | -------------------------- 33 | 34 | .. automodule:: djpro.utils.logging 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | djpro.utils.write\_and\_config module 40 | ------------------------------------- 41 | 42 | .. automodule:: djpro.utils.write_and_config 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | Module contents 48 | --------------- 49 | 50 | .. automodule:: djpro.utils 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | -------------------------------------------------------------------------------- /djpro/commands/man.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | from ..utils.logging import logging, log_with_color, Fore 4 | from .help import man_help 5 | 6 | import sys 7 | 8 | 9 | def man(command: str): 10 | if command == "help": 11 | return man_help() 12 | 13 | try: 14 | subprocess.run( 15 | ["python", "src/bin/manage.py", command], 16 | text=True, 17 | check=True, 18 | ) 19 | 20 | except subprocess.CalledProcessError: 21 | log_with_color( 22 | logging.INFO, 23 | "\nError while running the command.", 24 | Fore.RED, 25 | ) 26 | 27 | except KeyboardInterrupt: 28 | log_with_color( 29 | logging.WARNING, 30 | "\nServer stopped: KeyboardInterrupt", 31 | Fore.YELLOW, 32 | ) 33 | exit(1) 34 | 35 | 36 | def run(args): 37 | """Entry point for command 'man'.""" 38 | 39 | try: 40 | man( 41 | command=args.man_command, 42 | ) 43 | 44 | except Exception as e: 45 | log_with_color( 46 | logging.INFO, 47 | f"\nError while running commands: {e}", 48 | Fore.RED, 49 | ) 50 | -------------------------------------------------------------------------------- /djpro/__init__.py: -------------------------------------------------------------------------------- 1 | # This file is part of djpro. 2 | # 3 | # Copyright (c) 2024, Franco Gidaszewski 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE.txt file that was distributed with this source code. 7 | 8 | """The top-level module for dj-pro package. 9 | 10 | This module tracks the version of the package as well as the base 11 | package info used by various functions within dj-pro. 12 | 13 | """ 14 | 15 | from .base import * 16 | 17 | __copyright__ = "Copyright (c) 2024-2034, Franco Gidaszewski" 18 | """The copyright notice of the package.""" 19 | 20 | __version__ = "0.0.6" 21 | """The version of the package.""" 22 | 23 | __license__ = "MIT" 24 | """The license of the package.""" 25 | 26 | __author__ = "Franco Gidaszewski" 27 | """The author of the package.""" 28 | 29 | __author_email__ = "gidaszewskifranco@gmail.com" 30 | """The email of the author of the package.""" 31 | 32 | __url__ = "https://djpro.readthedocs.io/en/latest/index.html" 33 | """The URL of the package.""" 34 | 35 | __description__ = "Package that allows you to create a Django project using a modular and scalable architecture with options like API configuration, DjangoAdminSite custom theme and Docker to optimize your development time" 36 | """The description of the package.""" 37 | -------------------------------------------------------------------------------- /docs/_build/html/_static/debug.css: -------------------------------------------------------------------------------- 1 | /* 2 | This CSS file should be overridden by the theme authors. It's 3 | meant for debugging and developing the skeleton that this theme provides. 4 | */ 5 | body { 6 | font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, 7 | "Apple Color Emoji", "Segoe UI Emoji"; 8 | background: lavender; 9 | } 10 | .sb-announcement { 11 | background: rgb(131, 131, 131); 12 | } 13 | .sb-announcement__inner { 14 | background: black; 15 | color: white; 16 | } 17 | .sb-header { 18 | background: lightskyblue; 19 | } 20 | .sb-header__inner { 21 | background: royalblue; 22 | color: white; 23 | } 24 | .sb-header-secondary { 25 | background: lightcyan; 26 | } 27 | .sb-header-secondary__inner { 28 | background: cornflowerblue; 29 | color: white; 30 | } 31 | .sb-sidebar-primary { 32 | background: lightgreen; 33 | } 34 | .sb-main { 35 | background: blanchedalmond; 36 | } 37 | .sb-main__inner { 38 | background: antiquewhite; 39 | } 40 | .sb-header-article { 41 | background: lightsteelblue; 42 | } 43 | .sb-article-container { 44 | background: snow; 45 | } 46 | .sb-article-main { 47 | background: white; 48 | } 49 | .sb-footer-article { 50 | background: lightpink; 51 | } 52 | .sb-sidebar-secondary { 53 | background: lightgoldenrodyellow; 54 | } 55 | .sb-footer-content { 56 | background: plum; 57 | } 58 | .sb-footer-content__inner { 59 | background: palevioletred; 60 | } 61 | .sb-footer { 62 | background: pink; 63 | } 64 | .sb-footer__inner { 65 | background: salmon; 66 | } 67 | .sb-article { 68 | background: white; 69 | } 70 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ======================================= 2 | Welcome to djpro documentation 3 | ======================================= 4 | 5 | Release v\ |release| (`What's new? `). 6 | 7 | .. include:: ../README.rst 8 | :start-after: -teaser-begin- 9 | :end-before: -teaser-end- 10 | 11 | Overview 12 | ======== 13 | 14 | .. include:: ../README.rst 15 | :start-after: -overview- 16 | :end-before: -project-information- 17 | 18 | ---- 19 | 20 | Full Table of Contents 21 | ====================== 22 | 23 | Why use djpro? 24 | -------------- 25 | Django’s Command Line Interface (CLI) is a powerful tool for generating well-structured Django projects. 26 | However, maintaining that clean structure can become challenging as we create multiple 27 | apps, models, views, and routes. 28 | 29 | .. toctree:: 30 | :maxdepth: 2 31 | 32 | explanation 33 | 34 | The User Guide 35 | -------------- 36 | 37 | This part of the documentation, which is mostly prose, begins with some 38 | background information about dj-pro, then focuses on step-by-step 39 | instructions for getting the most out of dj-pro. 40 | 41 | .. toctree:: 42 | :maxdepth: 2 43 | 44 | install 45 | quickstart 46 | 47 | The Contributor Guide 48 | --------------------- 49 | 50 | If you want to contribute to the project, this part of the documentation is for 51 | you. 52 | 53 | .. toctree:: 54 | :maxdepth: 3 55 | 56 | contributing 57 | modules 58 | license 59 | 60 | .. include:: ../README.rst 61 | :start-after: -support- 62 | 63 | .. include:: ../README.rst 64 | :start-after: -project-information- 65 | :end-before: -support- 66 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | ======================================= 2 | Welcome to djpro documentation 3 | ======================================= 4 | 5 | Release v\ |release| (`What's new? `). 6 | 7 | .. include:: ../README.rst 8 | :start-after: -teaser-begin- 9 | :end-before: -teaser-end- 10 | 11 | Overview 12 | ======== 13 | 14 | .. include:: ../README.rst 15 | :start-after: -overview- 16 | :end-before: -project-information- 17 | 18 | ---- 19 | 20 | Full Table of Contents 21 | ====================== 22 | 23 | Why use djpro? 24 | -------------- 25 | Django’s Command Line Interface (CLI) is a powerful tool for generating well-structured Django projects. 26 | However, maintaining that clean structure can become challenging as we create multiple 27 | apps, models, views, and routes. 28 | 29 | .. toctree:: 30 | :maxdepth: 2 31 | 32 | explanation 33 | 34 | The User Guide 35 | -------------- 36 | 37 | This part of the documentation, which is mostly prose, begins with some 38 | background information about dj-pro, then focuses on step-by-step 39 | instructions for getting the most out of dj-pro. 40 | 41 | .. toctree:: 42 | :maxdepth: 2 43 | 44 | install 45 | quickstart 46 | 47 | The Contributor Guide 48 | --------------------- 49 | 50 | If you want to contribute to the project, this part of the documentation is for 51 | you. 52 | 53 | .. toctree:: 54 | :maxdepth: 3 55 | 56 | contributing 57 | modules 58 | license 59 | 60 | .. include:: ../README.rst 61 | :start-after: -support- 62 | 63 | .. include:: ../README.rst 64 | :start-after: -project-information- 65 | :end-before: -support- 66 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | All notable changes to this project will be documented in this file. 5 | The format is inspired by `Keep a Changelog `_ 6 | and this project adheres to `Semantic Versioning `_. 7 | 8 | `v0.0.6`_ - 21-December-2024 9 | ---------------------------- 10 | Changed 11 | +++++++ 12 | - Changed the location and organization of models, views and serializers. 13 | 14 | Fixed 15 | +++++ 16 | - Errors in the contents of some configuration files 17 | 18 | Added 19 | +++++ 20 | - Added the possibility to create apps.py and admin.py with the subcommand 'module'. 21 | - Error handling and validations in project subcommand 22 | - Error handling and validations in man subcommand 23 | 24 | .. _v0.0.6: https://github.com/szew404/djpro/releases/tag/v0.0.6 25 | 26 | `v0.0.5`_ - 16-December-2024 27 | ---------------------------- 28 | Added 29 | +++++ 30 | - Added man subcommand 31 | - Error handling in module subcommand 32 | 33 | Fixed 34 | +++++ 35 | - Errors in the contents of some configuration files 36 | 37 | Changed 38 | +++++++ 39 | - Improve help information 40 | 41 | .. _v0.0.5: https://github.com/szew404/djpro/releases/tag/v0.0.5 42 | 43 | `v0.0.4`_ - 19-November-2024 44 | ---------------------------- 45 | Fixed 46 | +++++ 47 | - Errors in the contents of some configuration files 48 | 49 | Added 50 | +++++ 51 | - More documentation when implementing Docker 52 | 53 | .. _v0.0.4: https://github.com/szew404/djpro/releases/tag/v0.0.4 54 | 55 | `v0.0.3`_ - 19-November-2024 56 | ---------------------------- 57 | Added 58 | +++++ 59 | - Added module subcommand with options 60 | 61 | Changed 62 | +++++++ 63 | - Improve documentation and logging 64 | 65 | .. _v0.0.3: https://github.com/szew404/djpro/releases/tag/v0.0.3 66 | 67 | `v0.0.2`_ - 17-November-2024 68 | ---------------------------- 69 | Changed 70 | +++++++ 71 | - Improve documentation and logging 72 | 73 | .. _v0.0.2: https://github.com/szew404/djpro/releases/tag/v0.0.2 74 | 75 | `v0.0.1`_ - 17-November-2024 76 | ---------------------------- 77 | Added 78 | +++++ 79 | - Initial release. 80 | 81 | .. _v0.0.1: https://github.com/szew404/djpro/releases/tag/v0.0.1 -------------------------------------------------------------------------------- /djpro/utils/write_and_config.py: -------------------------------------------------------------------------------- 1 | # This file is part of djpro. 2 | # 3 | # Copyright (c) 2024, Franco Gidaszewski 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE.txt file that was distributed with this source code. 7 | 8 | from pathlib import Path 9 | from ..utils.logging import logging, log_with_color, Fore 10 | 11 | from .files_content import ( 12 | settings_api, 13 | settings_unfold, 14 | settings_api_unfold, 15 | settings_base_content, 16 | requirements_api, 17 | requirements_unfold, 18 | ) 19 | 20 | 21 | def create_dirs(dirs: list[Path]): 22 | """Function to create folders""" 23 | for dir in dirs: 24 | dir.mkdir(parents=True, exist_ok=True) 25 | 26 | 27 | def create_files(files: list[Path]): 28 | """Function to create files.""" 29 | for file_path in files: 30 | file_path.parent.mkdir(parents=True, exist_ok=True) 31 | file_path.touch() 32 | 33 | 34 | def write_to_file(file_path: Path, content: str, mode: str = "w"): 35 | """Function to write content.""" 36 | file_path.parent.mkdir(parents=True, exist_ok=True) 37 | with open(file_path, mode) as f: 38 | f.write(content) 39 | 40 | 41 | def configure_requirements(api: bool, unfold: bool) -> str: 42 | """Config requirements content""" 43 | requirements = [] 44 | if api: 45 | requirements.append(requirements_api) 46 | if unfold: 47 | requirements.append(requirements_unfold) 48 | return "".join(requirements) 49 | 50 | 51 | def configure_settings_base(api: bool, unfold: bool) -> str: 52 | """Config settings content""" 53 | 54 | if api and unfold: 55 | log_with_color( 56 | logging.INFO, 57 | "\nConfiguring Unfold...", 58 | Fore.WHITE, 59 | delay=3, 60 | ) 61 | return settings_api_unfold 62 | 63 | if api: 64 | return settings_api 65 | 66 | if unfold: 67 | log_with_color( 68 | logging.INFO, 69 | "\nConfiguring Unfold...", 70 | Fore.WHITE, 71 | delay=2, 72 | ) 73 | return settings_unfold 74 | 75 | return settings_base_content # Default 76 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. raw:: html 2 | 3 |
4 |

djpro

5 | PyPI Downloads 6 | PyPI 7 | versions 8 | license 9 |
10 | 11 | .. -teaser-begin- 12 | 13 | ``djpro`` is the Python package that allows you to create a Django project 14 | using a modular and scalable architecture with options like API configuration, 15 | DjangoAdminSite custom theme and Docker to optimize your development time. 16 | 17 | .. -teaser-end- 18 | 19 | .. -overview- 20 | 21 | The idea of this package is to facilitate the creation of a Django project with a 22 | modular and scalable architecture, facilitating and optimizing the development time. 23 | Through CLI commands, you will be able to include configuration options such as: 24 | ``Django Rest Framework`` configuration for further API development. ``Unfold`` setup 25 | and configuration for a customization of the Django Admin Site theme. 26 | ``Docker`` configuration from an early stage of development to facilitate 27 | future deployment. 28 | 29 | Using ``djpro`` you can stop creating the directories of your Django project 30 | from scratch. 31 | 32 | **Feature Support** 33 | 34 | - Fast and easy API configuration 35 | - Automatic customization of the Django Admin Site 36 | - Easy implementation of the production environment configuration. 37 | 38 | .. -project-information- 39 | 40 | Project Information 41 | =================== 42 | 43 | ``djpro`` is released under the `MIT / X11 License `__, 44 | its documentation lives at `Read the Docs `_, 45 | the code on `GitHub `_, 46 | and the latest release on `PyPI `_. 47 | 48 | If you'd like to contribute to ``djpro`` you're most welcome! 49 | 50 | .. -support- 51 | 52 | Support 53 | ======= 54 | 55 | Should you have any question, any remark, or if you find a bug, or if there is 56 | something you can't do with the ``djpro``, please 57 | `open an issue `_. 58 | -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | Django Rest Framework project configuration 2 | ------------------------------------------- 3 | 4 | .. -api- 5 | 6 | To include an API configuration (Django Rest Framework) to your project, adds the ``--api`` option 7 | to the general djpro project creation command: 8 | 9 | .. code-block:: shell 10 | 11 | djpro project YOUR-PROJECT-NAME --api 12 | 13 | .. note:: 14 | 15 | Change ``YOUR-PROJECT-NAME`` to your project name. 16 | 17 | ``djpro`` will create a Django project including API configuration with the following structure: 18 | 19 | .. code-block:: shell 20 | 21 | root/ 22 | ├── .env.dev 23 | ├── .gitignore 24 | ├── requirements.txt 25 | └── src/ 26 | ├── bin/ 27 | │ ├── __init__.py 28 | │ └── manage.py 29 | ├── config/ 30 | │ ├── .env.conf 31 | │ ├── __init__.py 32 | │ ├── asgi.py 33 | │ ├── settings_base.py 34 | │ ├── settings_dev.py 35 | │ ├── settings_prod.py 36 | │ ├── settings.py 37 | │ ├── urls.py 38 | │ └── wsgi.py 39 | ├── modules/ 40 | │ ├── __init__.py 41 | │ ├── api/ 42 | │ │ ├── __init__.py 43 | │ │ ├── models/ 44 | │ │ │ ├── __init__.py 45 | │ │ │ └── product_model.py 46 | │ │ ├── serializers/ 47 | │ │ │ ├── __init__.py 48 | │ │ │ └── get_product.py 49 | │ │ ├── urls.py 50 | │ │ └── views/ 51 | │ │ ├── __init__.py 52 | │ │ └── get_product.py 53 | │ └── authentication/ 54 | │ ├── __init__.py 55 | │ ├── models/ 56 | │ │ ├── __init__.py 57 | │ │ └── auth_model.py 58 | │ ├── serializers/ 59 | │ │ ├── __init__.py 60 | │ │ └── login_serializer.py 61 | │ ├── urls.py 62 | │ └── views/ 63 | │ ├── __init__.py 64 | │ └── login.py 65 | ├── static/ 66 | ├── tests/ 67 | ├── templates/ 68 | └── utils/ 69 | └── __init__.py 70 | 71 | .. note:: 72 | 73 | djpro includes ``DRF Spectacular`` already configured for your API documentation. 74 | Find your docs configuration in ``settings_base``. 75 | 76 | * `Learn more about Django Rest Framework `_ 77 | * `DRF Spectacular `_ 78 | 79 | .. -end-api- -------------------------------------------------------------------------------- /docs/_build/html/_sources/api.rst.txt: -------------------------------------------------------------------------------- 1 | Django Rest Framework project configuration 2 | ------------------------------------------- 3 | 4 | .. -api- 5 | 6 | To include an API configuration (Django Rest Framework) to your project, adds the ``--api`` option 7 | to the general djpro project creation command: 8 | 9 | .. code-block:: shell 10 | 11 | djpro project YOUR-PROJECT-NAME --api 12 | 13 | .. note:: 14 | 15 | Change ``YOUR-PROJECT-NAME`` to your project name. 16 | 17 | ``djpro`` will create a Django project including API configuration with the following structure: 18 | 19 | .. code-block:: shell 20 | 21 | root/ 22 | ├── .env.dev 23 | ├── .gitignore 24 | ├── requirements.txt 25 | └── src/ 26 | ├── bin/ 27 | │ ├── __init__.py 28 | │ └── manage.py 29 | ├── config/ 30 | │ ├── .env.conf 31 | │ ├── __init__.py 32 | │ ├── asgi.py 33 | │ ├── settings_base.py 34 | │ ├── settings_dev.py 35 | │ ├── settings_prod.py 36 | │ ├── settings.py 37 | │ ├── urls.py 38 | │ └── wsgi.py 39 | ├── modules/ 40 | │ ├── __init__.py 41 | │ ├── api/ 42 | │ │ ├── __init__.py 43 | │ │ ├── models/ 44 | │ │ │ ├── __init__.py 45 | │ │ │ └── product_model.py 46 | │ │ ├── serializers/ 47 | │ │ │ ├── __init__.py 48 | │ │ │ └── get_product.py 49 | │ │ ├── urls.py 50 | │ │ └── views/ 51 | │ │ ├── __init__.py 52 | │ │ └── get_product.py 53 | │ └── authentication/ 54 | │ ├── __init__.py 55 | │ ├── models/ 56 | │ │ ├── __init__.py 57 | │ │ └── auth_model.py 58 | │ ├── serializers/ 59 | │ │ ├── __init__.py 60 | │ │ └── login_serializer.py 61 | │ ├── urls.py 62 | │ └── views/ 63 | │ ├── __init__.py 64 | │ └── login.py 65 | ├── static/ 66 | ├── tests/ 67 | ├── templates/ 68 | └── utils/ 69 | └── __init__.py 70 | 71 | .. note:: 72 | 73 | djpro includes ``DRF Spectacular`` already configured for your API documentation. 74 | Find your docs configuration in ``settings_base``. 75 | 76 | * `Learn more about Django Rest Framework `_ 77 | * `DRF Spectacular `_ 78 | 79 | .. -end-api- -------------------------------------------------------------------------------- /docs/docker.rst: -------------------------------------------------------------------------------- 1 | Docker configuration for easy deployment 2 | ---------------------------------------- 3 | 4 | .. -docker- 5 | 6 | To include Docker configuration to your project, adds the ``--docker`` option 7 | to the general djpro project creation command: 8 | 9 | .. code-block:: shell 10 | 11 | djpro project YOUR-PROJECT-NAME --docker 12 | 13 | .. note:: 14 | 15 | Change ``YOUR-PROJECT-NAME`` to your project name. 16 | 17 | ``djpro`` will create a Django project including API configuration with the following structure: 18 | 19 | .. code-block:: shell 20 | 21 | root/ 22 | ├── .env.dev 23 | ├── .env.prod 24 | ├── .env.prod.db 25 | ├── docker-compose.yml 26 | ├── Dockerfile 27 | ├── .gitignore 28 | ├── requirements.txt 29 | └── src/ 30 | ├── bin/ 31 | │ ├── __init__.py 32 | │ └── manage.py 33 | ├── config/ 34 | │ ├── .env.conf 35 | │ ├── __init__.py 36 | │ ├── asgi.py 37 | │ ├── settings_base.py 38 | │ ├── settings_dev.py 39 | │ ├── settings_prod.py 40 | │ ├── settings.py 41 | │ ├── urls.py 42 | │ └── wsgi.py 43 | ├── modules/ 44 | │ ├── __init__.py 45 | │ └── authentication/ 46 | │ ├── __init__.py 47 | │ ├── models/ 48 | │ │ ├── __init__.py 49 | │ │ └── auth_model.py 50 | │ ├── serializers/ 51 | │ │ ├── __init__.py 52 | │ │ └── login_serializer.py 53 | │ ├── urls.py 54 | │ └── views/ 55 | │ ├── __init__.py 56 | │ └── login.py 57 | ├── static/ 58 | ├── tests/ 59 | ├── templates/ 60 | └── utils/ 61 | └── __init__.py 62 | 63 | .. note:: 64 | 65 | djpro automatically sets a ``production environment`` when the ``--docker`` option is run, 66 | you can change this by modifying the ``DJANGO_ENV`` from ``prod`` to ``dev`` in ``config/.env.conf``. 67 | 68 | IMPORTANT 69 | --------- 70 | 71 | Before running your Django project using Docker Compose, you have to set your database 72 | configuration in ``.env.prod`` and ``.env.prod.db``. 73 | 74 | .. note:: 75 | 76 | ``.env.prod`` contains the environment variables needed to run Django. 77 | ``.env.prod.db`` contains the environment variables to run the Docker ``db`` container. 78 | 79 | Then you can run the project using the following command: 80 | 81 | .. code-block:: shell 82 | 83 | docker-compose up --build -d 84 | 85 | Aplying migrations and collecting static files: 86 | 87 | .. code-block:: shell 88 | 89 | docker-compose exec web python src/bin/manage.py migrate --noinput 90 | docker-compose exec web python src/bin/manage.py collectstatic 91 | 92 | .. note:: 93 | 94 | If you want to run the project on local using Docker, then you will have to change to 'True' the DEBUG mode on ``settings_prod.py``. 95 | 96 | * `Learn more about Docker `_ 97 | 98 | .. -end-docker- -------------------------------------------------------------------------------- /docs/_build/html/_sources/docker.rst.txt: -------------------------------------------------------------------------------- 1 | Docker configuration for easy deployment 2 | ---------------------------------------- 3 | 4 | .. -docker- 5 | 6 | To include Docker configuration to your project, adds the ``--docker`` option 7 | to the general djpro project creation command: 8 | 9 | .. code-block:: shell 10 | 11 | djpro project YOUR-PROJECT-NAME --docker 12 | 13 | .. note:: 14 | 15 | Change ``YOUR-PROJECT-NAME`` to your project name. 16 | 17 | ``djpro`` will create a Django project including API configuration with the following structure: 18 | 19 | .. code-block:: shell 20 | 21 | root/ 22 | ├── .env.dev 23 | ├── .env.prod 24 | ├── .env.prod.db 25 | ├── docker-compose.yml 26 | ├── Dockerfile 27 | ├── .gitignore 28 | ├── requirements.txt 29 | └── src/ 30 | ├── bin/ 31 | │ ├── __init__.py 32 | │ └── manage.py 33 | ├── config/ 34 | │ ├── .env.conf 35 | │ ├── __init__.py 36 | │ ├── asgi.py 37 | │ ├── settings_base.py 38 | │ ├── settings_dev.py 39 | │ ├── settings_prod.py 40 | │ ├── settings.py 41 | │ ├── urls.py 42 | │ └── wsgi.py 43 | ├── modules/ 44 | │ ├── __init__.py 45 | │ └── authentication/ 46 | │ ├── __init__.py 47 | │ ├── models/ 48 | │ │ ├── __init__.py 49 | │ │ └── auth_model.py 50 | │ ├── serializers/ 51 | │ │ ├── __init__.py 52 | │ │ └── login_serializer.py 53 | │ ├── urls.py 54 | │ └── views/ 55 | │ ├── __init__.py 56 | │ └── login.py 57 | ├── static/ 58 | ├── tests/ 59 | ├── templates/ 60 | └── utils/ 61 | └── __init__.py 62 | 63 | .. note:: 64 | 65 | djpro automatically sets a ``production environment`` when the ``--docker`` option is run, 66 | you can change this by modifying the ``DJANGO_ENV`` from ``prod`` to ``dev`` in ``config/.env.conf``. 67 | 68 | IMPORTANT 69 | --------- 70 | 71 | Before running your Django project using Docker Compose, you have to set your database 72 | configuration in ``.env.prod`` and ``.env.prod.db``. 73 | 74 | .. note:: 75 | 76 | ``.env.prod`` contains the environment variables needed to run Django. 77 | ``.env.prod.db`` contains the environment variables to run the Docker ``db`` container. 78 | 79 | Then you can run the project using the following command: 80 | 81 | .. code-block:: shell 82 | 83 | docker-compose up --build -d 84 | 85 | Aplying migrations and collecting static files: 86 | 87 | .. code-block:: shell 88 | 89 | docker-compose exec web python src/bin/manage.py migrate --noinput 90 | docker-compose exec web python src/bin/manage.py collectstatic 91 | 92 | .. note:: 93 | 94 | If you want to run the project on local using Docker, then you will have to change to 'True' the DEBUG mode on ``settings_prod.py``. 95 | 96 | * `Learn more about Docker `_ 97 | 98 | .. -end-docker- -------------------------------------------------------------------------------- /djpro/commands/module.py: -------------------------------------------------------------------------------- 1 | # This file is part of djpro. 2 | # 3 | # Copyright (c) 2024, Franco Gidaszewski 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE.txt file that was distributed with this source code. 7 | 8 | from pathlib import Path 9 | 10 | from ..utils.logging import logging, log_with_color, Fore 11 | from ..utils.write_and_config import create_dirs, create_files 12 | 13 | 14 | def create_module( 15 | base_dir: Path, 16 | module_name: str, 17 | args: list[str] = None, 18 | ): 19 | """Function to create a new module in the current project""" 20 | 21 | base_dir_path = Path(base_dir) 22 | modules_dir = base_dir_path / "modules" 23 | 24 | if not modules_dir.exists(): 25 | raise FileNotFoundError( 26 | log_with_color( 27 | logging.INFO, 28 | f"\nThe 'modules' directory does not exist in {base_dir_path}. \nRun this command in the root folder of your project.", 29 | Fore.YELLOW, 30 | ) 31 | ) 32 | 33 | new_module_dir = [ 34 | modules_dir / module_name, 35 | modules_dir / module_name / "models", 36 | modules_dir / module_name / "views", 37 | modules_dir / module_name / "serializers", 38 | ] 39 | 40 | if new_module_dir[0].exists(): 41 | raise FileExistsError( 42 | log_with_color( 43 | logging.INFO, 44 | f"\nThe module '{module_name}' already exists.", 45 | Fore.YELLOW, 46 | ) 47 | ) 48 | 49 | files = [ 50 | new_module_dir[0] / "__init__.py", 51 | new_module_dir[1] / "__init__.py", 52 | new_module_dir[2] / "__init__.py", 53 | new_module_dir[3] / "__init__.py", 54 | ] 55 | 56 | file_mapping = { 57 | "models": (new_module_dir[1], "models.py"), 58 | "views": (new_module_dir[2], "views.py"), 59 | "serializers": (new_module_dir[3], "serializers.py"), 60 | "urls": (new_module_dir[0], "urls.py"), 61 | "forms": (new_module_dir[0], "forms.py"), 62 | "admin": (new_module_dir[0], "admin.py"), 63 | "apps": (new_module_dir[0], "apps.py"), 64 | } 65 | 66 | if args: 67 | files.extend( 68 | directory / filename 69 | for key, (directory, filename) in file_mapping.items() 70 | if getattr(args, key, False) 71 | ) 72 | 73 | create_dirs(new_module_dir) 74 | create_files(files) 75 | 76 | 77 | def run(args): 78 | """Entry point for command 'module'.""" 79 | 80 | try: 81 | create_module( 82 | base_dir=args.base_dir, 83 | module_name=args.module_name, 84 | args=args, 85 | ) 86 | 87 | except Exception as e: 88 | error_message = "\nError while creating module" 89 | if f"{e}" != "None": 90 | error_message += f": {e}" 91 | 92 | log_with_color( 93 | logging.INFO, 94 | error_message, 95 | Fore.RED, 96 | ) 97 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | # This file is part of the django-environ. 2 | # 3 | # Copyright (c) 2021-2022, Serghei Iakovlev 4 | # Copyright (c) 2013-2021, Daniele Faraglia 5 | # 6 | # For the full copyright and license information, please view 7 | # the LICENSE.txt file that was distributed with this source code. 8 | 9 | import pytest 10 | 11 | from djpro import utils 12 | from unittest.mock import patch 13 | 14 | 15 | @pytest.fixture 16 | def temp_path(tmp_path): 17 | """Fixture for temporary directories""" 18 | return tmp_path 19 | 20 | 21 | def test_create_dirs(temp_path): 22 | """Test for create_dirs""" 23 | dirs = [temp_path / "dir1", temp_path / "dir2/subdir"] 24 | utils.create_dirs(dirs) 25 | 26 | for dir_path in dirs: 27 | assert dir_path.exists() 28 | assert dir_path.is_dir() 29 | 30 | 31 | def test_create_files(temp_path): 32 | """Test for create_files""" 33 | files = [temp_path / "file1.txt", temp_path / "subdir/file2.txt"] 34 | utils.create_files(files) 35 | 36 | for file_path in files: 37 | assert file_path.exists() 38 | assert file_path.is_file() 39 | 40 | 41 | def test_write_to_file(temp_path): 42 | """Test for write_to_file.""" 43 | file_path = temp_path / "file.txt" 44 | content = "Hello, djpro!" 45 | 46 | utils.write_to_file(file_path, content) 47 | 48 | assert file_path.exists() 49 | with open(file_path, "r") as f: 50 | assert f.read() == content 51 | 52 | 53 | def test_configure_requirements(): 54 | """Test for configure_requirements.""" 55 | 56 | # API and Unfold case 57 | result = utils.configure_requirements(api=True, unfold=True) 58 | assert ( 59 | result 60 | == utils.files_content.requirements_api 61 | + utils.files_content.requirements_unfold 62 | ) 63 | 64 | # API case 65 | result = utils.configure_requirements(api=True, unfold=False) 66 | assert result == utils.files_content.requirements_api 67 | 68 | # Unfold case 69 | result = utils.configure_requirements(api=False, unfold=True) 70 | assert result == utils.files_content.requirements_unfold 71 | 72 | # No option case 73 | result = utils.configure_requirements(api=False, unfold=False) 74 | assert result == "" 75 | 76 | 77 | @patch("..djpro.utils.logging.log_with_color") 78 | def test_configure_settings_base(mock_log): 79 | """Test for configure_settings_base.""" 80 | 81 | # API and Unfold case 82 | result = utils.configure_settings_base(api=True, unfold=True) 83 | assert result == utils.files_content.settings_api_unfold 84 | 85 | # API case 86 | result = utils.configure_settings_base(api=True, unfold=False) 87 | mock_log.assert_not_called() 88 | assert result == utils.files_content.settings_api 89 | 90 | # Unfold case 91 | result = utils.configure_settings_base(api=False, unfold=True) 92 | assert result == utils.files_content.settings_unfold 93 | 94 | # No option case 95 | result = utils.configure_settings_base(api=False, unfold=False) 96 | mock_log.assert_not_called() 97 | assert result == utils.files_content.settings_base_content 98 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | If you would like to contribute to ``djpro``, please take a look at the 5 | `current issues `_. If there is 6 | a bug or feature that you want but it isn't listed, make an issue and work on it. 7 | 8 | Bug reports 9 | ----------- 10 | 11 | *Before raising an issue, please ensure that you are using the latest version 12 | of djpro.* 13 | 14 | Please provide the following information with your issue to enable us to 15 | respond as quickly as possible. 16 | 17 | * The relevant versions of the packages you are using. 18 | * The steps to recreate your issue. 19 | * The full stacktrace if there is an exception. 20 | * An executable code example where possible 21 | 22 | Guidelines for bug reports: 23 | 24 | * **Use the GitHub issue search** — check if the issue has already been 25 | reported. 26 | * **Check if the issue has been fixed** — try to reproduce it using the latest 27 | ``main`` or ``develop`` branch in the repository. 28 | * Isolate the problem — create a reduced test case and a live example. 29 | 30 | A good bug report shouldn't leave others needing to chase you up for more 31 | information. Please try to be as detailed as possible in your report. What is 32 | your environment? What steps will reproduce the issue? What OS experience the 33 | problem? What would you expect to be the outcome? All these details will help 34 | people to fix any potential bugs. 35 | 36 | Feature requests 37 | ---------------- 38 | 39 | Feature requests are welcome. But take a moment to find out whether your idea 40 | fits with the scope and aims of the project. It's up to *you* to make a strong 41 | case to convince the project's developers of the merits of this feature. Please 42 | provide as much detail and context as possible. 43 | 44 | Pull requests 45 | ------------- 46 | 47 | Good pull requests - patches, improvements, new features - are a fantastic 48 | help. They should remain focused in scope and avoid containing unrelated 49 | commits. 50 | 51 | Follow this process if you'd like your work considered for inclusion in the 52 | project: 53 | 54 | 1. Check for open issues or open a fresh issue to start a discussion around a 55 | feature idea or a bug. 56 | 2. Fork `the repository `_ 57 | on GitHub to start making your changes to the ``develop`` branch 58 | (or branch off of it). 59 | 3. Write a test which shows that the bug was fixed or that the feature works as 60 | expected. 61 | 4. Send a pull request and bug the maintainer until it gets merged and published. 62 | 63 | If you are intending to implement a fairly large feature we'd appreciate if you 64 | open an issue with GitHub detailing your use case and intended solution to 65 | discuss how it might impact other work that is in flight. 66 | 67 | We also appreciate it if you take the time to update and write tests for any 68 | changes you submit. 69 | 70 | **By submitting a patch, you agree to allow the project owner to license your 71 | work under the same license as that used by the project.** 72 | 73 | Resources 74 | --------- 75 | 76 | * `How to Contribute to Open Source `_ 77 | * `Using Pull Requests `_ 78 | * `Writing good commit messages `_ -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # This file is part of djpro. 2 | # 3 | # Copyright (c) 2024, Franco Gidaszewski 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE.txt file that was distributed with this source code. 7 | 8 | # 9 | # -- Utils --------------------------------------------------------- 10 | # 11 | 12 | import codecs 13 | import os 14 | import re 15 | import sys 16 | from datetime import date 17 | 18 | PROJECT_DIR = os.path.abspath("..") 19 | sys.path.insert(0, PROJECT_DIR) 20 | 21 | 22 | def read_file(filepath): 23 | """Read content from a UTF-8 encoded text file.""" 24 | with codecs.open(filepath, "rb", "utf-8") as file_handle: 25 | return file_handle.read() 26 | 27 | 28 | def find_version(meta_file): 29 | """Extract ``__version__`` from meta_file.""" 30 | contents = read_file(os.path.join(PROJECT_DIR, meta_file)) 31 | meta_match = re.search(r"^__version__\s+=\s+['\"]([^'\"]*)['\"]", contents, re.M) 32 | 33 | if meta_match: 34 | return meta_match.group(1) 35 | raise RuntimeError("Unable to find __version__ string in package meta file") 36 | 37 | 38 | # 39 | # -- Project information ----------------------------------------------------- 40 | # 41 | 42 | # General information about the project. 43 | project = "djpro" 44 | copyright = f"2024-{date.today().year}, Franco Gidaszewski" 45 | author = "Franco Gidaszewski" 46 | 47 | # -- General configuration --------------------------------------------------- 48 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 49 | 50 | extensions = [ 51 | "sphinx.ext.autodoc", 52 | "sphinx.ext.doctest", 53 | "sphinx.ext.intersphinx", 54 | "sphinx.ext.todo", 55 | "sphinx.ext.viewcode", 56 | ] 57 | 58 | # Add any paths that contain templates here, relative to this directory. 59 | templates_path = ["_templates"] 60 | 61 | # The suffix of source filenames. 62 | source_suffix = ".rst" 63 | 64 | # Allow non-local URIs, so we can have images in CHANGELOG etc. 65 | suppress_warnings = [ 66 | "image.nonlocal_uri", 67 | ] 68 | 69 | # The master toctree document. 70 | master_doc = "index" 71 | # The version info 72 | # The short X.Y version. 73 | release = find_version(os.path.join("djpro", "__init__.py")) 74 | version = release.rsplit(".", 1)[0] 75 | # The full version, including alpha/beta/rc tags. 76 | 77 | # List of patterns, relative to source directory, that match files and 78 | # directories to ignore when looking for source files. 79 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 80 | 81 | # The reST default role (used for this markup: `text`) to use for all 82 | # documents. 83 | default_role = "any" 84 | 85 | # If true, '()' will be appended to :func: etc. cross-reference text. 86 | add_function_parentheses = True 87 | 88 | 89 | # -- Options for HTML output ------------------------------------------------- 90 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 91 | 92 | # html_favicon = None 93 | html_theme = "furo" 94 | html_title = project 95 | html_static_path = ["_static"] 96 | 97 | # If false, no module index is generated. 98 | html_domain_indices = True 99 | 100 | # If false, no index is generated. 101 | html_use_index = True 102 | 103 | # If true, the index is split into individual pages for each letter. 104 | html_split_index = False 105 | 106 | # If true, links to the reST sources are added to the pages. 107 | html_show_sourcelink = False 108 | 109 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 110 | html_show_sphinx = True 111 | 112 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 113 | html_show_copyright = True 114 | -------------------------------------------------------------------------------- /docs/explanation.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | Explanation 3 | =========== 4 | 5 | Why use djpro? 6 | -------------- 7 | Django’s Command Line Interface (CLI) is a powerful tool for generating well-structured Django projects. 8 | However, maintaining that clean structure can become challenging as we create multiple 9 | apps, models, templates, views, and routes. 10 | 11 | 12 | The Default Structure 13 | --------------------- 14 | 15 | .. code-block:: shell 16 | 17 | project/ 18 | ├── manage.py 19 | ├── requirements.txt 20 | ├── project/ 21 | │ ├── __init__.py 22 | │ ├── settings.py 23 | │ ├── urls.py 24 | │ ├── asgi.py 25 | │ └── wsgi.py 26 | └── app/ 27 | ├── migrations/ 28 | │ └── __init__.py 29 | ├── __init__.py 30 | ├── admin.py 31 | ├── apps.py 32 | ├── models.py 33 | ├── tests.py 34 | └── views.py 35 | 36 | When we create an app in Django, a folder is made with the name of the app, 37 | and typically, it consists of a migrations folder and several files to configure 38 | the admin, models, tests, and views. 39 | 40 | While it is an excellent structure already, the problem arises when the project grows. 41 | Imagine a project with 80+ models. So, we can’t have a single Python file with thousands of lines. 42 | It becomes a lot less readable. 43 | 44 | Something similar happens with templates. 45 | You’ll need paths like my_app/templates/my_app/template.html, which can feel repetitive. 46 | Switching between app directories can be tedious when managing multiple templates. 47 | 48 | When we talk about applications, we find ourselves in the same situation. 49 | As our project grows, understanding the structure becomes more and more complicated. 50 | 51 | The solution 52 | ------------ 53 | 54 | In-Project App Location: All our applications live in a central folder called “modules”. 55 | This method allows us to keep our applications organized and separated. 56 | 57 | Organizing Models and Views: Over time, the original problem revolved around the increasing size of 58 | our Django project’s models and view files. Django doesn’t strictly enforce placing all models inside 59 | the models.py file. Organizing models and views by placing them in separate files within dedicated 60 | directories. By adopting this approach, we maintain a clean and modular project structure, 61 | ensuring that our models and views remain organized and readable as our project grows. 62 | 63 | In-Project Template Location: In this method, all templates live in one central templates 64 | folder at the project level. Each app gets its own subdirectory within this folder. 65 | 66 | With the same thinking in mind, we organized each Django directory and went 67 | from a structure that is difficult to scale, to an organized, simple structure 68 | that allows us to scale. 69 | 70 | .. code-block:: shell 71 | 72 | root/ 73 | ├── .env.dev 74 | ├── .gitignore 75 | ├── requirements.txt 76 | └── src/ 77 | ├── bin/ 78 | │ ├── __init__.py 79 | │ └── manage.py 80 | ├── config/ 81 | │ ├── .env.conf 82 | │ ├── __init__.py 83 | │ ├── asgi.py 84 | │ ├── settings_base.py 85 | │ ├── settings_dev.py 86 | │ ├── settings_prod.py 87 | │ ├── settings.py 88 | │ ├── urls.py 89 | │ └── wsgi.py 90 | ├── modules/ 91 | │ ├── __init__.py 92 | │ └── authentication/ 93 | │ ├── __init__.py 94 | │ ├── models/ 95 | │ │ ├── __init__.py 96 | │ │ └── auth_model.py 97 | │ ├── serializers/ 98 | │ │ ├── __init__.py 99 | │ │ └── login_serializer.py 100 | │ ├── urls.py 101 | │ └── views/ 102 | │ ├── __init__.py 103 | │ └── login.py 104 | ├── static/ 105 | ├── tests/ 106 | ├── templates/ 107 | └── utils/ 108 | └── __init__.py -------------------------------------------------------------------------------- /docs/_build/html/_sources/explanation.rst.txt: -------------------------------------------------------------------------------- 1 | =========== 2 | Explanation 3 | =========== 4 | 5 | Why use djpro? 6 | -------------- 7 | Django’s Command Line Interface (CLI) is a powerful tool for generating well-structured Django projects. 8 | However, maintaining that clean structure can become challenging as we create multiple 9 | apps, models, templates, views, and routes. 10 | 11 | 12 | The Default Structure 13 | --------------------- 14 | 15 | .. code-block:: shell 16 | 17 | project/ 18 | ├── manage.py 19 | ├── requirements.txt 20 | ├── project/ 21 | │ ├── __init__.py 22 | │ ├── settings.py 23 | │ ├── urls.py 24 | │ ├── asgi.py 25 | │ └── wsgi.py 26 | └── app/ 27 | ├── migrations/ 28 | │ └── __init__.py 29 | ├── __init__.py 30 | ├── admin.py 31 | ├── apps.py 32 | ├── models.py 33 | ├── tests.py 34 | └── views.py 35 | 36 | When we create an app in Django, a folder is made with the name of the app, 37 | and typically, it consists of a migrations folder and several files to configure 38 | the admin, models, tests, and views. 39 | 40 | While it is an excellent structure already, the problem arises when the project grows. 41 | Imagine a project with 80+ models. So, we can’t have a single Python file with thousands of lines. 42 | It becomes a lot less readable. 43 | 44 | Something similar happens with templates. 45 | You’ll need paths like my_app/templates/my_app/template.html, which can feel repetitive. 46 | Switching between app directories can be tedious when managing multiple templates. 47 | 48 | When we talk about applications, we find ourselves in the same situation. 49 | As our project grows, understanding the structure becomes more and more complicated. 50 | 51 | The solution 52 | ------------ 53 | 54 | In-Project App Location: All our applications live in a central folder called “modules”. 55 | This method allows us to keep our applications organized and separated. 56 | 57 | Organizing Models and Views: Over time, the original problem revolved around the increasing size of 58 | our Django project’s models and view files. Django doesn’t strictly enforce placing all models inside 59 | the models.py file. Organizing models and views by placing them in separate files within dedicated 60 | directories. By adopting this approach, we maintain a clean and modular project structure, 61 | ensuring that our models and views remain organized and readable as our project grows. 62 | 63 | In-Project Template Location: In this method, all templates live in one central templates 64 | folder at the project level. Each app gets its own subdirectory within this folder. 65 | 66 | With the same thinking in mind, we organized each Django directory and went 67 | from a structure that is difficult to scale, to an organized, simple structure 68 | that allows us to scale. 69 | 70 | .. code-block:: shell 71 | 72 | root/ 73 | ├── .env.dev 74 | ├── .gitignore 75 | ├── requirements.txt 76 | └── src/ 77 | ├── bin/ 78 | │ ├── __init__.py 79 | │ └── manage.py 80 | ├── config/ 81 | │ ├── .env.conf 82 | │ ├── __init__.py 83 | │ ├── asgi.py 84 | │ ├── settings_base.py 85 | │ ├── settings_dev.py 86 | │ ├── settings_prod.py 87 | │ ├── settings.py 88 | │ ├── urls.py 89 | │ └── wsgi.py 90 | ├── modules/ 91 | │ ├── __init__.py 92 | │ └── authentication/ 93 | │ ├── __init__.py 94 | │ ├── models/ 95 | │ │ ├── __init__.py 96 | │ │ └── auth_model.py 97 | │ ├── serializers/ 98 | │ │ ├── __init__.py 99 | │ │ └── login_serializer.py 100 | │ ├── urls.py 101 | │ └── views/ 102 | │ ├── __init__.py 103 | │ └── login.py 104 | ├── static/ 105 | ├── tests/ 106 | ├── templates/ 107 | └── utils/ 108 | └── __init__.py -------------------------------------------------------------------------------- /docs/quickstart.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | Quick Start 3 | =========== 4 | 5 | Usage 6 | ===== 7 | 8 | Start by creating the architecture of a Django project. 9 | 10 | Execute the following line of code inside the root folder of your project: 11 | 12 | .. code-block:: shell 13 | 14 | djpro project YOUR-PROJECT-NAME 15 | 16 | .. note:: 17 | 18 | Change ``YOUR-PROJECT-NAME`` to your project name. 19 | 20 | ``djpro`` will create a Django project with the following structure: 21 | 22 | .. code-block:: shell 23 | 24 | root/ 25 | ├── .env.dev 26 | ├── .gitignore 27 | ├── requirements.txt 28 | └── src/ 29 | ├── bin/ 30 | │ ├── __init__.py 31 | │ └── manage.py 32 | ├── config/ 33 | │ ├── .env.conf 34 | │ ├── __init__.py 35 | │ ├── asgi.py 36 | │ ├── settings_base.py 37 | │ ├── settings_dev.py 38 | │ ├── settings_prod.py 39 | │ ├── settings.py 40 | │ ├── urls.py 41 | │ └── wsgi.py 42 | ├── modules/ 43 | │ ├── __init__.py 44 | │ └── authentication/ 45 | │ ├── __init__.py 46 | │ ├── models/ 47 | │ │ ├── __init__.py 48 | │ │ └── auth_model.py 49 | │ ├── serializers/ 50 | │ │ ├── __init__.py 51 | │ │ └── login_serializer.py 52 | │ ├── urls.py 53 | │ └── views/ 54 | │ ├── __init__.py 55 | │ └── login.py 56 | ├── static/ 57 | ├── tests/ 58 | ├── templates/ 59 | └── utils/ 60 | └── __init__.py 61 | 62 | Run your Django project executing the following commands inside the folder ``src``: 63 | 64 | .. code-block:: shell 65 | 66 | pip install -r requirements.txt 67 | djpro man collectstatic 68 | djpro man runserver 69 | 70 | Create a new Module 71 | ------------------- 72 | 73 | .. note:: 74 | 75 | We call ``modules`` to the applications contained in your Django project. 76 | 77 | You can create a new Module in your existing project executing the following command: 78 | 79 | .. code-block:: shell 80 | 81 | djpro module YOUR-MODULE-NAME 82 | 83 | .. note:: 84 | 85 | Change ``YOUR-MODULE-NAME`` to your Module name. 86 | 87 | .. note:: 88 | 89 | IMPORTANT: The ``module`` subcommand needs to find the ``src`` folder. Run the command in the root folder of your project. 90 | 91 | You can also add the files you want to be created in your module: 92 | 93 | .. code-block:: shell 94 | 95 | djpro module YOUR-MODULE-NAME -models -views -urls 96 | 97 | .. note:: 98 | 99 | This command will create the module folder including the ``models.py``, ``views.py`` and ``urls.py`` files. 100 | 101 | .. code-block:: shell 102 | 103 | root/ 104 | └── src/ 105 | └── modules/ 106 | ├── __init__.py 107 | └── YOUR-MODULE/ 108 | ├── __init__.py 109 | ├── models/ 110 | │ ├── __init__.py 111 | │ └── models.py 112 | ├── urls.py 113 | └── views/ 114 | ├── __init__.py 115 | └── views.py 116 | 117 | See the list of available files: 118 | 119 | .. code-block:: shell 120 | 121 | -models 122 | -views 123 | -serializers 124 | -urls 125 | -forms 126 | -admin 127 | -apps 128 | 129 | Run the develop environment locally 130 | ----------------------------------- 131 | 132 | .. code-block:: shell 133 | 134 | djpro man runserver 135 | 136 | .. note:: 137 | 138 | The ``man`` command was created to make it faster and easier to run the ``manage.py`` commands in Django. 139 | `Find out more about its use `_. 140 | 141 | ---- 142 | 143 | Including API configuration 144 | =========================== 145 | 146 | .. include:: ./api.rst 147 | :start-after: -api- 148 | :end-before: -end-api- 149 | 150 | Adding a custom theme for Django Admin Site 151 | =========================================== 152 | 153 | .. include:: ./unfold.rst 154 | :start-after: -unfold- 155 | :end-before: -end-unfold- 156 | 157 | Including Docker configuration 158 | ============================== 159 | 160 | .. include:: ./docker.rst 161 | :start-after: -docker- 162 | :end-before: -end-docker- 163 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/quickstart.rst.txt: -------------------------------------------------------------------------------- 1 | =========== 2 | Quick Start 3 | =========== 4 | 5 | Usage 6 | ===== 7 | 8 | Start by creating the architecture of a Django project. 9 | 10 | Execute the following line of code inside the root folder of your project: 11 | 12 | .. code-block:: shell 13 | 14 | djpro project YOUR-PROJECT-NAME 15 | 16 | .. note:: 17 | 18 | Change ``YOUR-PROJECT-NAME`` to your project name. 19 | 20 | ``djpro`` will create a Django project with the following structure: 21 | 22 | .. code-block:: shell 23 | 24 | root/ 25 | ├── .env.dev 26 | ├── .gitignore 27 | ├── requirements.txt 28 | └── src/ 29 | ├── bin/ 30 | │ ├── __init__.py 31 | │ └── manage.py 32 | ├── config/ 33 | │ ├── .env.conf 34 | │ ├── __init__.py 35 | │ ├── asgi.py 36 | │ ├── settings_base.py 37 | │ ├── settings_dev.py 38 | │ ├── settings_prod.py 39 | │ ├── settings.py 40 | │ ├── urls.py 41 | │ └── wsgi.py 42 | ├── modules/ 43 | │ ├── __init__.py 44 | │ └── authentication/ 45 | │ ├── __init__.py 46 | │ ├── models/ 47 | │ │ ├── __init__.py 48 | │ │ └── auth_model.py 49 | │ ├── serializers/ 50 | │ │ ├── __init__.py 51 | │ │ └── login_serializer.py 52 | │ ├── urls.py 53 | │ └── views/ 54 | │ ├── __init__.py 55 | │ └── login.py 56 | ├── static/ 57 | ├── tests/ 58 | ├── templates/ 59 | └── utils/ 60 | └── __init__.py 61 | 62 | Run your Django project executing the following commands inside the folder ``src``: 63 | 64 | .. code-block:: shell 65 | 66 | pip install -r requirements.txt 67 | djpro man collectstatic 68 | djpro man runserver 69 | 70 | Create a new Module 71 | ------------------- 72 | 73 | .. note:: 74 | 75 | We call ``modules`` to the applications contained in your Django project. 76 | 77 | You can create a new Module in your existing project executing the following command: 78 | 79 | .. code-block:: shell 80 | 81 | djpro module YOUR-MODULE-NAME 82 | 83 | .. note:: 84 | 85 | Change ``YOUR-MODULE-NAME`` to your Module name. 86 | 87 | .. note:: 88 | 89 | IMPORTANT: The ``module`` subcommand needs to find the ``src`` folder. Run the command in the root folder of your project. 90 | 91 | You can also add the files you want to be created in your module: 92 | 93 | .. code-block:: shell 94 | 95 | djpro module YOUR-MODULE-NAME -models -views -urls 96 | 97 | .. note:: 98 | 99 | This command will create the module folder including the ``models.py``, ``views.py`` and ``urls.py`` files. 100 | 101 | .. code-block:: shell 102 | 103 | root/ 104 | └── src/ 105 | └── modules/ 106 | ├── __init__.py 107 | └── YOUR-MODULE/ 108 | ├── __init__.py 109 | ├── models/ 110 | │ ├── __init__.py 111 | │ └── models.py 112 | ├── urls.py 113 | └── views/ 114 | ├── __init__.py 115 | └── views.py 116 | 117 | See the list of available files: 118 | 119 | .. code-block:: shell 120 | 121 | -models 122 | -views 123 | -serializers 124 | -urls 125 | -forms 126 | -admin 127 | -apps 128 | 129 | Run the develop environment locally 130 | ----------------------------------- 131 | 132 | .. code-block:: shell 133 | 134 | djpro man runserver 135 | 136 | .. note:: 137 | 138 | The ``man`` command was created to make it faster and easier to run the ``manage.py`` commands in Django. 139 | `Find out more about its use `. 140 | 141 | ---- 142 | 143 | Including API configuration 144 | =========================== 145 | 146 | .. include:: ./api.rst 147 | :start-after: -api- 148 | :end-before: -end-api- 149 | 150 | Adding a custom theme for Django Admin Site 151 | =========================================== 152 | 153 | .. include:: ./unfold.rst 154 | :start-after: -unfold- 155 | :end-before: -end-unfold- 156 | 157 | Including Docker configuration 158 | ============================== 159 | 160 | .. include:: ./docker.rst 161 | :start-after: -docker- 162 | :end-before: -end-docker- 163 | -------------------------------------------------------------------------------- /docs/_build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Base JavaScript utilities for all Sphinx HTML documentation. 3 | */ 4 | "use strict"; 5 | 6 | const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ 7 | "TEXTAREA", 8 | "INPUT", 9 | "SELECT", 10 | "BUTTON", 11 | ]); 12 | 13 | const _ready = (callback) => { 14 | if (document.readyState !== "loading") { 15 | callback(); 16 | } else { 17 | document.addEventListener("DOMContentLoaded", callback); 18 | } 19 | }; 20 | 21 | /** 22 | * Small JavaScript module for the documentation. 23 | */ 24 | const Documentation = { 25 | init: () => { 26 | Documentation.initDomainIndexTable(); 27 | Documentation.initOnKeyListeners(); 28 | }, 29 | 30 | /** 31 | * i18n support 32 | */ 33 | TRANSLATIONS: {}, 34 | PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), 35 | LOCALE: "unknown", 36 | 37 | // gettext and ngettext don't access this so that the functions 38 | // can safely bound to a different name (_ = Documentation.gettext) 39 | gettext: (string) => { 40 | const translated = Documentation.TRANSLATIONS[string]; 41 | switch (typeof translated) { 42 | case "undefined": 43 | return string; // no translation 44 | case "string": 45 | return translated; // translation exists 46 | default: 47 | return translated[0]; // (singular, plural) translation tuple exists 48 | } 49 | }, 50 | 51 | ngettext: (singular, plural, n) => { 52 | const translated = Documentation.TRANSLATIONS[singular]; 53 | if (typeof translated !== "undefined") 54 | return translated[Documentation.PLURAL_EXPR(n)]; 55 | return n === 1 ? singular : plural; 56 | }, 57 | 58 | addTranslations: (catalog) => { 59 | Object.assign(Documentation.TRANSLATIONS, catalog.messages); 60 | Documentation.PLURAL_EXPR = new Function( 61 | "n", 62 | `return (${catalog.plural_expr})` 63 | ); 64 | Documentation.LOCALE = catalog.locale; 65 | }, 66 | 67 | /** 68 | * helper function to focus on search bar 69 | */ 70 | focusSearchBar: () => { 71 | document.querySelectorAll("input[name=q]")[0]?.focus(); 72 | }, 73 | 74 | /** 75 | * Initialise the domain index toggle buttons 76 | */ 77 | initDomainIndexTable: () => { 78 | const toggler = (el) => { 79 | const idNumber = el.id.substr(7); 80 | const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); 81 | if (el.src.substr(-9) === "minus.png") { 82 | el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; 83 | toggledRows.forEach((el) => (el.style.display = "none")); 84 | } else { 85 | el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; 86 | toggledRows.forEach((el) => (el.style.display = "")); 87 | } 88 | }; 89 | 90 | const togglerElements = document.querySelectorAll("img.toggler"); 91 | togglerElements.forEach((el) => 92 | el.addEventListener("click", (event) => toggler(event.currentTarget)) 93 | ); 94 | togglerElements.forEach((el) => (el.style.display = "")); 95 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); 96 | }, 97 | 98 | initOnKeyListeners: () => { 99 | // only install a listener if it is really needed 100 | if ( 101 | !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && 102 | !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS 103 | ) 104 | return; 105 | 106 | document.addEventListener("keydown", (event) => { 107 | // bail for input elements 108 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; 109 | // bail with special keys 110 | if (event.altKey || event.ctrlKey || event.metaKey) return; 111 | 112 | if (!event.shiftKey) { 113 | switch (event.key) { 114 | case "ArrowLeft": 115 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 116 | 117 | const prevLink = document.querySelector('link[rel="prev"]'); 118 | if (prevLink && prevLink.href) { 119 | window.location.href = prevLink.href; 120 | event.preventDefault(); 121 | } 122 | break; 123 | case "ArrowRight": 124 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 125 | 126 | const nextLink = document.querySelector('link[rel="next"]'); 127 | if (nextLink && nextLink.href) { 128 | window.location.href = nextLink.href; 129 | event.preventDefault(); 130 | } 131 | break; 132 | } 133 | } 134 | 135 | // some keyboard layouts may need Shift to get / 136 | switch (event.key) { 137 | case "/": 138 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; 139 | Documentation.focusSearchBar(); 140 | event.preventDefault(); 141 | } 142 | }); 143 | }, 144 | }; 145 | 146 | // quick alias for translations 147 | const _ = Documentation.gettext; 148 | 149 | _ready(Documentation.init); 150 | -------------------------------------------------------------------------------- /docs/_build/html/_static/scripts/furo.js: -------------------------------------------------------------------------------- 1 | /*! For license information please see furo.js.LICENSE.txt */ 2 | (()=>{var t={856:function(t,e,n){var o,r;r=void 0!==n.g?n.g:"undefined"!=typeof window?window:this,o=function(){return function(t){"use strict";var e={navClass:"active",contentClass:"active",nested:!1,nestedClass:"active",offset:0,reflow:!1,events:!0},n=function(t,e,n){if(n.settings.events){var o=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n});e.dispatchEvent(o)}},o=function(t){var e=0;if(t.offsetParent)for(;t;)e+=t.offsetTop,t=t.offsetParent;return e>=0?e:0},r=function(t){t&&t.sort((function(t,e){return o(t.content)=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},l=function(t,e){var n=t[t.length-1];if(function(t,e){return!(!s()||!c(t.content,e,!0))}(n,e))return n;for(var o=t.length-1;o>=0;o--)if(c(t[o].content,e))return t[o]},a=function(t,e){if(e.nested&&t.parentNode){var n=t.parentNode.closest("li");n&&(n.classList.remove(e.nestedClass),a(n,e))}},i=function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.remove(e.navClass),t.content.classList.remove(e.contentClass),a(o,e),n("gumshoeDeactivate",o,{link:t.nav,content:t.content,settings:e}))}},u=function(t,e){if(e.nested){var n=t.parentNode.closest("li");n&&(n.classList.add(e.nestedClass),u(n,e))}};return function(o,c){var s,a,d,f,m,v={setup:function(){s=document.querySelectorAll(o),a=[],Array.prototype.forEach.call(s,(function(t){var e=document.getElementById(decodeURIComponent(t.hash.substr(1)));e&&a.push({nav:t,content:e})})),r(a)},detect:function(){var t=l(a,m);t?d&&t.content===d.content||(i(d,m),function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.add(e.navClass),t.content.classList.add(e.contentClass),u(o,e),n("gumshoeActivate",o,{link:t.nav,content:t.content,settings:e}))}}(t,m),d=t):d&&(i(d,m),d=null)}},h=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame(v.detect)},g=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame((function(){r(a),v.detect()}))};return v.destroy=function(){d&&i(d,m),t.removeEventListener("scroll",h,!1),m.reflow&&t.removeEventListener("resize",g,!1),a=null,s=null,d=null,f=null,m=null},m=function(){var t={};return Array.prototype.forEach.call(arguments,(function(e){for(var n in e){if(!e.hasOwnProperty(n))return;t[n]=e[n]}})),t}(e,c||{}),v.setup(),v.detect(),t.addEventListener("scroll",h,!1),m.reflow&&t.addEventListener("resize",g,!1),v}}(r)}.apply(e,[]),void 0===o||(t.exports=o)}},e={};function n(o){var r=e[o];if(void 0!==r)return r.exports;var c=e[o]={exports:{}};return t[o].call(c.exports,c,c.exports,n),c.exports}n.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var o in e)n.o(e,o)&&!n.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{"use strict";var t=n(856),e=n.n(t),o=null,r=null,c=document.documentElement.scrollTop;const s=64;function l(){const t=localStorage.getItem("theme")||"auto";var e;"light"!==(e=window.matchMedia("(prefers-color-scheme: dark)").matches?"auto"===t?"light":"light"==t?"dark":"auto":"auto"===t?"dark":"dark"==t?"light":"auto")&&"dark"!==e&&"auto"!==e&&(console.error(`Got invalid theme mode: ${e}. Resetting to auto.`),e="auto"),document.body.dataset.theme=e,localStorage.setItem("theme",e),console.log(`Changed to ${e} mode.`)}function a(){!function(){const t=document.getElementsByClassName("theme-toggle");Array.from(t).forEach((t=>{t.addEventListener("click",l)}))}(),function(){let t=0,e=!1;window.addEventListener("scroll",(function(n){t=window.scrollY,e||(window.requestAnimationFrame((function(){var n;(function(t){const e=Math.floor(r.getBoundingClientRect().top);console.log(`headerTop: ${e}`),0==e&&t!=e?r.classList.add("scrolled"):r.classList.remove("scrolled")})(n=t),function(t){tc&&document.documentElement.classList.remove("show-back-to-top"),c=t}(n),function(t){null!==o&&(0==t?o.scrollTo(0,0):Math.ceil(t)>=Math.floor(document.documentElement.scrollHeight-window.innerHeight)?o.scrollTo(0,o.scrollHeight):document.querySelector(".scroll-current"))}(n),e=!1})),e=!0)})),window.scroll()}(),null!==o&&new(e())(".toc-tree a",{reflow:!0,recursive:!0,navClass:"scroll-current",offset:()=>{let t=parseFloat(getComputedStyle(document.documentElement).fontSize);return r.getBoundingClientRect().height+2.5*t+1}})}document.addEventListener("DOMContentLoaded",(function(){document.body.parentNode.classList.remove("no-js"),r=document.querySelector("header"),o=document.querySelector(".toc-scroll"),a()}))})()})(); 3 | //# sourceMappingURL=furo.js.map -------------------------------------------------------------------------------- /docs/_build/html/_static/styles/furo-extensions.css: -------------------------------------------------------------------------------- 1 | #furo-sidebar-ad-placement{padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)}#furo-sidebar-ad-placement .ethical-sidebar{background:var(--color-background-secondary);border:none;box-shadow:none}#furo-sidebar-ad-placement .ethical-sidebar:hover{background:var(--color-background-hover)}#furo-sidebar-ad-placement .ethical-sidebar a{color:var(--color-foreground-primary)}#furo-sidebar-ad-placement .ethical-callout a{color:var(--color-foreground-secondary)!important}#furo-readthedocs-versions{background:transparent;display:block;position:static;width:100%}#furo-readthedocs-versions .rst-versions{background:#1a1c1e}#furo-readthedocs-versions .rst-current-version{background:var(--color-sidebar-item-background);cursor:unset}#furo-readthedocs-versions .rst-current-version:hover{background:var(--color-sidebar-item-background)}#furo-readthedocs-versions .rst-current-version .fa-book{color:var(--color-foreground-primary)}#furo-readthedocs-versions>.rst-other-versions{padding:0}#furo-readthedocs-versions>.rst-other-versions small{opacity:1}#furo-readthedocs-versions .injected .rst-versions{position:unset}#furo-readthedocs-versions:focus-within,#furo-readthedocs-versions:hover{box-shadow:0 0 0 1px var(--color-sidebar-background-border)}#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:hover .rst-current-version{background:#1a1c1e;font-size:inherit;height:auto;line-height:inherit;padding:12px;text-align:right}#furo-readthedocs-versions:focus-within .rst-current-version .fa-book,#furo-readthedocs-versions:hover .rst-current-version .fa-book{color:#fff;float:left}#furo-readthedocs-versions:focus-within .fa-caret-down,#furo-readthedocs-versions:hover .fa-caret-down{display:none}#furo-readthedocs-versions:focus-within .injected,#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:focus-within .rst-other-versions,#furo-readthedocs-versions:hover .injected,#furo-readthedocs-versions:hover .rst-current-version,#furo-readthedocs-versions:hover .rst-other-versions{display:block}#furo-readthedocs-versions:focus-within>.rst-current-version,#furo-readthedocs-versions:hover>.rst-current-version{display:none}.highlight:hover button.copybtn{color:var(--color-code-foreground)}.highlight button.copybtn{align-items:center;background-color:var(--color-code-background);border:none;color:var(--color-background-item);cursor:pointer;height:1.25em;right:.5rem;top:.625rem;transition:color .3s,opacity .3s;width:1.25em}.highlight button.copybtn:hover{background-color:var(--color-code-background);color:var(--color-brand-content)}.highlight button.copybtn:after{background-color:transparent;color:var(--color-code-foreground);display:none}.highlight button.copybtn.success{color:#22863a;transition:color 0ms}.highlight button.copybtn.success:after{display:block}.highlight button.copybtn svg{padding:0}body{--sd-color-primary:var(--color-brand-primary);--sd-color-primary-highlight:var(--color-brand-content);--sd-color-primary-text:var(--color-background-primary);--sd-color-shadow:rgba(0,0,0,.05);--sd-color-card-border:var(--color-card-border);--sd-color-card-border-hover:var(--color-brand-content);--sd-color-card-background:var(--color-card-background);--sd-color-card-text:var(--color-foreground-primary);--sd-color-card-header:var(--color-card-marginals-background);--sd-color-card-footer:var(--color-card-marginals-background);--sd-color-tabs-label-active:var(--color-brand-content);--sd-color-tabs-label-hover:var(--color-foreground-muted);--sd-color-tabs-label-inactive:var(--color-foreground-muted);--sd-color-tabs-underline-active:var(--color-brand-content);--sd-color-tabs-underline-hover:var(--color-foreground-border);--sd-color-tabs-underline-inactive:var(--color-background-border);--sd-color-tabs-overline:var(--color-background-border);--sd-color-tabs-underline:var(--color-background-border)}.sd-tab-content{box-shadow:0 -2px var(--sd-color-tabs-overline),0 1px var(--sd-color-tabs-underline)}.sd-card{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)}.sd-shadow-sm{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-md{box-shadow:0 .3rem .75rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-lg{box-shadow:0 .6rem 1.5rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-card-hover:hover{transform:none}.sd-cards-carousel{gap:.25rem;padding:.25rem}body{--tabs--label-text:var(--color-foreground-muted);--tabs--label-text--hover:var(--color-foreground-muted);--tabs--label-text--active:var(--color-brand-content);--tabs--label-text--active--hover:var(--color-brand-content);--tabs--label-background:transparent;--tabs--label-background--hover:transparent;--tabs--label-background--active:transparent;--tabs--label-background--active--hover:transparent;--tabs--padding-x:0.25em;--tabs--margin-x:1em;--tabs--border:var(--color-background-border);--tabs--label-border:transparent;--tabs--label-border--hover:var(--color-foreground-muted);--tabs--label-border--active:var(--color-brand-content);--tabs--label-border--active--hover:var(--color-brand-content)}[role=main] .container{max-width:none;padding-left:0;padding-right:0}.shadow.docutils{border:none;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1)!important}.sphinx-bs .card{background-color:var(--color-background-secondary);color:var(--color-foreground)} 2 | /*# sourceMappingURL=furo-extensions.css.map*/ -------------------------------------------------------------------------------- /docs/_build/html/_static/language_data.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This script contains the language-specific data used by searchtools.js, 3 | * namely the list of stopwords, stemmer, scorer and splitter. 4 | */ 5 | 6 | var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; 7 | 8 | 9 | /* Non-minified version is copied as a separate JS file, if available */ 10 | 11 | /** 12 | * Porter Stemmer 13 | */ 14 | var Stemmer = function() { 15 | 16 | var step2list = { 17 | ational: 'ate', 18 | tional: 'tion', 19 | enci: 'ence', 20 | anci: 'ance', 21 | izer: 'ize', 22 | bli: 'ble', 23 | alli: 'al', 24 | entli: 'ent', 25 | eli: 'e', 26 | ousli: 'ous', 27 | ization: 'ize', 28 | ation: 'ate', 29 | ator: 'ate', 30 | alism: 'al', 31 | iveness: 'ive', 32 | fulness: 'ful', 33 | ousness: 'ous', 34 | aliti: 'al', 35 | iviti: 'ive', 36 | biliti: 'ble', 37 | logi: 'log' 38 | }; 39 | 40 | var step3list = { 41 | icate: 'ic', 42 | ative: '', 43 | alize: 'al', 44 | iciti: 'ic', 45 | ical: 'ic', 46 | ful: '', 47 | ness: '' 48 | }; 49 | 50 | var c = "[^aeiou]"; // consonant 51 | var v = "[aeiouy]"; // vowel 52 | var C = c + "[^aeiouy]*"; // consonant sequence 53 | var V = v + "[aeiou]*"; // vowel sequence 54 | 55 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 56 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 57 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 58 | var s_v = "^(" + C + ")?" + v; // vowel in stem 59 | 60 | this.stemWord = function (w) { 61 | var stem; 62 | var suffix; 63 | var firstch; 64 | var origword = w; 65 | 66 | if (w.length < 3) 67 | return w; 68 | 69 | var re; 70 | var re2; 71 | var re3; 72 | var re4; 73 | 74 | firstch = w.substr(0,1); 75 | if (firstch == "y") 76 | w = firstch.toUpperCase() + w.substr(1); 77 | 78 | // Step 1a 79 | re = /^(.+?)(ss|i)es$/; 80 | re2 = /^(.+?)([^s])s$/; 81 | 82 | if (re.test(w)) 83 | w = w.replace(re,"$1$2"); 84 | else if (re2.test(w)) 85 | w = w.replace(re2,"$1$2"); 86 | 87 | // Step 1b 88 | re = /^(.+?)eed$/; 89 | re2 = /^(.+?)(ed|ing)$/; 90 | if (re.test(w)) { 91 | var fp = re.exec(w); 92 | re = new RegExp(mgr0); 93 | if (re.test(fp[1])) { 94 | re = /.$/; 95 | w = w.replace(re,""); 96 | } 97 | } 98 | else if (re2.test(w)) { 99 | var fp = re2.exec(w); 100 | stem = fp[1]; 101 | re2 = new RegExp(s_v); 102 | if (re2.test(stem)) { 103 | w = stem; 104 | re2 = /(at|bl|iz)$/; 105 | re3 = new RegExp("([^aeiouylsz])\\1$"); 106 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 107 | if (re2.test(w)) 108 | w = w + "e"; 109 | else if (re3.test(w)) { 110 | re = /.$/; 111 | w = w.replace(re,""); 112 | } 113 | else if (re4.test(w)) 114 | w = w + "e"; 115 | } 116 | } 117 | 118 | // Step 1c 119 | re = /^(.+?)y$/; 120 | if (re.test(w)) { 121 | var fp = re.exec(w); 122 | stem = fp[1]; 123 | re = new RegExp(s_v); 124 | if (re.test(stem)) 125 | w = stem + "i"; 126 | } 127 | 128 | // Step 2 129 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 130 | if (re.test(w)) { 131 | var fp = re.exec(w); 132 | stem = fp[1]; 133 | suffix = fp[2]; 134 | re = new RegExp(mgr0); 135 | if (re.test(stem)) 136 | w = stem + step2list[suffix]; 137 | } 138 | 139 | // Step 3 140 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 141 | if (re.test(w)) { 142 | var fp = re.exec(w); 143 | stem = fp[1]; 144 | suffix = fp[2]; 145 | re = new RegExp(mgr0); 146 | if (re.test(stem)) 147 | w = stem + step3list[suffix]; 148 | } 149 | 150 | // Step 4 151 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 152 | re2 = /^(.+?)(s|t)(ion)$/; 153 | if (re.test(w)) { 154 | var fp = re.exec(w); 155 | stem = fp[1]; 156 | re = new RegExp(mgr1); 157 | if (re.test(stem)) 158 | w = stem; 159 | } 160 | else if (re2.test(w)) { 161 | var fp = re2.exec(w); 162 | stem = fp[1] + fp[2]; 163 | re2 = new RegExp(mgr1); 164 | if (re2.test(stem)) 165 | w = stem; 166 | } 167 | 168 | // Step 5 169 | re = /^(.+?)e$/; 170 | if (re.test(w)) { 171 | var fp = re.exec(w); 172 | stem = fp[1]; 173 | re = new RegExp(mgr1); 174 | re2 = new RegExp(meq1); 175 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 176 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 177 | w = stem; 178 | } 179 | re = /ll$/; 180 | re2 = new RegExp(mgr1); 181 | if (re.test(w) && re2.test(w)) { 182 | re = /.$/; 183 | w = w.replace(re,""); 184 | } 185 | 186 | // and turn initial Y back to y 187 | if (firstch == "y") 188 | w = firstch.toLowerCase() + w.substr(1); 189 | return w; 190 | } 191 | } 192 | 193 | -------------------------------------------------------------------------------- /docs/_build/html/_static/sphinx_highlight.js: -------------------------------------------------------------------------------- 1 | /* Highlighting utilities for Sphinx HTML documentation. */ 2 | "use strict"; 3 | 4 | const SPHINX_HIGHLIGHT_ENABLED = true 5 | 6 | /** 7 | * highlight a given string on a node by wrapping it in 8 | * span elements with the given class name. 9 | */ 10 | const _highlight = (node, addItems, text, className) => { 11 | if (node.nodeType === Node.TEXT_NODE) { 12 | const val = node.nodeValue; 13 | const parent = node.parentNode; 14 | const pos = val.toLowerCase().indexOf(text); 15 | if ( 16 | pos >= 0 && 17 | !parent.classList.contains(className) && 18 | !parent.classList.contains("nohighlight") 19 | ) { 20 | let span; 21 | 22 | const closestNode = parent.closest("body, svg, foreignObject"); 23 | const isInSVG = closestNode && closestNode.matches("svg"); 24 | if (isInSVG) { 25 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 26 | } else { 27 | span = document.createElement("span"); 28 | span.classList.add(className); 29 | } 30 | 31 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 32 | const rest = document.createTextNode(val.substr(pos + text.length)); 33 | parent.insertBefore( 34 | span, 35 | parent.insertBefore( 36 | rest, 37 | node.nextSibling 38 | ) 39 | ); 40 | node.nodeValue = val.substr(0, pos); 41 | /* There may be more occurrences of search term in this node. So call this 42 | * function recursively on the remaining fragment. 43 | */ 44 | _highlight(rest, addItems, text, className); 45 | 46 | if (isInSVG) { 47 | const rect = document.createElementNS( 48 | "http://www.w3.org/2000/svg", 49 | "rect" 50 | ); 51 | const bbox = parent.getBBox(); 52 | rect.x.baseVal.value = bbox.x; 53 | rect.y.baseVal.value = bbox.y; 54 | rect.width.baseVal.value = bbox.width; 55 | rect.height.baseVal.value = bbox.height; 56 | rect.setAttribute("class", className); 57 | addItems.push({ parent: parent, target: rect }); 58 | } 59 | } 60 | } else if (node.matches && !node.matches("button, select, textarea")) { 61 | node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); 62 | } 63 | }; 64 | const _highlightText = (thisNode, text, className) => { 65 | let addItems = []; 66 | _highlight(thisNode, addItems, text, className); 67 | addItems.forEach((obj) => 68 | obj.parent.insertAdjacentElement("beforebegin", obj.target) 69 | ); 70 | }; 71 | 72 | /** 73 | * Small JavaScript module for the documentation. 74 | */ 75 | const SphinxHighlight = { 76 | 77 | /** 78 | * highlight the search words provided in localstorage in the text 79 | */ 80 | highlightSearchWords: () => { 81 | if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight 82 | 83 | // get and clear terms from localstorage 84 | const url = new URL(window.location); 85 | const highlight = 86 | localStorage.getItem("sphinx_highlight_terms") 87 | || url.searchParams.get("highlight") 88 | || ""; 89 | localStorage.removeItem("sphinx_highlight_terms") 90 | url.searchParams.delete("highlight"); 91 | window.history.replaceState({}, "", url); 92 | 93 | // get individual terms from highlight string 94 | const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); 95 | if (terms.length === 0) return; // nothing to do 96 | 97 | // There should never be more than one element matching "div.body" 98 | const divBody = document.querySelectorAll("div.body"); 99 | const body = divBody.length ? divBody[0] : document.querySelector("body"); 100 | window.setTimeout(() => { 101 | terms.forEach((term) => _highlightText(body, term, "highlighted")); 102 | }, 10); 103 | 104 | const searchBox = document.getElementById("searchbox"); 105 | if (searchBox === null) return; 106 | searchBox.appendChild( 107 | document 108 | .createRange() 109 | .createContextualFragment( 110 | '" 114 | ) 115 | ); 116 | }, 117 | 118 | /** 119 | * helper function to hide the search marks again 120 | */ 121 | hideSearchWords: () => { 122 | document 123 | .querySelectorAll("#searchbox .highlight-link") 124 | .forEach((el) => el.remove()); 125 | document 126 | .querySelectorAll("span.highlighted") 127 | .forEach((el) => el.classList.remove("highlighted")); 128 | localStorage.removeItem("sphinx_highlight_terms") 129 | }, 130 | 131 | initEscapeListener: () => { 132 | // only install a listener if it is really needed 133 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; 134 | 135 | document.addEventListener("keydown", (event) => { 136 | // bail for input elements 137 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; 138 | // bail with special keys 139 | if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; 140 | if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { 141 | SphinxHighlight.hideSearchWords(); 142 | event.preventDefault(); 143 | } 144 | }); 145 | }, 146 | }; 147 | 148 | _ready(() => { 149 | /* Do not call highlightSearchWords() when we are on the search page. 150 | * It will highlight words from the *previous* search query. 151 | */ 152 | if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); 153 | SphinxHighlight.initEscapeListener(); 154 | }); 155 | -------------------------------------------------------------------------------- /djpro/base.py: -------------------------------------------------------------------------------- 1 | # This file is part of djpro. 2 | # 3 | # Copyright (c) 2024, Franco Gidaszewski 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE.txt file that was distributed with this source code. 7 | 8 | import argparse 9 | import os 10 | from importlib import import_module 11 | from .utils.logging import logging, log_with_color, Fore 12 | 13 | 14 | class BaseCommand: 15 | def __init__(self): 16 | self.parser = argparse.ArgumentParser( 17 | description="CLI tool to create scalable and modular Django projects." 18 | ) 19 | self.subparsers = self.parser.add_subparsers(dest="command", help="Commands") 20 | 21 | def execute(self): 22 | """Parse and run user command""" 23 | args = self.parser.parse_args() 24 | args.base_dir = os.path.join(os.getcwd(), "src") # sources folder 25 | 26 | if not args.command: 27 | log_with_color( 28 | logging.INFO, 29 | "\nCommand not found.", 30 | Fore.YELLOW, 31 | delay=1, 32 | ) 33 | help_module = import_module("djpro.commands.help") 34 | help_module.help() 35 | return 36 | 37 | if args.command == "help": 38 | try: 39 | help_module = import_module("djpro.commands.help") 40 | help_module.help() 41 | except ModuleNotFoundError: 42 | log_with_color( 43 | logging.INFO, 44 | "\nHelp command module not found.", 45 | Fore.YELLOW, 46 | delay=1, 47 | ) 48 | return 49 | 50 | try: 51 | command_module = import_module(f"djpro.commands.{args.command}") 52 | log_with_color(logging.INFO, "Running commands...", Fore.BLUE, delay=2) 53 | command_module.run(args) 54 | 55 | except ModuleNotFoundError: 56 | log_with_color( 57 | logging.INFO, 58 | "\nCommand not found.", 59 | Fore.YELLOW, 60 | delay=1, 61 | ) 62 | help_module = import_module("djpro.commands.help") 63 | help_module.help() 64 | 65 | def add_command(self, name, help_message, arguments=None): 66 | """Register a new subcommand""" 67 | command_parser = self.subparsers.add_parser(name, help=help_message) 68 | 69 | if arguments: 70 | for arg_name, arg_options in arguments.items(): 71 | command_parser.add_argument(arg_name, **arg_options) 72 | 73 | 74 | def main(): 75 | cli = BaseCommand() 76 | 77 | # Help 78 | cli.add_command( 79 | "help", 80 | "Show help for a command.", 81 | ) 82 | 83 | # Project 84 | cli.add_command( 85 | "project", 86 | "Create a new project.", 87 | arguments={ 88 | "project_name": { 89 | "help": "Create a Django project with a scalable and modular architecture.", 90 | "type": str, 91 | }, 92 | "--api": { 93 | "help": "Include API configuration", 94 | "action": "store_true", 95 | }, 96 | "--docker": { 97 | "help": "Include Docker configuration for easy deployment", 98 | "action": "store_true", 99 | }, 100 | "--unfold": { 101 | "help": "Include Unfold custom theme to Django admin site", 102 | "action": "store_true", 103 | }, 104 | }, 105 | ) 106 | 107 | """ # Add service (not implemented) 108 | cli.add_command( 109 | "service", 110 | "Add a new service to your current project.", 111 | arguments={ 112 | "--unfold": { 113 | "help": "Add Unfold configuration to your current project.", 114 | "action": "store_true", 115 | }, 116 | "--docker": { 117 | "help": "Add Docker configuration to your current project.", 118 | "action": "store_true", 119 | }, 120 | }, 121 | )""" 122 | 123 | # Module 124 | cli.add_command( 125 | "module", 126 | "Create a new module.", 127 | arguments={ 128 | "module_name": { 129 | "help": "Create a new module in your current project.", 130 | "type": str, 131 | }, 132 | "-models": { 133 | "help": "Include models.py file.", 134 | "action": "store_true", 135 | }, 136 | "-views": { 137 | "help": "Include views.py file.", 138 | "action": "store_true", 139 | }, 140 | "-serializers": { 141 | "help": "Include serializers.py file.", 142 | "action": "store_true", 143 | }, 144 | "-urls": { 145 | "help": "Include urls.py file.", 146 | "action": "store_true", 147 | }, 148 | "-forms": { 149 | "help": "Include forms.py file.", 150 | "action": "store_true", 151 | }, 152 | "-admin": { 153 | "help": "Include admin.py file.", 154 | "action": "store_true", 155 | }, 156 | "-apps": { 157 | "help": "Include apps.py file.", 158 | "action": "store_true", 159 | }, 160 | }, 161 | ) 162 | 163 | # Simplify manage.py commands 164 | cli.add_command( 165 | "man", 166 | "Run manage.py commands in a shorter form.", 167 | arguments={ 168 | "man_command": { 169 | "help": "The manage.py command you want to run.", 170 | "type": str, 171 | }, 172 | "help": { 173 | "help": "View list of available manage.py commands.", 174 | "action": "store_true", 175 | }, 176 | }, 177 | ) 178 | 179 | cli.execute() 180 | -------------------------------------------------------------------------------- /djpro/commands/help.py: -------------------------------------------------------------------------------- 1 | # This file is part of djpro. 2 | # 3 | # Copyright (c) 2024, Franco Gidaszewski 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE.txt file that was distributed with this source code. 7 | 8 | from ..utils.logging import logging, log_with_color, Fore 9 | 10 | 11 | def help(): 12 | log_with_color( 13 | logging.INFO, 14 | "\nCommand help guide:", 15 | Fore.WHITE, 16 | delay=1, 17 | ) 18 | 19 | log_with_color( 20 | logging.INFO, 21 | "\n djpro [options]", 22 | Fore.GREEN, 23 | ) 24 | 25 | log_with_color( 26 | logging.INFO, 27 | "\nAvailable subcommands:", 28 | Fore.WHITE, 29 | ) 30 | 31 | # project 32 | log_with_color( 33 | logging.INFO, 34 | "\n project Creates a Django project with a scalable and modular architecture.", 35 | Fore.YELLOW, 36 | delay=0, 37 | ) 38 | 39 | log_with_color( 40 | logging.INFO, 41 | " Options:", 42 | Fore.WHITE, 43 | delay=0, 44 | ) 45 | 46 | log_with_color( 47 | logging.INFO, 48 | " --api Includes basic configuration for an API (Django REST Framework).", 49 | Fore.BLUE, 50 | delay=0, 51 | ) 52 | log_with_color( 53 | logging.INFO, 54 | " --docker Adds Docker configuration for easy deployment.", 55 | Fore.BLUE, 56 | delay=0, 57 | ) 58 | log_with_color( 59 | logging.INFO, 60 | " --unfold Adds Unfold custom theme to Django admin site.", 61 | Fore.BLUE, 62 | delay=0, 63 | ) 64 | 65 | # module 66 | log_with_color( 67 | logging.INFO, 68 | "\n module Creates a new module in your current project.", 69 | Fore.YELLOW, 70 | delay=0, 71 | ) 72 | 73 | log_with_color( 74 | logging.INFO, 75 | " Options:", 76 | Fore.WHITE, 77 | delay=0, 78 | ) 79 | 80 | log_with_color( 81 | logging.INFO, 82 | " -models Include models.py file.", 83 | Fore.BLUE, 84 | delay=0, 85 | ) 86 | log_with_color( 87 | logging.INFO, 88 | " -views Include views.py file", 89 | Fore.BLUE, 90 | delay=0, 91 | ) 92 | log_with_color( 93 | logging.INFO, 94 | " -serializers Include serializers.py file.", 95 | Fore.BLUE, 96 | delay=0, 97 | ) 98 | log_with_color( 99 | logging.INFO, 100 | " -urls Include urls.py file", 101 | Fore.BLUE, 102 | delay=0, 103 | ) 104 | log_with_color( 105 | logging.INFO, 106 | " -forms Include forms.py file", 107 | Fore.BLUE, 108 | delay=0, 109 | ) 110 | log_with_color( 111 | logging.INFO, 112 | " -admin Include admin.py file", 113 | Fore.BLUE, 114 | delay=0, 115 | ) 116 | log_with_color( 117 | logging.INFO, 118 | " -apps Include apps.py file", 119 | Fore.BLUE, 120 | delay=0, 121 | ) 122 | 123 | # man 124 | log_with_color( 125 | logging.INFO, 126 | "\n man Run manage.py commands easier.", 127 | Fore.YELLOW, 128 | delay=0, 129 | ) 130 | log_with_color( 131 | logging.INFO, 132 | " djpro man ", 133 | Fore.GREEN, 134 | ) 135 | log_with_color( 136 | logging.INFO, 137 | "\n Examples of use:", 138 | Fore.WHITE, 139 | delay=0, 140 | ) 141 | log_with_color( 142 | logging.INFO, 143 | " djpro man help View list of available manage.py commands.", 144 | Fore.BLUE, 145 | delay=0, 146 | ) 147 | log_with_color( 148 | logging.INFO, 149 | " djpro man runserver", 150 | Fore.BLUE, 151 | delay=0, 152 | ) 153 | log_with_color( 154 | logging.INFO, 155 | " djpro man makemigrations", 156 | Fore.BLUE, 157 | delay=0, 158 | ) 159 | log_with_color( 160 | logging.INFO, 161 | " djpro man migrate\n", 162 | Fore.BLUE, 163 | delay=0, 164 | ) 165 | 166 | 167 | def man_help(): 168 | log_with_color( 169 | logging.INFO, 170 | "\nCommand help guide:", 171 | Fore.GREEN, 172 | delay=1, 173 | ) 174 | 175 | log_with_color( 176 | logging.INFO, 177 | "\nAvailable subcommands:", 178 | Fore.WHITE, 179 | ) 180 | 181 | log_with_color( 182 | logging.INFO, 183 | "\n[auth]", 184 | Fore.YELLOW, 185 | delay=0, 186 | ) 187 | 188 | log_with_color( 189 | logging.INFO, 190 | " changepassword\n createsuperuser", 191 | Fore.WHITE, 192 | delay=0, 193 | ) 194 | 195 | log_with_color( 196 | logging.INFO, 197 | "\n[contenttypes]", 198 | Fore.YELLOW, 199 | delay=0, 200 | ) 201 | 202 | log_with_color( 203 | logging.INFO, 204 | " remove_stale_contenttypes", 205 | Fore.WHITE, 206 | delay=0, 207 | ) 208 | 209 | log_with_color( 210 | logging.INFO, 211 | "\n[django]", 212 | Fore.YELLOW, 213 | delay=0, 214 | ) 215 | 216 | log_with_color( 217 | logging.INFO, 218 | " check\n compilemessages\n createcachetable\n dbshell\n diffsettings\n dumpdata\n flush\n inspectdb\n loaddata\n makemessages\n makemigrations\n migrate\n optimizemigration\n sendtestemail\n shell\n showmigrations\n sqlflush\n sqlmigrate\n sqlsequencereset\n squashmigrations\n startapp\n startproject\n test\n testserver\n", 219 | Fore.WHITE, 220 | delay=0, 221 | ) 222 | 223 | log_with_color( 224 | logging.INFO, 225 | "\n[sessions]", 226 | Fore.YELLOW, 227 | delay=0, 228 | ) 229 | 230 | log_with_color( 231 | logging.INFO, 232 | " clearsessions", 233 | Fore.WHITE, 234 | delay=0, 235 | ) 236 | 237 | log_with_color( 238 | logging.INFO, 239 | "\n[staticfiles]", 240 | Fore.YELLOW, 241 | delay=0, 242 | ) 243 | 244 | log_with_color( 245 | logging.INFO, 246 | " collectstatic\n findstatic\n runserver", 247 | Fore.WHITE, 248 | delay=0, 249 | ) 250 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This file is part of djpro. 4 | # 5 | # Copyright (c) 2024, Franco Gidaszewski 6 | # 7 | # For the full copyright and license information, please view 8 | # the LICENSE.txt file that was distributed with this source code. 9 | 10 | import codecs 11 | import re 12 | from os import path 13 | 14 | from setuptools import find_packages, setup 15 | 16 | # Use this code block for future deprecations of Python version: 17 | # 18 | # import warnings 19 | # import sys 20 | # 21 | # if sys.version_info < (3, 6): 22 | # warnings.warn( 23 | # "Support of Python < 3.6 is deprecated" 24 | # "and will be removed in a future release.", 25 | # DeprecationWarning 26 | # ) 27 | 28 | 29 | def read_file(filepath): 30 | """Read content from a UTF-8 encoded text file.""" 31 | with codecs.open(filepath, "rb", "utf-8") as file_handle: 32 | return file_handle.read() 33 | 34 | 35 | PKG_NAME = "djpro" 36 | PKG_DIR = path.abspath(path.dirname(__file__)) 37 | META_PATH = path.join(PKG_DIR, "djpro", "__init__.py") 38 | META_CONTENTS = read_file(META_PATH) 39 | 40 | 41 | def load_long_description(): 42 | """Load long description from file README.rst.""" 43 | 44 | def changes(): 45 | changelog = path.join(PKG_DIR, "CHANGELOG.rst") 46 | pattern = ( 47 | r"(`(v\d+.\d+.\d+)`_( - \d{1,2}-\w+-\d{4}\r?\n-+\r?\n.*?))" 48 | r"\r?\n\r?\n\r?\n`v\d+.\d+.\d+`_" 49 | ) 50 | result = re.search(pattern, read_file(changelog), re.S) 51 | 52 | return result.group(2) + result.group(3) if result else "" 53 | 54 | try: 55 | title = PKG_NAME 56 | head = "=" * (len(title)) 57 | 58 | contents = ( 59 | head, 60 | format(title.strip(" .")), 61 | head, 62 | read_file(path.join(PKG_DIR, "README.rst")).split(".. -teaser-begin-")[1], 63 | "", 64 | read_file(path.join(PKG_DIR, "CONTRIBUTING.rst")), 65 | "", 66 | "Release Information", 67 | "===================\n", 68 | changes(), 69 | "", 70 | "`Full changelog <{}/en/latest/changelog.html>`_.".format(find_meta("url")), 71 | "", 72 | read_file(path.join(PKG_DIR, "SECURITY.rst")), 73 | "", 74 | read_file(path.join(PKG_DIR, "AUTHORS.rst")), 75 | ) 76 | 77 | return "\n".join(contents) 78 | except (RuntimeError, FileNotFoundError) as read_error: 79 | message = "Long description could not be read from README.rst" 80 | raise RuntimeError("%s: %s" % (message, read_error)) from read_error 81 | 82 | 83 | def is_canonical_version(version): 84 | """Check if a version string is in the canonical format of PEP 440.""" 85 | pattern = ( 86 | r"^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))" 87 | r"*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))" 88 | r"?(\.dev(0|[1-9][0-9]*))?$" 89 | ) 90 | return re.match(pattern, version) is not None 91 | 92 | 93 | def find_meta(meta): 94 | """Extract __*meta*__ from META_CONTENTS.""" 95 | meta_match = re.search( 96 | r"^__{meta}__\s+=\s+['\"]([^'\"]*)['\"]".format(meta=meta), META_CONTENTS, re.M 97 | ) 98 | 99 | if meta_match: 100 | return meta_match.group(1) 101 | raise RuntimeError("Unable to find __%s__ string in package meta file" % meta) 102 | 103 | 104 | def get_version_string(): 105 | """Return package version as listed in `__version__` in meta file.""" 106 | # Parse version string 107 | version_string = find_meta("version") 108 | 109 | # Check validity 110 | if not is_canonical_version(version_string): 111 | message = ( 112 | 'The detected version string "{}" is not in canonical ' 113 | "format as defined in PEP 440.".format(version_string) 114 | ) 115 | raise ValueError(message) 116 | 117 | return version_string 118 | 119 | 120 | # What does this project relate to? 121 | KEYWORDS = [ 122 | "django", 123 | "productivity", 124 | "cli", 125 | ] 126 | 127 | # Classifiers: available ones listed at https://pypi.org/classifiers 128 | CLASSIFIERS = [ 129 | "Development Status :: 4 - Beta ", 130 | "Framework :: Django", 131 | "Framework :: Django :: 2.0", 132 | "Framework :: Django :: 2.1", 133 | "Framework :: Django :: 2.2", 134 | "Framework :: Django :: 3.0", 135 | "Framework :: Django :: 3.1", 136 | "Framework :: Django :: 3.2", 137 | "Framework :: Django :: 4.0", 138 | "Framework :: Django :: 4.1", 139 | "Framework :: Django :: 4.2", 140 | "Framework :: Django :: 5", 141 | "Framework :: Django :: 5.0", 142 | "Framework :: Django :: 5.1", 143 | "Operating System :: OS Independent", 144 | "Intended Audience :: Developers", 145 | "Natural Language :: English", 146 | "Programming Language :: Python", 147 | "Programming Language :: Python :: 3", 148 | "Programming Language :: Python :: 3.6", 149 | "Programming Language :: Python :: 3.7", 150 | "Programming Language :: Python :: 3.8", 151 | "Programming Language :: Python :: 3.9", 152 | "Programming Language :: Python :: 3.10", 153 | "Programming Language :: Python :: 3.11", 154 | "Programming Language :: Python :: Implementation :: CPython", 155 | "Programming Language :: Python :: Implementation :: PyPy", 156 | "Topic :: Software Development :: Libraries :: Python Modules", 157 | "Topic :: Utilities", 158 | "License :: OSI Approved :: MIT License", 159 | ] 160 | 161 | # Project's URLs 162 | PROJECT_URLS = { 163 | "Documentation": find_meta("url"), 164 | "Bug Tracker": "https://github.com/szew404/dj-pro/issues", 165 | "Source Code": "https://github.com/szew404/dj-pro", 166 | } 167 | 168 | # Dependencies that are downloaded by pip on installation 169 | INSTALL_REQUIRES = [ 170 | "django>=5.0", # djpro needs a Django function to create a SECRET KEY. 171 | "colorama>=0.4.6", # logging colors 172 | ] 173 | 174 | if __name__ == "__main__": 175 | setup( 176 | name=PKG_NAME, 177 | version=get_version_string(), 178 | author=find_meta("author"), 179 | author_email=find_meta("author_email"), 180 | license=find_meta("license"), 181 | description=find_meta("description"), 182 | long_description=load_long_description(), 183 | long_description_content_type="text/x-rst", 184 | url=find_meta("url"), 185 | project_urls=PROJECT_URLS, 186 | classifiers=CLASSIFIERS, 187 | packages=find_packages(), 188 | platforms=["any"], 189 | include_package_data=True, 190 | zip_safe=False, 191 | install_requires=INSTALL_REQUIRES, 192 | python_requires=">=3.7", 193 | entry_points={ 194 | "console_scripts": [ 195 | "djpro=djpro.base:main", 196 | ], 197 | }, 198 | ) 199 | -------------------------------------------------------------------------------- /docs/_build/html/_static/styles/furo-extensions.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"styles/furo-extensions.css","mappings":"AAGA,2BACE,oFACA,4CAKE,6CAHA,YACA,eAEA,CACA,kDACE,yCAEF,8CACE,sCAEJ,8CACE,kDAEJ,2BAGE,uBACA,cAHA,gBACA,UAEA,CAGA,yCACE,mBAEF,gDAEE,gDADA,YACA,CACA,sDACE,gDACF,yDACE,sCAEJ,+CACE,UACA,qDACE,UAGF,mDACE,eAEJ,yEAEE,4DAEA,mHASE,mBAPA,kBAEA,YADA,oBAGA,aADA,gBAIA,CAEA,qIAEE,WADA,UACA,CAEJ,uGACE,aAEF,iUAGE,cAEF,mHACE,aC1EJ,gCACE,mCAEF,0BAEE,mBAUA,8CACA,YAFA,mCAKA,eAZA,cAIA,YADA,YAYA,iCAdA,YAcA,CAEA,gCAEE,8CADA,gCACA,CAEF,gCAGE,6BADA,mCADA,YAEA,CAEF,kCAEE,cADA,oBACA,CACA,wCACE,cAEJ,8BACE,UCzCN,KAEE,6CAA8C,CAC9C,uDAAwD,CACxD,uDAAwD,CAGxD,iCAAsC,CAGtC,+CAAgD,CAChD,uDAAwD,CACxD,uDAAwD,CACxD,oDAAqD,CACrD,6DAA8D,CAC9D,6DAA8D,CAG9D,uDAAwD,CACxD,yDAA0D,CAC1D,4DAA6D,CAC7D,2DAA4D,CAC5D,8DAA+D,CAC/D,iEAAkE,CAClE,uDAAwD,CACxD,wDAAyD,CAG3D,gBACE,qFAGF,SACE,6EAEF,cACE,uFAEF,cACE,uFAEF,cACE,uFAGF,qBACE,eAEF,mBACE,WACA,eChDF,KACE,gDAAiD,CACjD,uDAAwD,CACxD,qDAAsD,CACtD,4DAA6D,CAC7D,oCAAqC,CACrC,2CAA4C,CAC5C,4CAA6C,CAC7C,mDAAoD,CACpD,wBAAyB,CACzB,oBAAqB,CACrB,6CAA8C,CAC9C,gCAAiC,CACjC,yDAA0D,CAC1D,uDAAwD,CACxD,8DAA+D,CCbjE,uBACE,eACA,eACA,gBAGF,iBACE,YACA,+EAGF,iBACE,mDACA","sources":["webpack:///./src/furo/assets/styles/extensions/_readthedocs.sass","webpack:///./src/furo/assets/styles/extensions/_copybutton.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-design.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-inline-tabs.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-panels.sass"],"sourcesContent":["// This file contains the styles used for tweaking how ReadTheDoc's embedded\n// contents would show up inside the theme.\n\n#furo-sidebar-ad-placement\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n .ethical-sidebar\n // Remove the border and box-shadow.\n border: none\n box-shadow: none\n // Manage the background colors.\n background: var(--color-background-secondary)\n &:hover\n background: var(--color-background-hover)\n // Ensure the text is legible.\n a\n color: var(--color-foreground-primary)\n\n .ethical-callout a\n color: var(--color-foreground-secondary) !important\n\n#furo-readthedocs-versions\n position: static\n width: 100%\n background: transparent\n display: block\n\n // Make the background color fit with the theme's aesthetic.\n .rst-versions\n background: rgb(26, 28, 30)\n\n .rst-current-version\n cursor: unset\n background: var(--color-sidebar-item-background)\n &:hover\n background: var(--color-sidebar-item-background)\n .fa-book\n color: var(--color-foreground-primary)\n\n > .rst-other-versions\n padding: 0\n small\n opacity: 1\n\n .injected\n .rst-versions\n position: unset\n\n &:hover,\n &:focus-within\n box-shadow: 0 0 0 1px var(--color-sidebar-background-border)\n\n .rst-current-version\n // Undo the tweaks done in RTD's CSS\n font-size: inherit\n line-height: inherit\n height: auto\n text-align: right\n padding: 12px\n\n // Match the rest of the body\n background: #1a1c1e\n\n .fa-book\n float: left\n color: white\n\n .fa-caret-down\n display: none\n\n .rst-current-version,\n .rst-other-versions,\n .injected\n display: block\n\n > .rst-current-version\n display: none\n",".highlight\n &:hover button.copybtn\n color: var(--color-code-foreground)\n\n button.copybtn\n // Align things correctly\n align-items: center\n\n height: 1.25em\n width: 1.25em\n\n top: 0.625rem // $code-spacing-vertical\n right: 0.5rem\n\n // Make it look better\n color: var(--color-background-item)\n background-color: var(--color-code-background)\n border: none\n\n // Change to cursor to make it obvious that you can click on it\n cursor: pointer\n\n // Transition smoothly, for aesthetics\n transition: color 300ms, opacity 300ms\n\n &:hover\n color: var(--color-brand-content)\n background-color: var(--color-code-background)\n\n &::after\n display: none\n color: var(--color-code-foreground)\n background-color: transparent\n\n &.success\n transition: color 0ms\n color: #22863a\n &::after\n display: block\n\n svg\n padding: 0\n","body\n // Colors\n --sd-color-primary: var(--color-brand-primary)\n --sd-color-primary-highlight: var(--color-brand-content)\n --sd-color-primary-text: var(--color-background-primary)\n\n // Shadows\n --sd-color-shadow: rgba(0, 0, 0, 0.05)\n\n // Cards\n --sd-color-card-border: var(--color-card-border)\n --sd-color-card-border-hover: var(--color-brand-content)\n --sd-color-card-background: var(--color-card-background)\n --sd-color-card-text: var(--color-foreground-primary)\n --sd-color-card-header: var(--color-card-marginals-background)\n --sd-color-card-footer: var(--color-card-marginals-background)\n\n // Tabs\n --sd-color-tabs-label-active: var(--color-brand-content)\n --sd-color-tabs-label-hover: var(--color-foreground-muted)\n --sd-color-tabs-label-inactive: var(--color-foreground-muted)\n --sd-color-tabs-underline-active: var(--color-brand-content)\n --sd-color-tabs-underline-hover: var(--color-foreground-border)\n --sd-color-tabs-underline-inactive: var(--color-background-border)\n --sd-color-tabs-overline: var(--color-background-border)\n --sd-color-tabs-underline: var(--color-background-border)\n\n// Tabs\n.sd-tab-content\n box-shadow: 0 -2px var(--sd-color-tabs-overline), 0 1px var(--sd-color-tabs-underline)\n\n// Shadows\n.sd-card // Have a shadow by default\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n.sd-shadow-sm\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-md\n box-shadow: 0 0.3rem 0.75rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-lg\n box-shadow: 0 0.6rem 1.5rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Cards\n.sd-card-hover:hover // Don't change scale on hover\n transform: none\n\n.sd-cards-carousel // Have a bit of gap in the carousel by default\n gap: 0.25rem\n padding: 0.25rem\n","// This file contains styles to tweak sphinx-inline-tabs to work well with Furo.\n\nbody\n --tabs--label-text: var(--color-foreground-muted)\n --tabs--label-text--hover: var(--color-foreground-muted)\n --tabs--label-text--active: var(--color-brand-content)\n --tabs--label-text--active--hover: var(--color-brand-content)\n --tabs--label-background: transparent\n --tabs--label-background--hover: transparent\n --tabs--label-background--active: transparent\n --tabs--label-background--active--hover: transparent\n --tabs--padding-x: 0.25em\n --tabs--margin-x: 1em\n --tabs--border: var(--color-background-border)\n --tabs--label-border: transparent\n --tabs--label-border--hover: var(--color-foreground-muted)\n --tabs--label-border--active: var(--color-brand-content)\n --tabs--label-border--active--hover: var(--color-brand-content)\n","// This file contains styles to tweak sphinx-panels to work well with Furo.\n\n// sphinx-panels includes Bootstrap 4, which uses .container which can conflict\n// with docutils' `.. container::` directive.\n[role=\"main\"] .container\n max-width: initial\n padding-left: initial\n padding-right: initial\n\n// Make the panels look nicer!\n.shadow.docutils\n border: none\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Make panel colors respond to dark mode\n.sphinx-bs .card\n background-color: var(--color-background-secondary)\n color: var(--color-foreground)\n"],"names":[],"sourceRoot":""} -------------------------------------------------------------------------------- /docs/_build/html/_static/skeleton.css: -------------------------------------------------------------------------------- 1 | /* Some sane resets. */ 2 | html { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | min-height: 100%; 9 | } 10 | 11 | /* All the flexbox magic! */ 12 | body, 13 | .sb-announcement, 14 | .sb-content, 15 | .sb-main, 16 | .sb-container, 17 | .sb-container__inner, 18 | .sb-article-container, 19 | .sb-footer-content, 20 | .sb-header, 21 | .sb-header-secondary, 22 | .sb-footer { 23 | display: flex; 24 | } 25 | 26 | /* These order things vertically */ 27 | body, 28 | .sb-main, 29 | .sb-article-container { 30 | flex-direction: column; 31 | } 32 | 33 | /* Put elements in the center */ 34 | .sb-header, 35 | .sb-header-secondary, 36 | .sb-container, 37 | .sb-content, 38 | .sb-footer, 39 | .sb-footer-content { 40 | justify-content: center; 41 | } 42 | /* Put elements at the ends */ 43 | .sb-article-container { 44 | justify-content: space-between; 45 | } 46 | 47 | /* These elements grow. */ 48 | .sb-main, 49 | .sb-content, 50 | .sb-container, 51 | article { 52 | flex-grow: 1; 53 | } 54 | 55 | /* Because padding making this wider is not fun */ 56 | article { 57 | box-sizing: border-box; 58 | } 59 | 60 | /* The announcements element should never be wider than the page. */ 61 | .sb-announcement { 62 | max-width: 100%; 63 | } 64 | 65 | .sb-sidebar-primary, 66 | .sb-sidebar-secondary { 67 | flex-shrink: 0; 68 | width: 17rem; 69 | } 70 | 71 | .sb-announcement__inner { 72 | justify-content: center; 73 | 74 | box-sizing: border-box; 75 | height: 3rem; 76 | 77 | overflow-x: auto; 78 | white-space: nowrap; 79 | } 80 | 81 | /* Sidebars, with checkbox-based toggle */ 82 | .sb-sidebar-primary, 83 | .sb-sidebar-secondary { 84 | position: fixed; 85 | height: 100%; 86 | top: 0; 87 | } 88 | 89 | .sb-sidebar-primary { 90 | left: -17rem; 91 | transition: left 250ms ease-in-out; 92 | } 93 | .sb-sidebar-secondary { 94 | right: -17rem; 95 | transition: right 250ms ease-in-out; 96 | } 97 | 98 | .sb-sidebar-toggle { 99 | display: none; 100 | } 101 | .sb-sidebar-overlay { 102 | position: fixed; 103 | top: 0; 104 | width: 0; 105 | height: 0; 106 | 107 | transition: width 0ms ease 250ms, height 0ms ease 250ms, opacity 250ms ease; 108 | 109 | opacity: 0; 110 | background-color: rgba(0, 0, 0, 0.54); 111 | } 112 | 113 | #sb-sidebar-toggle--primary:checked 114 | ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--primary"], 115 | #sb-sidebar-toggle--secondary:checked 116 | ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--secondary"] { 117 | width: 100%; 118 | height: 100%; 119 | opacity: 1; 120 | transition: width 0ms ease, height 0ms ease, opacity 250ms ease; 121 | } 122 | 123 | #sb-sidebar-toggle--primary:checked ~ .sb-container .sb-sidebar-primary { 124 | left: 0; 125 | } 126 | #sb-sidebar-toggle--secondary:checked ~ .sb-container .sb-sidebar-secondary { 127 | right: 0; 128 | } 129 | 130 | /* Full-width mode */ 131 | .drop-secondary-sidebar-for-full-width-content 132 | .hide-when-secondary-sidebar-shown { 133 | display: none !important; 134 | } 135 | .drop-secondary-sidebar-for-full-width-content .sb-sidebar-secondary { 136 | display: none !important; 137 | } 138 | 139 | /* Mobile views */ 140 | .sb-page-width { 141 | width: 100%; 142 | } 143 | 144 | .sb-article-container, 145 | .sb-footer-content__inner, 146 | .drop-secondary-sidebar-for-full-width-content .sb-article, 147 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 148 | width: 100vw; 149 | } 150 | 151 | .sb-article, 152 | .match-content-width { 153 | padding: 0 1rem; 154 | box-sizing: border-box; 155 | } 156 | 157 | @media (min-width: 32rem) { 158 | .sb-article, 159 | .match-content-width { 160 | padding: 0 2rem; 161 | } 162 | } 163 | 164 | /* Tablet views */ 165 | @media (min-width: 42rem) { 166 | .sb-article-container { 167 | width: auto; 168 | } 169 | .sb-footer-content__inner, 170 | .drop-secondary-sidebar-for-full-width-content .sb-article, 171 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 172 | width: 42rem; 173 | } 174 | .sb-article, 175 | .match-content-width { 176 | width: 42rem; 177 | } 178 | } 179 | @media (min-width: 46rem) { 180 | .sb-footer-content__inner, 181 | .drop-secondary-sidebar-for-full-width-content .sb-article, 182 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 183 | width: 46rem; 184 | } 185 | .sb-article, 186 | .match-content-width { 187 | width: 46rem; 188 | } 189 | } 190 | @media (min-width: 50rem) { 191 | .sb-footer-content__inner, 192 | .drop-secondary-sidebar-for-full-width-content .sb-article, 193 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 194 | width: 50rem; 195 | } 196 | .sb-article, 197 | .match-content-width { 198 | width: 50rem; 199 | } 200 | } 201 | 202 | /* Tablet views */ 203 | @media (min-width: 59rem) { 204 | .sb-sidebar-secondary { 205 | position: static; 206 | } 207 | .hide-when-secondary-sidebar-shown { 208 | display: none !important; 209 | } 210 | .sb-footer-content__inner, 211 | .drop-secondary-sidebar-for-full-width-content .sb-article, 212 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 213 | width: 59rem; 214 | } 215 | .sb-article, 216 | .match-content-width { 217 | width: 42rem; 218 | } 219 | } 220 | @media (min-width: 63rem) { 221 | .sb-footer-content__inner, 222 | .drop-secondary-sidebar-for-full-width-content .sb-article, 223 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 224 | width: 63rem; 225 | } 226 | .sb-article, 227 | .match-content-width { 228 | width: 46rem; 229 | } 230 | } 231 | @media (min-width: 67rem) { 232 | .sb-footer-content__inner, 233 | .drop-secondary-sidebar-for-full-width-content .sb-article, 234 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 235 | width: 67rem; 236 | } 237 | .sb-article, 238 | .match-content-width { 239 | width: 50rem; 240 | } 241 | } 242 | 243 | /* Desktop views */ 244 | @media (min-width: 76rem) { 245 | .sb-sidebar-primary { 246 | position: static; 247 | } 248 | .hide-when-primary-sidebar-shown { 249 | display: none !important; 250 | } 251 | .sb-footer-content__inner, 252 | .drop-secondary-sidebar-for-full-width-content .sb-article, 253 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 254 | width: 59rem; 255 | } 256 | .sb-article, 257 | .match-content-width { 258 | width: 42rem; 259 | } 260 | } 261 | 262 | /* Full desktop views */ 263 | @media (min-width: 80rem) { 264 | .sb-article, 265 | .match-content-width { 266 | width: 46rem; 267 | } 268 | .sb-footer-content__inner, 269 | .drop-secondary-sidebar-for-full-width-content .sb-article, 270 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 271 | width: 63rem; 272 | } 273 | } 274 | 275 | @media (min-width: 84rem) { 276 | .sb-article, 277 | .match-content-width { 278 | width: 50rem; 279 | } 280 | .sb-footer-content__inner, 281 | .drop-secondary-sidebar-for-full-width-content .sb-article, 282 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 283 | width: 67rem; 284 | } 285 | } 286 | 287 | @media (min-width: 88rem) { 288 | .sb-footer-content__inner, 289 | .drop-secondary-sidebar-for-full-width-content .sb-article, 290 | .drop-secondary-sidebar-for-full-width-content .match-content-width { 291 | width: 67rem; 292 | } 293 | .sb-page-width { 294 | width: 88rem; 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /djpro/commands/project.py: -------------------------------------------------------------------------------- 1 | # This file is part of djpro. 2 | # 3 | # Copyright (c) 2024, Franco Gidaszewski 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE.txt file that was distributed with this source code. 7 | 8 | from pathlib import Path 9 | 10 | from ..utils.logging import logging, log_with_color, Fore 11 | from ..utils.messages import run_dev, run_prod 12 | from ..utils.django_utils import generate_secret_key 13 | from ..utils.write_and_config import ( 14 | create_dirs, 15 | create_files, 16 | write_to_file, 17 | configure_requirements, 18 | configure_settings_base, 19 | ) 20 | from ..utils.files_content import ( 21 | settings_content, 22 | settings_dev_content, 23 | settings_prod_content, 24 | wsgi_content, 25 | asgi_content, 26 | urls_content, 27 | env_dev_content, 28 | requirements_content, 29 | gitignore_content, 30 | views_auth_content, 31 | urls_auth_content, 32 | manage_content, 33 | dockerfile_content, 34 | dockercompose_content, 35 | env_prod_content, 36 | env_prod_db_content, 37 | urls_api_content, 38 | ) 39 | 40 | 41 | def create_project( 42 | base_dir: Path, 43 | project_name: str, 44 | api: bool = False, 45 | docker: bool = False, 46 | unfold: bool = False, 47 | ): 48 | """Function to create directories and files""" 49 | 50 | base_dir_path = Path(base_dir) 51 | 52 | if base_dir_path.exists(): 53 | raise FileExistsError( 54 | log_with_color( 55 | logging.INFO, 56 | "\nError: a project already exists in the current path.", 57 | Fore.YELLOW, 58 | ) 59 | ) 60 | 61 | # Directories 62 | directories = [ 63 | base_dir_path / "bin", 64 | base_dir_path / "config", 65 | base_dir_path / "static", 66 | base_dir_path / "modules", 67 | base_dir_path / "modules" / "authentication", 68 | base_dir_path / "modules" / "authentication" / "models", 69 | base_dir_path / "modules" / "authentication" / "views", 70 | base_dir_path / "modules" / "authentication" / "serializers", 71 | base_dir_path / "utils", 72 | base_dir_path / "tests", 73 | base_dir_path / "templates", 74 | ] 75 | 76 | # Files 77 | project_files = [ 78 | base_dir_path / "bin" / "__init__.py", 79 | base_dir_path / "bin" / "manage.py", 80 | base_dir_path / "config" / "__init__.py", 81 | base_dir_path / "config" / "settings.py", 82 | base_dir_path / "config" / "settings_base.py", 83 | base_dir_path / "config" / "settings_prod.py", 84 | base_dir_path / "config" / "settings_dev.py", 85 | base_dir_path / "config" / "asgi.py", 86 | base_dir_path / "config" / "wsgi.py", 87 | base_dir_path / "config" / "urls.py", 88 | base_dir_path / "config" / ".env.conf", 89 | base_dir_path / "modules" / "__init__.py", 90 | base_dir_path / "modules" / "authentication" / "__init__.py", 91 | base_dir_path / "modules" / "authentication" / "serializers" / "__init__.py", 92 | base_dir_path 93 | / "modules" 94 | / "authentication" 95 | / "serializers" 96 | / "login_serializer.py", 97 | base_dir_path / "modules" / "authentication" / "models" / "__init__.py", 98 | base_dir_path / "modules" / "authentication" / "models" / "auth_model.py", 99 | base_dir_path / "modules" / "authentication" / "views" / "__init__.py", 100 | base_dir_path / "modules" / "authentication" / "views" / "login.py", 101 | base_dir_path / "modules" / "authentication" / "urls.py", 102 | base_dir_path / "utils" / "__init__.py", 103 | base_dir_path / "tests" / "__init__.py", 104 | ] 105 | 106 | root_files = [ 107 | Path(".env.dev"), 108 | Path(".gitignore"), 109 | Path("requirements.txt"), 110 | ] 111 | 112 | if docker: 113 | log_with_color( 114 | logging.INFO, 115 | "\nConfiguring Docker...", 116 | Fore.WHITE, 117 | delay=2, 118 | ) 119 | docker_files = [ 120 | Path(".env.prod"), 121 | Path(".env.prod.db"), 122 | Path("Dockerfile"), 123 | Path("docker-compose.yml"), 124 | ] 125 | for file in docker_files: 126 | root_files.append(file) 127 | 128 | if api: 129 | log_with_color( 130 | logging.INFO, 131 | "\nConfiguring Django Rest Framework...", 132 | Fore.WHITE, 133 | delay=1, 134 | ) 135 | 136 | api_dir = [ 137 | base_dir_path / "modules" / "api", 138 | base_dir_path / "modules" / "api" / "models", 139 | base_dir_path / "modules" / "api" / "views", 140 | base_dir_path / "modules" / "api" / "serializers", 141 | ] 142 | for dir in api_dir: 143 | directories.append(dir) # Include API dirs 144 | 145 | api_files = [ 146 | base_dir_path / "modules" / "api" / "__init__.py", 147 | base_dir_path / "modules" / "api" / "serializers" / "__init__.py", 148 | base_dir_path / "modules" / "api" / "serializers" / "get_product.py", 149 | base_dir_path / "modules" / "api" / "models" / "__init__.py", 150 | base_dir_path / "modules" / "api" / "models" / "product_model.py", 151 | base_dir_path / "modules" / "api" / "views" / "__init__.py", 152 | base_dir_path / "modules" / "api" / "views" / "get_product.py", 153 | base_dir_path / "modules" / "api" / "urls.py", 154 | ] 155 | for file in api_files: 156 | project_files.append(file) 157 | 158 | log_with_color(logging.INFO, "Creating directories...", Fore.BLUE) 159 | create_dirs(directories) # Create dirs 160 | 161 | log_with_color(logging.INFO, "Almost ready...", Fore.YELLOW, delay=3) 162 | create_files(project_files + root_files) # Create files 163 | write(base_dir, project_name, api, docker, unfold) # Write files 164 | 165 | 166 | def write( 167 | base_dir: Path, 168 | project_name: str, 169 | api: bool = False, 170 | docker: bool = False, 171 | unfold: bool = False, 172 | ): 173 | """Function to write the content in each file of the project.""" 174 | log_with_color(logging.INFO, "Configuring files...", Fore.YELLOW, delay=3) 175 | 176 | base_dir_path = Path(base_dir) 177 | config_dir = base_dir_path / "config" 178 | bin_dir = base_dir_path / "bin" 179 | auth_module_dir = base_dir_path / "modules" / "authentication" 180 | 181 | files_to_write = [ 182 | ( 183 | config_dir / ".env.conf", 184 | "DJANGO_ENV=dev", 185 | ), # Development environment by default 186 | ( 187 | config_dir / "settings.py", 188 | settings_content.format(project_name=project_name), 189 | ), 190 | (config_dir / "settings_dev.py", settings_dev_content), 191 | (config_dir / "settings_prod.py", settings_prod_content), 192 | (config_dir / "wsgi.py", wsgi_content.format(project_name=project_name)), 193 | (config_dir / "asgi.py", asgi_content.format(project_name=project_name)), 194 | (config_dir / "urls.py", urls_content.format(project_name=project_name)), 195 | (bin_dir / "manage.py", manage_content), 196 | (auth_module_dir / "views" / "login.py", views_auth_content), 197 | (auth_module_dir / "urls.py", urls_auth_content), 198 | (Path("requirements.txt"), requirements_content), 199 | (Path(".gitignore"), gitignore_content), 200 | (Path(".env.dev"), env_dev_content.format(secret_key=generate_secret_key())), 201 | ] 202 | 203 | if api: 204 | files_to_write[6] = ( 205 | config_dir / "urls.py", 206 | urls_api_content.format(project_name=project_name), 207 | ) 208 | 209 | if docker: 210 | # Set production environment 211 | files_to_write[0] = ( 212 | config_dir / ".env.conf", 213 | "DJANGO_ENV=prod", 214 | ) 215 | 216 | docker_files = [ 217 | ( 218 | Path(".env.prod"), 219 | env_prod_content.format(secret_key=generate_secret_key()), 220 | ), 221 | (Path(".env.prod.db"), env_prod_db_content), 222 | (Path("Dockerfile"), dockerfile_content), 223 | (Path("docker-compose.yml"), dockercompose_content), 224 | ] 225 | for file in docker_files: 226 | files_to_write.append(file) 227 | 228 | for file_path, content in files_to_write: 229 | write_to_file(file_path, content) 230 | 231 | # settings_base.py 232 | settings_base_content = configure_settings_base(api, unfold) 233 | write_to_file(config_dir / "settings_base.py", settings_base_content) 234 | 235 | # sub-commands requirements.txt 236 | additional_requirements = configure_requirements(api, unfold) 237 | if additional_requirements: 238 | write_to_file(Path("requirements.txt"), additional_requirements, mode="a") 239 | 240 | 241 | def run(args): 242 | """Entry point for command 'project'.""" 243 | 244 | try: 245 | create_project( 246 | base_dir=args.base_dir, 247 | project_name=args.project_name, 248 | api=args.api, 249 | docker=args.docker, 250 | unfold=args.unfold, 251 | ) 252 | 253 | log_with_color(logging.INFO, "---- Project created successfully.", Fore.GREEN) 254 | 255 | log_with_color( 256 | logging.INFO, 257 | "\nIMPORTANT:\n", 258 | Fore.YELLOW, 259 | ) 260 | 261 | # Messages 262 | if args.docker: 263 | run_prod.run_prod_messages() 264 | else: 265 | run_dev.run_dev_messages() 266 | 267 | except Exception as e: 268 | error_message = "\nError while creating project" 269 | if f"{e}" != "None": 270 | error_message += f": {e}" 271 | 272 | log_with_color( 273 | logging.INFO, 274 | error_message, 275 | Fore.RED, 276 | ) 277 | -------------------------------------------------------------------------------- /docs/_build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Search - djpro 11 | 12 | 13 | 14 | 15 | 16 | 17 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | Contents 48 | 49 | 50 | 51 | 52 | 53 | Menu 54 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Expand 63 | 65 | 66 | 67 | 68 | 69 | Light mode 70 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Dark mode 85 | 87 | 88 | 89 | 90 | 91 | 92 | Auto light/dark, in light mode 93 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | Auto light/dark, in dark mode 110 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 137 | 138 | 139 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 152 | 155 | 156 | Skip to content 157 | 158 | 159 | 160 |
161 |
162 |
163 | 167 |
168 |
169 |
djpro
170 |
171 |
172 |
173 | 180 |
181 | 185 |
186 |
187 | 232 |
233 |
234 |
235 | 236 | 237 | 238 | 239 | Back to top 240 | 241 |
242 |
243 | 250 |
251 | 255 |
256 |
257 | 258 | 266 | 267 |
268 | 269 |
270 |
271 |
272 | 273 | 277 |
278 |
279 | 282 | Made with Sphinx and @pradyunsg's 283 | 284 | Furo 285 | 286 |
287 |
288 | 289 |
290 |
291 | 292 |
293 |
294 | 299 |
300 |
301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | -------------------------------------------------------------------------------- /docs/_build/html/_modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Overview: module code - djpro 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | 46 | Contents 47 | 48 | 49 | 50 | 51 | 52 | Menu 53 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Expand 62 | 64 | 65 | 66 | 67 | 68 | Light mode 69 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Dark mode 84 | 86 | 87 | 88 | 89 | 90 | 91 | Auto light/dark, in light mode 92 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | Auto light/dark, in dark mode 109 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 136 | 137 | 138 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 151 | 154 | 155 | Skip to content 156 | 157 | 158 | 159 |
160 |
161 |
162 | 166 |
167 |
168 |
djpro
169 |
170 |
171 |
172 | 179 |
180 | 184 |
185 |
186 | 231 |
232 |
233 |
234 | 235 | 236 | 237 | 238 | Back to top 239 | 240 |
241 |
242 | 249 |
250 | 254 |
255 | 269 |
270 |
271 | 272 | 276 |
277 |
278 | 281 | Made with Sphinx and @pradyunsg's 282 | 283 | Furo 284 | 285 |
286 |
287 | 288 |
289 |
290 | 291 |
292 |
293 | 298 |
299 |
300 | 301 | 302 | 303 | 304 | -------------------------------------------------------------------------------- /docs/_build/html/_modules/djpro/utils/django_utils.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | djpro.utils.django_utils - djpro 0.0.1 documentation 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | 46 | Contents 47 | 48 | 49 | 50 | 51 | 52 | Menu 53 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Expand 62 | 64 | 65 | 66 | 67 | 68 | Light mode 69 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Dark mode 84 | 86 | 87 | 88 | 89 | 90 | 91 | Auto light/dark, in light mode 92 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | Auto light/dark, in dark mode 109 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 136 | 137 | 138 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 151 | 154 | 155 | Skip to content 156 | 157 | 158 | 159 |
160 |
161 |
162 | 166 |
167 | 170 |
171 |
172 | 179 |
180 | 184 |
185 |
186 | 228 |
229 |
230 |
231 | 232 | 233 | 234 | 235 | Back to top 236 | 237 |
238 |
239 | 246 |
247 | 251 |
252 |
253 |

Source code for djpro.utils.django_utils

254 | from django.core.management.utils import get_random_secret_key
255 | 
256 | 
257 | 
258 | [docs] 259 | def generate_secret_key(): 260 | """Django predefined function to create the Django secret key. 261 | Return a 50 character random string usable as a SECRET_KEY setting value.""" 262 | return get_random_secret_key()
263 | 264 |
265 |
266 |
267 |
268 | 269 | 273 |
274 |
275 | 278 | Made with Sphinx and @pradyunsg's 279 | 280 | Furo 281 | 282 |
283 |
284 | 285 |
286 |
287 | 288 |
289 |
290 | 295 |
296 |
297 | 298 | 299 | 300 | 301 | -------------------------------------------------------------------------------- /docs/_build/html/unfold.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Unfold configuration - djpro 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | Contents 48 | 49 | 50 | 51 | 52 | 53 | Menu 54 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Expand 63 | 65 | 66 | 67 | 68 | 69 | Light mode 70 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Dark mode 85 | 87 | 88 | 89 | 90 | 91 | 92 | Auto light/dark, in light mode 93 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | Auto light/dark, in dark mode 110 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 137 | 138 | 139 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 152 | 155 | 156 | Skip to content 157 | 158 | 159 | 160 |
161 |
162 |
163 | 167 |
168 |
169 |
djpro
170 |
171 |
172 |
173 | 180 |
181 | 185 |
186 |
187 | 232 |
233 |
234 |
235 | 236 | 237 | 238 | 239 | Back to top 240 | 241 |
242 | 243 | 244 |
245 | 252 |
253 | 257 |
258 |
259 |
260 |

Unfold configuration

261 |

To include the Unfold custom theme for Django Admin Site, adds the --unfold option 262 | to the general djpro project creation command:

263 |
djpro project YOUR-PROJECT-NAME --unfold
264 | 
265 |
266 |
267 |

Note

268 |

Change YOUR-PROJECT-NAME to your project name. 269 | Find your unfold configuration in settings_base.

270 |
271 | 274 |
275 | 276 |
277 |
278 |
279 | 280 | 284 |
285 |
286 | 289 | Made with Sphinx and @pradyunsg's 290 | 291 | Furo 292 | 293 |
294 |
295 | 296 |
297 |
298 | 299 |
300 |
301 | 306 |
307 |
308 | 309 | 310 | 311 | 312 | --------------------------------------------------------------------------------