From c7c50741e992bbf7443b9ad27ce9fbd29269f99a Mon Sep 17 00:00:00 2001 From: Tobi DEGNON Date: Tue, 12 Dec 2023 11:23:55 +0100 Subject: [PATCH] move old docs stuff into new structure --- README.md | 7 + {docs/assets => assets}/cuzzy_demo.gif | Bin docs/_old_docs/deployment.md | 36 --- docs/_old_docs/documentation.md | 80 ------ docs/_old_docs/project.md | 123 ---------- docs/_old_docs/requirements.txt | 55 ----- docs/_old_docs/usage.md | 231 ------------------ docs/guides/Databases.md | 19 +- docs/guides/Deployment.md | 36 +++ docs/guides/Static and media files.md | 25 ++ docs/guides/Task queues and schedulers.md | 31 +++ .../Working around Fat models.md} | 0 docs/guides/Writing documentation.md | 80 ++++++ docs/{_old_docs => }/license.md | 0 docs/the-cli/Intro.md | 42 ++++ docs/the-cli/rm-migrations.md | 50 ++++ docs/the-cli/start-project.md | 179 ++++++++++++++ docs/the-cli/work.md | 32 +++ docs/the-cli/write-env.md | 25 ++ docs/tips and extra.md | 40 +++ docs/tips.md | 107 -------- 21 files changed, 565 insertions(+), 633 deletions(-) rename {docs/assets => assets}/cuzzy_demo.gif (100%) delete mode 100644 docs/_old_docs/deployment.md delete mode 100644 docs/_old_docs/documentation.md delete mode 100644 docs/_old_docs/project.md delete mode 100644 docs/_old_docs/requirements.txt delete mode 100644 docs/_old_docs/usage.md rename docs/{How to use this project.md => guides/Working around Fat models.md} (100%) rename docs/{_old_docs => }/license.md (100%) create mode 100644 docs/the-cli/Intro.md create mode 100644 docs/tips and extra.md delete mode 100644 docs/tips.md diff --git a/README.md b/README.md index 4b7e8cf..1fbedc7 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,13 @@ The cli also comes with [additional commands](https://tobi-de.github.io/fuzzy-co ![showcase gif](https://raw.githubusercontent.com/Tobi-De/fuzzy-couscous/main/docs/assets/cuzzy_demo.gif) + +## How to use this project + +very opinionated stuff + +choice are already made, give options but already pick something to start with. + ## Features - Django 4+ diff --git a/docs/assets/cuzzy_demo.gif b/assets/cuzzy_demo.gif similarity index 100% rename from docs/assets/cuzzy_demo.gif rename to assets/cuzzy_demo.gif diff --git a/docs/_old_docs/deployment.md b/docs/_old_docs/deployment.md deleted file mode 100644 index 50c599c..0000000 --- a/docs/_old_docs/deployment.md +++ /dev/null @@ -1,36 +0,0 @@ -This template was configured to simplify deployment on [caprover](https://caprover.com/), since that is what I use 99% of the time. - -!!! Quote - CapRover is an extremely easy to use app/database deployment & web server manager for your NodeJS, Python, PHP, ASP.NET, Ruby, MySQL, MongoDB, Postgres, WordPress (and etc...) applications! - - **Official site** - -CapRover is a self-hosted [PaaS](https://en.wikipedia.org/wiki/Platform_as_a_service) solution, think [heroku](https://www.heroku.com/) but on your own servers. -Nowadays, I tend to prefer PaaS solutions over manual deployment and configuration, as they are easy to use with little configuration to deploy most apps. -Software is usually quite a pain to deploy and even though I've gotten better at it over time, I'll always choose a managed solution over manual deployment. -Some other options than **CapRover** are: - -- [Dokku](https://dokku.com/) (self hosted) -- [Fly](https://fly.io/) (hosted) -- [Render](https://render.com/) (hosted) -- [Coolify](https://github.com/coollabsio/coolify) (self hosted) -- [DigitalOcean App Platform](https://www.digitalocean.com/products/app-platform) (hosted) -- [AWS Elastic Beanstalk](https://aws.amazon.com/elasticbeanstalk/) (hosted) -- [Btn](https://btn.dev/) (hosted and not ready yet) - -!!! Info - I recently discovered [django-simple-deploy](https://github.com/ehmatthes/django-simple-deploy) which can configure your django project for some of the alternatives to - caprover I listed above. - -I find that self-hosted solutions are generally cheaper than managed/hosted solutions, but I don't have much experience with managed solutions, -so I could be wrong, do your own research and if you can afford it, try them out to see what works best for you. - -After installing CaProver with the [getting started guide](https://caprover.com/docs/get-started.html), there is not much left to do, create a new application and in the section `deployment`. -configure your application using the third method `Method 3: Deploy from Github/Bitbucket/Gitlab`. - -!!! Info - If you use github, instead of entering your password directly into the `password` field, you can use a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token), - which is a more secure option. - -!!! Tip - Checkout [caprover automatic deploy](https://caprover.com/docs/deployment-methods.html#automatic-deploy-using-github-bitbucket-and-etc) to automate the deployment of your applications. diff --git a/docs/_old_docs/documentation.md b/docs/_old_docs/documentation.md deleted file mode 100644 index e190e47..0000000 --- a/docs/_old_docs/documentation.md +++ /dev/null @@ -1,80 +0,0 @@ -This template does not include a documentation setup, but it is very important for most projects (at least it should be) -to have a documentation site, especially if you are not working alone. Here are the options I would suggest for setting -up a documentation, recently I tend to favor the first one. - -- [Mkdocs](https://www.mkdocs.org/) with the [Material theme](https://squidfunk.github.io/mkdocs-material/getting-started/) -- [Sphinx](https://www.sphinx-doc.org/en/master/) with the [Furo theme](https://github.com/pradyunsg/furo) - -There is a chance that in the future I will include the docs directly in the template but for now here is a quick guide to -configure mkdocs with the material theme: - -### Installation and configurations - -Copy the configuration below into your `pyproject.toml` file under the `[tool.poetry.dependencies]` section. - -```toml -[tool.poetry.group.docs] -optional = true - -[tool.poetry.group.docs.dependencies] -mkdocs = "^1.4.2" -mkdocs-material = "^8.5.10" -mkdocs-material-extensions = "^1.1.1" -mkdocs-include-markdown-plugin = "3.9.1" -``` - -Install the new dependencies. - -```shell -poetry install --with docs -``` - -Create your new **mkdocs** site. - -```shell -mkdocs new . -``` - -Update the `mkdocs.yml` file to specify the **material** theme, your configuration should look like this: - -```yaml -site_name: My Docs # change this to the name of your project -theme: - name: material -``` - -Run the documentation site locally - -```shell -mkdocs serve -``` - -If you noticed, the dependencies added above via the section `[tool.poetry.group.docs.dependencies]` include more than just -mkdocs and the material theme, specifically : - -- [mkdocs-material-extensions](https://github.com/facelessuser/mkdocs-material-extensions): Markdown extension resources for MkDocs for Material -- [mkdocs-include-markdown-plugin](https://github.com/mondeja/mkdocs-include-markdown-plugin): Include other markdown files in your mkdocs site - -For a complete example of how I configure them in projects, see this [configuration file](https://github.com/Tobi-De/dj-shop-cart/blob/master/mkdocs.yml). - -### Deploy your documentation - -**Mkdocs** can turn your documentation into a static site that you can host anywhere, [netlify](https://www.netlify.com/), [github pages](https://pages.github.com/), etc. -To build your site, run the command below and you will have a new `site` directory at the root of your project: - -```shell -mkdocs build -``` - -This folder contains everything that is necessary to deploy your static site. - -If you choose the **github pages** route, you can automate the process with [github actions](https://github.com/features/actions), -the official **mkdocs-material** documentation explains [how to do it](https://squidfunk.github.io/mkdocs-material/publishing-your-site/). -To use github actions, you will probably need a `requirements.txt` file, you can generate one with only what is needed -to build the docs with the command below. - -```shell -poetry export -f requirements.txt --output docs/requirements.txt --without-hashes --only docs -``` - -Read the [mkdocs](https://www.mkdocs.org/) and [mkdocs-material](https://squidfunk.github.io/mkdocs-material/getting-started/) docs for more advanced configurations and details on what is possible. diff --git a/docs/_old_docs/project.md b/docs/_old_docs/project.md deleted file mode 100644 index 51a8197..0000000 --- a/docs/_old_docs/project.md +++ /dev/null @@ -1,123 +0,0 @@ -This page gives more details about the structure, layouts and packages used for the project template and therefore available -in your generated project. - - -## Login via email instead of username - -I completely removed the `username` field from the `User` model and replaced it with the `email` field as the user unique identifier. -This `email` field is what I configured as the login field via [django-allauth](https://github.com/pennersr/django-allauth). More often then not when I create a new django project -I need to use something other than the `username` field provided by django as the unique identifier of the user, and the `username` field -just becomes an annoyance to deal with. It is also more common nowadays for modern web and mobile applications to rely on a unique identifier -such as an email address or phone number instead of a username. -The project also includes [django-improved-user](https://django-improved-user.readthedocs.io/en/latest/index.html -) which replaces the common `first_name` and `last_name` used for user details with `full_name` -and the `short_name` fields. If you want to know the reasoning behind this, read the [project rationale]( -https://django-improved-user.readthedocs.io/en/latest/rationale.html). -Currently, the latest version of `django-improved-user` that works without problems is an alpha version (v2.0a2). This can be annoying -to deal with when updating dependencies, you can get the same result as I just described with the django-authtools package. - -!!! Note "Don't ask for what you don't need" - Make sure you need `first_name` - `last_name` or `short_name` - `full_name` before asking your users for this information. - - !!! Quote "[rezaid.co.uk](https://rezaid.co.uk/app-website-gdpr-compliant/)" - The less customer information you hold, the more your chances are of becoming [GDPR](https://gdpr-info.eu/art-5-gdpr/) compliant. - However, this does not mean that you let go of relevant data. It is important is to always ask: Do you need it? - If you ever decide you need them you can always request them later - -If on the other hand you don't agree with what I just wrote or for the particular project you are currently working on -my configuration doesn't work for you, removing django-improved-user should be an easy change. - -First update the `User` models to inherit from django `AbstractUser` instead of the django-improved-ser one. - -```python -# users/models.py - -from django.contrib.auth.models import AbstractUser - -class User(AbstractUser): - pass -``` - -Then delete the `forms.py`, `admin.py` and `migrations/0001_initial.py` files in the `users` app. -With that you should be good to go, if you want something a little more complete to start with you can grab some -code from the [cookiecutter-django users app](https://github.com/cookiecutter/cookiecutter-django/tree/master/%7B%7Bcookiecutter.project_slug%7D%7D/%7B%7Bcookiecutter.project_slug%7D%7D/users). - -## DjangoFastDev - -Occasionally you may see a `FastDevVariableDoesNotExist` error, this exception is thrown during template rendering -by [django-fastdev](https://github.com/boxed/django-fastdev) when you try to access a variable that is not defined in the context -context of the view associated with that template. This is intended to help you avoid typos and small errors that will -have you scratching your head for hours, read the project [readme](https://github.com/boxed/django-fastdev#django-fastdev) if you want more reasons -to why it make sense to use it. But since this can be annoying for some people, you can disable it by removing `django-fastdev` -entirely or by commenting out the *django-fastdev* application in the `settings.py` file. - -```python -THIRD_PARTY_APPS = [ - ... - # 'django_fastdev', -] -``` - -## Dependencies management - -If you are using poetry then you probably already knows what to do, using poetry is pretty straightforward and that's why I like it. -With poetry the simplest workflow looks something like this: - -```shell -poetry install -poetry add package_name -poetry remove package_name -``` - -!!! Note "Updating your dependencies" - I recommend the [poetry-plugin-up](https://github.com/MousaZeidBaker/poetry-plugin-up) to easily update your dependencies. - I used to include [poetryup](https://github.com/MousaZeidBaker/poetryup) in the project template, but that has been deprecated - in favor of the new [up plugin](https://github.com/MousaZeidBaker/poetryup). - -If on the other hand you choose to remove poetry using the [`cuzzy remove-poetry`](https://tobi-de.github.io/fuzzy-couscous/usage/#cuzzy-remove-poetry) and additionally -created a virtualenv with the `-c` option, then I've added a few things that might be useful to you. - -### The `pyproject.toml` file - -When I first started using poetry I thought this file was a poetry specific thing, but it turns out that it is not. The `pyproject.toml` file is a -python standard introduced to unify and simplify python project packaging and configurations. -The pip documentation gives much more details on this than I can cover here, so I will just link to it [here](https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml/). -A loot of tools in the python ecosystem support it and it seems this is what we are going to be using in the future so I've kept it. - -### Pip-tools - -When you run the `remove-poetry` with the `-c` option which create a virtual environment for you, you will also get [`pip-tools`](https://github.com/jazzband/pip-tools) and [`hatch`](https://github.com/pypa/hatch) installed. -Pip-tools is a set of tools to help you manage your dependencies. As the name suggests, it is based on pip. -The most basic workflow will look something like this: - -Add a new package in your `pyproject.toml` (or `requirements.ini` if you prefer) file and run `pip-compile` to generate a new `requirements.txt` file. -```shell -pip-tools compile -o requirements.txt pyproject.toml --resolver=backtracking -``` -The command also take an `--extra` option to specify dependencies groups, more infos on their [github readme](https://github.com/jazzband/pip-tools). - -```shell -pip-sync -``` -`pip-sync` will synchronize your virtual environment with the `requirements.txt` file, this means that any package in the virtual -environment that is not in the `requirements.txt` file will be removed. You can also just use a good old `python -m pip install -r requirements.txt` -to install the dependencies. - -### Hatch - -Installed at the same time as `pip-tools`, [Hatch](https://hatch.pypa.io/latest/) is the build system specified in the `pyproject.toml` file. Since you are probably -not going to package and publish your django project you don't really need it, but `pip-tools` does need a build system defined -to work. - -!!! Quote "Official hatch documentation" - Hatch is a modern, extensible Python project manager. - -Hatch does everything you need to manage a python project, dependencies, virtual environments, packaging, publishing, scripts, etc and it also uses -the `pyproject.toml` file. The one available after the `remove-poetry` command is a good base to start using hatch. - -Just run -```shell -hatch env create -``` - -Read the [hatch documentation](https://hatch.pypa.io/latest/) for more infos. diff --git a/docs/_old_docs/requirements.txt b/docs/_old_docs/requirements.txt deleted file mode 100644 index 2e2f958..0000000 --- a/docs/_old_docs/requirements.txt +++ /dev/null @@ -1,55 +0,0 @@ -anyio==4.0.0 ; python_version >= "3.10" and python_version < "4.0" -asgiref==3.7.2 ; python_version >= "3.10" and python_version < "4.0" -babel==2.13.1 ; python_version >= "3.10" and python_version < "4.0" -bracex==2.4 ; python_version >= "3.10" and python_version < "4.0" -cappa==0.13.1 ; python_version >= "3.10" and python_version < "4" -certifi==2023.11.17 ; python_version >= "3.10" and python_version < "4.0" -charset-normalizer==3.3.2 ; python_version >= "3.10" and python_version < "4.0" -click==8.1.7 ; python_version >= "3.10" and python_version < "4.0" -colorama==0.4.6 ; python_version >= "3.10" and python_version < "4.0" -dict-deep==4.1.2 ; python_version >= "3.10" and python_version < "4.0" -django==4.2.7 ; python_version >= "3.10" and python_version < "4.0" -exceptiongroup==1.1.3 ; python_version >= "3.10" and python_version < "3.11" -ghp-import==2.1.0 ; python_version >= "3.10" and python_version < "4.0" -h11==0.14.0 ; python_version >= "3.10" and python_version < "4.0" -honcho==1.1.0 ; python_version >= "3.10" and python_version < "4.0" -httpcore==1.0.2 ; python_version >= "3.10" and python_version < "4.0" -httpx==0.25.1 ; python_version >= "3.10" and python_version < "4.0" -hupper==1.12 ; python_version >= "3.10" and python_version < "4.0" -idna==3.4 ; python_version >= "3.10" and python_version < "4.0" -jinja2==3.1.2 ; python_version >= "3.10" and python_version < "4.0" -markdown-it-py==3.0.0 ; python_version >= "3.10" and python_version < "4.0" -markdown==3.5.1 ; python_version >= "3.10" and python_version < "4.0" -markupsafe==2.1.3 ; python_version >= "3.10" and python_version < "4.0" -mdurl==0.1.2 ; python_version >= "3.10" and python_version < "4.0" -mergedeep==1.3.4 ; python_version >= "3.10" and python_version < "4.0" -mkdocs-include-markdown-plugin==6.0.4 ; python_version >= "3.10" and python_version < "4.0" -mkdocs-material-extensions==1.3 ; python_version >= "3.10" and python_version < "4.0" -mkdocs-material==9.4.10 ; python_version >= "3.10" and python_version < "4.0" -mkdocs==1.5.3 ; python_version >= "3.10" and python_version < "4.0" -mypy-extensions==1.0.0 ; python_version >= "3.10" and python_version < "4" -packaging==23.2 ; python_version >= "3.10" and python_version < "4.0" -paginate==0.5.6 ; python_version >= "3.10" and python_version < "4.0" -pathspec==0.11.2 ; python_version >= "3.10" and python_version < "4.0" -platformdirs==3.11.0 ; python_version >= "3.10" and python_version < "4.0" -pygments==2.17.1 ; python_version >= "3.10" and python_version < "4.0" -pymdown-extensions==10.4 ; python_version >= "3.10" and python_version < "4.0" -python-dateutil==2.8.2 ; python_version >= "3.10" and python_version < "4.0" -python-dotenv==1.0.0 ; python_version >= "3.10" and python_version < "4.0" -pyyaml-env-tag==0.1 ; python_version >= "3.10" and python_version < "4.0" -pyyaml==6.0.1 ; python_version >= "3.10" and python_version < "4.0" -regex==2023.10.3 ; python_version >= "3.10" and python_version < "4.0" -requests==2.31.0 ; python_version >= "3.10" and python_version < "4.0" -rich==13.7.0 ; python_version >= "3.10" and python_version < "4.0" -setuptools==68.2.2 ; python_version >= "3.12" and python_version < "4.0" -six==1.16.0 ; python_version >= "3.10" and python_version < "4.0" -sniffio==1.3.0 ; python_version >= "3.10" and python_version < "4.0" -sqlparse==0.4.4 ; python_version >= "3.10" and python_version < "4.0" -tomli-w==1.0.0 ; python_version >= "3.10" and python_version < "4.0" -tomli==2.0.1 ; python_version >= "3.10" and python_version < "3.11" -typing-extensions==4.8.0 ; python_version >= "3.10" and python_version < "4" -typing-inspect==0.9.0 ; python_version >= "3.10" and python_version < "4" -tzdata==2023.3 ; python_version >= "3.10" and python_version < "4.0" and sys_platform == "win32" -urllib3==2.1.0 ; python_version >= "3.10" and python_version < "4.0" -watchdog==3.0.0 ; python_version >= "3.10" and python_version < "4.0" -wcmatch==8.5 ; python_version >= "3.10" and python_version < "4.0" diff --git a/docs/_old_docs/usage.md b/docs/_old_docs/usage.md deleted file mode 100644 index 0c4463d..0000000 --- a/docs/_old_docs/usage.md +++ /dev/null @@ -1,231 +0,0 @@ -This page describe how to use the all available commands. - -## Intro - -!!! Note -`fuzzy-couscous` is the name of the cli installed when you install this package but since it's a bit annoying to -type it every time, there is the short version `cuzzy` that you can use instead. -The short version is the one that is used throughout the documentation for the examples. - -Since this template -uses [django's startproject --template](https://docs.djangoproject.com/en/stable/ref/django-admin/#startproject), you -can -easily clone the project on your computer and generate a django project by using the command `django-admin` and -specifying the -`fuzzy-couscous/templates/project_name` folder as the template. The final command is a bit long, that's why I made this -[cli](https://en.wikipedia.org/wiki/Command-line_interface) to simplify the process. The cli command is installed -together with the package. - -??? Tip "Install the package" - - ```shell - pip install fuzzy-couscous --upgrade - ``` - -## `cuzzy` - -**Usage**: - -```console -$ cuzzy [OPTIONS] COMMAND [ARGS]... -``` - -**Options**: - -* `--install-completion`: Install completion for the current shell. -* `--show-completion`: Show completion for the current shell, to copy it or customize the installation. -* `--help`: Show the help message and exit. - -**Commands**: - -* `make`: Initialize a new django project. -* `remove-poetry`: Run this command to remove poetry as a dependency from your project. -* `work`: Run multiple commands in parallel. -* `write-env`: Update or create a .env file from a .env.template file. - -## `cuzzy make` - -Initialize a new django project. This template makes a lot of assumptions, if you want to make some adjustments to the -template -you can [fork the github repository](https://github.com/Tobi-De/fuzzy-couscous/fork) of this project and make your -changes in the `templates` folder, -you can then use the `--repo` option to specify your Github repository. - -??? Info "Custom repository" -Actually you don't need to fork my repository, you can use this command on any github repository hosting a django -project template -as long as the template is defined in a `templates` folder in the root of the repository. Basically, the github -repository -structure would look something like this: - - ```shell - . - ├── templates - │   └── project_name - ``` - -**Usage**: - -```console -$ cuzzy make [OPTIONS] PROJECT_NAME -``` - -!!! Info -The **authors** key of the `[tool.poetry]` section in the `pyproject.toml` is set using your git global user -configuration. -If you haven't set it -yet, [see this page](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup#_your_identity). - -**Arguments**: - -* `PROJECT_NAME`: [required] - -**Options**: - -* `-r, --repo TEXT`: The github repository to pull the template from. The format to use - is `username/repo` [default: Tobi-De/fuzzy-couscous] -* `-b, --branch [main|tailwind|bootstrap]`: The github branch to use. [default: main] -* `-s, --skip-install`: Skip dependencies installation. [default: False] -* `--help`: Show the help message and exit. - -## `cuzzy remove-poetry` - -Run this command to remove poetry as a dependency from your project, it updates your pyproject.toml -file to use [hatch](https://hatch.pypa.io/latest/) as the build system and can optionally create a virtual environment -using [virtualenv](https://github.com/pypa/virtualenv). -Hatch is a modern and extensible Python project manager, it can handle environment creation, package publishing, -versioning, etc, -everything you need to manage a python project, but here I chose to use it only as a build backend. -If you add the `--create-virtualenv` option, [pip-tools](https://github.com/jazzband/pip-tools) will be installed in the -created environment, -you can use it to manage your dependencies. -If you are familiar with hatch, you can easily complete the hatch configurations from the generated `pyproject.toml` -file -and use it instead of virtualenv to manage your project. - -!!! Info -The virtualenv is created using your global python interpreter. - -!!! Warning -Be sure to commit your changes before running this command, that way you can undo the changes if something goes -wrong or if you simply change your mind - -**Usage**: - -```console -$ cuzzy remove-poetry [OPTIONS] -``` - -**Options**: - -* `-c, --create-virtualenv`: Create an environment using virtualenv. [default: False] -* `--help`: Show the help message and exit. - -## `cuzzy work` - -This command allows you to run multiple commands simultaneously. Typically, when working with tailwind, you need to run -both the django `runserver` command and the tailwind `compile` command. This command uses the python package [honcho](https://github.com/nickstenning/honcho) to -manage multiple processes. By default, it runs the django server, a redis server (if `REDIS_URL` is in your environment -or `.env` file), the tailwind compile and watch command if `pytailwindcss` is listed as a dependency in -your `pyproject.toml` file. It also runs the qcluster command from django-q2 (if defined in your dependencies). -Additionally, if hupper is listed as a development dependency, it uses that to run the qcluster command.. -You can specify the commands to run in the `[tool.cuzzy]` section using the `work` key. If -you define a command with the same name as the default, it will override it. Here are the default commands: - -```toml -[tool.cuzzy] -work = { server = "python manage.py migrate && python manage.py runserver --nostatic", tailwind = "tailwindcss -i project_name/static/css/input.css -o project_name/static/css/output.css --watch", redis = "redis-server" } -``` -**Usage**: - -```console -$ cuzzy work [OPTIONS] -``` - -**Options**: - -* `--dry-run`: Display the list of commands without running them. [default: False] -* `--help`: Show the help message and exit. - -Can be configured via the `pyproject.toml` file. - -```toml -[tool.cuzzy] -work = { server = "python manage.py runserver --nostatic", "tailwind" = "poe t", "worker" = "python manage.py qcluster" } -``` - -## `cuzzy write-env` - -Running this will create a new `.env` by filling the file with the keys and values from the following options: - -1. a `env.template` file, used if it exists -2. a `DEFAULT_VALUES` dictionary, internal to the `fuzzy-couscous` package, contains some default for common - keys, `DJANGO_DEBUG`, `DJANGO_SECRET_KEY`, etc. -3. a `.env` file, used if it exists - -The order defines the priority of the values that are used, which means that the values contained in your -original `.env` file are preserved if the file exists. - -**Usage**: - -```console -$ cuzzy write-env [OPTIONS] -``` - -**Options**: - -* `-f, --fill-missing`: Prompt to fill missing values. [default: False] -* `-o, --output-file FILE`: The output file path. [default: .env] -* `-p, --postgres-pass`: Prompt for the postgres password to use to build the `DATABASE_URL`. -* `--help`: Show the help message and exit. - -## `cuzzy rm-migrations` - -!!! Note -This command was previously part of the generated project as a django management command, but I decided to move it to -the -`fuzzy-couscous` package since I'm probably the only one using it and I don't want to pollute the generated project with -unnecessary code. - -Remove all migrations for the specified applications directory, intended only for development. - -!!! Warning -This command will delete all your migrations files, be sure to commit your changes before running this command. - -**Usage**: - -```console -$ cuzzy rm-migrations [OPTIONS] APPS_DIR -``` - -**Arguments**: - -* `APPS_DIR`: The path to your django apps directory. [required] - -**Options**: - -* `-e, --exclude TEXT`: A file to exclude from the deletion. This option can be repeated. - -## `cuzzy htmx` - -Download the htmx javascript library or one of its extension if specified. You won't have to download htmx or its -extensions -often but at least if you need it, I think this is an easy way to get the file available locally. - -**Usage**: - -```console -$ cuzzy htmx [OPTIONS] VERSION -``` - -**Arguments**: - -* `VERSION`: The version of htmx to download. [default: latest] - -**Options**: - -* `-e, --extension TEXT`: The name of the extension to download. -* `-f, --output-file TEXT`: The filename for the htmx download. [default: htmx.min.js] -* `-d, --output-dir DIRECTORY`: The directory to write the downloaded file to, default to the current working directory. -* `-w, --web-types`: Download the web-types file. -* `--help`: Show the help message and exit. diff --git a/docs/guides/Databases.md b/docs/guides/Databases.md index 89e1263..fc7d341 100644 --- a/docs/guides/Databases.md +++ b/docs/guides/Databases.md @@ -1,7 +1,24 @@ ## Intro -## Backup +## django-pgtriggers + + +## Database backup + +Whenever possible, take advantage of a fully managed database solution, they usually offer automatic backup of your databases. +In my opinion, this is the best option if you don't want to deal with the hassle of managing your own database. + +- [Amazon RDS](https://aws.amazon.com/rds/) +- [Linode Managed Databases](https://www.linode.com/products/databases/) +- [DigitalOcean Managed Databases](https://www.digitalocean.com/products/managed-databases) +- [Heroku postgres](https://www.heroku.com/postgres) + +For specific postgresql options, see their [hosting support page](https://www.postgresql.org/support/professional_hosting/). + +However, if for some reason you want / need to manage your database yourself and just want an automatic backup solution +then [django-dbbackup](https://github.com/jazzband/django-dbbackup) is what you need. You can use one of the scheduling +packages discussed above to periodically run the backup command. ## Scaling strategies \ No newline at end of file diff --git a/docs/guides/Deployment.md b/docs/guides/Deployment.md index e69de29..50c599c 100644 --- a/docs/guides/Deployment.md +++ b/docs/guides/Deployment.md @@ -0,0 +1,36 @@ +This template was configured to simplify deployment on [caprover](https://caprover.com/), since that is what I use 99% of the time. + +!!! Quote + CapRover is an extremely easy to use app/database deployment & web server manager for your NodeJS, Python, PHP, ASP.NET, Ruby, MySQL, MongoDB, Postgres, WordPress (and etc...) applications! + + **Official site** + +CapRover is a self-hosted [PaaS](https://en.wikipedia.org/wiki/Platform_as_a_service) solution, think [heroku](https://www.heroku.com/) but on your own servers. +Nowadays, I tend to prefer PaaS solutions over manual deployment and configuration, as they are easy to use with little configuration to deploy most apps. +Software is usually quite a pain to deploy and even though I've gotten better at it over time, I'll always choose a managed solution over manual deployment. +Some other options than **CapRover** are: + +- [Dokku](https://dokku.com/) (self hosted) +- [Fly](https://fly.io/) (hosted) +- [Render](https://render.com/) (hosted) +- [Coolify](https://github.com/coollabsio/coolify) (self hosted) +- [DigitalOcean App Platform](https://www.digitalocean.com/products/app-platform) (hosted) +- [AWS Elastic Beanstalk](https://aws.amazon.com/elasticbeanstalk/) (hosted) +- [Btn](https://btn.dev/) (hosted and not ready yet) + +!!! Info + I recently discovered [django-simple-deploy](https://github.com/ehmatthes/django-simple-deploy) which can configure your django project for some of the alternatives to + caprover I listed above. + +I find that self-hosted solutions are generally cheaper than managed/hosted solutions, but I don't have much experience with managed solutions, +so I could be wrong, do your own research and if you can afford it, try them out to see what works best for you. + +After installing CaProver with the [getting started guide](https://caprover.com/docs/get-started.html), there is not much left to do, create a new application and in the section `deployment`. +configure your application using the third method `Method 3: Deploy from Github/Bitbucket/Gitlab`. + +!!! Info + If you use github, instead of entering your password directly into the `password` field, you can use a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token), + which is a more secure option. + +!!! Tip + Checkout [caprover automatic deploy](https://caprover.com/docs/deployment-methods.html#automatic-deploy-using-github-bitbucket-and-etc) to automate the deployment of your applications. diff --git a/docs/guides/Static and media files.md b/docs/guides/Static and media files.md index e69de29..4629ec2 100644 --- a/docs/guides/Static and media files.md +++ b/docs/guides/Static and media files.md @@ -0,0 +1,25 @@ + + + +## Media storage + +Media files in django usually refer to files uploaded by users, profile pictures, product images, etc. +I usually manage my media files using [django-storages](https://github.com/jschneier/django-storages). +Here is how I set it up. + +```python +# core/storages.py +from storages.backends.s3boto3 import S3Boto3Storage + +class MediaRootS3Boto3Storage(S3Boto3Storage): + location = "media" + file_overwrite = False + + +# settings.py - production settings +AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID") +AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY") +AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME") +DEFAULT_FILE_STORAGE = "project_name.core.storages.MediaRootS3Boto3Storage" +MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/" +``` \ No newline at end of file diff --git a/docs/guides/Task queues and schedulers.md b/docs/guides/Task queues and schedulers.md index e69de29..c465a88 100644 --- a/docs/guides/Task queues and schedulers.md +++ b/docs/guides/Task queues and schedulers.md @@ -0,0 +1,31 @@ +## Task queues and schedulers + +Task queues are used to offload tasks to a dedicated worker process when the processing of those tasks does not fit into a traditional request-response cycle. +Basically, if you need to do something that might take too long to process and whose result does not need to be shown immediately to the user, you use a queue manager. +Schedulers are used to periodically run tasks. +There are many options available in the [django third-party ecosystem](https://djangopackages.org/grids/g/workers-queues-tasks/), some focus solely on providing a task queue, +others are just schedulers and many of them provide both in one package. You can also search for purely python solutions and +integrate them into your django project yourself. + +I prefer options that do not require additional infrastructure (redis, rabbitmq, etc.) for simple tasks. +For more complex tasks, I tend to choose a solution that supports redis as a task broker. + +**Doesn't require setup of external tools, redis, rabbitmq, etc..** + +- [django-q2](https://github.com/GDay/django-q2) : Task queue + scheduler +- [django-chard](https://github.com/drpancake/chard) : Task queue +- [django-pgpubsub](https://github.com/Opus10/django-pgpubsub) : Task queue +- [procrastinate](https://github.com/procrastinate-org/procrastinate) : Task queue + scheduler +- [rocketry](https://github.com/Miksus/rocketry) : Scheduler + +**Require the setup of external tools, redis, rabbitmq, etc.** + +- [django-dramatiq](https://github.com/Bogdanp/django_dramatiq) : Task queue +- [django-rq](https://github.com/rq/django-rq) : Task queue + scheduler via [django-rq-scheduler](https://github.com/dsoftwareinc/django-rq-scheduler) +- [wakaq](https://github.com/wakatime/wakaq) : Task queue + scheduler + +!!! Note + The order matters, that's the order in which I would choose one of these packages. + +If you are using one of these you might want an automatic reload feature when files changes, you can use the `hupper` python +package for that purpose. If your project was generated with fuzzy-couscous then it is already declared as a dev dependencies. \ No newline at end of file diff --git a/docs/How to use this project.md b/docs/guides/Working around Fat models.md similarity index 100% rename from docs/How to use this project.md rename to docs/guides/Working around Fat models.md diff --git a/docs/guides/Writing documentation.md b/docs/guides/Writing documentation.md index e69de29..e190e47 100644 --- a/docs/guides/Writing documentation.md +++ b/docs/guides/Writing documentation.md @@ -0,0 +1,80 @@ +This template does not include a documentation setup, but it is very important for most projects (at least it should be) +to have a documentation site, especially if you are not working alone. Here are the options I would suggest for setting +up a documentation, recently I tend to favor the first one. + +- [Mkdocs](https://www.mkdocs.org/) with the [Material theme](https://squidfunk.github.io/mkdocs-material/getting-started/) +- [Sphinx](https://www.sphinx-doc.org/en/master/) with the [Furo theme](https://github.com/pradyunsg/furo) + +There is a chance that in the future I will include the docs directly in the template but for now here is a quick guide to +configure mkdocs with the material theme: + +### Installation and configurations + +Copy the configuration below into your `pyproject.toml` file under the `[tool.poetry.dependencies]` section. + +```toml +[tool.poetry.group.docs] +optional = true + +[tool.poetry.group.docs.dependencies] +mkdocs = "^1.4.2" +mkdocs-material = "^8.5.10" +mkdocs-material-extensions = "^1.1.1" +mkdocs-include-markdown-plugin = "3.9.1" +``` + +Install the new dependencies. + +```shell +poetry install --with docs +``` + +Create your new **mkdocs** site. + +```shell +mkdocs new . +``` + +Update the `mkdocs.yml` file to specify the **material** theme, your configuration should look like this: + +```yaml +site_name: My Docs # change this to the name of your project +theme: + name: material +``` + +Run the documentation site locally + +```shell +mkdocs serve +``` + +If you noticed, the dependencies added above via the section `[tool.poetry.group.docs.dependencies]` include more than just +mkdocs and the material theme, specifically : + +- [mkdocs-material-extensions](https://github.com/facelessuser/mkdocs-material-extensions): Markdown extension resources for MkDocs for Material +- [mkdocs-include-markdown-plugin](https://github.com/mondeja/mkdocs-include-markdown-plugin): Include other markdown files in your mkdocs site + +For a complete example of how I configure them in projects, see this [configuration file](https://github.com/Tobi-De/dj-shop-cart/blob/master/mkdocs.yml). + +### Deploy your documentation + +**Mkdocs** can turn your documentation into a static site that you can host anywhere, [netlify](https://www.netlify.com/), [github pages](https://pages.github.com/), etc. +To build your site, run the command below and you will have a new `site` directory at the root of your project: + +```shell +mkdocs build +``` + +This folder contains everything that is necessary to deploy your static site. + +If you choose the **github pages** route, you can automate the process with [github actions](https://github.com/features/actions), +the official **mkdocs-material** documentation explains [how to do it](https://squidfunk.github.io/mkdocs-material/publishing-your-site/). +To use github actions, you will probably need a `requirements.txt` file, you can generate one with only what is needed +to build the docs with the command below. + +```shell +poetry export -f requirements.txt --output docs/requirements.txt --without-hashes --only docs +``` + +Read the [mkdocs](https://www.mkdocs.org/) and [mkdocs-material](https://squidfunk.github.io/mkdocs-material/getting-started/) docs for more advanced configurations and details on what is possible. diff --git a/docs/_old_docs/license.md b/docs/license.md similarity index 100% rename from docs/_old_docs/license.md rename to docs/license.md diff --git a/docs/the-cli/Intro.md b/docs/the-cli/Intro.md new file mode 100644 index 0000000..85fc28c --- /dev/null +++ b/docs/the-cli/Intro.md @@ -0,0 +1,42 @@ +## Intro + +!!! Note +`fuzzy-couscous` is the name of the cli installed when you install this package but since it's a bit annoying to +type it every time, there is the short version `cuzzy` that you can use instead. +The short version is the one that is used throughout the documentation for the examples. + +Since this template +uses [django's startproject --template](https://docs.djangoproject.com/en/stable/ref/django-admin/#startproject), you +can +easily clone the project on your computer and generate a django project by using the command `django-admin` and +specifying the +`fuzzy-couscous/templates/project_name` folder as the template. The final command is a bit long, that's why I made this +[cli](https://en.wikipedia.org/wiki/Command-line_interface) to simplify the process. The cli command is installed +together with the package. + +??? Tip "Install the package" + + ```shell + pip install fuzzy-couscous --upgrade + ``` + +## `cuzzy` + +**Usage**: + +```console +$ cuzzy [OPTIONS] COMMAND [ARGS]... +``` + +**Options**: + +* `--install-completion`: Install completion for the current shell. +* `--show-completion`: Show completion for the current shell, to copy it or customize the installation. +* `--help`: Show the help message and exit. + +**Commands**: + +* `make`: Initialize a new django project. +* `remove-poetry`: Run this command to remove poetry as a dependency from your project. +* `work`: Run multiple commands in parallel. +* `write-env`: Update or create a .env file from a .env.template file. \ No newline at end of file diff --git a/docs/the-cli/rm-migrations.md b/docs/the-cli/rm-migrations.md index e69de29..a62fd8d 100644 --- a/docs/the-cli/rm-migrations.md +++ b/docs/the-cli/rm-migrations.md @@ -0,0 +1,50 @@ +## `cuzzy rm-migrations` + +!!! Note +This command was previously part of the generated project as a django management command, but I decided to move it to +the +`fuzzy-couscous` package since I'm probably the only one using it and I don't want to pollute the generated project with +unnecessary code. + +Remove all migrations for the specified applications directory, intended only for development. + +!!! Warning +This command will delete all your migrations files, be sure to commit your changes before running this command. + +**Usage**: + +```console +$ cuzzy rm-migrations [OPTIONS] APPS_DIR +``` + +**Arguments**: + +* `APPS_DIR`: The path to your django apps directory. [required] + +**Options**: + +* `-e, --exclude TEXT`: A file to exclude from the deletion. This option can be repeated. + +## `cuzzy htmx` + +Download the htmx javascript library or one of its extension if specified. You won't have to download htmx or its +extensions +often but at least if you need it, I think this is an easy way to get the file available locally. + +**Usage**: + +```console +$ cuzzy htmx [OPTIONS] VERSION +``` + +**Arguments**: + +* `VERSION`: The version of htmx to download. [default: latest] + +**Options**: + +* `-e, --extension TEXT`: The name of the extension to download. +* `-f, --output-file TEXT`: The filename for the htmx download. [default: htmx.min.js] +* `-d, --output-dir DIRECTORY`: The directory to write the downloaded file to, default to the current working directory. +* `-w, --web-types`: Download the web-types file. +* `--help`: Show the help message and exit. diff --git a/docs/the-cli/start-project.md b/docs/the-cli/start-project.md index e69de29..5e7208b 100644 --- a/docs/the-cli/start-project.md +++ b/docs/the-cli/start-project.md @@ -0,0 +1,179 @@ +Talk a bit about project management + + +why I choose Hatch + + + +This page gives more details about the structure, layouts and packages used for the project template and therefore available +in your generated project. + + + + +## `cuzzy make` + +Initialize a new django project. This template makes a lot of assumptions, if you want to make some adjustments to the +template +you can [fork the github repository](https://github.com/Tobi-De/fuzzy-couscous/fork) of this project and make your +changes in the `templates` folder, +you can then use the `--repo` option to specify your Github repository. + +??? Info "Custom repository" +Actually you don't need to fork my repository, you can use this command on any github repository hosting a django +project template +as long as the template is defined in a `templates` folder in the root of the repository. Basically, the github +repository +structure would look something like this: + + ```shell + . + ├── templates + │   └── project_name + ``` + +**Usage**: + +```console +$ cuzzy make [OPTIONS] PROJECT_NAME +``` + +!!! Info +The **authors** key of the `[tool.poetry]` section in the `pyproject.toml` is set using your git global user +configuration. +If you haven't set it +yet, [see this page](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup#_your_identity). + +**Arguments**: + +* `PROJECT_NAME`: [required] + +**Options**: + +* `-r, --repo TEXT`: The github repository to pull the template from. The format to use + is `username/repo` [default: Tobi-De/fuzzy-couscous] +* `-b, --branch [main|tailwind|bootstrap]`: The github branch to use. [default: main] +* `-s, --skip-install`: Skip dependencies installation. [default: False] +* `--help`: Show the help message and exit. + + + +## Login via email instead of username + +I completely removed the `username` field from the `User` model and replaced it with the `email` field as the user unique identifier. +This `email` field is what I configured as the login field via [django-allauth](https://github.com/pennersr/django-allauth). More often then not when I create a new django project +I need to use something other than the `username` field provided by django as the unique identifier of the user, and the `username` field +just becomes an annoyance to deal with. It is also more common nowadays for modern web and mobile applications to rely on a unique identifier +such as an email address or phone number instead of a username. +The project also includes [django-improved-user](https://django-improved-user.readthedocs.io/en/latest/index.html +) which replaces the common `first_name` and `last_name` used for user details with `full_name` +and the `short_name` fields. If you want to know the reasoning behind this, read the [project rationale]( +https://django-improved-user.readthedocs.io/en/latest/rationale.html). +Currently, the latest version of `django-improved-user` that works without problems is an alpha version (v2.0a2). This can be annoying +to deal with when updating dependencies, you can get the same result as I just described with the django-authtools package. + +!!! Note "Don't ask for what you don't need" + Make sure you need `first_name` - `last_name` or `short_name` - `full_name` before asking your users for this information. + + !!! Quote "[rezaid.co.uk](https://rezaid.co.uk/app-website-gdpr-compliant/)" + The less customer information you hold, the more your chances are of becoming [GDPR](https://gdpr-info.eu/art-5-gdpr/) compliant. + However, this does not mean that you let go of relevant data. It is important is to always ask: Do you need it? + If you ever decide you need them you can always request them later + +If on the other hand you don't agree with what I just wrote or for the particular project you are currently working on +my configuration doesn't work for you, removing django-improved-user should be an easy change. + +First update the `User` models to inherit from django `AbstractUser` instead of the django-improved-ser one. + +```python +# users/models.py + +from django.contrib.auth.models import AbstractUser + +class User(AbstractUser): + pass +``` + +Then delete the `forms.py`, `admin.py` and `migrations/0001_initial.py` files in the `users` app. +With that you should be good to go, if you want something a little more complete to start with you can grab some +code from the [cookiecutter-django users app](https://github.com/cookiecutter/cookiecutter-django/tree/master/%7B%7Bcookiecutter.project_slug%7D%7D/%7B%7Bcookiecutter.project_slug%7D%7D/users). + +## DjangoFastDev + +Occasionally you may see a `FastDevVariableDoesNotExist` error, this exception is thrown during template rendering +by [django-fastdev](https://github.com/boxed/django-fastdev) when you try to access a variable that is not defined in the context +context of the view associated with that template. This is intended to help you avoid typos and small errors that will +have you scratching your head for hours, read the project [readme](https://github.com/boxed/django-fastdev#django-fastdev) if you want more reasons +to why it make sense to use it. But since this can be annoying for some people, you can disable it by removing `django-fastdev` +entirely or by commenting out the *django-fastdev* application in the `settings.py` file. + +```python +THIRD_PARTY_APPS = [ + ... + # 'django_fastdev', +] +``` + +## Dependencies management + +If you are using poetry then you probably already knows what to do, using poetry is pretty straightforward and that's why I like it. +With poetry the simplest workflow looks something like this: + +```shell +poetry install +poetry add package_name +poetry remove package_name +``` + +!!! Note "Updating your dependencies" + I recommend the [poetry-plugin-up](https://github.com/MousaZeidBaker/poetry-plugin-up) to easily update your dependencies. + I used to include [poetryup](https://github.com/MousaZeidBaker/poetryup) in the project template, but that has been deprecated + in favor of the new [up plugin](https://github.com/MousaZeidBaker/poetryup). + +If on the other hand you choose to remove poetry using the [`cuzzy remove-poetry`](https://tobi-de.github.io/fuzzy-couscous/usage/#cuzzy-remove-poetry) and additionally +created a virtualenv with the `-c` option, then I've added a few things that might be useful to you. + +### The `pyproject.toml` file + +When I first started using poetry I thought this file was a poetry specific thing, but it turns out that it is not. The `pyproject.toml` file is a +python standard introduced to unify and simplify python project packaging and configurations. +The pip documentation gives much more details on this than I can cover here, so I will just link to it [here](https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml/). +A loot of tools in the python ecosystem support it and it seems this is what we are going to be using in the future so I've kept it. + +### Pip-tools + +When you run the `remove-poetry` with the `-c` option which create a virtual environment for you, you will also get [`pip-tools`](https://github.com/jazzband/pip-tools) and [`hatch`](https://github.com/pypa/hatch) installed. +Pip-tools is a set of tools to help you manage your dependencies. As the name suggests, it is based on pip. +The most basic workflow will look something like this: + +Add a new package in your `pyproject.toml` (or `requirements.ini` if you prefer) file and run `pip-compile` to generate a new `requirements.txt` file. +```shell +pip-tools compile -o requirements.txt pyproject.toml --resolver=backtracking +``` +The command also take an `--extra` option to specify dependencies groups, more infos on their [github readme](https://github.com/jazzband/pip-tools). + +```shell +pip-sync +``` +`pip-sync` will synchronize your virtual environment with the `requirements.txt` file, this means that any package in the virtual +environment that is not in the `requirements.txt` file will be removed. You can also just use a good old `python -m pip install -r requirements.txt` +to install the dependencies. + +### Hatch + +Installed at the same time as `pip-tools`, [Hatch](https://hatch.pypa.io/latest/) is the build system specified in the `pyproject.toml` file. Since you are probably +not going to package and publish your django project you don't really need it, but `pip-tools` does need a build system defined +to work. + +!!! Quote "Official hatch documentation" + Hatch is a modern, extensible Python project manager. + +Hatch does everything you need to manage a python project, dependencies, virtual environments, packaging, publishing, scripts, etc and it also uses +the `pyproject.toml` file. The one available after the `remove-poetry` command is a good base to start using hatch. + +Just run +```shell +hatch env create +``` + +Read the [hatch documentation](https://hatch.pypa.io/latest/) for more infos. diff --git a/docs/the-cli/work.md b/docs/the-cli/work.md index e69de29..141f84f 100644 --- a/docs/the-cli/work.md +++ b/docs/the-cli/work.md @@ -0,0 +1,32 @@ +## `cuzzy work` + +This command allows you to run multiple commands simultaneously. Typically, when working with tailwind, you need to run +both the django `runserver` command and the tailwind `compile` command. This command uses the python package [honcho](https://github.com/nickstenning/honcho) to +manage multiple processes. By default, it runs the django server, a redis server (if `REDIS_URL` is in your environment +or `.env` file), the tailwind compile and watch command if `pytailwindcss` is listed as a dependency in +your `pyproject.toml` file. It also runs the qcluster command from django-q2 (if defined in your dependencies). +Additionally, if hupper is listed as a development dependency, it uses that to run the qcluster command.. +You can specify the commands to run in the `[tool.cuzzy]` section using the `work` key. If +you define a command with the same name as the default, it will override it. Here are the default commands: + +```toml +[tool.cuzzy] +work = { server = "python manage.py migrate && python manage.py runserver --nostatic", tailwind = "tailwindcss -i project_name/static/css/input.css -o project_name/static/css/output.css --watch", redis = "redis-server" } +``` +**Usage**: + +```console +$ cuzzy work [OPTIONS] +``` + +**Options**: + +* `--dry-run`: Display the list of commands without running them. [default: False] +* `--help`: Show the help message and exit. + +Can be configured via the `pyproject.toml` file. + +```toml +[tool.cuzzy] +work = { server = "python manage.py runserver --nostatic", "tailwind" = "poe t", "worker" = "python manage.py qcluster" } +``` \ No newline at end of file diff --git a/docs/the-cli/write-env.md b/docs/the-cli/write-env.md index e69de29..d94f01b 100644 --- a/docs/the-cli/write-env.md +++ b/docs/the-cli/write-env.md @@ -0,0 +1,25 @@ + +## `cuzzy write-env` + +Running this will create a new `.env` by filling the file with the keys and values from the following options: + +1. a `env.template` file, used if it exists +2. a `DEFAULT_VALUES` dictionary, internal to the `fuzzy-couscous` package, contains some default for common + keys, `DJANGO_DEBUG`, `DJANGO_SECRET_KEY`, etc. +3. a `.env` file, used if it exists + +The order defines the priority of the values that are used, which means that the values contained in your +original `.env` file are preserved if the file exists. + +**Usage**: + +```console +$ cuzzy write-env [OPTIONS] +``` + +**Options**: + +* `-f, --fill-missing`: Prompt to fill missing values. [default: False] +* `-o, --output-file FILE`: The output file path. [default: .env] +* `-p, --postgres-pass`: Prompt for the postgres password to use to build the `DATABASE_URL`. +* `--help`: Show the help message and exit. \ No newline at end of file diff --git a/docs/tips and extra.md b/docs/tips and extra.md new file mode 100644 index 0000000..c9a473b --- /dev/null +++ b/docs/tips and extra.md @@ -0,0 +1,40 @@ +This section gathers tips, **copy and paste** configurations and package recommendations that I use quite often in my projects to solve specific problems. + +Stuff too short to deserve a full guide or I don't know where to put them + +## Understanding django Settings + +If there is a setting in `settings.py` or elsewhere that you don't understand, go to the [official django settings reference page](https://docs.djangoproject.com/en/dev/ref/settings/) +and press Ctrl + F to search for it. I used the [django-production](https://github.com/lincolnloop/django-production) package to configure the production settings which I then customized. +I have removed the package as a dependency, but I advise you to go and check for yourself what is available. + + + +## Health check your django project + +**Health check** is about making sure that your django application and related services are always available / running. +My go-to package for this is [django-health-check](https://github.com/revsys/django-health-check). +After installing and configuring **django-health-check**, you need to associate it with an uptime monitoring service, this +is the service that will periodically call your **health-check** endpoint to make sure everything is fine. +Here is a list of available options. + +- [upptime](https://github.com/upptime/upptime) +- [uptime-kuma](https://github.com/louislam/uptime-kuma) +- [uptimerobot](https://uptimerobot.com/) +- [better-uptime](https://betterstack.com/better-uptime) +- [glitchtip](https://glitchtip.com/) + +Read more on the health check pattern [here](https://learn.microsoft.com/en-us/azure/architecture/patterns/health-endpoint-monitoring). + + +## Lifecycle not signals + + +## Avoid huge apps for large projects + + +## Extra that I haven't tried myself yet + +- [django-linear-migrations](https://github.com/adamchainz/django-linear-migrations): Read [introduction post](https://adamj.eu/tech/2020/12/10/introducing-django-linear-migrations/) +- [django-read-only](https://github.com/adamchainz/django-read-only): Disable Django database writes. + diff --git a/docs/tips.md b/docs/tips.md deleted file mode 100644 index 223849f..0000000 --- a/docs/tips.md +++ /dev/null @@ -1,107 +0,0 @@ -This section gathers tips, **copy and paste** configurations and package recommendations that I use quite often in my projects to solve specific problems. - -## Settings - -If there is a setting in `settings.py` or elsewhere that you don't understand, go to the [official django settings reference page](https://docs.djangoproject.com/en/dev/ref/settings/) -and press Ctrl + F to search for it. I used the [django-production](https://github.com/lincolnloop/django-production) package to configure the production settings which I then customized. -I have removed the package as a dependency, but I advise you to go and check for yourself what is available. - -## Dynamic web pages - -[HTMX](https://htmx.org/) for simple interactive elements, [django-unicorn](https://github.com/adamghill/django-unicorn) if I need something more integrated with django. -It's not a binary choice, you can use both, the main advantage for me is the simplicity compared to a frontend javascript framework. - -!!! Note - If you use [htmx boost](https://htmx.org/docs/#boosting) + [debug toolbar](https://github.com/jazzband/django-debug-toolbar) (already included in the template), you will need [this](https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#htmx). - -## Task queues and schedulers - -Task queues are used to offload tasks to a dedicated worker process when the processing of those tasks does not fit into a traditional request-response cycle. -Basically, if you need to do something that might take too long to process and whose result does not need to be shown immediately to the user, you use a queue manager. -Schedulers are used to periodically run tasks. -There are many options available in the [django third-party ecosystem](https://djangopackages.org/grids/g/workers-queues-tasks/), some focus solely on providing a task queue, -others are just schedulers and many of them provide both in one package. You can also search for purely python solutions and -integrate them into your django project yourself. - -I prefer options that do not require additional infrastructure (redis, rabbitmq, etc.) for simple tasks. -For more complex tasks, I tend to choose a solution that supports redis as a task broker. - -**Doesn't require setup of external tools, redis, rabbitmq, etc..** - -- [django-q2](https://github.com/GDay/django-q2) : Task queue + scheduler -- [django-chard](https://github.com/drpancake/chard) : Task queue -- [django-pgpubsub](https://github.com/Opus10/django-pgpubsub) : Task queue -- [procrastinate](https://github.com/procrastinate-org/procrastinate) : Task queue + scheduler -- [rocketry](https://github.com/Miksus/rocketry) : Scheduler - -**Require the setup of external tools, redis, rabbitmq, etc.** - -- [django-dramatiq](https://github.com/Bogdanp/django_dramatiq) : Task queue -- [django-rq](https://github.com/rq/django-rq) : Task queue + scheduler via [django-rq-scheduler](https://github.com/dsoftwareinc/django-rq-scheduler) -- [wakaq](https://github.com/wakatime/wakaq) : Task queue + scheduler - -!!! Note - The order matters, that's the order in which I would choose one of these packages. - -If you are using one of these you might want an automatic reload feature when files changes, you can use the `hupper` python -package for that purpose. If your project was generated with fuzzy-couscous then it is already declared as a dev dependencies. - -## Media storage - -Media files in django usually refer to files uploaded by users, profile pictures, product images, etc. -I usually manage my media files using [django-storages](https://github.com/jschneier/django-storages). -Here is how I set it up. - -```python -# core/storages.py -from storages.backends.s3boto3 import S3Boto3Storage - -class MediaRootS3Boto3Storage(S3Boto3Storage): - location = "media" - file_overwrite = False - - -# settings.py - production settings -AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID") -AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY") -AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME") -DEFAULT_FILE_STORAGE = "project_name.core.storages.MediaRootS3Boto3Storage" -MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/" -``` - -## Database backup - -Whenever possible, take advantage of a fully managed database solution, they usually offer automatic backup of your databases. -In my opinion, this is the best option if you don't want to deal with the hassle of managing your own database. - -- [Amazon RDS](https://aws.amazon.com/rds/) -- [Linode Managed Databases](https://www.linode.com/products/databases/) -- [DigitalOcean Managed Databases](https://www.digitalocean.com/products/managed-databases) -- [Heroku postgres](https://www.heroku.com/postgres) - -For specific postgresql options, see their [hosting support page](https://www.postgresql.org/support/professional_hosting/). - -However, if for some reason you want / need to manage your database yourself and just want an automatic backup solution -then [django-dbbackup](https://github.com/jazzband/django-dbbackup) is what you need. You can use one of the scheduling -packages discussed above to periodically run the backup command. - -## Health check your django project - -**Health check** is about making sure that your django application and related services are always available / running. -My go-to package for this is [django-health-check](https://github.com/revsys/django-health-check). -After installing and configuring **django-health-check**, you need to associate it with an uptime monitoring service, this -is the service that will periodically call your **health-check** endpoint to make sure everything is fine. -Here is a list of available options. - -- [upptime](https://github.com/upptime/upptime) -- [uptime-kuma](https://github.com/louislam/uptime-kuma) -- [uptimerobot](https://uptimerobot.com/) -- [better-uptime](https://betterstack.com/better-uptime) -- [glitchtip](https://glitchtip.com/) - -Read more on the health check pattern [here](https://learn.microsoft.com/en-us/azure/architecture/patterns/health-endpoint-monitoring). - -## Extra that I haven't tried myself yet - -- [django-linear-migrations](https://github.com/adamchainz/django-linear-migrations): Read [introduction post](https://adamj.eu/tech/2020/12/10/introducing-django-linear-migrations/) -- [django-read-only](https://github.com/adamchainz/django-read-only): Disable Django database writes.