[
  {
    "path": ".editorconfig",
    "content": "# http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.{py,rst,ini}]\nindent_style = space\nindent_size = 4\n\n[*.{html,css,scss,json,yml,xml,toml}]\nindent_style = space\nindent_size = 2\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[Makefile]\nindent_style = tab\n\n[nginx.conf]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\n"
  },
  {
    "path": ".github/CONTRIBUTORS-template.md",
    "content": "# Contributors\n\n## Core Developers\n\nThese contributors have commit flags for the repository, and are able to\naccept and merge pull requests.\n\n<table>\n  <tr>\n    <th>Name</th>\n    <th>Github</th>\n    <th>Twitter</th>\n  </tr>\n  {%- for contributor in core_contributors %}\n  <tr>\n    <td>{{ contributor.name }}</td>\n    <td>\n      <a href=\"https://github.com/{{ contributor.github_login }}\">{{ contributor.github_login }}</a>\n    </td>\n    <td>{{ contributor.twitter_username }}</td>\n  </tr>\n  {%- endfor %}\n</table>\n\n_Audrey is also the creator of Cookiecutter. Audrey and Daniel are on\nthe Cookiecutter core team._\n\n## Other Contributors\n\nListed in alphabetical order.\n\n<table>\n  <tr>\n    <th>Name</th>\n    <th>Github</th>\n    <th>Twitter</th>\n  </tr>\n  {%- for contributor in other_contributors %}\n  <tr>\n    <td>{{ contributor.name }}</td>\n    <td>\n      <a href=\"https://github.com/{{ contributor.github_login }}\">{{ contributor.github_login }}</a>\n    </td>\n    <td>{{ contributor.twitter_username }}</td>\n  </tr>\n  {%- endfor %}\n</table>\n\n### Special Thanks\n\nThe following haven't provided code directly, but have provided\nguidance and advice.\n\n- Jannis Leidel\n- Nate Aune\n- Barry Morrison\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [pydanny, browniebroke, luzfcb]\npatreon: feldroy\nopen_collective: cookiecutter-django\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug.md",
    "content": "---\nname: Bug Report\nabout: Report a bug\nlabels: bug\n---\n\n## What happened?\n\n## What should've happened instead?\n\n## Additional details\n\n<!-- To assist you best, please include commands that you've run, options you've selected and any relevant logs -->\n\n- Host system configuration:\n  - Version of cookiecutter CLI (get it with `cookiecutter --version`):\n  - OS name and version:\n\n    On Linux, run\n\n    ```bash\n    lsb_release -a 2> /dev/null || cat /etc/redhat-release 2> /dev/null || cat /etc/*-release 2> /dev/null || cat /etc/issue 2> /dev/null\n    ```\n\n    On MacOs, run\n\n    ```bash\n    sw_vers\n    ```\n\n    On Windows, via CMD, run\n\n    ```\n    systeminfo | findstr /B /C:\"OS Name\" /C:\"OS Version\"\n    ```\n\n    ```bash\n    # Insert here the OS name and version\n\n    ```\n\n  - Python version, run `python3 -V`:\n  - Docker version (if using Docker), run `docker --version`:\n  - docker compose version (if using Docker), run `docker compose --version`:\n  - ...\n\n- Options selected and/or [replay file](https://cookiecutter.readthedocs.io/en/latest/advanced/replay.html):\n  On Linux and macOS: `cat ${HOME}/.cookiecutter_replay/cookiecutter-django.json`\n  (Please, take care to remove sensitive information)\n\n```json\n\n```\n\n<summary>\nLogs:\n<details>\n<pre>\n$ cookiecutter https://github.com/cookiecutter/cookiecutter-django\nproject_name [Project Name]: ...\n</pre>\n</details>\n</summary>\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature.md",
    "content": "---\nname: New Feature Proposal\nabout: Propose a new feature\nlabels: enhancement\n---\n\n## Description\n\nWhat are you proposing? How should it be implemented?\n\n## Rationale\n\nWhy should this feature be implemented?\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/paid-support.md",
    "content": "---\nname: Paid Support Request\nabout: Ask Core Team members to help you out\n---\n\nProvided your question goes beyond [regular support](https://github.com/cookiecutter/cookiecutter-django/issues/new?template=question.md), and/or the task at hand is of timely/high priority nature use the below information to reach out for contributors directly.\n\n- Bruno Alla, Core Developer ([GitHub](https://github.com/sponsors/browniebroke)).\n\n- Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB.\n\n- Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "content": "---\nname: Question\nabout: Please ask your question on StackOverflow, Discord or GitHub Discussions.\nlabels: question\n---\n\nFirst, make sure to examine [the docs](https://cookiecutter-django.readthedocs.io/en/latest/). If that doesn't help, we recommend one of these 3 main channels:\n\n- If your issue is related to Django + something else but was generated with cookiecutter-django, the best is to post a question on [StackOverflow](https://stackoverflow.com/questions/tagged/cookiecutter-django) tagged with `cookiecutter-django`, you would get more visibility from other communities as well.\n- Join us on [Discord](https://discord.gg/uFXweDQc5a) and ask around.\n- Start [a discussion](https://github.com/cookiecutter/cookiecutter-django/discussions) on our project's GitHub.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!-- Thank you for helping us out: your efforts mean a great deal to the project and the community as a whole! -->\n\n## Description\n\n<!-- What's it you're proposing? -->\n\nChecklist:\n\n- [ ] I've made sure that tests are updated accordingly (especially if adding or updating a template option)\n- [ ] I've updated the documentation or confirm that my change doesn't require any updates\n\n## Rationale\n\n<!--\nWhy does this project need the change you're proposing?\nIf this pull request fixes an open issue, don't forget to link it with `Fix #NNNN`\n-->\n"
  },
  {
    "path": ".github/changelog-template.md",
    "content": "{%- for change_type, pulls in grouped_pulls.items() %}\n{%- if pulls %}\n\n### {{ change_type }}\n\n{%- for pull_request in pulls %}\n\n- {{ pull_request.title }} ([#{{ pull_request.number }}]({{ pull_request.html_url }}))\n  {%- endfor -%}\n  {% endif -%}\n  {% endfor -%}\n"
  },
  {
    "path": ".github/contributors.json",
    "content": "[\n  {\n    \"name\": \"Daniel Roy Greenfeld\",\n    \"github_login\": \"pydanny\",\n    \"twitter_username\": \"pydanny\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"Audrey Roy Greenfeld\",\n    \"github_login\": \"audreyr\",\n    \"twitter_username\": \"audreyr\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"Fábio C. Barrionuevo da Luz\",\n    \"github_login\": \"luzfcb\",\n    \"twitter_username\": \"luzfcb\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"Saurabh Kumar\",\n    \"github_login\": \"theskumar\",\n    \"twitter_username\": \"_theskumar\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"Jannis Gebauer\",\n    \"github_login\": \"jayfk\",\n    \"twitter_username\": \"\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"Burhan Khalid\",\n    \"github_login\": \"burhan\",\n    \"twitter_username\": \"burhan\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"Shupeyko Nikita\",\n    \"github_login\": \"webyneter\",\n    \"twitter_username\": \"webyneter\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"Bruno Alla\",\n    \"github_login\": \"browniebroke\",\n    \"twitter_username\": \"_BrunoAlla\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"Wan Liuyang\",\n    \"github_login\": \"sfdye\",\n    \"twitter_username\": \"sfdye\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"Jelmer Draaijer\",\n    \"github_login\": \"foarsitter\",\n    \"twitter_username\": \"\",\n    \"is_core\": true\n  },\n  {\n    \"name\": \"18\",\n    \"github_login\": \"dezoito\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"2O4\",\n    \"github_login\": \"2O4\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"a7p\",\n    \"github_login\": \"a7p\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Aadith PM\",\n    \"github_login\": \"aadithpm\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Aaron Eikenberry\",\n    \"github_login\": \"aeikenberry\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Adam Bogdał\",\n    \"github_login\": \"bogdal\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Adam Dobrawy\",\n    \"github_login\": \"ad-m\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Adam Steele\",\n    \"github_login\": \"adammsteele\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Agam Dua\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Agustín Scaramuzza\",\n    \"github_login\": \"scaramagus\",\n    \"twitter_username\": \"scaramagus\"\n  },\n  {\n    \"name\": \"Alberto Sanchez\",\n    \"github_login\": \"alb3rto\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Alex Tsai\",\n    \"github_login\": \"caffodian\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Alvaro [Andor]\",\n    \"github_login\": \"andor-pierdelacabeza\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Amjith Ramanujam\",\n    \"github_login\": \"amjith\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Andreas Meistad\",\n    \"github_login\": \"ameistad\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Andres Gonzalez\",\n    \"github_login\": \"andresgz\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Andrew Mikhnevich\",\n    \"github_login\": \"zcho\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Andrew Chen Wang\",\n    \"github_login\": \"Andrew-Chen-Wang\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Andy Rose\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Anna Callahan\",\n    \"github_login\": \"jazztpt\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Anna Sidwell\",\n    \"github_login\": \"takkaria\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Antonia Blair\",\n    \"github_login\": \"antoniablair\",\n    \"twitter_username\": \"antoniablairart\"\n  },\n  {\n    \"name\": \"Anuj Bansal\",\n    \"github_login\": \"ahhda\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Arcuri Davide\",\n    \"github_login\": \"dadokkio\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Areski Belaid\",\n    \"github_login\": \"areski\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"AsheKR\",\n    \"github_login\": \"ashekr\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Ashley Camba\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Barclay Gauld\",\n    \"github_login\": \"yunti\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Bartek\",\n    \"github_login\": \"btknu\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Ben Lopatin\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Ben Warren\",\n    \"github_login\": \"bwarren2\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Benjamin Abel\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Bert de Miranda\",\n    \"github_login\": \"bertdemiranda\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Bo Lopker\",\n    \"github_login\": \"blopker\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Bo Peng\",\n    \"github_login\": \"BoPeng\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Bouke Haarsma\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Brent Payne\",\n    \"github_login\": \"brentpayne\",\n    \"twitter_username\": \"brentpayne\"\n  },\n  {\n    \"name\": \"Bruce Olivier\",\n    \"github_login\": \"bolivierjr\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Caio Ariede\",\n    \"github_login\": \"caioariede\",\n    \"twitter_username\": \"caioariede\"\n  },\n  {\n    \"name\": \"Carl Johnson\",\n    \"github_login\": \"carlmjohnson\",\n    \"twitter_username\": \"carlmjohnson\"\n  },\n  {\n    \"name\": \"Catherine Devlin\",\n    \"github_login\": \"catherinedevlin\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Cédric Gaspoz\",\n    \"github_login\": \"cgaspoz\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Charlie Smith\",\n    \"github_login\": \"chuckus\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Chris Curvey\",\n    \"github_login\": \"ccurvey\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Chris Franklin\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Chris Franklin\",\n    \"github_login\": \"hairychris\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Chris Pappalardo\",\n    \"github_login\": \"ChrisPappalardo\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Christopher Clarke\",\n    \"github_login\": \"chrisdev\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Cole Mackenzie\",\n    \"github_login\": \"cmackenzie1\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Cole Maclean\",\n    \"github_login\": \"cole\",\n    \"twitter_username\": \"cole\"\n  },\n  {\n    \"name\": \"Collederas\",\n    \"github_login\": \"Collederas\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Craig Margieson\",\n    \"github_login\": \"cmargieson\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Cristian Vargas\",\n    \"github_login\": \"cdvv7788\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Cullen Rhodes\",\n    \"github_login\": \"c-rhodes\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Curtis St Pierre\",\n    \"github_login\": \"curtisstpierre\",\n    \"twitter_username\": \"cstpierre1388\"\n  },\n  {\n    \"name\": \"Dan Shultz\",\n    \"github_login\": \"shultz\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Dani Hodovic\",\n    \"github_login\": \"danihodovic\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Daniel Hepper\",\n    \"github_login\": \"dhepper\",\n    \"twitter_username\": \"danielhepper\"\n  },\n  {\n    \"name\": \"Daniel Hillier\",\n    \"github_login\": \"danifus\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Daniel Sears\",\n    \"github_login\": \"highpost\",\n    \"twitter_username\": \"highpost\"\n  },\n  {\n    \"name\": \"Daniele Tricoli\",\n    \"github_login\": \"eriol\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"David Díaz\",\n    \"github_login\": \"ddiazpinto\",\n    \"twitter_username\": \"DavidDiazPinto\"\n  },\n  {\n    \"name\": \"Davit Tovmasyan\",\n    \"github_login\": \"davitovmasyan\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Davur Clementsen\",\n    \"github_login\": \"dsclementsen\",\n    \"twitter_username\": \"davur\"\n  },\n  {\n    \"name\": \"Delio Castillo\",\n    \"github_login\": \"jangeador\",\n    \"twitter_username\": \"jangeador\"\n  },\n  {\n    \"name\": \"Demetris Stavrou\",\n    \"github_login\": \"demestav\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Denis Bobrov\",\n    \"github_login\": \"delneg\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Denis Orehovsky\",\n    \"github_login\": \"apirobot\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Denis Savran\",\n    \"github_login\": \"blaxpy\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Diane Chen\",\n    \"github_login\": \"purplediane\",\n    \"twitter_username\": \"purplediane88\"\n  },\n  {\n    \"name\": \"Dónal Adams\",\n    \"github_login\": \"epileptic-fish\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Dong Huynh\",\n    \"github_login\": \"trungdong\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Duda Nogueira\",\n    \"github_login\": \"dudanogueira\",\n    \"twitter_username\": \"dudanogueira\"\n  },\n  {\n    \"name\": \"Emanuel Calso\",\n    \"github_login\": \"bloodpet\",\n    \"twitter_username\": \"bloodpet\"\n  },\n  {\n    \"name\": \"Eraldo Energy\",\n    \"github_login\": \"eraldo\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Eric Groom\",\n    \"github_login\": \"ericgroom\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Ernesto Cedeno\",\n    \"github_login\": \"codnee\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Eyad Al Sibai\",\n    \"github_login\": \"eyadsibai\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Felipe Arruda\",\n    \"github_login\": \"arruda\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Florian Idelberger\",\n    \"github_login\": \"step21\",\n    \"twitter_username\": \"windrush\"\n  },\n  {\n    \"name\": \"Gabriel Mejia\",\n    \"github_login\": \"elgartoinf\",\n    \"twitter_username\": \"elgartoinf\"\n  },\n  {\n    \"name\": \"Garry Cairns\",\n    \"github_login\": \"garry-cairns\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Garry Polley\",\n    \"github_login\": \"garrypolley\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Gilbishkosma\",\n    \"github_login\": \"Gilbishkosma\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Glenn Wiskur\",\n    \"github_login\": \"gwiskur\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Guilherme Guy\",\n    \"github_login\": \"guilherme1guy\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Hamish Durkin\",\n    \"github_login\": \"durkode\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Hana Quadara\",\n    \"github_login\": \"hanaquadara\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Hannah Lazarus\",\n    \"github_login\": \"hanhanhan\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Harry Moreno\",\n    \"github_login\": \"morenoh149\",\n    \"twitter_username\": \"morenoh149\"\n  },\n  {\n    \"name\": \"Harry Percival\",\n    \"github_login\": \"hjwp\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Hendrik Schneider\",\n    \"github_login\": \"hendrikschneider\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Henrique G. G. Pereira\",\n    \"github_login\": \"ikkebr\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Howie Zhao\",\n    \"github_login\": \"howiezhao\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Ian Lee\",\n    \"github_login\": \"IanLee1521\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Irfan Ahmad\",\n    \"github_login\": \"erfaan\",\n    \"twitter_username\": \"erfaan\"\n  },\n  {\n    \"name\": \"Isaac12x\",\n    \"github_login\": \"Isaac12x\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Ivan Khomutov\",\n    \"github_login\": \"ikhomutov\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"James Williams\",\n    \"github_login\": \"jameswilliams1\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Jan Van Bruggen\",\n    \"github_login\": \"jvanbrug\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Jerome Caisip\",\n    \"github_login\": \"jeromecaisip\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Jens Nilsson\",\n    \"github_login\": \"phiberjenz\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Jerome Leclanche\",\n    \"github_login\": \"jleclanche\",\n    \"twitter_username\": \"Adys\"\n  },\n  {\n    \"name\": \"Jimmy Gitonga\",\n    \"github_login\": \"Afrowave\",\n    \"twitter_username\": \"afrowave\"\n  },\n  {\n    \"name\": \"John Cass\",\n    \"github_login\": \"jcass77\",\n    \"twitter_username\": \"cass_john\"\n  },\n  {\n    \"name\": \"Jonathan Thompson\",\n    \"github_login\": \"nojanath\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Jules Cheron\",\n    \"github_login\": \"jules-ch\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Julien Almarcha\",\n    \"github_login\": \"sladinji\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Julio Castillo\",\n    \"github_login\": \"juliocc\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Kaido Kert\",\n    \"github_login\": \"kaidokert\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"kappataumu\",\n    \"github_login\": \"kappataumu\",\n    \"twitter_username\": \"kappataumu\"\n  },\n  {\n    \"name\": \"Kaveh\",\n    \"github_login\": \"ka7eh\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Keith Bailey\",\n    \"github_login\": \"keithjeb\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Keith Webber\",\n    \"github_login\": \"townie\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Kevin A. Stone\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Kevin Ndung'u\",\n    \"github_login\": \"kevgathuku\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Keyvan Mosharraf\",\n    \"github_login\": \"keyvanm\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Krzysztof Szumny\",\n    \"github_login\": \"noisy\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Krzysztof Żuraw\",\n    \"github_login\": \"krzysztofzuraw\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Leo won\",\n    \"github_login\": \"leollon\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Leo Zhou\",\n    \"github_login\": \"glasslion\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Leon Kim\",\n    \"github_login\": \"PilhwanKim\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Leonardo Jimenez\",\n    \"github_login\": \"xpostudio4\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Lin Xianyi\",\n    \"github_login\": \"iynaix\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Luis Nell\",\n    \"github_login\": \"originell\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Lukas Klein\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Lyla Fischer\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Malik Sulaimanov\",\n    \"github_login\": \"flyudvik\",\n    \"twitter_username\": \"flyudvik\"\n  },\n  {\n    \"name\": \"Martin Blech\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Martin Saizar\",\n    \"github_login\": \"msaizar\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Mateusz Ostaszewski\",\n    \"github_login\": \"mostaszewski\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Mathijs Hoogland\",\n    \"github_login\": \"MathijsHoogland\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Matt Braymer-Hayes\",\n    \"github_login\": \"mattayes\",\n    \"twitter_username\": \"mattayes\"\n  },\n  {\n    \"name\": \"Matt Knapper\",\n    \"github_login\": \"mknapper1\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Matt Linares\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Matt Menzenski\",\n    \"github_login\": \"menzenski\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Matt Warren\",\n    \"github_login\": \"mfwarren\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Matthew Sisley\",\n    \"github_login\": \"mjsisley\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Matthias Sieber\",\n    \"github_login\": \"manonthemat\",\n    \"twitter_username\": \"MatzeOne\"\n  },\n  {\n    \"name\": \"Meghan Heintz\",\n    \"github_login\": \"dot2dotseurat\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Mesut Yılmaz\",\n    \"github_login\": \"myilmaz\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Michael Gecht\",\n    \"github_login\": \"mimischi\",\n    \"twitter_username\": \"_mischi\"\n  },\n  {\n    \"name\": \"Michael Samoylov\",\n    \"github_login\": \"msamoylov\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Min ho Kim\",\n    \"github_login\": \"minho42\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"mozillazg\",\n    \"github_login\": \"mozillazg\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Nico Stefani\",\n    \"github_login\": \"nicolas471\",\n    \"twitter_username\": \"moby_dick91\"\n  },\n  {\n    \"name\": \"Oleg Russkin\",\n    \"github_login\": \"rolep\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Pablo\",\n    \"github_login\": \"oubiga\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Parbhat Puri\",\n    \"github_login\": \"parbhat\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Pawan Chaurasia\",\n    \"github_login\": \"rjsnh1522\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Peter Bittner\",\n    \"github_login\": \"bittner\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Peter Coles\",\n    \"github_login\": \"mrcoles\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Philipp Matthies\",\n    \"github_login\": \"canonnervio\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Pierre Chiquet\",\n    \"github_login\": \"pchiquet\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Raony Guimarães Corrêa\",\n    \"github_login\": \"raonyguimaraes\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Raphael Pierzina\",\n    \"github_login\": \"hackebrot\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Reggie Riser\",\n    \"github_login\": \"reggieriser\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"René Muhl\",\n    \"github_login\": \"rm--\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Richard Hajdu\",\n    \"github_login\": \"Tusky\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Roman Afanaskin\",\n    \"github_login\": \"siauPatrick\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Roman Osipenko\",\n    \"github_login\": \"romanosipenko\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Russell Davies\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Sam Collins\",\n    \"github_login\": \"MightySCollins\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Sascha\",\n    \"github_login\": \"saschalalala\",\n    \"twitter_username\": \"saschalalala\"\n  },\n  {\n    \"name\": \"Sławek Ehlert\",\n    \"github_login\": \"slafs\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Sorasful\",\n    \"github_login\": \"sorasful\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Srinivas Nyayapati\",\n    \"github_login\": \"shireenrao\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"stepmr\",\n    \"github_login\": \"stepmr\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Steve Steiner\",\n    \"github_login\": \"ssteinerX\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Sudarshan Wadkar\",\n    \"github_login\": \"wadkar\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Sule Marshall\",\n    \"github_login\": \"suledev\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Tano Abeleyra\",\n    \"github_login\": \"tanoabeleyra\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Taylor Baldwin\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Théo Segonds\",\n    \"github_login\": \"show0k\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Tim Claessens\",\n    \"github_login\": \"timclaessens\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Tim Freund\",\n    \"github_login\": \"timfreund\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Tom Atkins\",\n    \"github_login\": \"knitatoms\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Tom Offermann\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Travis McNeill\",\n    \"github_login\": \"Travistock\",\n    \"twitter_username\": \"tavistock_esq\"\n  },\n  {\n    \"name\": \"Tubo Shi\",\n    \"github_login\": \"Tubo\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Umair Ashraf\",\n    \"github_login\": \"umrashrf\",\n    \"twitter_username\": \"fabumair\"\n  },\n  {\n    \"name\": \"Vadim Iskuchekov\",\n    \"github_login\": \"Egregors\",\n    \"twitter_username\": \"egregors\"\n  },\n  {\n    \"name\": \"Vicente G. Reyes\",\n    \"github_login\": \"reyesvicente\",\n    \"twitter_username\": \"highcenburg\"\n  },\n  {\n    \"name\": \"Vitaly Babiy\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Vivian Guillen\",\n    \"github_login\": \"viviangb\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Vlad Doster\",\n    \"github_login\": \"vladdoster\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Will Farley\",\n    \"github_login\": \"goldhand\",\n    \"twitter_username\": \"g01dhand\"\n  },\n  {\n    \"name\": \"William Archinal\",\n    \"github_login\": \"archinal\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Xaver Y.R. Chen\",\n    \"github_login\": \"yrchen\",\n    \"twitter_username\": \"yrchen\"\n  },\n  {\n    \"name\": \"Yaroslav Halchenko\",\n    \"github_login\": \"\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Yuchen Xie\",\n    \"github_login\": \"mapx\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"enchance\",\n    \"github_login\": \"enchance\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Jan Fabry\",\n    \"github_login\": \"janfabry\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Corey Garvey\",\n    \"github_login\": \"coreygarvey\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Arnav Choudhury\",\n    \"github_login\": \"arnav13081994\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Wes Turner\",\n    \"github_login\": \"westurner\",\n    \"twitter_username\": \"westurner\"\n  },\n  {\n    \"name\": \"Jakub Musko\",\n    \"github_login\": \"umgelurgel\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Fabian Affolter\",\n    \"github_login\": \"fabaff\",\n    \"twitter_username\": \"fabaff\"\n  },\n  {\n    \"name\": \"Simon Rey\",\n    \"github_login\": \"eqqe\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Yotam Tal\",\n    \"github_login\": \"yotamtal\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"John\",\n    \"github_login\": \"thorrak\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"vascop\",\n    \"github_login\": \"vascop\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"PJ Hoberman\",\n    \"github_login\": \"pjhoberman\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"lcd1232\",\n    \"github_login\": \"lcd1232\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Tames McTigue\",\n    \"github_login\": \"Tamerz\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Ray Besiga\",\n    \"github_login\": \"raybesiga\",\n    \"twitter_username\": \"raybesiga\"\n  },\n  {\n    \"name\": \"Grant McLean\",\n    \"github_login\": \"grantm\",\n    \"twitter_username\": \"grantmnz\"\n  },\n  {\n    \"name\": \"Kuo Chao Cheng\",\n    \"github_login\": \"wwwtony5488\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"LECbg\",\n    \"github_login\": \"LECbg\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Haseeb ur Rehman\",\n    \"github_login\": \"professorhaseeb\",\n    \"twitter_username\": \"professorhaseeb\"\n  },\n  {\n    \"name\": \"Abdul Qoyyuum\",\n    \"github_login\": \"Qoyyuum\",\n    \"twitter_username\": \"Qoyyuum\"\n  },\n  {\n    \"name\": \"Matthew Foster Walsh\",\n    \"github_login\": \"mfosterw\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Keith Callenberg\",\n    \"github_login\": \"keithcallenberg\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Mike97M\",\n    \"github_login\": \"Mike97M\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Charlie Macfarlane Brodie\",\n    \"github_login\": \"tannart\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Floyd Hightower\",\n    \"github_login\": \"fhightower\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Manjit Pardeshi\",\n    \"github_login\": \"Manjit2003\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Meraj \",\n    \"github_login\": \"ichbinmeraj\",\n    \"twitter_username\": \"merajsafari\"\n  },\n  {\n    \"name\": \"dalrrard\",\n    \"github_login\": \"dalrrard\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Liam Brenner\",\n    \"github_login\": \"SableWalnut\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Noah H\",\n    \"github_login\": \"nthall\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Diego Montes\",\n    \"github_login\": \"d57montes\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Chao Yang Wu\",\n    \"github_login\": \"goatwu1993\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"mpoli\",\n    \"github_login\": \"mpoli\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Zach Borboa\",\n    \"github_login\": \"zachborboa\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Timm Simpkins\",\n    \"github_login\": \"PoDuck\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Douglas\",\n    \"github_login\": \"douglascdev\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Will Gordon\",\n    \"github_login\": \"wgordon17\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Bogdan Mateescu\",\n    \"github_login\": \"mateesville93\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Fuzzwah\",\n    \"github_login\": \"Fuzzwah\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Thibault J.\",\n    \"github_login\": \"thibault\",\n    \"twitter_username\": \"thibault\"\n  },\n  {\n    \"name\": \"Pedro Campos\",\n    \"github_login\": \"pcampos119104\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Vikas Yadav\",\n    \"github_login\": \"vik-y\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Abdullah Adeel\",\n    \"github_login\": \"mabdullahadeel\",\n    \"twitter_username\": \"abdadeel_\"\n  },\n  {\n    \"name\": \"Jorge Valdez\",\n    \"github_login\": \"jorgeavaldez\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Ryan Fitch\",\n    \"github_login\": \"ryfi\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"ghazi-git\",\n    \"github_login\": \"ghazi-git\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Cebrail Yılmaz\",\n    \"github_login\": \"b1sar\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Artur Barseghyan\",\n    \"github_login\": \"barseghyanartur\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"innicoder\",\n    \"github_login\": \"innicoder\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Naveen\",\n    \"github_login\": \"naveensrinivasan\",\n    \"twitter_username\": \"snaveen\"\n  },\n  {\n    \"name\": \"Nikita Sobolev\",\n    \"github_login\": \"sobolevn\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Sebastian Reyes Espinosa\",\n    \"github_login\": \"sebastian-code\",\n    \"twitter_username\": \"sebastianreyese\"\n  },\n  {\n    \"name\": \"jugglinmike\",\n    \"github_login\": \"jugglinmike\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"monosans\",\n    \"github_login\": \"monosans\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Marcio Mazza\",\n    \"github_login\": \"marciomazza\",\n    \"twitter_username\": \"marciomazza\"\n  },\n  {\n    \"name\": \"Brandon Rumiser\",\n    \"github_login\": \"brumiser1550\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"krati yadav\",\n    \"github_login\": \"krati5\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Abe Hanoka\",\n    \"github_login\": \"abe-101\",\n    \"twitter_username\": \"abe__101\"\n  },\n  {\n    \"name\": \"Adin Hodovic\",\n    \"github_login\": \"adinhodovic\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Leifur Halldor Asgeirsson\",\n    \"github_login\": \"leifurhauks\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"David\",\n    \"github_login\": \"buckldav\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"rguptar\",\n    \"github_login\": \"rguptar\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Omer-5\",\n    \"github_login\": \"Omer-5\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"TAKAHASHI Shuuji\",\n    \"github_login\": \"shuuji3\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Thomas Booij\",\n    \"github_login\": \"ThomasBooij95\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Pamela Fox\",\n    \"github_login\": \"pamelafox\",\n    \"twitter_username\": \"pamelafox\"\n  },\n  {\n    \"name\": \"Robin\",\n    \"github_login\": \"Kaffeetasse\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Patrick Tran\",\n    \"github_login\": \"theptrk\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"tildebox\",\n    \"github_login\": \"tildebox\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"duffn\",\n    \"github_login\": \"duffn\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Delphine LEMIRE\",\n    \"github_login\": \"DelphineLemire\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Hoai-Thu Vuong\",\n    \"github_login\": \"thuvh\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Arkadiusz Michał Ryś\",\n    \"github_login\": \"arrys\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"mpsantos\",\n    \"github_login\": \"mpsantos\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Morten Kaae\",\n    \"github_login\": \"MortenKaae\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Birtibu\",\n    \"github_login\": \"Birtibu\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Matheus Jardim Bernardes\",\n    \"github_login\": \"matheusjardimb\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"masavini\",\n    \"github_login\": \"masavini\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Joseph Hanna\",\n    \"github_login\": \"sanchimenea\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"tmajerech\",\n    \"github_login\": \"tmajerech\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"villancikos\",\n    \"github_login\": \"villancikos\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Imran Rahman\",\n    \"github_login\": \"infraredCoding\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"hleroy\",\n    \"github_login\": \"hleroy\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Shayan Karimi\",\n    \"github_login\": \"shywn-mrk\",\n    \"twitter_username\": \"shywn_mrk\"\n  },\n  {\n    \"name\": \"Sadra Yahyapour\",\n    \"github_login\": \"lnxpy\",\n    \"twitter_username\": \"lnxpylnxpy\"\n  },\n  {\n    \"name\": \"Tharushan\",\n    \"github_login\": \"Tharushan\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Fateme Fouladkar\",\n    \"github_login\": \"FatemeFouladkar\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"zhaoruibing\",\n    \"github_login\": \"zhaoruibing\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"MinWoo Sung\",\n    \"github_login\": \"SungMinWoo\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"itisnotyourenv\",\n    \"github_login\": \"itisnotyourenv\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Vageeshan Mankala\",\n    \"github_login\": \"vagi8\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Jakub Boukal\",\n    \"github_login\": \"SukiCZ\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Christian Jauvin\",\n    \"github_login\": \"cjauvin\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Plurific\",\n    \"github_login\": \"paulschwenn\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"GitBib\",\n    \"github_login\": \"GitBib\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Freddy\",\n    \"github_login\": \"Hraesvelg\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"aiden\",\n    \"github_login\": \"anyidea\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Michael V. Battista\",\n    \"github_login\": \"mvbattista\",\n    \"twitter_username\": \"mvbattista\"\n  },\n  {\n    \"name\": \"Nix Siow\",\n    \"github_login\": \"nixsiow\",\n    \"twitter_username\": \"nixsiow\"\n  },\n  {\n    \"name\": \"Jens Kaeske\",\n    \"github_login\": \"jkaeske\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"henningbra\",\n    \"github_login\": \"henningbra\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Paul Wulff\",\n    \"github_login\": \"mtmpaulwulff\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Mounir\",\n    \"github_login\": \"mounirmesselmeni\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"JAEGYUN JUNG\",\n    \"github_login\": \"TGoddessana\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Simeon Emanuilov\",\n    \"github_login\": \"s-emanuilov\",\n    \"twitter_username\": \"s_emanuilov\"\n  },\n  {\n    \"name\": \"Patrick Zhang\",\n    \"github_login\": \"PatDuJour\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"GvS\",\n    \"github_login\": \"GvS666\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"David Păcioianu\",\n    \"github_login\": \"DavidPacioianu\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"farwill\",\n    \"github_login\": \"farwill\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"quroom\",\n    \"github_login\": \"quroom\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Marios Frixou\",\n    \"github_login\": \"frixou89\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Geo Maciolek\",\n    \"github_login\": \"GeoMaciolek\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Nadav Peretz\",\n    \"github_login\": \"nadavperetz\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Param Kapur\",\n    \"github_login\": \"paramkpr\",\n    \"twitter_username\": \"ParamKapur\"\n  },\n  {\n    \"name\": \"Jason Mok\",\n    \"github_login\": \"jasonmokk\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Manas Mallick\",\n    \"github_login\": \"ManDun\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Alexandr Artemyev\",\n    \"github_login\": \"Mogost\",\n    \"twitter_username\": \"MOGOST\"\n  },\n  {\n    \"name\": \"Ali Shamakhi\",\n    \"github_login\": \"ali-shamakhi\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Filipe Nascimento\",\n    \"github_login\": \"FilipeNas\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Kevin Mills\",\n    \"github_login\": \"millsks\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"milvagox\",\n    \"github_login\": \"milvagox\",\n    \"twitter_username\": \"milvagox\"\n  },\n  {\n    \"name\": \"Johnny Metz\",\n    \"github_login\": \"johnnymetz\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Will\",\n    \"github_login\": \"novucs\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"rxm7706\",\n    \"github_login\": \"rxm7706\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Marlon Castillo\",\n    \"github_login\": \"mcastle\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Alex Kanavos\",\n    \"github_login\": \"alexkanavos\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"LJFP\",\n    \"github_login\": \"ljfp\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Francisco Navarro Morales \",\n    \"github_login\": \"spothound\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Mariot Tsitoara\",\n    \"github_login\": \"mariot\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Christian Jensen\",\n    \"github_login\": \"jensenbox\",\n    \"twitter_username\": \"cjensen\"\n  },\n  {\n    \"name\": \"Denis Darii\",\n    \"github_login\": \"DNX\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"qwerrrqw\",\n    \"github_login\": \"qwerrrqw\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Pulse-Mind\",\n    \"github_login\": \"pulse-mind\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Hana Belay\",\n    \"github_login\": \"earthcomfy\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Ed Morley\",\n    \"github_login\": \"edmorley\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Alan Cyment\",\n    \"github_login\": \"acyment\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Kawsar Alam Foysal\",\n    \"github_login\": \"iamfoysal\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Igor Jerosimić\",\n    \"github_login\": \"igor-wl\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Pepa\",\n    \"github_login\": \"07pepa\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Aidos Kanapyanov\",\n    \"github_login\": \"aidoskanapyanov\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Jeongseok Kang\",\n    \"github_login\": \"rapsealk\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Jeff Foster\",\n    \"github_login\": \"jeffpfoster\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Dominique Plante\",\n    \"github_login\": \"dominiqueplante\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Lucas Klasa\",\n    \"github_login\": \"lucaskbr\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"DevForsure\",\n    \"github_login\": \"DevForsure\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Vincent Leduc\",\n    \"github_login\": \"leducvin\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Martín Blech\",\n    \"github_login\": \"martinblech\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"jlitrell\",\n    \"github_login\": \"jlitrell\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Maurício Gioachini\",\n    \"github_login\": \"MauGx3\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Donghoon Nam\",\n    \"github_login\": \"codenamenam\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Tosinibikunle\",\n    \"github_login\": \"Tosinibikunle\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Josh596\",\n    \"github_login\": \"Josh596\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Harshit Ranjan\",\n    \"github_login\": \"HarshitR2004\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Mohamed Feddad\",\n    \"github_login\": \"mrf345\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Christian González\",\n    \"github_login\": \"nerdoc\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"Soldatov Serhii\",\n    \"github_login\": \"soldatov-ss\",\n    \"twitter_username\": \"\"\n  },\n  {\n    \"name\": \"asmo\",\n    \"github_login\": \"a5m0\",\n    \"twitter_username\": \"\"\n  }\n]"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# Config for Dependabot updates. See Documentation here:\n# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file\n\nversion: 2\nenable-beta-ecosystems: true\nupdates:\n  # Update Python deps for the template (not the generated project)\n  - package-ecosystem: \"uv\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n    labels:\n      - \"project infrastructure\"\n    ignore:\n      - dependency-name: \"ruff\" # updated via PyUp\n\n  # Update GitHub actions in workflows\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n    labels:\n      - \"project infrastructure\"\n\n  # Update npm packages\n  - package-ecosystem: \"npm\"\n    directories:\n      - \"{{cookiecutter.project_slug}}/\"\n    schedule:\n      interval: \"daily\"\n    labels:\n      - \"update\"\n\n  # Enable version updates for Docker\n  - package-ecosystem: \"docker\"\n    directories:\n      - \"{{cookiecutter.project_slug}}/compose/local/django/\"\n      - \"{{cookiecutter.project_slug}}/compose/local/docs/\"\n      - \"{{cookiecutter.project_slug}}/compose/production/django/\"\n      - \"{{cookiecutter.project_slug}}/compose/local/node/\"\n      - \"{{cookiecutter.project_slug}}/compose/production/aws/\"\n      - \"{{cookiecutter.project_slug}}/compose/production/postgres/\"\n      - \"{{cookiecutter.project_slug}}/compose/production/nginx/\"\n      - \"{{cookiecutter.project_slug}}/compose/production/traefik/\"\n    schedule:\n      interval: \"daily\"\n    labels:\n      - \"update\"\n\n  # NOTE: Package ecosystem \"docker-compose\" can't handle Jinja tags in yml files\n"
  },
  {
    "path": ".github/workflows/align-versions.yml",
    "content": "name: align versions\n\non:\n  pull_request:\n    paths:\n      - \"{{cookiecutter.project_slug}}/requirements/local.txt\"\n      - \"{{cookiecutter.project_slug}}/compose/local/node/Dockerfile\"\n  # Manual trigger\n  workflow_dispatch:\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  run:\n    if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' && (github.event.pull_request.user.login == 'pyup-bot' || github.event.pull_request.user.login == 'dependabot[bot]') }}\n    runs-on: ubuntu-latest\n    env:\n      GH_PAT: ${{ secrets.GH_PAT }}\n\n    strategy:\n      fail-fast: false\n      matrix:\n        job:\n          - script: scripts/ruff_version.py\n            name: Ruff\n          - script: scripts/node_version.py\n            name: Node\n\n    name: \"${{ matrix.job.name }} versions\"\n    steps:\n      - name: Checkout with token\n        uses: actions/checkout@v6\n        if: ${{ env.GH_PAT != '' }}\n        with:\n          token: ${{ env.GH_PAT }}\n          ref: ${{ github.head_ref }}\n\n      - name: Checkout without token\n        uses: actions/checkout@v6\n        if: ${{ env.GH_PAT == '' }}\n        with:\n          ref: ${{ github.head_ref }}\n\n      - uses: astral-sh/setup-uv@v7\n\n      - run: uv run ${{ matrix.job.script }}\n\n      - uses: stefanzweifel/git-auto-commit-action@v7\n        with:\n          commit_message: Align versions\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches: [\"main\"]\n  pull_request:\n\nconcurrency:\n  group: ${{ github.head_ref || github.run_id }}\n  cancel-in-progress: true\n\njobs:\n  tests:\n    strategy:\n      fail-fast: false\n      matrix:\n        os:\n          - ubuntu-latest\n          - windows-latest\n          - macOS-latest\n\n    name: \"pytest ${{ matrix.os }}\"\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install uv\n        uses: astral-sh/setup-uv@v7\n      - name: Install dependencies\n        run: uv sync --locked\n      - name: Run tests\n        run: uv run pytest -n auto tests\n\n  docker:\n    strategy:\n      fail-fast: false\n      matrix:\n        script:\n          - name: Basic\n            args: \"ci_tool=Gitlab\"\n          - name: Celery & DRF\n            args: \"use_celery=y rest_api=DRF\"\n          - name: Gulp\n            args: \"frontend_pipeline=Gulp\"\n          - name: Webpack\n            args: \"frontend_pipeline=Webpack\"\n\n    name: \"Docker ${{ matrix.script.name }}\"\n    runs-on: ubuntu-latest\n    env:\n      DOCKER_BUILDKIT: 1\n      COMPOSE_DOCKER_CLI_BUILD: 1\n\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install uv\n        uses: astral-sh/setup-uv@v7\n      - name: Install dependencies\n        run: uv sync --locked\n      - name: Docker ${{ matrix.script.name }}\n        run: sh tests/test_docker.sh ${{ matrix.script.args }}\n\n  bare:\n    strategy:\n      fail-fast: false\n      matrix:\n        script:\n          - name: Celery\n            args: \"use_celery=y frontend_pipeline='Django Compressor'\"\n          - name: Gulp\n            args: \"frontend_pipeline=Gulp\"\n          - name: Webpack\n            args: \"frontend_pipeline=Webpack use_heroku=y\"\n          - name: Email Username\n            args: \"username_type=email ci_tool=Github project_name='Something superduper long - the great amazing project' project_slug=my_awesome_project\"\n          - name: Email username & DRF\n            args: \"username_type=email rest_api=DRF ci_tool=Gitlab\"\n          - name: Async & Django-Ninja\n            args: \"use_async=y rest_api='Django Ninja'\"\n          - name: Async, email username & Django-Ninja\n            args: \"use_async=y username_type=email rest_api='Django Ninja'\"\n\n    name: \"Bare metal ${{ matrix.script.name }}\"\n    runs-on: ubuntu-latest\n    services:\n      redis:\n        image: redis:7.2\n        ports:\n          - 6379:6379\n      postgres:\n        image: postgres:14\n        ports:\n          - 5432:5432\n        env:\n          POSTGRES_PASSWORD: postgres\n\n    env:\n      REDIS_URL: \"redis://localhost:6379/0\"\n      # postgres://user:password@host:port/database\n      DATABASE_URL: \"postgres://postgres:postgres@localhost:5432/postgres\"\n\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install uv\n        uses: astral-sh/setup-uv@v7\n      - name: Install dependencies\n        run: uv sync --locked\n      - uses: actions/setup-node@v6\n        with:\n          node-version-file: \"{{cookiecutter.project_slug}}/package.json\"\n      - name: Bare Metal ${{ matrix.script.name }}\n        run: sh tests/test_bare.sh ${{ matrix.script.args }}\n"
  },
  {
    "path": ".github/workflows/dependabot-uv-lock.yml",
    "content": "name: uv\n\non:\n  pull_request:\n    paths:\n      - \"pyproject.toml\"\n  # Manual trigger\n  workflow_dispatch:\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  lock:\n    if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' && (github.event.pull_request.user.login == 'pyup-bot' || github.event.pull_request.user.login == 'dependabot[bot]') }}\n    runs-on: ubuntu-latest\n    env:\n      GH_PAT: ${{ secrets.GH_PAT }}\n    steps:\n      - name: Checkout with token\n        uses: actions/checkout@v6\n        if: ${{ env.GH_PAT != '' }}\n        with:\n          token: ${{ env.GH_PAT }}\n\n      - name: Checkout without token\n        uses: actions/checkout@v6\n        if: ${{ env.GH_PAT == '' }}\n\n      - uses: astral-sh/setup-uv@v7\n      - run: uv lock\n      - uses: stefanzweifel/git-auto-commit-action@v7\n        with:\n          commit_message: Regenerate uv.lock\n"
  },
  {
    "path": ".github/workflows/django-issue-checker.yml",
    "content": "# Creates a new issue for Major/Minor Django updates that keeps track\n# of all dependencies that need to be updated/merged in order for the\n# latest Django version to also be merged.\nname: Django Issue Checker\n\non:\n  schedule:\n    - cron: \"28 5 * * *\"\n  # Manual trigger\n  workflow_dispatch:\n\njobs:\n  issue-checker:\n    # Disables this workflow from running in a repository that is not part of the indicated organization/user\n    if: github.repository_owner == 'cookiecutter'\n\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install uv\n        uses: astral-sh/setup-uv@v7\n      - name: Create Django Major Issue\n        run: uv run --locked scripts/create_django_issue.py\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/issue-manager.yml",
    "content": "# Automatically close issues or pull requests that have a label, after a custom delay, if no one replies.\n# https://github.com/tiangolo/issue-manager\nname: Issue Manager\n\non:\n  schedule:\n    - cron: \"12 0 * * *\"\n  issue_comment:\n    types:\n      - created\n  issues:\n    types:\n      - labeled\n  pull_request_target:\n    types:\n      - labeled\n  workflow_dispatch:\n\njobs:\n  issue-manager:\n    # Disables this workflow from running in a repository that is not part of the indicated organization/user\n    if: github.repository_owner == 'cookiecutter'\n\n    runs-on: ubuntu-latest\n    steps:\n      - uses: tiangolo/issue-manager@0.6.0\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n          config: >\n            {\n              \"answered\": {\n                \"delay\": 864000,\n                \"message\": \"Assuming the question was answered, this will be automatically closed now.\"\n              },\n              \"solved\": {\n                \"delay\": 864000,\n                \"message\": \"Assuming the original issue was solved, it will be automatically closed now.\"\n              },\n              \"waiting\": {\n                \"delay\": 864000,\n                \"message\": \"Automatically closing after waiting for additional info. To re-open, please provide the additional information requested.\"\n              },\n              \"wontfix\": {\n                \"delay\": 864000,\n                \"message\": \"As discussed, we won't be implementing this. Automatically closing.\"\n              }\n            }\n"
  },
  {
    "path": ".github/workflows/pre-commit-autoupdate.yml",
    "content": "# Run pre-commit autoupdate every day at midnight\n# and create a pull request if any changes\n\nname: Pre-commit auto-update\n\non:\n  schedule:\n    - cron: \"15 2 * * *\"\n  workflow_dispatch: # to trigger manually\n\npermissions:\n  contents: read\n\njobs:\n  auto-update:\n    # Disables this workflow from running in a repository that is not part of the indicated organization/user\n    if: github.repository_owner == 'cookiecutter'\n    permissions:\n      contents: write # for peter-evans/create-pull-request to create branch\n      pull-requests: write # for peter-evans/create-pull-request to create a PR\n\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install uv\n        uses: astral-sh/setup-uv@v7\n\n      - name: Autoupdate template\n        run: uv tool run pre-commit autoupdate\n\n      - name: Autoupdate generated projects\n        working-directory: \"{{cookiecutter.project_slug}}\"\n        run: uv tool run pre-commit autoupdate\n\n      - name: Create Pull Request\n        uses: peter-evans/create-pull-request@v8\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n          branch: update/pre-commit-autoupdate\n          title: Auto-update pre-commit hooks\n          commit-message: Auto-update pre-commit hooks\n          body: Update versions of tools in pre-commit configs to latest version\n          labels: update\n"
  },
  {
    "path": ".github/workflows/update-changelog.yml",
    "content": "name: Update Changelog\n\non:\n  # Every day at 2am\n  schedule:\n    - cron: \"0 2 * * *\"\n  # Manual trigger\n  workflow_dispatch:\n\njobs:\n  update:\n    # Disables this workflow from running in a repository that is not part of the indicated organization/user\n    if: github.repository_owner == 'cookiecutter'\n\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install uv\n        uses: astral-sh/setup-uv@v7\n      - name: Set git details\n        run: |\n          git config --global user.name \"github-actions\"\n          git config --global user.email \"action@github.com\"\n      - name: Update changelog\n        run: uv run --locked scripts/update_changelog.py\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/update-contributors.yml",
    "content": "name: Update Contributors\n\non:\n  push:\n    branches:\n      - main\n\npermissions:\n  contents: read\n\njobs:\n  build:\n    # Disables this workflow from running in a repository that is not part of the indicated organization/user\n    if: github.repository_owner == 'cookiecutter'\n    permissions:\n      contents: write # for stefanzweifel/git-auto-commit-action to push code in repo\n\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install uv\n        uses: astral-sh/setup-uv@v7\n      - name: Update list\n        run: uv run --locked scripts/update_contributors.py\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Commit changes\n        uses: stefanzweifel/git-auto-commit-action@v7\n        with:\n          commit_message: Update Contributors\n          file_pattern: CONTRIBUTORS.md .github/contributors.json\n"
  },
  {
    "path": ".gitignore",
    "content": "### Python template\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\n*.egg-info/\n.installed.cfg\n*.egg\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage.*\n.cache/\nnosetests.xml\ncoverage.xml\n*.cover\n.hypothesis/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n\n# pyenv\n.python-version\n\n# celery beat schedule file\ncelerybeat-schedule\n\n# Environments\n.env\n.venv\nenv/\nvenv/\nENV/\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n\n\n### Linux template\n*~\n\n# temporary files which can be created if a process still has a handle open of a deleted file\n.fuse_hidden*\n\n# KDE directory preferences\n.directory\n\n# Linux trash folder which might appear on any partition or disk\n.Trash-*\n\n# .nfs files are created when an open file is removed but is still being accessed\n.nfs*\n\n\n### VisualStudioCode template\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n\n### Windows template\n# Windows thumbnail cache files\nThumbs.db\nehthumbs.db\nehthumbs_vista.db\n\n# Dump file\n*.stackdump\n\n# Folder config file\nDesktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n\n### SublimeText template\n# Cache files for Sublime Text\n*.tmlanguage.cache\n*.tmPreferences.cache\n*.stTheme.cache\n\n# Workspace files are user-specific\n*.sublime-workspace\n\n# Project files should be checked into the repository, unless a significant\n# proportion of contributors will probably not be using Sublime Text\n# *.sublime-project\n\n# SFTP configuration file\nsftp-config.json\n\n# Package control specific files\nPackage Control.last-run\nPackage Control.ca-list\nPackage Control.ca-bundle\nPackage Control.system-ca-bundle\nPackage Control.cache/\nPackage Control.ca-certs/\nPackage Control.merged-ca-bundle\nPackage Control.user-ca-bundle\noscrypto-ca-bundle.crt\nbh_unicode_properties.cache\n\n# Sublime-github package stores a github token in this file\n# https://packagecontrol.io/packages/sublime-github\nGitHub.sublime-settings\n\n\n### macOS template\n# General\n*.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n\n### Vim template\n# Swap\n[._]*.s[a-v][a-z]\n[._]*.sw[a-p]\n[._]s[a-v][a-z]\n[._]sw[a-p]\n\n# Session\nSession.vim\n\n# Temporary\n.netrwhist\n# Auto-generated tag files\ntags\n\n\n# Even though the project might be opened and edited\n# in any of the JetBrains IDEs, it makes no sence whatsoever\n# to 'run' anything within it since any particular cookiecutter\n# is declarative by nature.\n.idea/\n\n.pytest_cache/\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "exclude: \"{{cookiecutter.project_slug}}|.github/contributors.json|CHANGELOG.md|CONTRIBUTORS.md\"\ndefault_stages: [pre-commit]\nminimum_pre_commit_version: \"3.2.0\"\n\ndefault_language_version:\n  python: python3.13\n\nrepos:\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v6.0.0\n    hooks:\n      - id: trailing-whitespace\n      - id: end-of-file-fixer\n      - id: check-json\n      - id: check-toml\n      - id: check-xml\n      - id: check-yaml\n      - id: debug-statements\n      - id: check-builtin-literals\n      - id: check-case-conflict\n      - id: detect-private-key\n\n  - repo: https://github.com/pre-commit/mirrors-prettier\n    rev: v4.0.0-alpha.8\n    hooks:\n      - id: prettier\n        args: [\"--tab-width\", \"2\"]\n\n  - repo: https://github.com/astral-sh/ruff-pre-commit\n    rev: v0.15.7\n    hooks:\n      - id: ruff\n        args: [--fix, --exit-non-zero-on-fix]\n      - id: ruff-format\n\n  - repo: https://github.com/tox-dev/pyproject-fmt\n    rev: v2.20.0\n    hooks:\n      - id: pyproject-fmt\n\nci:\n  autoupdate_schedule: weekly\n  skip: []\n  submodules: false\n"
  },
  {
    "path": ".pyup.yml",
    "content": "# configure updates globally\n# default: all\n# allowed: all, insecure, False\nupdate: all\n\n# configure dependency pinning globally\n# default: True\n# allowed: True, False\npin: True\n\n# add a label to pull requests, default is not set\n# requires private repo permissions, even on public repos\n# default: empty\nlabel_prs: update\n\nrequirements:\n  - \"{{cookiecutter.project_slug}}/requirements/base.txt\"\n  - \"{{cookiecutter.project_slug}}/requirements/local.txt\"\n  - \"{{cookiecutter.project_slug}}/requirements/production.txt\"\n"
  },
  {
    "path": ".readthedocs.yaml",
    "content": "# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\nversion: 2\n\nbuild:\n  os: ubuntu-24.04\n  tools:\n    python: \"3.13\"\n  jobs:\n    pre_create_environment:\n      - asdf plugin add uv\n      - asdf install uv latest\n      - asdf global uv latest\n    create_environment:\n      - uv venv \"${READTHEDOCS_VIRTUALENV_PATH}\"\n    install:\n      - UV_PROJECT_ENVIRONMENT=\"${READTHEDOCS_VIRTUALENV_PATH}\" uv sync --frozen --no-dev --only-group docs\n\nsphinx:\n  configuration: docs/conf.py\n"
  },
  {
    "path": "AGENTS.md",
    "content": "# AGENTS.md\n\nThis file provides guidance to AI coding agents when working with code in this repository.\n\n## What This Project Is\n\ncookiecutter-django is a **Cookiecutter template** that generates production-ready Django projects. It is NOT a Django application itself — it's a Jinja2-templated project scaffold. The generated project lives inside `{{cookiecutter.project_slug}}/` and gets processed by Cookiecutter when users run the generator.\n\n## Commands\n\n### Install dependencies\n\n```bash\nuv sync --locked\n```\n\n### Run tests\n\n```bash\n# Full test suite (parallel, via tox)\nuv run tox run -e py\n\n# Direct pytest (parallel)\nuv run pytest -n auto tests\n\n# Single test\nuv run pytest tests/test_cookiecutter_generation.py -k \"test_name\"\n\n# Run with auto-fixable style checks enabled\nAUTOFIXABLE_STYLES=1 uv run pytest -n auto tests\n```\n\n### Linting and formatting\n\n```bash\n# Run all pre-commit hooks\nuv run pre-commit run --all-files\n\n# Ruff only\nuv run ruff check --fix\nuv run ruff format\n```\n\n### Integration tests (require Docker or PostgreSQL+Redis)\n\n```bash\n# Docker-based\nsh tests/test_docker.sh                          # defaults\nsh tests/test_docker.sh use_celery=y use_drf=y   # with options\n\n# Bare metal (needs PostgreSQL and Redis running)\nsh tests/test_bare.sh\nsh tests/test_bare.sh use_celery=y frontend_pipeline=Gulp\n```\n\n### Generate a project locally for debugging\n\n```bash\nuv run cookiecutter . --no-input --output-dir=/tmp/debug\n```\n\n## Architecture\n\n### Template Generation Flow\n\n1. User runs `cookiecutter` — prompted with options from `cookiecutter.json`\n2. `hooks/pre_gen_project.py` validates input (project_slug format, conflicting options)\n3. Jinja2 renders all files under `{{cookiecutter.project_slug}}/` with user choices\n4. `hooks/post_gen_project.py` (~550 lines) removes files not needed for the chosen options, generates random secrets, and adjusts config files\n\n### Key Files\n\n- **`cookiecutter.json`** — All template variables and their choices (project name, Docker, Celery, cloud provider, frontend pipeline, etc.)\n- **`hooks/pre_gen_project.py`** — Pre-generation validation (uses Jinja2 syntax at the top for context manipulation)\n- **`hooks/post_gen_project.py`** — Post-generation cleanup: removes files based on user choices, generates Django secret key, sets DB credentials, modifies package.json and .pre-commit-config.yaml\n- **`{{cookiecutter.project_slug}}/`** — The template directory; files here use Jinja2 conditionals (`{% if cookiecutter.use_celery == 'y' %}`) to include/exclude content\n\n### Test Structure\n\n- **`tests/test_cookiecutter_generation.py`** — Main test file. Uses `pytest-cookies` to bake the template with 50+ option combinations defined in `SUPPORTED_COMBINATIONS`. Verifies: no Jinja syntax left in output, generated code passes linting, correct files present/absent. Skips on Windows (sh module) and macOS CI (slow).\n- **`tests/test_hooks.py`** — Unit tests for hook helper functions\n- **`tests/test_bare.sh`** / **`tests/test_docker.sh`** — Integration tests that generate a project and run its full test suite\n\n### Generated Project Layout\n\nThe generated Django project uses:\n\n- `config/settings/{base,local,test,production}.py` — Split settings with django-environ\n- `config/urls.py` — URL routing\n- `<project_slug>/users/` — Custom user model (username or email-based auth via django-allauth)\n- `compose/` — Docker configs for local and production\n- `requirements/` — Not used; dependencies managed via `pyproject.toml` + `uv.lock`\n\n## Conventions\n\n- **Python 3.13** required (`requires-python = \"==3.13.*\"`)\n- **Line length**: 119 characters (ruff and djlint)\n- **Ruff** for linting/formatting; config in `pyproject.toml` under `[tool.ruff]`\n- **djLint** for HTML template linting with `profile = \"jinja\"`\n- Template files under `{{cookiecutter.project_slug}}/` are excluded from ruff (not parseable Python)\n- **Calendar versioning**: `YYYY.MM.DD`\n\n## Adding a New Template Option\n\n1. Add the variable and choices to `cookiecutter.json`\n2. Add validation in `hooks/pre_gen_project.py` if needed\n3. Add file removal/modification logic in `hooks/post_gen_project.py`\n4. Use Jinja2 conditionals in template files: `{% if cookiecutter.option == 'y' %}`\n5. Add test combinations to `SUPPORTED_COMBINATIONS` in `tests/test_cookiecutter_generation.py`\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\nAll enhancements and patches to Cookiecutter Django will be documented in this file.\n\n<!-- GENERATOR_PLACEHOLDER -->\n\n## 2026.03.19\n\n\n### Updated\n\n- Update ruff to 0.15.7 ([#6451](https://github.com/cookiecutter/cookiecutter-django/pull/6451))\n\n- Update pyproject-fmt pre-commit hook ([#6449](https://github.com/cookiecutter/cookiecutter-django/pull/6449))\n\n## 2026.03.18\n\n\n### Updated\n\n- Update django-ninja to 1.6.2 ([#6448](https://github.com/cookiecutter/cookiecutter-django/pull/6448))\n\n- Update djangorestframework to 3.17.0 ([#6447](https://github.com/cookiecutter/cookiecutter-django/pull/6447))\n\n- Update django-ninja to 1.6.1 ([#6446](https://github.com/cookiecutter/cookiecutter-django/pull/6446))\n\n- Update django-stubs to 6.0.1 ([#6445](https://github.com/cookiecutter/cookiecutter-django/pull/6445))\n\n## 2026.03.17\n\n\n### Updated\n\n- Update sentry-sdk to 2.55.0 ([#6443](https://github.com/cookiecutter/cookiecutter-django/pull/6443))\n\n- Update coverage to 7.13.5 ([#6442](https://github.com/cookiecutter/cookiecutter-django/pull/6442))\n\n- Update pyproject-fmt from v2.18.1 to v2.19.0 ([#6441](https://github.com/cookiecutter/cookiecutter-django/pull/6441))\n\n- Update django-stubs to 6.0.0 ([#6440](https://github.com/cookiecutter/cookiecutter-django/pull/6440))\n\n## 2026.03.16\n\n\n### Updated\n\n- Update hiredis to 3.3.1 ([#6438](https://github.com/cookiecutter/cookiecutter-django/pull/6438))\n\n- Update uvicorn to 0.42.0 ([#6437](https://github.com/cookiecutter/cookiecutter-django/pull/6437))\n\n## 2026.03.13\n\n\n### Updated\n\n- Update ruff to 0.15.6 ([#6432](https://github.com/cookiecutter/cookiecutter-django/pull/6432))\n\n## 2026.03.12\n\n\n### Updated\n\n- Update django-ninja to 1.6.0 ([#6431](https://github.com/cookiecutter/cookiecutter-django/pull/6431))\n\n- Update pyproject-fmt pre-commit hook from 2.16.2 to 2.18.1 ([#6428](https://github.com/cookiecutter/cookiecutter-django/pull/6428))\n\n- Bump traefik from 3.6.9 to v3.6.10 ([#6423](https://github.com/cookiecutter/cookiecutter-django/pull/6423))\n\n- Bump nginx from 1.29.5 to 1.29.6 ([#6427](https://github.com/cookiecutter/cookiecutter-django/pull/6427))\n\n## 2026.03.10\n\n\n### Changed\n\n- Upgrade to Django 6.0 ([#6411](https://github.com/cookiecutter/cookiecutter-django/pull/6411))\n\n## 2026.03.09\n\n\n### Changed\n\n- Upgrade factory-boy to 3.3.3 and fix mypy compatibility ([#6417](https://github.com/cookiecutter/cookiecutter-django/pull/6417))\n\n### Updated\n\n- Update django-allauth to 65.15.0 ([#6424](https://github.com/cookiecutter/cookiecutter-django/pull/6424))\n\n- Update redis to 7.3.0 ([#6418](https://github.com/cookiecutter/cookiecutter-django/pull/6418))\n\n## 2026.03.06\n\n\n### Updated\n\n- Update ruff to 0.15.5 ([#6414](https://github.com/cookiecutter/cookiecutter-django/pull/6414))\n\n## 2026.03.03\n\n\n### Updated\n\n- Update django to 5.2.12 ([#6407](https://github.com/cookiecutter/cookiecutter-django/pull/6407))\n\n## 2026.03.02\n\n\n### Changed\n\n- Update dependabot.yml to remove Django 6.0 ignore rule ([#6402](https://github.com/cookiecutter/cookiecutter-django/pull/6402))\n\n### Updated\n\n- Update sentry-sdk to 2.54.0 ([#6403](https://github.com/cookiecutter/cookiecutter-django/pull/6403))\n\n- Bump amazon/aws-cli from 2.33.0 to 2.34.0 ([#6400](https://github.com/cookiecutter/cookiecutter-django/pull/6400))\n\n## 2026.03.01\n\n\n### Changed\n\n- Add `django-ninja` as REST API option ([#6088](https://github.com/cookiecutter/cookiecutter-django/pull/6088))\n\n### Updated\n\n- Update crispy-bootstrap5 to 2026.3 ([#6399](https://github.com/cookiecutter/cookiecutter-django/pull/6399))\n\n- Update django-crispy-forms to 2.6 ([#6398](https://github.com/cookiecutter/cookiecutter-django/pull/6398))\n\n## 2026.02.28\n\n\n### Updated\n\n- Update django-celery-beat to 2.9.0 ([#6397](https://github.com/cookiecutter/cookiecutter-django/pull/6397))\n\n## 2026.02.27\n\n\n### Updated\n\n- Update whitenoise to 6.12.0 ([#6396](https://github.com/cookiecutter/cookiecutter-django/pull/6396))\n\n## 2026.02.26\n\n\n### Changed\n\n- Add pyproject-fmt to the generated project ([#6074](https://github.com/cookiecutter/cookiecutter-django/pull/6074))\n\n### Updated\n\n- Update ruff to 0.15.4 ([#6395](https://github.com/cookiecutter/cookiecutter-django/pull/6395))\n\n- Update redis to 7.2.1 ([#6391](https://github.com/cookiecutter/cookiecutter-django/pull/6391))\n\n## 2026.02.25\n\n\n### Updated\n\n- Bump node from 24.13 to 24.14 ([#6386](https://github.com/cookiecutter/cookiecutter-django/pull/6386))\n\n- Update django-upgrade pre-commit hook ([#6385](https://github.com/cookiecutter/cookiecutter-django/pull/6385))\n\n## 2026.02.24\n\n\n### Changed\n\n- Add agents instructions ([#6208](https://github.com/cookiecutter/cookiecutter-django/pull/6208))\n\n### Updated\n\n- Bump traefik from 3.6.8 to 3.6.9 ([#6384](https://github.com/cookiecutter/cookiecutter-django/pull/6384))\n\n## 2026.02.20\n\n\n### Updated\n\n- Update ruff to 0.15.2 ([#6375](https://github.com/cookiecutter/cookiecutter-django/pull/6375))\n\n## 2026.02.19\n\n\n### Updated\n\n- Update werkzeug to 3.1.6 ([#6374](https://github.com/cookiecutter/cookiecutter-django/pull/6374))\n\n- Update django-environ to 0.13.0 ([#6368](https://github.com/cookiecutter/cookiecutter-django/pull/6368))\n\n- Update psycopg to 3.3.3 ([#6371](https://github.com/cookiecutter/cookiecutter-django/pull/6371))\n\n- Update pyproject-fmt to 2.16.1 ([#6369](https://github.com/cookiecutter/cookiecutter-django/pull/6369))\n\n## 2026.02.17\n\n\n### Updated\n\n- Update uvicorn to 0.41.0 ([#6366](https://github.com/cookiecutter/cookiecutter-django/pull/6366))\n\n## 2026.02.16\n\n\n### Updated\n\n- Update redis to 7.2.0 ([#6365](https://github.com/cookiecutter/cookiecutter-django/pull/6365))\n\n- Update sentry-sdk to 2.53.0 ([#6363](https://github.com/cookiecutter/cookiecutter-django/pull/6363))\n\n- Update pytest-django to 4.12.0 ([#6361](https://github.com/cookiecutter/cookiecutter-django/pull/6361))\n\n- Update django-environ to 0.12.1 ([#6360](https://github.com/cookiecutter/cookiecutter-django/pull/6360))\n\n- Update django-allauth to 65.14.3 ([#6359](https://github.com/cookiecutter/cookiecutter-django/pull/6359))\n\n## 2026.02.13\n\n\n### Updated\n\n- Update django-allauth to 65.14.2 ([#6358](https://github.com/cookiecutter/cookiecutter-django/pull/6358))\n\n- Update gunicorn to 25.1.0 ([#6357](https://github.com/cookiecutter/cookiecutter-django/pull/6357))\n\n- Update ruff to 0.15.1 ([#6354](https://github.com/cookiecutter/cookiecutter-django/pull/6354))\n\n## 2026.02.12\n\n\n### Updated\n\n- Bump traefik from 3.6.7 to 3.6.8 ([#6353](https://github.com/cookiecutter/cookiecutter-django/pull/6353))\n\n## 2026.02.11\n\n\n### Updated\n\n- Update pillow to 12.1.1 ([#6351](https://github.com/cookiecutter/cookiecutter-django/pull/6351))\n\n## 2026.02.10\n\n\n### Updated\n\n- Update redis to 7.1.1 ([#6338](https://github.com/cookiecutter/cookiecutter-django/pull/6338))\n\n- Update coverage to 7.13.4 ([#6336](https://github.com/cookiecutter/cookiecutter-django/pull/6336))\n\n## 2026.02.09\n\n\n### Updated\n\n- Update django-allauth to 65.14.1 ([#6324](https://github.com/cookiecutter/cookiecutter-django/pull/6324))\n\n- Update gunicorn to 25.0.3 ([#6323](https://github.com/cookiecutter/cookiecutter-django/pull/6323))\n\n## 2026.02.06\n\n\n### Updated\n\n- Update gunicorn to 25.0.2 ([#6322](https://github.com/cookiecutter/cookiecutter-django/pull/6322))\n\n## 2026.02.05\n\n\n### Updated\n\n- Bump nginx from 1.29.4 to 1.29.5 ([#6321](https://github.com/cookiecutter/cookiecutter-django/pull/6321))\n\n## 2026.02.04\n\n\n### Updated\n\n- Update sentry-sdk to 2.52.0 ([#6320](https://github.com/cookiecutter/cookiecutter-django/pull/6320))\n\n- Update ruff to 0.15.0 ([#6319](https://github.com/cookiecutter/cookiecutter-django/pull/6319))\n\n- Update gunicorn to 25.0.1 ([#6313](https://github.com/cookiecutter/cookiecutter-django/pull/6313))\n\n- Update djangorestframework-stubs to 3.16.8 ([#6317](https://github.com/cookiecutter/cookiecutter-django/pull/6317))\n\n- Update coverage to 7.13.3 ([#6315](https://github.com/cookiecutter/cookiecutter-django/pull/6315))\n\n- Update django to 5.2.11 ([#6314](https://github.com/cookiecutter/cookiecutter-django/pull/6314))\n\n## 2026.02.02\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#6311](https://github.com/cookiecutter/cookiecutter-django/pull/6311))\n\n- Update gunicorn to 25.0.0 ([#6312](https://github.com/cookiecutter/cookiecutter-django/pull/6312))\n\n- Update sentry-sdk to 2.51.0 ([#6309](https://github.com/cookiecutter/cookiecutter-django/pull/6309))\n\n- Update coverage to 7.13.2 ([#6307](https://github.com/cookiecutter/cookiecutter-django/pull/6307))\n\n## 2026.01.24\n\n\n### Updated\n\n- Update gunicorn to 24.1.1 ([#6306](https://github.com/cookiecutter/cookiecutter-django/pull/6306))\n\n## 2026.01.23\n\n\n### Updated\n\n- Update gunicorn to 24.1.0 ([#6305](https://github.com/cookiecutter/cookiecutter-django/pull/6305))\n\n- Update gunicorn to 24.0.0 ([#6303](https://github.com/cookiecutter/cookiecutter-django/pull/6303))\n\n- Update ruff to 0.14.14 ([#6302](https://github.com/cookiecutter/cookiecutter-django/pull/6302))\n\n## 2026.01.22\n\n\n### Updated\n\n- Update django-stubs to 5.2.9 ([#6301](https://github.com/cookiecutter/cookiecutter-django/pull/6301))\n\n## 2026.01.20\n\n\n### Updated\n\n- Update sentry-sdk to 2.50.0 ([#6300](https://github.com/cookiecutter/cookiecutter-django/pull/6300))\n\n- Update django-debug-toolbar to 6.2.0 ([#6299](https://github.com/cookiecutter/cookiecutter-django/pull/6299))\n\n## 2026.01.18\n\n\n### Updated\n\n- Update django-allauth to 65.14.0 ([#6298](https://github.com/cookiecutter/cookiecutter-django/pull/6298))\n\n## 2026.01.16\n\n\n### Updated\n\n- Update ruff to 0.14.13 ([#6293](https://github.com/cookiecutter/cookiecutter-django/pull/6293))\n\n## 2026.01.15\n\n\n### Updated\n\n- Bump traefik from 3.6.6 to 3.6.7 ([#6291](https://github.com/cookiecutter/cookiecutter-django/pull/6291))\n\n- Bump node from 24.12 to 24.13 ([#6288](https://github.com/cookiecutter/cookiecutter-django/pull/6288))\n\n- Bump amazon/aws-cli from 2.32.3 to 2.33.0 ([#6289](https://github.com/cookiecutter/cookiecutter-django/pull/6289))\n\n## 2026.01.13\n\n\n### Updated\n\n- Update djangorestframework-stubs to 3.16.7 ([#6285](https://github.com/cookiecutter/cookiecutter-django/pull/6285))\n\n## 2026.01.08\n\n\n### Updated\n\n- Update ruff to 0.14.11 ([#6280](https://github.com/cookiecutter/cookiecutter-django/pull/6280))\n\n- Update werkzeug to 3.1.5 ([#6279](https://github.com/cookiecutter/cookiecutter-django/pull/6279))\n\n- Update sentry-sdk to 2.49.0 ([#6278](https://github.com/cookiecutter/cookiecutter-django/pull/6278))\n\n## 2026.01.07\n\n\n### Fixed\n\n- Fix virtual environment setup to GitLab CI ([#6175](https://github.com/cookiecutter/cookiecutter-django/pull/6175))\n\n### Updated\n\n- Update django to 5.2.10 ([#6277](https://github.com/cookiecutter/cookiecutter-django/pull/6277))\n\n## 2026.01.04\n\n\n### Updated\n\n- Update celery to 5.6.2 ([#6275](https://github.com/cookiecutter/cookiecutter-django/pull/6275))\n\n## 2026.01.02\n\n\n### Updated\n\n- Update sphinx to 9.1.0 ([#6269](https://github.com/cookiecutter/cookiecutter-django/pull/6269))\n\n- Update pillow to 12.1.0 ([#6271](https://github.com/cookiecutter/cookiecutter-django/pull/6271))\n\n## 2025.12.30\n\n\n### Updated\n\n- Update celery to 5.6.1 ([#6267](https://github.com/cookiecutter/cookiecutter-django/pull/6267))\n\n- Bump traefik from 3.6.5 to 3.6.6 ([#6268](https://github.com/cookiecutter/cookiecutter-django/pull/6268))\n\n## 2025.12.29\n\n\n### Updated\n\n- Update coverage to 7.13.1 ([#6266](https://github.com/cookiecutter/cookiecutter-django/pull/6266))\n\n- Update collectfasta to 3.3.3 ([#6265](https://github.com/cookiecutter/cookiecutter-django/pull/6265))\n\n## 2025.12.23\n\n\n### Fixed\n\n- Remove silent `ImportError` suppression in `UsersConfig.ready()` ([#6263](https://github.com/cookiecutter/cookiecutter-django/pull/6263))\n\n- Switch Dependabot to uv ecosystem ([#6258](https://github.com/cookiecutter/cookiecutter-django/pull/6258))\n\n### Updated\n\n- Update collectfasta to 3.3.2 ([#6262](https://github.com/cookiecutter/cookiecutter-django/pull/6262))\n\n## 2025.12.22\n\n\n### Updated\n\n- Update uvicorn to 0.40.0 ([#6261](https://github.com/cookiecutter/cookiecutter-django/pull/6261))\n\n## 2025.12.19\n\n\n### Updated\n\n- Update ruff to 0.14.10 ([#6255](https://github.com/cookiecutter/cookiecutter-django/pull/6255))\n\n## 2025.12.18\n\n\n### Updated\n\n- Update django-anymail to 14.0 ([#6254](https://github.com/cookiecutter/cookiecutter-django/pull/6254))\n\n## 2025.12.17\n\n\n### Updated\n\n- Bump traefik from 3.6.4 to 3.6.5 ([#6253](https://github.com/cookiecutter/cookiecutter-django/pull/6253))\n\n- Update pre-commit to 4.5.1 ([#6251](https://github.com/cookiecutter/cookiecutter-django/pull/6251))\n\n## 2025.12.16\n\n\n### Updated\n\n- Update sentry-sdk to 2.48.0 ([#6250](https://github.com/cookiecutter/cookiecutter-django/pull/6250))\n\n## 2025.12.15\n\n\n### Updated\n\n- Update mypy to 1.19.1 ([#6249](https://github.com/cookiecutter/cookiecutter-django/pull/6249))\n\n## 2025.12.12\n\n\n### Updated\n\n- Bump node from 24.11 to 24.12 ([#6247](https://github.com/cookiecutter/cookiecutter-django/pull/6247))\n\n- Update ruff to 0.14.9 ([#6245](https://github.com/cookiecutter/cookiecutter-django/pull/6245))\n\n## 2025.12.10\n\n\n### Updated\n\n- Bump nginx from 1.29.3 to 1.29.4 ([#6244](https://github.com/cookiecutter/cookiecutter-django/pull/6244))\n\n## 2025.12.09\n\n\n### Updated\n\n- Update django-webpack-loader to 3.2.3 ([#6241](https://github.com/cookiecutter/cookiecutter-django/pull/6241))\n\n- Update coverage to 7.13.0 ([#6240](https://github.com/cookiecutter/cookiecutter-django/pull/6240))\n\n## 2025.12.08\n\n\n### Updated\n\n- Bump traefik from 3.6.2 to 3.6.4 ([#6239](https://github.com/cookiecutter/cookiecutter-django/pull/6239))\n\n- Update psycopg to 3.3.2 ([#6237](https://github.com/cookiecutter/cookiecutter-django/pull/6237))\n\n- Update pytest to 9.0.2 ([#6236](https://github.com/cookiecutter/cookiecutter-django/pull/6236))\n\n## 2025.12.05\n\n\n### Updated\n\n- Update rcssmin to 1.2.2 ([#6232](https://github.com/cookiecutter/cookiecutter-django/pull/6232))\n\n- Update django-compressor to 4.6.0 ([#6231](https://github.com/cookiecutter/cookiecutter-django/pull/6231))\n\n- Update ruff to 0.14.8 ([#6229](https://github.com/cookiecutter/cookiecutter-django/pull/6229))\n\n- Update sphinx to 9.0.4 ([#6228](https://github.com/cookiecutter/cookiecutter-django/pull/6228))\n\n- Update djangorestframework-stubs to 3.16.6 ([#6224](https://github.com/cookiecutter/cookiecutter-django/pull/6224))\n\n## 2025.12.03\n\n\n### Changed\n\n- Add docker buildkit flag ([#6219](https://github.com/cookiecutter/cookiecutter-django/pull/6219))\n\n### Updated\n\n- Update sentry-sdk to 2.47.0 ([#6223](https://github.com/cookiecutter/cookiecutter-django/pull/6223))\n\n- Update psycopg to 3.3.1 ([#6221](https://github.com/cookiecutter/cookiecutter-django/pull/6221))\n\n## 2025.12.02\n\n\n### Updated\n\n- Update django to 5.2.9 ([#6220](https://github.com/cookiecutter/cookiecutter-django/pull/6220))\n\n- Update mypy to 1.19.0 ([#6218](https://github.com/cookiecutter/cookiecutter-django/pull/6218))\n\n- Update django-stubs to 5.2.8 ([#6216](https://github.com/cookiecutter/cookiecutter-django/pull/6216))\n\n- Update psycopg to 3.3.0 ([#6215](https://github.com/cookiecutter/cookiecutter-django/pull/6215))\n\n- Update sphinx to 9.0.1 ([#6214](https://github.com/cookiecutter/cookiecutter-django/pull/6214))\n\n- Update werkzeug to 3.1.4 ([#6212](https://github.com/cookiecutter/cookiecutter-django/pull/6212))\n\n- Update celery to 5.6.0 ([#6211](https://github.com/cookiecutter/cookiecutter-django/pull/6211))\n\n- Update ruff to 0.14.7 ([#6205](https://github.com/cookiecutter/cookiecutter-django/pull/6205))\n\n## 2025.11.25\n\n\n### Changed\n\n- Add optional args to &#34;just build&#34; ([#6196](https://github.com/cookiecutter/cookiecutter-django/pull/6196))\n\n### Documentation\n\n- Update PostgreSQL version range in README ([#6203](https://github.com/cookiecutter/cookiecutter-django/pull/6203))\n\n### Updated\n\n- Update sentry-sdk to 2.46.0 ([#6202](https://github.com/cookiecutter/cookiecutter-django/pull/6202))\n\n## 2025.11.24\n\n\n### Updated\n\n- Update coverage to 7.12.0 ([#6200](https://github.com/cookiecutter/cookiecutter-django/pull/6200))\n\n- Update pre-commit to 4.5.0 ([#6199](https://github.com/cookiecutter/cookiecutter-django/pull/6199))\n\n- Bump amazon/aws-cli from 2.31.0 to 2.32.3 ([#6197](https://github.com/cookiecutter/cookiecutter-django/pull/6197))\n\n- Update psycopg to 3.2.13 ([#6194](https://github.com/cookiecutter/cookiecutter-django/pull/6194))\n\n- Bump traefik from 3.5.4 to 3.6.2 ([#6192](https://github.com/cookiecutter/cookiecutter-django/pull/6192))\n\n- Update django-allauth to 65.13.1 ([#6189](https://github.com/cookiecutter/cookiecutter-django/pull/6189))\n\n- Update sentry-sdk to 2.45.0 ([#6185](https://github.com/cookiecutter/cookiecutter-django/pull/6185))\n\n- Update pytest to 9.0.1 ([#6179](https://github.com/cookiecutter/cookiecutter-django/pull/6179))\n\n- Update redis to 7.1.0 ([#6187](https://github.com/cookiecutter/cookiecutter-django/pull/6187))\n\n- Update ruff to 0.14.6 ([#6193](https://github.com/cookiecutter/cookiecutter-django/pull/6193))\n\n## 2025.11.16\n\n\n### Changed\n\n- Add PostgreSQL 18 ([#6144](https://github.com/cookiecutter/cookiecutter-django/pull/6144))\n\n### Updated\n\n- Update ruff to 0.14.5 ([#6182](https://github.com/cookiecutter/cookiecutter-django/pull/6182))\n\n## 2025.11.07\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#6165](https://github.com/cookiecutter/cookiecutter-django/pull/6165))\n\n- Update ruff to 0.14.4 ([#6164](https://github.com/cookiecutter/cookiecutter-django/pull/6164))\n\n- Update django-crispy-forms to 2.5 ([#6163](https://github.com/cookiecutter/cookiecutter-django/pull/6163))\n\n## 2025.11.06\n\n\n### Updated\n\n- Update django-webpack-loader to 3.2.2 ([#6161](https://github.com/cookiecutter/cookiecutter-django/pull/6161))\n\n- Update django to 5.2.8 ([#6160](https://github.com/cookiecutter/cookiecutter-django/pull/6160))\n\n## 2025.11.03\n\n\n### Updated\n\n- Update drf-spectacular to 0.29.0 ([#6158](https://github.com/cookiecutter/cookiecutter-django/pull/6158))\n\n## 2025.10.31\n\n\n### Updated\n\n- Update psycopg to 3.2.12 ([#6143](https://github.com/cookiecutter/cookiecutter-django/pull/6143))\n\n- Update django-allauth to 65.13.0 ([#6157](https://github.com/cookiecutter/cookiecutter-django/pull/6157))\n\n- Update ruff to 0.14.3 ([#6155](https://github.com/cookiecutter/cookiecutter-django/pull/6155))\n\n- Update django-debug-toolbar to 6.1.0 ([#6154](https://github.com/cookiecutter/cookiecutter-django/pull/6154))\n\n- Update sentry-sdk to 2.43.0 ([#6151](https://github.com/cookiecutter/cookiecutter-django/pull/6151))\n\n- Update redis to 7.0.1 ([#6146](https://github.com/cookiecutter/cookiecutter-django/pull/6146))\n\n- Bump traefik from 3.5.3 to 3.5.4 ([#6150](https://github.com/cookiecutter/cookiecutter-django/pull/6150))\n\n- Bump nginx from 1.29.2 to 1.29.3 ([#6149](https://github.com/cookiecutter/cookiecutter-django/pull/6149))\n\n- Bump node from 24.10 to 24.11 ([#6147](https://github.com/cookiecutter/cookiecutter-django/pull/6147))\n\n## 2025.10.27\n\n\n### Fixed\n\n- keep_local_envs_in_vcs user preference ([#6132](https://github.com/cookiecutter/cookiecutter-django/pull/6132))\n\n## 2025.10.24\n\n\n### Updated\n\n- Update django-upgrade pre-commit hook to 1.29.1 ([#6141](https://github.com/cookiecutter/cookiecutter-django/pull/6141))\n\n## 2025.10.23\n\n\n### Updated\n\n- Update ruff to 0.14.2 ([#6140](https://github.com/cookiecutter/cookiecutter-django/pull/6140))\n\n## 2025.10.22\n\n\n### Updated\n\n- Update djangorestframework-stubs to 3.16.5 ([#6137](https://github.com/cookiecutter/cookiecutter-django/pull/6137))\n\n## 2025.10.21\n\n\n### Updated\n\n- Update sentry-sdk to 2.42.1 ([#6136](https://github.com/cookiecutter/cookiecutter-django/pull/6136))\n\n- Update psycopg to 3.2.11 ([#6135](https://github.com/cookiecutter/cookiecutter-django/pull/6135))\n\n## 2025.10.20\n\n\n### Changed\n\n- Update pre-commit GitLab image to python3.13-bookworm ([#6126](https://github.com/cookiecutter/cookiecutter-django/pull/6126))\n\n### Documentation\n\n- Fixed various broken URLs and typos in the documentation ([#6133](https://github.com/cookiecutter/cookiecutter-django/pull/6133))\n\n### Updated\n\n- Update uvicorn to 0.38.0 ([#6134](https://github.com/cookiecutter/cookiecutter-django/pull/6134))\n\n## 2025.10.17\n\n\n### Updated\n\n- Update ruff to 0.14.1 ([#6128](https://github.com/cookiecutter/cookiecutter-django/pull/6128))\n\n## 2025.10.16\n\n\n### Updated\n\n- Update django-allauth to 65.12.1 ([#6127](https://github.com/cookiecutter/cookiecutter-django/pull/6127))\n\n- Update pillow to 12.0.0 ([#6122](https://github.com/cookiecutter/cookiecutter-django/pull/6122))\n\n- Update sentry-sdk to 2.42.0 ([#6124](https://github.com/cookiecutter/cookiecutter-django/pull/6124))\n\n- Update coverage to 7.11.0 ([#6123](https://github.com/cookiecutter/cookiecutter-django/pull/6123))\n\n## 2025.10.15\n\n\n### Updated\n\n- Bump redis from 6 to 7.2 ([#6118](https://github.com/cookiecutter/cookiecutter-django/pull/6118))\n\n## 2025.10.14\n\n\n### Updated\n\n- Update watchfiles to 1.1.1 ([#6120](https://github.com/cookiecutter/cookiecutter-django/pull/6120))\n\n- Update hiredis to 3.3.0 ([#6119](https://github.com/cookiecutter/cookiecutter-django/pull/6119))\n\n## 2025.10.13\n\n\n### Changed\n\n- Enable version updates for Docker Compose files ([#6116](https://github.com/cookiecutter/cookiecutter-django/pull/6116))\n\n## 2025.10.10\n\n\n### Updated\n\n- Bump node from 24.9 to 24.10 ([#6107](https://github.com/cookiecutter/cookiecutter-django/pull/6107))\n\n## 2025.10.09\n\n\n### Updated\n\n- Update sentry-sdk to 2.41.0 ([#6106](https://github.com/cookiecutter/cookiecutter-django/pull/6106))\n\n## 2025.10.08\n\n\n### Updated\n\n- Update django-stubs to 5.2.7 ([#6104](https://github.com/cookiecutter/cookiecutter-django/pull/6104))\n\n- Bump nginx from 1.29.1 to 1.29.2 ([#6103](https://github.com/cookiecutter/cookiecutter-django/pull/6103))\n\n## 2025.10.07\n\n\n### Updated\n\n- Update ruff to 0.14.0 ([#6100](https://github.com/cookiecutter/cookiecutter-django/pull/6100))\n\n## 2025.10.06\n\n\n### Changed\n\n- fix(project generation fails with docker --load flag) ([#6097](https://github.com/cookiecutter/cookiecutter-django/pull/6097))\n\n### Updated\n\n- Update sentry-sdk to 2.40.0 ([#6096](https://github.com/cookiecutter/cookiecutter-django/pull/6096))\n\n- Update django-coverage-plugin to 3.2.0 ([#6095](https://github.com/cookiecutter/cookiecutter-django/pull/6095))\n\n- Update django-stubs to 5.2.6 ([#6093](https://github.com/cookiecutter/cookiecutter-django/pull/6093))\n\n- Update django-allauth to 65.12.0 ([#6092](https://github.com/cookiecutter/cookiecutter-django/pull/6092))\n\n## 2025.10.02\n\n\n### Updated\n\n- Update ruff to 0.13.3 ([#6089](https://github.com/cookiecutter/cookiecutter-django/pull/6089))\n\n## 2025.10.01\n\n\n### Fixed\n\n- Fix Docker error volume name is too short during project generation ([#6086](https://github.com/cookiecutter/cookiecutter-django/pull/6086))\n\n### Updated\n\n- Update django to 5.2.7 ([#6087](https://github.com/cookiecutter/cookiecutter-django/pull/6087))\n\n## 2025.09.30\n\n\n### Updated\n\n- Bump node from 24.8 to 24.9 ([#6081](https://github.com/cookiecutter/cookiecutter-django/pull/6081))\n\n- Bump traefik from 3.5.2 to 3.5.3 ([#6083](https://github.com/cookiecutter/cookiecutter-django/pull/6083))\n\n- Update djangorestframework-stubs to 3.16.4 ([#6080](https://github.com/cookiecutter/cookiecutter-django/pull/6080))\n\n## 2025.09.25\n\n\n### Updated\n\n- Update ruff to 0.13.2 ([#6078](https://github.com/cookiecutter/cookiecutter-django/pull/6078))\n\n- Update sentry-sdk to 2.39.0 ([#6077](https://github.com/cookiecutter/cookiecutter-django/pull/6077))\n\n## 2025.09.24\n\n\n### Updated\n\n- Bump amazon/aws-cli from 2.30.1 to 2.31.0 ([#6075](https://github.com/cookiecutter/cookiecutter-django/pull/6075))\n\n## 2025.09.23\n\n\n### Changed\n\n- Added help command to sphinx Makefile ([#6024](https://github.com/cookiecutter/cookiecutter-django/pull/6024))\n\n- Update RTD config to latest recommendation for uv ([#6072](https://github.com/cookiecutter/cookiecutter-django/pull/6072))\n\n### Updated\n\n- Update uvicorn to 0.37.0 ([#6073](https://github.com/cookiecutter/cookiecutter-django/pull/6073))\n\n- Bump sass from 1.93.0 to 1.93.1 ([#6071](https://github.com/cookiecutter/cookiecutter-django/pull/6071))\n\n## 2025.09.22\n\n\n### Updated\n\n- Update coverage to 7.10.7 ([#6070](https://github.com/cookiecutter/cookiecutter-django/pull/6070))\n\n- Upgrade to Python 3.13 ([#6067](https://github.com/cookiecutter/cookiecutter-django/pull/6067))\n\n## 2025.09.20\n\n\n### Updated\n\n- Update uvicorn-worker to 0.4.0 ([#6069](https://github.com/cookiecutter/cookiecutter-django/pull/6069))\n\n- Update uvicorn to 0.36.0 ([#6068](https://github.com/cookiecutter/cookiecutter-django/pull/6068))\n\n## 2025.09.19\n\n\n### Updated\n\n- Bump sass from 1.92.1 to 1.93.0 ([#6066](https://github.com/cookiecutter/cookiecutter-django/pull/6066))\n\n- Update ruff to 0.13.1 ([#6065](https://github.com/cookiecutter/cookiecutter-django/pull/6065))\n\n- Update mypy to 1.18.2 ([#6062](https://github.com/cookiecutter/cookiecutter-django/pull/6062))\n\n## 2025.09.18\n\n\n### Updated\n\n- Update djangorestframework-stubs to 3.16.3 ([#6061](https://github.com/cookiecutter/cookiecutter-django/pull/6061))\n\n- Update django-cors-headers to 4.9.0 ([#6060](https://github.com/cookiecutter/cookiecutter-django/pull/6060))\n\n- Update whitenoise to 6.11.0 ([#6059](https://github.com/cookiecutter/cookiecutter-django/pull/6059))\n\n## 2025.09.15\n\n\n### Changed\n\n- Upgrade to Django 5.2 ([#5962](https://github.com/cookiecutter/cookiecutter-django/pull/5962))\n\n### Updated\n\n- Update sentry-sdk to 2.38.0 ([#6057](https://github.com/cookiecutter/cookiecutter-django/pull/6057))\n\n- Bump sass from 1.77.6 to 1.92.1 ([#6021](https://github.com/cookiecutter/cookiecutter-django/pull/6021))\n\n- Bump amazon/aws-cli from 2.30.0 to 2.30.1 ([#6056](https://github.com/cookiecutter/cookiecutter-django/pull/6056))\n\n## 2025.09.14\n\n\n### Documentation\n\n- Update documentation for deploying on PythonAnywhere with uv ([#6017](https://github.com/cookiecutter/cookiecutter-django/pull/6017))\n\n### Updated\n\n- Update django-stubs to 5.2.5 ([#6055](https://github.com/cookiecutter/cookiecutter-django/pull/6055))\n\n## 2025.09.12\n\n\n### Updated\n\n- Bump amazon/aws-cli Docker image from 2.29.0 to 2.30.0 ([#6054](https://github.com/cookiecutter/cookiecutter-django/pull/6054))\n\n## 2025.09.11\n\n\n### Changed\n\n- Enable collectfasta for Azure storage ([#6052](https://github.com/cookiecutter/cookiecutter-django/pull/6052))\n\n### Updated\n\n- Update ruff to 0.13.0 ([#6045](https://github.com/cookiecutter/cookiecutter-django/pull/6045))\n\n- Bump ruff pre-commit hook from 0.12.12 to 0.13.0 ([#6046](https://github.com/cookiecutter/cookiecutter-django/pull/6046))\n\n- Bump node from 24.7 to 24.8 ([#6047](https://github.com/cookiecutter/cookiecutter-django/pull/6047))\n\n## 2025.09.10\n\n\n### Updated\n\n- Bump traefik from 3.5.1 to 3.5.2 ([#6041](https://github.com/cookiecutter/cookiecutter-django/pull/6041))\n\n## 2025.09.09\n\n\n### Updated\n\n- Bump nginx from 1.17.8 to 1.29.1 ([#6036](https://github.com/cookiecutter/cookiecutter-django/pull/6036))\n\n- Bump amazon/aws-cli image from 2.28.0 to 2.29.0 ([#6031](https://github.com/cookiecutter/cookiecutter-django/pull/6031))\n\n- Update django-allauth to 65.11.2 ([#6030](https://github.com/cookiecutter/cookiecutter-django/pull/6030))\n\n- Update sentry-sdk to 2.37.1 ([#6027](https://github.com/cookiecutter/cookiecutter-django/pull/6027))\n\n- Update whitenoise to 6.10.0 ([#6026](https://github.com/cookiecutter/cookiecutter-django/pull/6026))\n\n- Update django-upgrade pre-commit hook ([#6025](https://github.com/cookiecutter/cookiecutter-django/pull/6025))\n\n## 2025.09.08\n\n\n### Fixed\n\n- Use `--locked` instead of `--frozen` when running `uv sync` ([#6018](https://github.com/cookiecutter/cookiecutter-django/pull/6018))\n\n- Remove mentions of `pip` and `virtualenv` in the `install_python_dependencies.sh` utility script ([#6019](https://github.com/cookiecutter/cookiecutter-django/pull/6019))\n\n### Updated\n\n- Update psycopg to 3.2.10 ([#6023](https://github.com/cookiecutter/cookiecutter-django/pull/6023))\n\n- Update django-cors-headers to 4.8.0 ([#6022](https://github.com/cookiecutter/cookiecutter-django/pull/6022))\n\n## 2025.09.06\n\n\n### Changed\n\n- Migrate to `uv` as package manager for the generated project ([#5434](https://github.com/cookiecutter/cookiecutter-django/pull/5434))\n\n## 2025.09.05\n\n\n### Updated\n\n- Update sentry-sdk to 2.37.0 ([#6015](https://github.com/cookiecutter/cookiecutter-django/pull/6015))\n\n- Upgrade actions/setup-python to v6 in template ([#6012](https://github.com/cookiecutter/cookiecutter-django/pull/6012))\n\n- Update django to 5.1.12 ([#6009](https://github.com/cookiecutter/cookiecutter-django/pull/6009))\n\n- Update ruff to 0.12.12 ([#6013](https://github.com/cookiecutter/cookiecutter-django/pull/6013))\n\n- Update pytest to 8.4.2 ([#6011](https://github.com/cookiecutter/cookiecutter-django/pull/6011))\n\n## 2025.09.04\n\n\n### Updated\n\n- Update django-anymail to 13.1 ([#6007](https://github.com/cookiecutter/cookiecutter-django/pull/6007))\n\n- Update sentry-sdk to 2.36.0 ([#6006](https://github.com/cookiecutter/cookiecutter-django/pull/6006))\n\n## 2025.09.03\n\n\n### Documentation\n\n- Update PythonAnywhere deployment page ([#6003](https://github.com/cookiecutter/cookiecutter-django/pull/6003))\n\n### Updated\n\n- Bump traefik from 3.5.0 to 3.5.1 ([#6004](https://github.com/cookiecutter/cookiecutter-django/pull/6004))\n\n## 2025.09.02\n\n\n### Updated\n\n- Update sentry-sdk to 2.35.2 ([#6002](https://github.com/cookiecutter/cookiecutter-django/pull/6002))\n\n## 2025.08.31\n\n\n### Updated\n\n- Update coverage to 7.10.6 ([#5999](https://github.com/cookiecutter/cookiecutter-django/pull/5999))\n\n## 2025.08.29\n\n\n### Updated\n\n- Bump node from 24.6-bookworm-slim to 24.7-bookworm-slim in /{{cookiecutter.project_slug}}/compose/local/node ([#5997](https://github.com/cookiecutter/cookiecutter-django/pull/5997))\n\n- Update ruff to 0.12.11 ([#5998](https://github.com/cookiecutter/cookiecutter-django/pull/5998))\n\n## 2025.08.28\n\n\n### Updated\n\n- Update django-allauth to 65.11.1 ([#5992](https://github.com/cookiecutter/cookiecutter-django/pull/5992))\n\n- Auto-update pre-commit hooks ([#5993](https://github.com/cookiecutter/cookiecutter-django/pull/5993))\n\n## 2025.08.27\n\n\n### Updated\n\n- Update django-upgrade pre-commit hook ([#5991](https://github.com/cookiecutter/cookiecutter-django/pull/5991))\n\n## 2025.08.26\n\n\n### Updated\n\n- Update sentry-sdk to 2.35.1 ([#5988](https://github.com/cookiecutter/cookiecutter-django/pull/5988))\n\n- Update sphinx-autobuild to 2025.8.25 ([#5989](https://github.com/cookiecutter/cookiecutter-django/pull/5989))\n\n## 2025.08.25\n\n\n### Updated\n\n- Update collectfasta to 3.3.1 ([#5987](https://github.com/cookiecutter/cookiecutter-django/pull/5987))\n\n- Update coverage to 7.10.5 ([#5986](https://github.com/cookiecutter/cookiecutter-django/pull/5986))\n\n- Update pytest-sugar to 1.1.1 ([#5984](https://github.com/cookiecutter/cookiecutter-django/pull/5984))\n\n## 2025.08.21\n\n\n### Updated\n\n- Update ruff to 0.12.10 ([#5983](https://github.com/cookiecutter/cookiecutter-django/pull/5983))\n\n## 2025.08.18\n\n\n### Updated\n\n- Bump node from 24.5 to 24.6 ([#5981](https://github.com/cookiecutter/cookiecutter-django/pull/5981))\n\n- Update coverage to 7.10.4 ([#5980](https://github.com/cookiecutter/cookiecutter-django/pull/5980))\n\n- Update pytest-sugar to 1.1.0 ([#5979](https://github.com/cookiecutter/cookiecutter-django/pull/5979))\n\n## 2025.08.15\n\n\n### Updated\n\n- Update django-allauth to 65.11.0 ([#5977](https://github.com/cookiecutter/cookiecutter-django/pull/5977))\n\n- Update sentry-sdk to 2.35.0 ([#5976](https://github.com/cookiecutter/cookiecutter-django/pull/5976))\n\n## 2025.08.14\n\n\n### Updated\n\n- Update ruff to 0.12.9 ([#5975](https://github.com/cookiecutter/cookiecutter-django/pull/5975))\n\n## 2025.08.13\n\n\n### Fixed\n\n- Fix imagemin corruption with Gulp ([#5974](https://github.com/cookiecutter/cookiecutter-django/pull/5974))\n\n## 2025.08.12\n\n\n### Updated\n\n- Update coverage to 7.10.3 ([#5972](https://github.com/cookiecutter/cookiecutter-django/pull/5972))\n\n## 2025.08.10\n\n\n### Updated\n\n- Update pre-commit to 4.3.0 ([#5971](https://github.com/cookiecutter/cookiecutter-django/pull/5971))\n\n- Auto-update pre-commit hooks ([#5970](https://github.com/cookiecutter/cookiecutter-django/pull/5970))\n\n## 2025.08.08\n\n\n### Changed\n\n- Remove `project.css` when a bundler is used ([#5874](https://github.com/cookiecutter/cookiecutter-django/pull/5874))\n\n### Updated\n\n- Update redis to 6.4.0 ([#5968](https://github.com/cookiecutter/cookiecutter-django/pull/5968))\n\n- Update ruff to 0.12.8 ([#5969](https://github.com/cookiecutter/cookiecutter-django/pull/5969))\n\n## 2025.08.07\n\n\n### Updated\n\n- Update djangorestframework to 3.16.1 ([#5966](https://github.com/cookiecutter/cookiecutter-django/pull/5966))\n\n## 2025.08.06\n\n\n### Updated\n\n- Update coverage to 7.10.2 ([#5964](https://github.com/cookiecutter/cookiecutter-django/pull/5964))\n\n- Update redis to 6.3.0 ([#5963](https://github.com/cookiecutter/cookiecutter-django/pull/5963))\n\n## 2025.08.05\n\n\n### Changed\n\n- Rename `master` branch to `main` ([#5961](https://github.com/cookiecutter/cookiecutter-django/pull/5961))\n\n### Updated\n\n- Bump node from 22.14 to 24.5 in local Docker image ([#5960](https://github.com/cookiecutter/cookiecutter-django/pull/5960))\n\n## 2025.08.01\n\n\n### Updated\n\n- Update django-debug-toolbar to 6.0.0 ([#5945](https://github.com/cookiecutter/cookiecutter-django/pull/5945))\n\n- Bump amazon/aws-cli from 2.27.12 to 2.28.0 ([#5957](https://github.com/cookiecutter/cookiecutter-django/pull/5957))\n\n- Update mypy to 1.17.1 ([#5956](https://github.com/cookiecutter/cookiecutter-django/pull/5956))\n\n## 2025.07.30\n\n\n### Changed\n\n- docs: remove `$` from shell command examples for easier copy-pasting ([#5948](https://github.com/cookiecutter/cookiecutter-django/pull/5948))\n\n### Updated\n\n- Update sentry-sdk to 2.34.1 ([#5955](https://github.com/cookiecutter/cookiecutter-django/pull/5955))\n\n- Update ruff to 0.12.7 ([#5952](https://github.com/cookiecutter/cookiecutter-django/pull/5952))\n\n## 2025.07.27\n\n\n### Updated\n\n- Update coverage to 7.10.1 ([#5947](https://github.com/cookiecutter/cookiecutter-django/pull/5947))\n\n## 2025.07.25\n\n\n### Updated\n\n- Update django-anymail to 13.0.1 ([#5946](https://github.com/cookiecutter/cookiecutter-django/pull/5946))\n\n## 2025.07.24\n\n\n### Updated\n\n- Update coverage to 7.10.0 ([#5944](https://github.com/cookiecutter/cookiecutter-django/pull/5944))\n\n- Update ruff to 0.12.5 ([#5943](https://github.com/cookiecutter/cookiecutter-django/pull/5943))\n\n- Bump traefik from 3.4.4 to 3.5.0 ([#5942](https://github.com/cookiecutter/cookiecutter-django/pull/5942))\n\n## 2025.07.22\n\n\n### Updated\n\n- Update sentry-sdk to 2.33.2 ([#5941](https://github.com/cookiecutter/cookiecutter-django/pull/5941))\n\n## 2025.07.21\n\n\n### Updated\n\n- Update sentry-sdk to 2.33.1 ([#5940](https://github.com/cookiecutter/cookiecutter-django/pull/5940))\n\n## 2025.07.18\n\n\n### Updated\n\n- Update mypy to 1.17.0 ([#5937](https://github.com/cookiecutter/cookiecutter-django/pull/5937))\n\n- Update django-stubs to 5.2.2 ([#5936](https://github.com/cookiecutter/cookiecutter-django/pull/5936))\n\n## 2025.07.17\n\n\n### Updated\n\n- Update ruff to 0.12.4 ([#5935](https://github.com/cookiecutter/cookiecutter-django/pull/5935))\n\n## 2025.07.16\n\n\n### Updated\n\n- Update sentry-sdk to 2.33.0 ([#5933](https://github.com/cookiecutter/cookiecutter-django/pull/5933))\n\n## 2025.07.15\n\n\n### Updated\n\n- Update mypy to 1.16.1 ([#5901](https://github.com/cookiecutter/cookiecutter-django/pull/5901))\n\n- Bump traefik from 3.4.3 to 3.4.4 ([#5930](https://github.com/cookiecutter/cookiecutter-django/pull/5930))\n\n## 2025.07.14\n\n\n### Changed\n\n- Fix howto docker command ([#5929](https://github.com/cookiecutter/cookiecutter-django/pull/5929))\n\n## 2025.07.11\n\n\n### Updated\n\n- Update ruff to 0.12.3 ([#5928](https://github.com/cookiecutter/cookiecutter-django/pull/5928))\n\n- Update django-allauth to 65.10.0 ([#5927](https://github.com/cookiecutter/cookiecutter-django/pull/5927))\n\n## 2025.07.05\n\n\n### Updated\n\n- Update coverage to 7.9.2 ([#5925](https://github.com/cookiecutter/cookiecutter-django/pull/5925))\n\n## 2025.07.04\n\n\n### Updated\n\n- Update ruff to 0.12.2 ([#5923](https://github.com/cookiecutter/cookiecutter-django/pull/5923))\n\n## 2025.07.02\n\n\n### Updated\n\n- Update pillow to 11.3.0 ([#5921](https://github.com/cookiecutter/cookiecutter-django/pull/5921))\n\n## 2025.06.30\n\n\n### Updated\n\n- Bump traefik from 3.4.1 to 3.4.3 ([#5917](https://github.com/cookiecutter/cookiecutter-django/pull/5917))\n\n- Update uvicorn to 0.35.0 ([#5919](https://github.com/cookiecutter/cookiecutter-django/pull/5919))\n\n- Update sentry-sdk to 2.32.0 ([#5918](https://github.com/cookiecutter/cookiecutter-django/pull/5918))\n\n## 2025.06.26\n\n\n### Updated\n\n- Update ruff to 0.12.1 ([#5916](https://github.com/cookiecutter/cookiecutter-django/pull/5916))\n\n## 2025.06.24\n\n\n### Updated\n\n- Update sentry-sdk to 2.31.0 ([#5912](https://github.com/cookiecutter/cookiecutter-django/pull/5912))\n\n## 2025.06.19\n\n\n### Updated\n\n- Update pytest to 8.4.1 ([#5907](https://github.com/cookiecutter/cookiecutter-django/pull/5907))\n\n## 2025.06.18\n\n\n### Updated\n\n- Update ruff to 0.12.0 ([#5904](https://github.com/cookiecutter/cookiecutter-django/pull/5904))\n\n- Update django-stubs to 5.2.1 ([#5905](https://github.com/cookiecutter/cookiecutter-django/pull/5905))\n\n- Update django-redis to 6.0.0 ([#5903](https://github.com/cookiecutter/cookiecutter-django/pull/5903))\n\n- Update django-webpack-loader to 3.2.1 ([#5902](https://github.com/cookiecutter/cookiecutter-django/pull/5902))\n\n## 2025.06.17\n\n\n### Updated\n\n- Update django-coverage-plugin to 3.1.1 ([#5900](https://github.com/cookiecutter/cookiecutter-django/pull/5900))\n\n- Update watchfiles to 1.1.0 ([#5899](https://github.com/cookiecutter/cookiecutter-django/pull/5899))\n\n## 2025.06.15\n\n\n### Updated\n\n- Update coverage to 7.9.1 ([#5898](https://github.com/cookiecutter/cookiecutter-django/pull/5898))\n\n## 2025.06.13\n\n\n### Updated\n\n- Update coverage to 7.9.0 ([#5897](https://github.com/cookiecutter/cookiecutter-django/pull/5897))\n\n- Update sentry-sdk to 2.30.0 ([#5896](https://github.com/cookiecutter/cookiecutter-django/pull/5896))\n\n## 2025.06.11\n\n\n### Updated\n\n- Update collectfasta to 3.3.0 ([#5892](https://github.com/cookiecutter/cookiecutter-django/pull/5892))\n\n## 2025.06.10\n\n\n### Updated\n\n- Update django to 5.1.11 ([#5891](https://github.com/cookiecutter/cookiecutter-django/pull/5891))\n\n- Update crispy-bootstrap5 to 2025.6 ([#5888](https://github.com/cookiecutter/cookiecutter-django/pull/5888))\n\n## 2025.06.06\n\n\n### Updated\n\n- Update ruff to 0.11.13 ([#5887](https://github.com/cookiecutter/cookiecutter-django/pull/5887))\n\n## 2025.06.05\n\n\n### Updated\n\n- Bump python from 3.12.10 to 3.12.11 in docs Docker ([#5883](https://github.com/cookiecutter/cookiecutter-django/pull/5883))\n\n- Bump python from 3.12.10 to 3.12.11 in production Docker ([#5884](https://github.com/cookiecutter/cookiecutter-django/pull/5884))\n\n- Bump python from 3.12.10 3.12.11 in local Docker ([#5885](https://github.com/cookiecutter/cookiecutter-django/pull/5885))\n\n- Update django to 5.1.10 ([#5882](https://github.com/cookiecutter/cookiecutter-django/pull/5882))\n\n## 2025.06.04\n\n\n### Updated\n\n- Update argon2-cffi to 25.1.0 ([#5880](https://github.com/cookiecutter/cookiecutter-django/pull/5880))\n\n- Update pytest to 8.4.0 ([#5881](https://github.com/cookiecutter/cookiecutter-django/pull/5881))\n\n## 2025.06.02\n\n\n### Updated\n\n- Update django-allauth to 65.9.0 ([#5879](https://github.com/cookiecutter/cookiecutter-django/pull/5879))\n\n- Update uvicorn to 0.34.3 ([#5878](https://github.com/cookiecutter/cookiecutter-django/pull/5878))\n\n- Update celery to 5.5.3 ([#5877](https://github.com/cookiecutter/cookiecutter-django/pull/5877))\n\n- Update ruff to 0.11.12 ([#5872](https://github.com/cookiecutter/cookiecutter-django/pull/5872))\n\n## 2025.05.28\n\n\n### Updated\n\n- Update redis to 6.2.0 ([#5871](https://github.com/cookiecutter/cookiecutter-django/pull/5871))\n\n- Bump traefik from 3.4.0 to 3.4.1 ([#5870](https://github.com/cookiecutter/cookiecutter-django/pull/5870))\n\n## 2025.05.27\n\n\n### Updated\n\n- Update coverage to 7.8.2 ([#5868](https://github.com/cookiecutter/cookiecutter-django/pull/5868))\n\n- Update hiredis to 3.2.1 ([#5867](https://github.com/cookiecutter/cookiecutter-django/pull/5867))\n\n## 2025.05.24\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5866](https://github.com/cookiecutter/cookiecutter-django/pull/5866))\n\n## 2025.05.23\n\n\n### Updated\n\n- Update hiredis to 3.2.0 ([#5864](https://github.com/cookiecutter/cookiecutter-django/pull/5864))\n\n- Update ruff to 0.11.11 ([#5865](https://github.com/cookiecutter/cookiecutter-django/pull/5865))\n\n## 2025.05.22\n\n\n### Changed\n\n- Remove pin for fido2 library ([#5861](https://github.com/cookiecutter/cookiecutter-django/pull/5861))\n\n### Updated\n\n- Update coverage to 7.8.1 ([#5860](https://github.com/cookiecutter/cookiecutter-django/pull/5860))\n\n- Update django-allauth to 65.8.1 ([#5859](https://github.com/cookiecutter/cookiecutter-django/pull/5859))\n\n## 2025.05.21\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5858](https://github.com/cookiecutter/cookiecutter-django/pull/5858))\n\n## 2025.05.20\n\n\n### Fixed\n\n- Pin fido2&lt;2 ([#5854](https://github.com/cookiecutter/cookiecutter-django/pull/5854))\n\n### Updated\n\n- Update sentry-sdk to 2.29.1 ([#5853](https://github.com/cookiecutter/cookiecutter-django/pull/5853))\n\n- Update django-webpack-loader to 3.2.0 ([#5852](https://github.com/cookiecutter/cookiecutter-django/pull/5852))\n\n## 2025.05.16\n\n\n### Updated\n\n- Update django-celery-beat to 2.8.1 ([#5841](https://github.com/cookiecutter/cookiecutter-django/pull/5841))\n\n- Update ruff to 0.11.10 ([#5847](https://github.com/cookiecutter/cookiecutter-django/pull/5847))\n\n## 2025.05.14\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5846](https://github.com/cookiecutter/cookiecutter-django/pull/5846))\n\n## 2025.05.13\n\n\n### Changed\n\n- Remove redundant `use_celery` condition in local compose file ([#5845](https://github.com/cookiecutter/cookiecutter-django/pull/5845))\n\n### Updated\n\n- Update psycopg to 3.2.9 ([#5844](https://github.com/cookiecutter/cookiecutter-django/pull/5844))\n\n- Update redis to 6.1.0 ([#5842](https://github.com/cookiecutter/cookiecutter-django/pull/5842))\n\n## 2025.05.12\n\n\n### Changed\n\n- Remove extra spaces in Dockerfile `COPY` instruction paths ([#5822](https://github.com/cookiecutter/cookiecutter-django/pull/5822))\n\n- Add support for PostgreSQL 17 ([#5805](https://github.com/cookiecutter/cookiecutter-django/pull/5805))\n\n### Fixed\n\n- Fix media folder permissions prod dockerfile ([#5831](https://github.com/cookiecutter/cookiecutter-django/pull/5831))\n\n### Updated\n\n- Update sentry-sdk to 2.28.0 ([#5839](https://github.com/cookiecutter/cookiecutter-django/pull/5839))\n\n- Update djangorestframework-stubs to 3.16.0 ([#5806](https://github.com/cookiecutter/cookiecutter-django/pull/5806))\n\n- Bump traefik from 3.3.5 to 3.4.0 ([#5824](https://github.com/cookiecutter/cookiecutter-django/pull/5824))\n\n- Bump python from 3.12.9 to 3.12.10 in production Dockerfile ([#5774](https://github.com/cookiecutter/cookiecutter-django/pull/5774))\n\n- Bump python from 3.12.9 to 3.12.10 in docs Dockerfile ([#5773](https://github.com/cookiecutter/cookiecutter-django/pull/5773))\n\n- Bump python from 3.12.9 to 3.12.10 local Dockerfile ([#5772](https://github.com/cookiecutter/cookiecutter-django/pull/5772))\n\n- Update redis to 6.0.0 ([#5814](https://github.com/cookiecutter/cookiecutter-django/pull/5814))\n\n- Update psycopg to 3.2.8 ([#5836](https://github.com/cookiecutter/cookiecutter-django/pull/5836))\n\n- Update django-stubs to 5.2.0 ([#5804](https://github.com/cookiecutter/cookiecutter-django/pull/5804))\n\n- Bump amazon/aws-cli from 2.25.0 to 2.27.12 ([#5838](https://github.com/cookiecutter/cookiecutter-django/pull/5838))\n\n- Update ruff to 0.11.9 ([#5834](https://github.com/cookiecutter/cookiecutter-django/pull/5834))\n\n- Update hiredis to 3.1.1 ([#5833](https://github.com/cookiecutter/cookiecutter-django/pull/5833))\n\n## 2025.05.09\n\n\n### Updated\n\n- Update django-debug-toolbar to 5.2.0 ([#5816](https://github.com/cookiecutter/cookiecutter-django/pull/5816))\n\n- Update django-allauth to 65.8.0 ([#5830](https://github.com/cookiecutter/cookiecutter-django/pull/5830))\n\n- Update django to 5.1.9 ([#5828](https://github.com/cookiecutter/cookiecutter-django/pull/5828))\n\n## 2025.05.02\n\n\n### Updated\n\n- Update ruff to 0.11.8 ([#5819](https://github.com/cookiecutter/cookiecutter-django/pull/5819))\n\n## 2025.04.30\n\n\n### Updated\n\n- Update celery to 5.5.2 ([#5803](https://github.com/cookiecutter/cookiecutter-django/pull/5803))\n\n- Update ruff to 0.11.7 ([#5815](https://github.com/cookiecutter/cookiecutter-django/pull/5815))\n\n- Update sentry-sdk to 2.27.0 ([#5799](https://github.com/cookiecutter/cookiecutter-django/pull/5799))\n\n- Update uvicorn to 0.34.2 ([#5791](https://github.com/cookiecutter/cookiecutter-django/pull/5791))\n\n- Update django-crispy-forms to 2.4 ([#5780](https://github.com/cookiecutter/cookiecutter-django/pull/5780))\n\n- Update pillow to 11.2.1 ([#5779](https://github.com/cookiecutter/cookiecutter-django/pull/5779))\n\n- Update django-extensions to 4.1 ([#5776](https://github.com/cookiecutter/cookiecutter-django/pull/5776))\n\n- Update watchfiles to 1.0.5 ([#5771](https://github.com/cookiecutter/cookiecutter-django/pull/5771))\n\n- Update ruff to 0.11.6 ([#5789](https://github.com/cookiecutter/cookiecutter-django/pull/5789))\n\n- Update psycopg to 3.2.7 ([#5811](https://github.com/cookiecutter/cookiecutter-django/pull/5811))\n\n- Update redis to 5.3.0 ([#5813](https://github.com/cookiecutter/cookiecutter-django/pull/5813))\n\n## 2025.04.08\n\n\n### Updated\n\n- Update django-extensions to 4.0 ([#5770](https://github.com/cookiecutter/cookiecutter-django/pull/5770))\n\n## 2025.04.05\n\n\n### Changed\n\n- Add Docker build caching on GitHub Actions ([#5700](https://github.com/cookiecutter/cookiecutter-django/pull/5700))\n\n- Pin Pillow and Sphinx to non yanked release ([#5765](https://github.com/cookiecutter/cookiecutter-django/pull/5765))\n\n### Updated\n\n- Update ruff to 0.11.4 ([#5767](https://github.com/cookiecutter/cookiecutter-django/pull/5767))\n\n## 2025.04.03\n\n\n### Updated\n\n- Update django-anymail to 13.0 ([#5763](https://github.com/cookiecutter/cookiecutter-django/pull/5763))\n\n- Update pytest-django to 4.11.1 ([#5762](https://github.com/cookiecutter/cookiecutter-django/pull/5762))\n\n- Update ruff to 0.11.3 ([#5761](https://github.com/cookiecutter/cookiecutter-django/pull/5761))\n\n- Update django-allauth to 65.7.0 ([#5760](https://github.com/cookiecutter/cookiecutter-django/pull/5760))\n\n## 2025.04.02\n\n\n### Fixed\n\n- Fix line endings for dotenv merge script on Windows ([#5754](https://github.com/cookiecutter/cookiecutter-django/pull/5754))\n\n### Updated\n\n- Update crispy-bootstrap5 to 2025.4 ([#5756](https://github.com/cookiecutter/cookiecutter-django/pull/5756))\n\n- Update Django from 5.0 to 5.1 ([#5740](https://github.com/cookiecutter/cookiecutter-django/pull/5740))\n\n- Update sentry-sdk to 2.25.1 ([#5757](https://github.com/cookiecutter/cookiecutter-django/pull/5757))\n\n- Update django-storages to 1.14.6 ([#5753](https://github.com/cookiecutter/cookiecutter-django/pull/5753))\n\n- Update pytest-django to 4.11.0 ([#5752](https://github.com/cookiecutter/cookiecutter-django/pull/5752))\n\n## 2025.04.01\n\n\n### Updated\n\n- Update pillow to 11.2.0 ([#5751](https://github.com/cookiecutter/cookiecutter-django/pull/5751))\n\n- Bump traefik from 3.3.4 to 3.3.5 ([#5750](https://github.com/cookiecutter/cookiecutter-django/pull/5750))\n\n- Update celery to 5.5.0 ([#5748](https://github.com/cookiecutter/cookiecutter-django/pull/5748))\n\n## 2025.03.31\n\n\n### Updated\n\n- Update django-allauth to 65.6.0 ([#5741](https://github.com/cookiecutter/cookiecutter-django/pull/5741))\n\n- Update sentry-sdk to 2.25.0 ([#5747](https://github.com/cookiecutter/cookiecutter-django/pull/5747))\n\n- Update coverage to 7.8.0 ([#5745](https://github.com/cookiecutter/cookiecutter-django/pull/5745))\n\n## 2025.03.28\n\n\n### Updated\n\n- Update djangorestframework to 3.16.0 ([#5743](https://github.com/cookiecutter/cookiecutter-django/pull/5743))\n\n- Update django-upgrade pre-commit hook to v1.24.0 ([#5742](https://github.com/cookiecutter/cookiecutter-django/pull/5742))\n\n## 2025.03.24\n\n\n### Updated\n\n- Update django-allauth to 65.5.0 ([#5723](https://github.com/cookiecutter/cookiecutter-django/pull/5723))\n\n- Update sentry-sdk to 2.24.1 ([#5739](https://github.com/cookiecutter/cookiecutter-django/pull/5739))\n\n## 2025.03.22\n\n\n### Updated\n\n- Update coverage to 7.7.1 ([#5736](https://github.com/cookiecutter/cookiecutter-django/pull/5736))\n\n## 2025.03.21\n\n\n### Updated\n\n- Update sentry-sdk to 2.24.0 ([#5734](https://github.com/cookiecutter/cookiecutter-django/pull/5734))\n\n- Update django-debug-toolbar to 5.1.0 ([#5732](https://github.com/cookiecutter/cookiecutter-django/pull/5732))\n\n- Update ruff to 0.11.2 ([#5735](https://github.com/cookiecutter/cookiecutter-django/pull/5735))\n\n- Bump amazon/aws-cli from 2.24.0 to 2.25.0 ([#5733](https://github.com/cookiecutter/cookiecutter-django/pull/5733))\n\n- Auto-update pre-commit hooks ([#5657](https://github.com/cookiecutter/cookiecutter-django/pull/5657))\n\n## 2025.03.19\n\n\n### Updated\n\n- Update pre-commit to 4.2.0 ([#5730](https://github.com/cookiecutter/cookiecutter-django/pull/5730))\n\n## 2025.03.17\n\n\n### Updated\n\n- Update sentry-sdk to 2.23.1 ([#5727](https://github.com/cookiecutter/cookiecutter-django/pull/5727))\n\n- Update coverage to 7.7.0 ([#5725](https://github.com/cookiecutter/cookiecutter-django/pull/5725))\n\n## 2025.03.15\n\n\n### Updated\n\n- Update psycopg to 3.2.6 ([#5721](https://github.com/cookiecutter/cookiecutter-django/pull/5721))\n\n- Update ruff to 0.11.0 ([#5724](https://github.com/cookiecutter/cookiecutter-django/pull/5724))\n\n## 2025.03.08\n\n\n### Updated\n\n- Update ruff to 0.9.10 ([#5720](https://github.com/cookiecutter/cookiecutter-django/pull/5720))\n\n## 2025.03.06\n\n\n### Updated\n\n- Update django to 5.0.13 ([#5719](https://github.com/cookiecutter/cookiecutter-django/pull/5719))\n\n## 2025.03.04\n\n\n### Changed\n\n- Add groups for dependabot updates ([#5709](https://github.com/cookiecutter/cookiecutter-django/pull/5709))\n\n### Updated\n\n- Update sphinx to 8.3.0 ([#5714](https://github.com/cookiecutter/cookiecutter-django/pull/5714))\n\n- Update pytest to 8.3.5 ([#5713](https://github.com/cookiecutter/cookiecutter-django/pull/5713))\n\n## 2025.03.01\n\n\n### Updated\n\n- Update ruff to 0.9.9 ([#5711](https://github.com/cookiecutter/cookiecutter-django/pull/5711))\n\n## 2025.02.28\n\n\n### Updated\n\n- Update ruff to 0.9.8 ([#5708](https://github.com/cookiecutter/cookiecutter-django/pull/5708))\n\n- Bump babel-loader from 9.2.1 to 10.0.0 ([#5710](https://github.com/cookiecutter/cookiecutter-django/pull/5710))\n\n## 2025.02.26\n\n\n### Updated\n\n- Bump traefik from 3.3.3 to 3.3.4 ([#5705](https://github.com/cookiecutter/cookiecutter-django/pull/5705))\n\n## 2025.02.25\n\n\n### Documentation\n\n- Fix links to FAQ about `contrib.sites` directory ([#5704](https://github.com/cookiecutter/cookiecutter-django/pull/5704))\n\n## 2025.02.23\n\n\n### Changed\n\n- Group dependabot docker directories ([#5698](https://github.com/cookiecutter/cookiecutter-django/pull/5698))\n\n### Updated\n\n- Update sphinx to 8.2.1 ([#5696](https://github.com/cookiecutter/cookiecutter-django/pull/5696))\n\n- Update psycopg to 3.2.5 ([#5697](https://github.com/cookiecutter/cookiecutter-django/pull/5697))\n\n## 2025.02.21\n\n\n### Updated\n\n- Update djangorestframework-stubs to 3.15.3 ([#5695](https://github.com/cookiecutter/cookiecutter-django/pull/5695))\n\n- Update sphinx to 8.2.0 ([#5693](https://github.com/cookiecutter/cookiecutter-django/pull/5693))\n\n- Update ruff to 0.9.7 ([#5694](https://github.com/cookiecutter/cookiecutter-django/pull/5694))\n\n## 2025.02.17\n\n\n### Updated\n\n- Update sentry-sdk to 2.22.0 ([#5692](https://github.com/cookiecutter/cookiecutter-django/pull/5692))\n\n- Update django-storages to 1.14.5 ([#5690](https://github.com/cookiecutter/cookiecutter-django/pull/5690))\n\n## 2025.02.14\n\n\n### Updated\n\n- Bump node from 22.13 to 22.14 ([#5688](https://github.com/cookiecutter/cookiecutter-django/pull/5688))\n\n## 2025.02.13\n\n\n### Updated\n\n- Update sentry-sdk to 2.21.0 ([#5687](https://github.com/cookiecutter/cookiecutter-django/pull/5687))\n\n## 2025.02.11\n\n\n### Updated\n\n- Update coverage to 7.6.12 ([#5686](https://github.com/cookiecutter/cookiecutter-django/pull/5686))\n\n## 2025.02.10\n\n\n### Updated\n\n- Update pytest-django to 4.10.0 ([#5684](https://github.com/cookiecutter/cookiecutter-django/pull/5684))\n\n- Update ruff to 0.9.6 ([#5683](https://github.com/cookiecutter/cookiecutter-django/pull/5683))\n\n- Bump amazon/aws-cli from 2.23.0 to 2.24.0 ([#5682](https://github.com/cookiecutter/cookiecutter-django/pull/5682))\n\n## 2025.02.08\n\n\n### Updated\n\n- Update coverage to 7.6.11 ([#5681](https://github.com/cookiecutter/cookiecutter-django/pull/5681))\n\n## 2025.02.07\n\n\n### Updated\n\n- Update mypy to 1.15.0 ([#5664](https://github.com/cookiecutter/cookiecutter-django/pull/5664))\n\n- Update django-stubs to 5.1.3 ([#5680](https://github.com/cookiecutter/cookiecutter-django/pull/5680))\n\n- Bump python from 3.12.8 to 3.12.9 in local Docker image ([#5678](https://github.com/cookiecutter/cookiecutter-django/pull/5678))\n\n- Bump python from 3.12.8 to 3.12.9 in production Docker image ([#5677](https://github.com/cookiecutter/cookiecutter-django/pull/5677))\n\n- Bump python from 3.12.8 to 3.12.9 in docs Docker image ([#5676](https://github.com/cookiecutter/cookiecutter-django/pull/5676))\n\n- Update django-allauth to 65.4.1 ([#5679](https://github.com/cookiecutter/cookiecutter-django/pull/5679))\n\n- Update django-cors-headers to 4.7.0 ([#5675](https://github.com/cookiecutter/cookiecutter-django/pull/5675))\n\n- Update whitenoise to 6.9.0 ([#5674](https://github.com/cookiecutter/cookiecutter-django/pull/5674))\n\n## 2025.02.06\n\n\n### Fixed\n\n- Bump node version in production Dockerfile from 20 to 22.13 ([#5672](https://github.com/cookiecutter/cookiecutter-django/pull/5672))\n\n### Updated\n\n- Update ruff to 0.9.5 ([#5673](https://github.com/cookiecutter/cookiecutter-django/pull/5673))\n\n## 2025.02.05\n\n\n### Changed\n\n- Add missing trailing slash in test `MEDIA_URL` ([#5666](https://github.com/cookiecutter/cookiecutter-django/pull/5666))\n\n### Updated\n\n- Update django to 5.0.12 ([#5667](https://github.com/cookiecutter/cookiecutter-django/pull/5667))\n\n## 2025.02.03\n\n\n### Updated\n\n- Bump traefik from 3.3.2 to 3.3.3 ([#5660](https://github.com/cookiecutter/cookiecutter-django/pull/5660))\n\n- Update factory-boy to 3.3.2 ([#5661](https://github.com/cookiecutter/cookiecutter-django/pull/5661))\n\n## 2025.01.30\n\n\n### Updated\n\n- Update ruff to 0.9.4 ([#5659](https://github.com/cookiecutter/cookiecutter-django/pull/5659))\n\n## 2025.01.26\n\n\n### Changed\n\n- Migrate generated project from `runtime.txt` to `.python-version` ([#5652](https://github.com/cookiecutter/cookiecutter-django/pull/5652))\n\n### Documentation\n\n- Update Heroku deployment guide ([#5656](https://github.com/cookiecutter/cookiecutter-django/pull/5656))\n\n## 2025.01.24\n\n\n### Updated\n\n- Update ruff to 0.9.3 ([#5654](https://github.com/cookiecutter/cookiecutter-django/pull/5654))\n\n## 2025.01.21\n\n\n### Changed\n\n- Update linter error code from TCH to TC ([#5651](https://github.com/cookiecutter/cookiecutter-django/pull/5651))\n\n### Updated\n\n- Update pre-commit to 4.1.0 ([#5650](https://github.com/cookiecutter/cookiecutter-django/pull/5650))\n\n## 2025.01.20\n\n\n### Changed\n\n- Group all API tests under a `tests.api` namespace ([#5615](https://github.com/cookiecutter/cookiecutter-django/pull/5615))\n\n- Migrate post-generation hook to pathlib ([#5648](https://github.com/cookiecutter/cookiecutter-django/pull/5648))\n\n## 2025.01.16\n\n\n### Updated\n\n- Update ruff to 0.9.2 ([#5646](https://github.com/cookiecutter/cookiecutter-django/pull/5646))\n\n- Bump amazon/aws-cli from 2.22.1 to 2.23.0 ([#5645](https://github.com/cookiecutter/cookiecutter-django/pull/5645))\n\n## 2025.01.15\n\n\n### Fixed\n\n- Fix setting for to `CELERY_WORKER_HIJACK_ROOT_LOGGER` ([#5643](https://github.com/cookiecutter/cookiecutter-django/pull/5643))\n\n### Updated\n\n- Update psycopg to 3.2.4 ([#5644](https://github.com/cookiecutter/cookiecutter-django/pull/5644))\n\n- Update django-stubs to 5.1.2 ([#5639](https://github.com/cookiecutter/cookiecutter-django/pull/5639))\n\n- Bump traefik from 3.3.1 to 3.3.2 ([#5642](https://github.com/cookiecutter/cookiecutter-django/pull/5642))\n\n## 2025.01.14\n\n\n### Updated\n\n- Update django to 5.0.11 ([#5640](https://github.com/cookiecutter/cookiecutter-django/pull/5640))\n\n- Update sentry-sdk to 2.20.0 ([#5638](https://github.com/cookiecutter/cookiecutter-django/pull/5638))\n\n- Update django-debug-toolbar to 5.0.1 ([#5636](https://github.com/cookiecutter/cookiecutter-django/pull/5636))\n\n## 2025.01.13\n\n\n### Updated\n\n- Update django-environ to 0.12.0 ([#5635](https://github.com/cookiecutter/cookiecutter-django/pull/5635))\n\n- Bump traefik from 3.3.0 to 3.3.1 ([#5634](https://github.com/cookiecutter/cookiecutter-django/pull/5634))\n\n## 2025.01.11\n\n\n### Updated\n\n- Update ruff to 0.9.1 ([#5633](https://github.com/cookiecutter/cookiecutter-django/pull/5633))\n\n## 2025.01.10\n\n\n### Updated\n\n- Update watchfiles to 1.0.4 ([#5631](https://github.com/cookiecutter/cookiecutter-django/pull/5631))\n\n## 2025.01.09\n\n\n### Changed\n\n- Drop support for Python 2 in template generation hooks ([#5614](https://github.com/cookiecutter/cookiecutter-django/pull/5614))\n\n### Updated\n\n- Bump node from 22.12 to 22.13 ([#5627](https://github.com/cookiecutter/cookiecutter-django/pull/5627))\n\n## 2025.01.07\n\n\n### Fixed\n\n- Set `minimum_pre_commit_version` in pre-commit config ([#5626](https://github.com/cookiecutter/cookiecutter-django/pull/5626))\n\n### Updated\n\n- Bump traefik from 3.2.3 to 3.3.0 ([#5625](https://github.com/cookiecutter/cookiecutter-django/pull/5625))\n\n## 2025.01.06\n\n\n### Changed\n\n- Add justfile for use with docker ([#5621](https://github.com/cookiecutter/cookiecutter-django/pull/5621))\n\n## 2025.01.04\n\n\n### Updated\n\n- Update ruff to 0.8.6 ([#5622](https://github.com/cookiecutter/cookiecutter-django/pull/5622))\n\n## 2025.01.02\n\n\n### Fixed\n\n- Fix logging configuration for Celery tasks ([#5563](https://github.com/cookiecutter/cookiecutter-django/pull/5563))\n\n### Updated\n\n- Update ruff to 0.8.5 ([#5619](https://github.com/cookiecutter/cookiecutter-django/pull/5619))\n\n- Update pillow to 11.1.0 ([#5617](https://github.com/cookiecutter/cookiecutter-django/pull/5617))\n\n## 2024.12.27\n\n\n### Updated\n\n- Update coverage to 7.6.10 ([#5608](https://github.com/cookiecutter/cookiecutter-django/pull/5608))\n\n- Update uvicorn-worker to 0.3.0 ([#5607](https://github.com/cookiecutter/cookiecutter-django/pull/5607))\n\n## 2024.12.26\n\n\n### Updated\n\n- Update collectfasta to 3.2.1 ([#5606](https://github.com/cookiecutter/cookiecutter-django/pull/5606))\n\n- Update django-allauth to 65.3.1 ([#5605](https://github.com/cookiecutter/cookiecutter-django/pull/5605))\n\n## 2024.12.24\n\n\n### Updated\n\n- Update djlint to 1.36.4 ([#5603](https://github.com/cookiecutter/cookiecutter-django/pull/5603))\n\n- Update uvicorn to 0.34.0 ([#5592](https://github.com/cookiecutter/cookiecutter-django/pull/5592))\n\n## 2024.12.23\n\n\n### Updated\n\n- Bump webpack-cli from 5.1.4 to 6.0.1 ([#5601](https://github.com/cookiecutter/cookiecutter-django/pull/5601))\n\n## 2024.12.20\n\n\n### Updated\n\n- Update ruff to 0.8.4 ([#5595](https://github.com/cookiecutter/cookiecutter-django/pull/5595))\n\n## 2024.12.17\n\n\n### Updated\n\n- Update djangorestframework-stubs to 3.15.2 ([#5591](https://github.com/cookiecutter/cookiecutter-django/pull/5591))\n\n- Bump traefik from 3.2.2 to 3.2.3 ([#5594](https://github.com/cookiecutter/cookiecutter-django/pull/5594))\n\n## 2024.12.12\n\n\n### Updated\n\n- Update ruff to 0.8.3 ([#5587](https://github.com/cookiecutter/cookiecutter-django/pull/5587))\n\n## 2024.12.11\n\n\n### Updated\n\n- Bump traefik from 3.2.1 to 3.2.2 ([#5586](https://github.com/cookiecutter/cookiecutter-django/pull/5586))\n\n## 2024.12.10\n\n\n### Updated\n\n- Update watchfiles to 1.0.3 ([#5585](https://github.com/cookiecutter/cookiecutter-django/pull/5585))\n\n- Bump node from 22.11 to 22.12 ([#5583](https://github.com/cookiecutter/cookiecutter-django/pull/5583))\n\n## 2024.12.08\n\n\n### Fixed\n\n- Pin node to version 22.11 ([#5582](https://github.com/cookiecutter/cookiecutter-django/pull/5582))\n\n### Updated\n\n- Update ruff to 0.8.2 ([#5576](https://github.com/cookiecutter/cookiecutter-django/pull/5576))\n\n- Update coverage to 7.6.9 ([#5581](https://github.com/cookiecutter/cookiecutter-django/pull/5581))\n\n- Update sentry-sdk to 2.19.2 ([#5579](https://github.com/cookiecutter/cookiecutter-django/pull/5579))\n\n- Bump python from 3.12.7 to 3.12.8 in production Docker image ([#5575](https://github.com/cookiecutter/cookiecutter-django/pull/5575))\n\n- Bump python from 3.12.7 to 3.12.8 in local Docker image ([#5574](https://github.com/cookiecutter/cookiecutter-django/pull/5574))\n\n- Bump python from 3.12.7 to 3.12.8 in docs Docker image ([#5573](https://github.com/cookiecutter/cookiecutter-django/pull/5573))\n\n- Update hiredis to 3.1.0 ([#5571](https://github.com/cookiecutter/cookiecutter-django/pull/5571))\n\n- Update redis to 5.2.1 ([#5580](https://github.com/cookiecutter/cookiecutter-django/pull/5580))\n\n- Update django to 5.0.10 ([#5572](https://github.com/cookiecutter/cookiecutter-django/pull/5572))\n\n- Update drf-spectacular to 0.28.0 ([#5564](https://github.com/cookiecutter/cookiecutter-django/pull/5564))\n\n## 2024.12.03\n\n\n### Updated\n\n- Update django-upgrade to 1.22.2 ([#5567](https://github.com/cookiecutter/cookiecutter-django/pull/5567))\n\n## 2024.12.02\n\n\n### Updated\n\n- Update pytest to 8.3.4 ([#5566](https://github.com/cookiecutter/cookiecutter-django/pull/5566))\n\n## 2024.12.01\n\n\n### Updated\n\n- Update django-allauth to 65.3.0 ([#5565](https://github.com/cookiecutter/cookiecutter-django/pull/5565))\n\n## 2024.11.29\n\n\n### Updated\n\n- Update ruff to 0.8.1 ([#5557](https://github.com/cookiecutter/cookiecutter-django/pull/5557))\n\n- Update djlint to 1.36.3 ([#5558](https://github.com/cookiecutter/cookiecutter-django/pull/5558))\n\n## 2024.11.28\n\n\n### Updated\n\n- Update djlint to 1.36.2 ([#5555](https://github.com/cookiecutter/cookiecutter-django/pull/5555))\n\n## 2024.11.27\n\n\n### Fixed\n\n- Pin dart-sass to 1.77.6 to avoid deprecation warnings ([#5552](https://github.com/cookiecutter/cookiecutter-django/pull/5552))\n\n### Updated\n\n- Bump gulp-imagemin from 7.1.0 to 9.1.0 ([#5052](https://github.com/cookiecutter/cookiecutter-django/pull/5052))\n\n- Bump gulp from 4.0.2 to 5.0.0 ([#4949](https://github.com/cookiecutter/cookiecutter-django/pull/4949))\n\n## 2024.11.26\n\n\n### Updated\n\n- Update coverage to 7.6.8 ([#5547](https://github.com/cookiecutter/cookiecutter-django/pull/5547))\n\n- Update watchfiles to 1.0.0 ([#5548](https://github.com/cookiecutter/cookiecutter-django/pull/5548))\n\n## 2024.11.22\n\n\n### Updated\n\n- Update ruff to 0.8.0 ([#5545](https://github.com/cookiecutter/cookiecutter-django/pull/5545))\n\n## 2024.11.21\n\n\n### Changed\n\n- Add support for secure Redis (TLS support) ([#5526](https://github.com/cookiecutter/cookiecutter-django/pull/5526))\n\n### Updated\n\n- Update sentry-sdk to 2.19.0 ([#5543](https://github.com/cookiecutter/cookiecutter-django/pull/5543))\n\n- Update uvicorn to 0.32.1 ([#5539](https://github.com/cookiecutter/cookiecutter-django/pull/5539))\n\n- Bump traefik from 3.2.0 to 3.2.1 ([#5541](https://github.com/cookiecutter/cookiecutter-django/pull/5541))\n\n## 2024.11.20\n\n\n### Fixed\n\n- Fix typos in translation instructions in README ([#5538](https://github.com/cookiecutter/cookiecutter-django/pull/5538))\n\n### Updated\n\n- Bump amazon/aws-cli from 2.21.0 to 2.22.1 ([#5537](https://github.com/cookiecutter/cookiecutter-django/pull/5537))\n\n## 2024.11.16\n\n\n### Updated\n\n- Update ruff to 0.7.4 ([#5531](https://github.com/cookiecutter/cookiecutter-django/pull/5531))\n\n## 2024.11.15\n\n\n### Updated\n\n- Update coverage to 7.6.5 ([#5529](https://github.com/cookiecutter/cookiecutter-django/pull/5529))\n\n## 2024.11.14\n\n\n### Updated\n\n- Bump amazon/aws-cli from 2.20.0 to 2.21.0 ([#5528](https://github.com/cookiecutter/cookiecutter-django/pull/5528))\n\n## 2024.11.13\n\n\n### Updated\n\n- Update werkzeug to 3.1.3 ([#5524](https://github.com/cookiecutter/cookiecutter-django/pull/5524))\n\n- Update ruff to 0.7.3 ([#5521](https://github.com/cookiecutter/cookiecutter-django/pull/5521))\n\n- Bump amazon/aws-cli from 2.19.0 to 2.20.0 ([#5527](https://github.com/cookiecutter/cookiecutter-django/pull/5527))\n\n- Update django-allauth to 65.2.0 ([#5523](https://github.com/cookiecutter/cookiecutter-django/pull/5523))\n\n## 2024.11.08\n\n\n### Updated\n\n- Update ruff pre-commit hook to 0.7.3 ([#5522](https://github.com/cookiecutter/cookiecutter-django/pull/5522))\n\n## 2024.11.07\n\n\n### Updated\n\n- Update djlint to 1.36.1 ([#5519](https://github.com/cookiecutter/cookiecutter-django/pull/5519))\n\n## 2024.11.05\n\n\n### Updated\n\n- Update djlint to 1.36.0 ([#5517](https://github.com/cookiecutter/cookiecutter-django/pull/5517))\n\n## 2024.11.04\n\n\n### Updated\n\n- Update sentry-sdk to 2.18.0 ([#5515](https://github.com/cookiecutter/cookiecutter-django/pull/5515))\n\n## 2024.11.02\n\n\n### Updated\n\n- Update ruff to 0.7.2 ([#5510](https://github.com/cookiecutter/cookiecutter-django/pull/5510))\n\n## 2024.11.01\n\n\n### Updated\n\n- Update djlint to 1.35.4 ([#5508](https://github.com/cookiecutter/cookiecutter-django/pull/5508))\n\n- Bump amazon/aws-cli from 2.18.1 to 2.19.0 ([#5507](https://github.com/cookiecutter/cookiecutter-django/pull/5507))\n\n## 2024.10.30\n\n\n### Documentation\n\n- Small spelling correction in comment ([#5502](https://github.com/cookiecutter/cookiecutter-django/pull/5502))\n\n### Updated\n\n- Update djlint to 1.35.3 ([#5503](https://github.com/cookiecutter/cookiecutter-django/pull/5503))\n\n- Update whitenoise to 6.8.2 ([#5501](https://github.com/cookiecutter/cookiecutter-django/pull/5501))\n\n## 2024.10.29\n\n\n### Updated\n\n- Update django-cors-headers to 4.6.0 ([#5499](https://github.com/cookiecutter/cookiecutter-django/pull/5499))\n\n- Update whitenoise to 6.8.1 ([#5497](https://github.com/cookiecutter/cookiecutter-django/pull/5497))\n\n- Bump traefik from 3.1.6 to 3.2.0 ([#5498](https://github.com/cookiecutter/cookiecutter-django/pull/5498))\n\n## 2024.10.26\n\n\n### Updated\n\n- Update django-stubs to 5.1.1 ([#5495](https://github.com/cookiecutter/cookiecutter-django/pull/5495))\n\n- Update mypy to 1.13.0 ([#5484](https://github.com/cookiecutter/cookiecutter-django/pull/5484))\n\n- Update werkzeug to 3.0.6 ([#5492](https://github.com/cookiecutter/cookiecutter-django/pull/5492))\n\n## 2024.10.25\n\n\n### Updated\n\n- Update werkzeug to 3.0.5 and unpin watchdog&lt;5 ([#5489](https://github.com/cookiecutter/cookiecutter-django/pull/5489))\n\n## 2024.10.24\n\n\n### Updated\n\n- Update ruff to 0.7.1 ([#5487](https://github.com/cookiecutter/cookiecutter-django/pull/5487))\n\n- Update redis to 5.2.0 ([#5486](https://github.com/cookiecutter/cookiecutter-django/pull/5486))\n\n- Update django-allauth to 65.1.0 ([#5485](https://github.com/cookiecutter/cookiecutter-django/pull/5485))\n\n## 2024.10.22\n\n\n### Changed\n\n- Fix broken links in generated README ([#5482](https://github.com/cookiecutter/cookiecutter-django/pull/5482))\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5483](https://github.com/cookiecutter/cookiecutter-django/pull/5483))\n\n## 2024.10.21\n\n\n### Changed\n\n- Remove CELERY_BROKER_URL in favor of REDIS_URL ([#4861](https://github.com/cookiecutter/cookiecutter-django/pull/4861))\n\n### Fixed\n\n- Fix a number of issues with Azure storage ([#5476](https://github.com/cookiecutter/cookiecutter-django/pull/5476))\n\n### Updated\n\n- Update coverage to 7.6.4 ([#5480](https://github.com/cookiecutter/cookiecutter-django/pull/5480))\n\n## 2024.10.17\n\n\n### Updated\n\n- Update ruff to 0.7.0 ([#5474](https://github.com/cookiecutter/cookiecutter-django/pull/5474))\n\n- Update uvicorn to 0.32.0 ([#5471](https://github.com/cookiecutter/cookiecutter-django/pull/5471))\n\n- Update pillow to 11.0.0 ([#5470](https://github.com/cookiecutter/cookiecutter-django/pull/5470))\n\n- Update sentry-sdk to 2.17.0 ([#5473](https://github.com/cookiecutter/cookiecutter-django/pull/5473))\n\n## 2024.10.15\n\n\n### Changed\n\n- [pre-commit.ci] pre-commit autoupdate ([#5468](https://github.com/cookiecutter/cookiecutter-django/pull/5468))\n\n## 2024.10.14\n\n\n### Changed\n\n- Add requirements for ubuntu 24.04 ([#5467](https://github.com/cookiecutter/cookiecutter-django/pull/5467))\n\n### Updated\n\n- Update sphinx to 8.1.3 ([#5463](https://github.com/cookiecutter/cookiecutter-django/pull/5463))\n\n- Update coverage to 7.6.3 ([#5464](https://github.com/cookiecutter/cookiecutter-django/pull/5464))\n\n## 2024.10.12\n\n\n### Changed\n\n- Pin Python version to 3.12 ([#5456](https://github.com/cookiecutter/cookiecutter-django/pull/5456))\n\n### Updated\n\n- Update sphinx to 8.1.1 ([#5457](https://github.com/cookiecutter/cookiecutter-django/pull/5457))\n\n- Auto-update pre-commit hooks ([#5458](https://github.com/cookiecutter/cookiecutter-django/pull/5458))\n\n- Update django-cors-headers to 4.5.0 ([#5459](https://github.com/cookiecutter/cookiecutter-django/pull/5459))\n\n## 2024.10.11\n\n\n### Changed\n\n- Update README.md broken links ([#5454](https://github.com/cookiecutter/cookiecutter-django/pull/5454))\n\n- wait-for-it as dependency in the run stage ([#5452](https://github.com/cookiecutter/cookiecutter-django/pull/5452))\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5450](https://github.com/cookiecutter/cookiecutter-django/pull/5450))\n\n## 2024.10.10\n\n\n### Updated\n\n- Update sentry-sdk to 2.16.0 ([#5444](https://github.com/cookiecutter/cookiecutter-django/pull/5444))\n\n- Bump traefik from 3.1.5 to 3.1.6 ([#5449](https://github.com/cookiecutter/cookiecutter-django/pull/5449))\n\n## 2024.10.09\n\n\n### Updated\n\n- Update coverage to 7.6.2 ([#5448](https://github.com/cookiecutter/cookiecutter-django/pull/5448))\n\n## 2024.10.08\n\n\n### Changed\n\n- [pre-commit.ci] pre-commit autoupdate ([#5441](https://github.com/cookiecutter/cookiecutter-django/pull/5441))\n\n### Updated\n\n- Update pre-commit to 4.0.1 ([#5445](https://github.com/cookiecutter/cookiecutter-django/pull/5445))\n\n- Bump amazon/aws-cli from 2.18.0 to 2.18.1 in /{{cookiecutter.project_slug}}/compose/production/aws ([#5443](https://github.com/cookiecutter/cookiecutter-django/pull/5443))\n\n- Auto-update pre-commit hooks ([#5442](https://github.com/cookiecutter/cookiecutter-django/pull/5442))\n\n## 2024.10.07\n\n\n### Documentation\n\n- Docs: fix Mailgun include in troubleshooting sections ([#5439](https://github.com/cookiecutter/cookiecutter-django/pull/5439))\n\n### Updated\n\n- Update sphinx to 8.0.2 ([#5263](https://github.com/cookiecutter/cookiecutter-django/pull/5263))\n\n- Update pre-commit to 4.0.0 ([#5432](https://github.com/cookiecutter/cookiecutter-django/pull/5432))\n\n- Auto-update pre-commit hooks ([#5433](https://github.com/cookiecutter/cookiecutter-django/pull/5433))\n\n- Update sphinx-rtd-theme to 3.0.0 ([#5437](https://github.com/cookiecutter/cookiecutter-django/pull/5437))\n\n- Bump amazon/aws-cli from 2.17.0 to 2.18.0 in /{{cookiecutter.project_slug}}/compose/production/aws ([#5436](https://github.com/cookiecutter/cookiecutter-django/pull/5436))\n\n## 2024.10.05\n\n\n### Changed\n\n- Replace pip with uv for the project files ([#5356](https://github.com/cookiecutter/cookiecutter-django/pull/5356))\n\n- Use wait-for-it in favor of the custom python script when waiting for postgres ([#5327](https://github.com/cookiecutter/cookiecutter-django/pull/5327))\n\n### Documentation\n\n- Spit docs into sections ([#5426](https://github.com/cookiecutter/cookiecutter-django/pull/5426))\n\n### Updated\n\n- Update crispy-bootstrap5 to 2024.10 ([#5430](https://github.com/cookiecutter/cookiecutter-django/pull/5430))\n\n## 2024.10.04\n\n\n### Updated\n\n- Update ruff to 0.6.9 ([#5428](https://github.com/cookiecutter/cookiecutter-django/pull/5428))\n\n- Update redis to 5.1.1 ([#5427](https://github.com/cookiecutter/cookiecutter-django/pull/5427))\n\n## 2024.10.03\n\n\n### Updated\n\n- Update sphinx-autobuild to 2024.10.3 ([#5420](https://github.com/cookiecutter/cookiecutter-django/pull/5420))\n\n- Bump traefik from 3.1.4 to 3.1.5 ([#5423](https://github.com/cookiecutter/cookiecutter-django/pull/5423))\n\n## 2024.10.02\n\n\n### Updated\n\n- Bump python from 3.12.6 to 3.12.7 in docs Docker image ([#5416](https://github.com/cookiecutter/cookiecutter-django/pull/5416))\n\n- Bump python from 3.12.6 to 3.12.7 in local Docker image ([#5415](https://github.com/cookiecutter/cookiecutter-django/pull/5415))\n\n- Bump python from 3.12.6 to 3.12.7 production Docker ([#5414](https://github.com/cookiecutter/cookiecutter-django/pull/5414))\n\n## 2024.10.01\n\n\n### Updated\n\n- Update sentry-sdk to 2.15.0 ([#5413](https://github.com/cookiecutter/cookiecutter-django/pull/5413))\n\n## 2024.09.29\n\n\n### Updated\n\n- Update psycopg to 3.2.3 ([#5411](https://github.com/cookiecutter/cookiecutter-django/pull/5411))\n\n## 2024.09.28\n\n\n### Updated\n\n- Update uvicorn to 0.31.0 ([#5408](https://github.com/cookiecutter/cookiecutter-django/pull/5408))\n\n## 2024.09.27\n\n\n### Updated\n\n- Update redis to 5.1.0 ([#5406](https://github.com/cookiecutter/cookiecutter-django/pull/5406))\n\n- Update django-allauth to 65.0.2 ([#5405](https://github.com/cookiecutter/cookiecutter-django/pull/5405))\n\n## 2024.09.26\n\n\n### Updated\n\n- Update ruff to 0.6.8 ([#5402](https://github.com/cookiecutter/cookiecutter-django/pull/5402))\n\n## 2024.09.24\n\n\n### Updated\n\n- Update django-stubs to 5.1.0 ([#5400](https://github.com/cookiecutter/cookiecutter-django/pull/5400))\n\n## 2024.09.23\n\n\n### Changed\n\n- Fix Makefile and make.bat files used for automatic generation of documentation. ([#5347](https://github.com/cookiecutter/cookiecutter-django/pull/5347))\n\n### Updated\n\n- Update django-allauth to 65.0.1 ([#5399](https://github.com/cookiecutter/cookiecutter-django/pull/5399))\n\n- Auto-update pre-commit hooks ([#5392](https://github.com/cookiecutter/cookiecutter-django/pull/5392))\n\n- Update django-allauth to 65.0.0 ([#5393](https://github.com/cookiecutter/cookiecutter-django/pull/5393))\n\n- Update ruff to 0.6.7 ([#5394](https://github.com/cookiecutter/cookiecutter-django/pull/5394))\n\n## 2024.09.21\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5391](https://github.com/cookiecutter/cookiecutter-django/pull/5391))\n\n## 2024.09.20\n\n\n### Updated\n\n- Update sphinx-autobuild to 2024.9.19 ([#5386](https://github.com/cookiecutter/cookiecutter-django/pull/5386))\n\n- Bump traefik from 3.1.3 to 3.1.4 in /{{cookiecutter.project_slug}}/compose/production/traefik ([#5389](https://github.com/cookiecutter/cookiecutter-django/pull/5389))\n\n- Update ruff to 0.6.6 ([#5388](https://github.com/cookiecutter/cookiecutter-django/pull/5388))\n\n- Update tox to 4.20.0 ([#5387](https://github.com/cookiecutter/cookiecutter-django/pull/5387))\n\n## 2024.09.17\n\n\n### Fixed\n\n- Set allauth email subject prefix ([#5278](https://github.com/cookiecutter/cookiecutter-django/pull/5278))\n\n### Documentation\n\n- Update postgres plan in Heroku deployment docs ([#5383](https://github.com/cookiecutter/cookiecutter-django/pull/5383))\n\n### Updated\n\n- Update sphinx-autobuild to 2024.9.17 ([#5382](https://github.com/cookiecutter/cookiecutter-django/pull/5382))\n\n- Bump traefik from 3.1.2 to 3.1.3 ([#5380](https://github.com/cookiecutter/cookiecutter-django/pull/5380))\n\n## 2024.09.16\n\n\n### Updated\n\n- Update psycopg to 3.2.2 ([#5378](https://github.com/cookiecutter/cookiecutter-django/pull/5378))\n\n## 2024.09.15\n\n\n### Updated\n\n- Update ruff to 0.6.5 ([#5373](https://github.com/cookiecutter/cookiecutter-django/pull/5373))\n\n## 2024.09.11\n\n\n### Updated\n\n- Update djangorestframework-stubs to 3.15.1 ([#5372](https://github.com/cookiecutter/cookiecutter-django/pull/5372))\n\n- Update django-anymail to 12.0 ([#5366](https://github.com/cookiecutter/cookiecutter-django/pull/5366))\n\n## 2024.09.10\n\n\n### Changed\n\n- Add nginx container to dependabot automation ([#5345](https://github.com/cookiecutter/cookiecutter-django/pull/5345))\n\n### Updated\n\n- Update pytest to 8.3.3 ([#5371](https://github.com/cookiecutter/cookiecutter-django/pull/5371))\n\n- Bump postcss-preset-env from 9.6.0 to 10.0.3 ([#5368](https://github.com/cookiecutter/cookiecutter-django/pull/5368))\n\n- Bump concurrently from 8.2.2 to 9.0.0 ([#5363](https://github.com/cookiecutter/cookiecutter-django/pull/5363))\n\n- Bump python to 3.12.6 in local Docker ([#5370](https://github.com/cookiecutter/cookiecutter-django/pull/5370))\n\n- Bump python to 3.12.6 in production Docker ([#5367](https://github.com/cookiecutter/cookiecutter-django/pull/5367))\n\n- Bump python to 3.12.6 in docs Docker image ([#5369](https://github.com/cookiecutter/cookiecutter-django/pull/5369))\n\n## 2024.09.09\n\n\n### Updated\n\n- Update sentry-sdk to 2.14.0 ([#5365](https://github.com/cookiecutter/cookiecutter-django/pull/5365))\n\n## 2024.09.08\n\n\n### Changed\n\n- Remove &#34;storages&#34; from `INSTALLED_APPS` ([#5361](https://github.com/cookiecutter/cookiecutter-django/pull/5361))\n\n## 2024.09.07\n\n\n### Changed\n\n- Fix Requires Python to allow minor versions ([#5360](https://github.com/cookiecutter/cookiecutter-django/pull/5360))\n\n## 2024.09.06\n\n\n### Updated\n\n- Update ruff to 0.6.4 ([#5354](https://github.com/cookiecutter/cookiecutter-django/pull/5354))\n\n- Update django-allauth to 64.2.1 ([#5352](https://github.com/cookiecutter/cookiecutter-django/pull/5352))\n\n- Auto-update pre-commit hooks ([#5353](https://github.com/cookiecutter/cookiecutter-django/pull/5353))\n\n## 2024.09.05\n\n\n### Updated\n\n- Update django-upgrade to 1.21.0 ([#5348](https://github.com/cookiecutter/cookiecutter-django/pull/5348))\n\n## 2024.09.04\n\n\n### Updated\n\n- Update django-model-utils to 5.0.0 ([#5343](https://github.com/cookiecutter/cookiecutter-django/pull/5343))\n\n## 2024.09.03\n\n\n### Fixed\n\n- Pin watchdog to 4.0.2 ([#5335](https://github.com/cookiecutter/cookiecutter-django/pull/5335))\n\n### Updated\n\n- Update django to 5.0.9 ([#5341](https://github.com/cookiecutter/cookiecutter-django/pull/5341))\n\n- Update sphinx-autobuild to 2024.9.3 ([#5340](https://github.com/cookiecutter/cookiecutter-django/pull/5340))\n\n## 2024.09.02\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5334](https://github.com/cookiecutter/cookiecutter-django/pull/5334))\n\n- Update django-allauth to 64.2.0 ([#5337](https://github.com/cookiecutter/cookiecutter-django/pull/5337))\n\n- Update pytest-django to 4.9.0 ([#5338](https://github.com/cookiecutter/cookiecutter-django/pull/5338))\n\n## 2024.08.30\n\n\n### Updated\n\n- Update django-webpack-loader to 3.1.1 ([#5336](https://github.com/cookiecutter/cookiecutter-django/pull/5336))\n\n## 2024.08.29\n\n\n### Updated\n\n- Update ruff to 0.6.3 ([#5333](https://github.com/cookiecutter/cookiecutter-django/pull/5333))\n\n- Update djlint to 1.35.2 ([#5332](https://github.com/cookiecutter/cookiecutter-django/pull/5332))\n\n- Update djlint pre-commit hook to v1.34.2  ([#5331](https://github.com/cookiecutter/cookiecutter-django/pull/5331))\n\n## 2024.08.28\n\n\n### Updated\n\n- Update watchfiles to 0.24.0 ([#5330](https://github.com/cookiecutter/cookiecutter-django/pull/5330))\n\n- Update djlint to 1.34.2 ([#5329](https://github.com/cookiecutter/cookiecutter-django/pull/5329))\n\n## 2024.08.26\n\n\n### Changed\n\n- Check DB migrations in GitHub CI ([#5322](https://github.com/cookiecutter/cookiecutter-django/pull/5322))\n\n### Updated\n\n- Update mypy to 1.11.2 ([#5320](https://github.com/cookiecutter/cookiecutter-django/pull/5320))\n\n## 2024.08.23\n\n\n### Updated\n\n- Update werkzeug to 3.0.4 ([#5313](https://github.com/cookiecutter/cookiecutter-django/pull/5313))\n\n- Update ruff to 0.6.2 ([#5316](https://github.com/cookiecutter/cookiecutter-django/pull/5316))\n\n## 2024.08.22\n\n\n### Updated\n\n- Update django-celery-beat to 2.7.0 ([#5315](https://github.com/cookiecutter/cookiecutter-django/pull/5315))\n\n## 2024.08.21\n\n\n### Changed\n\n- Add type hint for UserFactory ([#5312](https://github.com/cookiecutter/cookiecutter-django/pull/5312))\n\n## 2024.08.20\n\n\n### Fixed\n\n- Add missing extra_body block in allauth entrance.html ([#5308](https://github.com/cookiecutter/cookiecutter-django/pull/5308))\n\n### Updated\n\n- Bump sass-loader from 14.2.1 to 16.0.1 ([#5309](https://github.com/cookiecutter/cookiecutter-django/pull/5309))\n\n- Bump node from 20 to 22 ([#5039](https://github.com/cookiecutter/cookiecutter-django/pull/5039))\n\n- Bump webpack-merge from 5.10.0 to 6.0.1 ([#5187](https://github.com/cookiecutter/cookiecutter-django/pull/5187))\n\n- Bump css-loader from 6.11.0 to 7.1.2 ([#5089](https://github.com/cookiecutter/cookiecutter-django/pull/5089))\n\n- Bump traefik from 2.11.2 to 3.1.2 ([#5282](https://github.com/cookiecutter/cookiecutter-django/pull/5282))\n\n## 2024.08.19\n\n\n### Updated\n\n- Update factory-boy to 3.3.1 ([#5307](https://github.com/cookiecutter/cookiecutter-django/pull/5307))\n\n## 2024.08.17\n\n\n### Updated\n\n- Update ruff to 0.6.1 ([#5303](https://github.com/cookiecutter/cookiecutter-django/pull/5303))\n\n## 2024.08.16\n\n\n### Updated\n\n- Update django-allauth to 64.1.0 ([#5302](https://github.com/cookiecutter/cookiecutter-django/pull/5302))\n\n## 2024.08.15\n\n\n### Updated\n\n- Update ruff to 0.6.0 ([#5300](https://github.com/cookiecutter/cookiecutter-django/pull/5300))\n\n## 2024.08.13\n\n\n### Updated\n\n- Update tox to 4.18.0 ([#5299](https://github.com/cookiecutter/cookiecutter-django/pull/5299))\n\n- Update sentry-sdk to 2.13.0 ([#5298](https://github.com/cookiecutter/cookiecutter-django/pull/5298))\n\n- Update uvicorn to 0.30.6 ([#5295](https://github.com/cookiecutter/cookiecutter-django/pull/5295))\n\n## 2024.08.12\n\n\n### Updated\n\n- Update gunicorn to 23.0.0 ([#5294](https://github.com/cookiecutter/cookiecutter-django/pull/5294))\n\n## 2024.08.09\n\n\n### Updated\n\n- Update Ruff pre-commit hook to v0.5.7 ([#5293](https://github.com/cookiecutter/cookiecutter-django/pull/5293))\n\n## 2024.08.08\n\n\n### Updated\n\n- Update ruff to 0.5.7 ([#5291](https://github.com/cookiecutter/cookiecutter-django/pull/5291))\n\n- Bump python from 3.12.4 to 3.12.5 in docs Docker image ([#5287](https://github.com/cookiecutter/cookiecutter-django/pull/5287))\n\n- Bump python from 3.12.4 to 3.12.5 in local Docker image ([#5289](https://github.com/cookiecutter/cookiecutter-django/pull/5289))\n\n- Bump python from 3.12.4 to 3.12.5 in production Docker image ([#5290](https://github.com/cookiecutter/cookiecutter-django/pull/5290))\n\n## 2024.08.07\n\n\n### Updated\n\n- Update tox to 4.17.1 ([#5285](https://github.com/cookiecutter/cookiecutter-django/pull/5285))\n\n- Update django-anymail to 11.1 ([#5286](https://github.com/cookiecutter/cookiecutter-django/pull/5286))\n\n## 2024.08.06\n\n\n### Updated\n\n- Update django to 5.0.8 ([#5281](https://github.com/cookiecutter/cookiecutter-django/pull/5281))\n\n## 2024.08.05\n\n\n### Documentation\n\n- Simplify documentation for https in local development ([#5252](https://github.com/cookiecutter/cookiecutter-django/pull/5252))\n\n- Add Medium story in the Articles section ([#5275](https://github.com/cookiecutter/cookiecutter-django/pull/5275))\n\n### Updated\n\n- Update coverage to 7.6.1 ([#5276](https://github.com/cookiecutter/cookiecutter-django/pull/5276))\n\n- Auto-update pre-commit hooks ([#5277](https://github.com/cookiecutter/cookiecutter-django/pull/5277))\n\n## 2024.08.04\n\n\n### Updated\n\n- Update uvicorn to 0.30.5 ([#5272](https://github.com/cookiecutter/cookiecutter-django/pull/5272))\n\n- Update ruff to 0.5.6 ([#5273](https://github.com/cookiecutter/cookiecutter-django/pull/5273))\n\n- Auto-update pre-commit hooks ([#5274](https://github.com/cookiecutter/cookiecutter-django/pull/5274))\n\n## 2024.07.31\n\n\n### Updated\n\n- Update uvicorn to 0.30.4 ([#5271](https://github.com/cookiecutter/cookiecutter-django/pull/5271))\n\n- Update mypy to 1.11.1 ([#5270](https://github.com/cookiecutter/cookiecutter-django/pull/5270))\n\n- Update pre-commit to 3.8.0 ([#5257](https://github.com/cookiecutter/cookiecutter-django/pull/5257))\n\n- Update pyupgrade pre-commit hook to v3.17.0 ([#5258](https://github.com/cookiecutter/cookiecutter-django/pull/5258))\n\n- Update redis to 5.0.8 ([#5265](https://github.com/cookiecutter/cookiecutter-django/pull/5265))\n\n- Update django-stubs to 5.0.4 ([#5256](https://github.com/cookiecutter/cookiecutter-django/pull/5256))\n\n- Update mypy to 1.11.0 ([#5231](https://github.com/cookiecutter/cookiecutter-django/pull/5231))\n\n- Update django-allauth to 64.0.0 ([#5269](https://github.com/cookiecutter/cookiecutter-django/pull/5269))\n\n- Update sentry-sdk to 2.12.0 ([#5268](https://github.com/cookiecutter/cookiecutter-django/pull/5268))\n\n## 2024.07.26\n\n\n### Updated\n\n- Update ruff to 0.5.5 ([#5250](https://github.com/cookiecutter/cookiecutter-django/pull/5250))\n\n## 2024.07.25\n\n\n### Changed\n\n- Upgrade to Django 5.0 ([#5199](https://github.com/cookiecutter/cookiecutter-django/pull/5199))\n\n### Updated\n\n- Update pytest to 8.3.2 ([#5249](https://github.com/cookiecutter/cookiecutter-django/pull/5249))\n\n- Update sentry-sdk to 2.11.0 ([#5247](https://github.com/cookiecutter/cookiecutter-django/pull/5247))\n\n## 2024.07.24\n\n\n### Changed\n\n- fix non existent of two scoops of django image ([#5248](https://github.com/cookiecutter/cookiecutter-django/pull/5248))\n\n## 2024.07.23\n\n\n### Changed\n\n- Ensure that awscli service has a CMD to fix #5241 ([#5245](https://github.com/cookiecutter/cookiecutter-django/pull/5245))\n\n### Fixed\n\n- Downgrade watchfiles ([#5243](https://github.com/cookiecutter/cookiecutter-django/pull/5243))\n\n## 2024.07.22\n\n\n### Updated\n\n- Update django-compressor to 4.5.1 ([#5240](https://github.com/cookiecutter/cookiecutter-django/pull/5240))\n\n## 2024.07.21\n\n\n### Updated\n\n- Update ruff to 0.5.4 ([#5237](https://github.com/cookiecutter/cookiecutter-django/pull/5237))\n\n- Update pytest to 8.3.1 ([#5236](https://github.com/cookiecutter/cookiecutter-django/pull/5236))\n\n- Update sphinx to 7.4.7 ([#5235](https://github.com/cookiecutter/cookiecutter-django/pull/5235))\n\n## 2024.07.20\n\n\n### Updated\n\n- Update hiredis to 3.0.0 ([#5228](https://github.com/cookiecutter/cookiecutter-django/pull/5228))\n\n- Update uvicorn to 0.30.3 ([#5234](https://github.com/cookiecutter/cookiecutter-django/pull/5234))\n\n- Update django-crispy-forms to 2.3 ([#5229](https://github.com/cookiecutter/cookiecutter-django/pull/5229))\n\n- Auto-update pre-commit hooks ([#5232](https://github.com/cookiecutter/cookiecutter-django/pull/5232))\n\n## 2024.07.19\n\n\n### Changed\n\n- Use &#34;ENV key=value&#34; instead of &#34;ENV key value&#34; in Dockerfiles ([#5225](https://github.com/cookiecutter/cookiecutter-django/pull/5225))\n\n### Updated\n\n- Update django-upgrade to 1.20.0 ([#5227](https://github.com/cookiecutter/cookiecutter-django/pull/5227))\n\n- Update ruff to 0.5.3 ([#5224](https://github.com/cookiecutter/cookiecutter-django/pull/5224))\n\n## 2024.07.18\n\n\n### Updated\n\n- Update sphinx to 7.4.6 ([#5223](https://github.com/cookiecutter/cookiecutter-django/pull/5223))\n\n## 2024.07.17\n\n\n### Updated\n\n- Update sphinx to 7.4.5 ([#5222](https://github.com/cookiecutter/cookiecutter-django/pull/5222))\n\n## 2024.07.16\n\n\n### Fixed\n\n- Clear `ENTRYPOINT` in `awscli` image to allow script execution ([#5221](https://github.com/cookiecutter/cookiecutter-django/pull/5221))\n\n### Updated\n\n- Update sphinx to 7.4.4 ([#5218](https://github.com/cookiecutter/cookiecutter-django/pull/5218))\n\n## 2024.07.15\n\n\n### Updated\n\n- Update sentry-sdk to 2.10.0 ([#5216](https://github.com/cookiecutter/cookiecutter-django/pull/5216))\n\n- Update sphinx to 7.4.2 ([#5215](https://github.com/cookiecutter/cookiecutter-django/pull/5215))\n\n- Update ruff to 0.5.2 ([#5211](https://github.com/cookiecutter/cookiecutter-django/pull/5211))\n\n- Update sphinx to 7.4.0 ([#5214](https://github.com/cookiecutter/cookiecutter-django/pull/5214))\n\n## 2024.07.12\n\n\n### Updated\n\n- Update django-allauth to 0.63.6 ([#5210](https://github.com/cookiecutter/cookiecutter-django/pull/5210))\n\n- Update django-allauth to 0.63.5 ([#5206](https://github.com/cookiecutter/cookiecutter-django/pull/5206))\n\n- Update coverage to 7.6.0 ([#5207](https://github.com/cookiecutter/cookiecutter-django/pull/5207))\n\n- Update django-anymail to 11.0.1 ([#5208](https://github.com/cookiecutter/cookiecutter-django/pull/5208))\n\n## 2024.07.10\n\n\n### Updated\n\n- Update django-allauth to 0.63.4 ([#5204](https://github.com/cookiecutter/cookiecutter-django/pull/5204))\n\n- Update django to 4.2.14 ([#5200](https://github.com/cookiecutter/cookiecutter-django/pull/5200))\n\n- Update collectfasta to 3.2.0 ([#5201](https://github.com/cookiecutter/cookiecutter-django/pull/5201))\n\n- Update sentry-sdk to 2.9.0 ([#5202](https://github.com/cookiecutter/cookiecutter-django/pull/5202))\n\n- Update django-debug-toolbar to 4.4.6 ([#5203](https://github.com/cookiecutter/cookiecutter-django/pull/5203))\n\n## 2024.07.09\n\n\n### Changed\n\n- Migrate from Collectfast to Collestfasta ([#5172](https://github.com/cookiecutter/cookiecutter-django/pull/5172))\n\n### Documentation\n\n- Fix a typo in the `--all` option of the `makemessages` command ([#5198](https://github.com/cookiecutter/cookiecutter-django/pull/5198))\n\n### Updated\n\n- Update django-storages to 1.14.4 ([#5197](https://github.com/cookiecutter/cookiecutter-django/pull/5197))\n\n## 2024.07.08\n\n\n### Updated\n\n- Update ruff to 0.5.1 ([#5190](https://github.com/cookiecutter/cookiecutter-django/pull/5190))\n\n- Update django-debug-toolbar to 4.4.5 ([#5192](https://github.com/cookiecutter/cookiecutter-django/pull/5192))\n\n- Update sentry-sdk to 2.8.0 ([#5195](https://github.com/cookiecutter/cookiecutter-django/pull/5195))\n\n## 2024.07.05\n\n\n### Updated\n\n- Update django-debug-toolbar to 4.4.3 ([#5189](https://github.com/cookiecutter/cookiecutter-django/pull/5189))\n\n## 2024.07.02\n\n\n### Updated\n\n- Update pillow to 10.4.0 ([#5182](https://github.com/cookiecutter/cookiecutter-django/pull/5182))\n\n## 2024.07.01\n\n\n### Updated\n\n- Update ruff to 0.5.0 ([#5181](https://github.com/cookiecutter/cookiecutter-django/pull/5181))\n\n- Update sentry-sdk to 2.7.1 ([#5174](https://github.com/cookiecutter/cookiecutter-django/pull/5174))\n\n- Auto-update pre-commit hooks ([#5175](https://github.com/cookiecutter/cookiecutter-django/pull/5175))\n\n- Update psycopg to 3.2.1 ([#5180](https://github.com/cookiecutter/cookiecutter-django/pull/5180))\n\n## 2024.06.30\n\n\n### Updated\n\n- Update django-upgrade to 1.19.0 ([#5171](https://github.com/cookiecutter/cookiecutter-django/pull/5171))\n\n## 2024.06.26\n\n\n### Fixed\n\n- Fix keywords case warning in Dockerfile ([#5164](https://github.com/cookiecutter/cookiecutter-django/pull/5164))\n\n### Updated\n\n- Update redis to 5.0.7 ([#5170](https://github.com/cookiecutter/cookiecutter-django/pull/5170))\n\n- Update sentry-sdk to 2.7.0 ([#5169](https://github.com/cookiecutter/cookiecutter-django/pull/5169))\n\n## 2024.06.24\n\n\n### Updated\n\n- Update django-anymail to 11.0 ([#5163](https://github.com/cookiecutter/cookiecutter-django/pull/5163))\n\n- Update coverage to 7.5.4 ([#5162](https://github.com/cookiecutter/cookiecutter-django/pull/5162))\n\n## 2024.06.22\n\n\n### Updated\n\n- Bump amazon/aws-cli from 2.16.10 to 2.17.0 ([#5161](https://github.com/cookiecutter/cookiecutter-django/pull/5161))\n\n- Auto-update pre-commit hooks ([#5160](https://github.com/cookiecutter/cookiecutter-django/pull/5160))\n\n- Update ruff to 0.4.10 ([#5159](https://github.com/cookiecutter/cookiecutter-django/pull/5159))\n\n## 2024.06.20\n\n\n### Fixed\n\n- Remove deprecated docker and python tags from GitLab CI config ([#5158](https://github.com/cookiecutter/cookiecutter-django/pull/5158))\n\n## 2024.06.19\n\n\n### Updated\n\n- Update djangorestframework to 3.15.2 ([#5156](https://github.com/cookiecutter/cookiecutter-django/pull/5156))\n\n- Update django-cors-headers to 4.4.0 ([#5154](https://github.com/cookiecutter/cookiecutter-django/pull/5154))\n\n- Update sentry-sdk to 2.6.0 ([#5153](https://github.com/cookiecutter/cookiecutter-django/pull/5153))\n\n- Update whitenoise to 6.7.0 ([#5155](https://github.com/cookiecutter/cookiecutter-django/pull/5155))\n\n## 2024.06.18\n\n\n### Updated\n\n- Bump amazon/aws-cli from 2.16.8 to 2.16.10 ([#5149](https://github.com/cookiecutter/cookiecutter-django/pull/5149))\n\n## 2024.06.17\n\n\n### Updated\n\n- Update django-compressor to 4.5 ([#5145](https://github.com/cookiecutter/cookiecutter-django/pull/5145))\n\n- Update rcssmin to 1.1.2 ([#4614](https://github.com/cookiecutter/cookiecutter-django/pull/4614))\n\n## 2024.06.15\n\n\n### Changed\n\n- Update start-flower in flower to wait until all celery workers are online ([#5012](https://github.com/cookiecutter/cookiecutter-django/pull/5012))\n\n- Enhancing the security of cookies ([#5102](https://github.com/cookiecutter/cookiecutter-django/pull/5102))\n\n### Updated\n\n- Update django-crispy-forms to 2.2 ([#5143](https://github.com/cookiecutter/cookiecutter-django/pull/5143))\n\n- Update sentry-sdk to 2.5.1 ([#5142](https://github.com/cookiecutter/cookiecutter-django/pull/5142))\n\n- Auto-update pre-commit hooks ([#5140](https://github.com/cookiecutter/cookiecutter-django/pull/5140))\n\n- Update django-allauth to 0.63.3 ([#5111](https://github.com/cookiecutter/cookiecutter-django/pull/5111))\n\n## 2024.06.14\n\n\n### Updated\n\n- Bump python from 3.12.3-slim-bookworm to 3.12.4-slim-bookworm in /{{cookiecutter.project_slug}}/compose/local/docs ([#5129](https://github.com/cookiecutter/cookiecutter-django/pull/5129))\n\n- Bump python from 3.12.3-slim-bookworm to 3.12.4-slim-bookworm in /{{cookiecutter.project_slug}}/compose/local/django ([#5130](https://github.com/cookiecutter/cookiecutter-django/pull/5130))\n\n- Bump python from 3.12.3-slim-bookworm to 3.12.4-slim-bookworm in /{{cookiecutter.project_slug}}/compose/production/django ([#5132](https://github.com/cookiecutter/cookiecutter-django/pull/5132))\n\n- Bump amazon/aws-cli from 2.16.6 to 2.16.8 in /{{cookiecutter.project_slug}}/compose/production/aws ([#5138](https://github.com/cookiecutter/cookiecutter-django/pull/5138))\n\n- Update ruff to 0.4.9 ([#5139](https://github.com/cookiecutter/cookiecutter-django/pull/5139))\n\n## 2024.06.13\n\n\n### Updated\n\n- Update redis to 5.0.6 ([#5137](https://github.com/cookiecutter/cookiecutter-django/pull/5137))\n\n## 2024.06.12\n\n\n### Updated\n\n- Bump amazon/aws-cli Docker image from 2.15.58 to 2.16.6 ([#5135](https://github.com/cookiecutter/cookiecutter-django/pull/5135))\n\n## 2024.06.08\n\n\n### Changed\n\n- Replace deprecated `uvicorn.workers` with `uvicorn-worker` ([#5110](https://github.com/cookiecutter/cookiecutter-django/pull/5110))\n\n- Change aws-cli docker image to use official amazon image ([#5116](https://github.com/cookiecutter/cookiecutter-django/pull/5116))\n\n## 2024.06.06\n\n\n### Updated\n\n- Update sentry-sdk to 2.5.0 ([#5126](https://github.com/cookiecutter/cookiecutter-django/pull/5126))\n\n- Update ruff to 0.4.8 ([#5122](https://github.com/cookiecutter/cookiecutter-django/pull/5122))\n\n- Update redis to 5.0.5 ([#5125](https://github.com/cookiecutter/cookiecutter-django/pull/5125))\n\n## 2024.06.04\n\n\n### Updated\n\n- Update pytest to 8.2.2 ([#5120](https://github.com/cookiecutter/cookiecutter-django/pull/5120))\n\n- Update sh to 2.0.7 ([#5114](https://github.com/cookiecutter/cookiecutter-django/pull/5114))\n\n- Update sentry-sdk to 2.4.0 ([#5119](https://github.com/cookiecutter/cookiecutter-django/pull/5119))\n\n## 2024.06.02\n\n\n### Updated\n\n- Update uvicorn to 0.30.1 ([#5115](https://github.com/cookiecutter/cookiecutter-django/pull/5115))\n\n## 2024.06.01\n\n\n### Updated\n\n- Update ruff to 0.4.7 ([#5112](https://github.com/cookiecutter/cookiecutter-django/pull/5112))\n\n## 2024.05.30\n\n\n### Updated\n\n- Update uvicorn to 0.30.0 ([#5101](https://github.com/cookiecutter/cookiecutter-django/pull/5101))\n\n## 2024.05.29\n\n\n### Updated\n\n- Update requests to 2.32.3 ([#5108](https://github.com/cookiecutter/cookiecutter-django/pull/5108))\n\n- Update ruff to 0.4.6 ([#5107](https://github.com/cookiecutter/cookiecutter-django/pull/5107))\n\n- Auto-update pre-commit hooks ([#5106](https://github.com/cookiecutter/cookiecutter-django/pull/5106))\n\n- Update coverage to 7.5.3 ([#5104](https://github.com/cookiecutter/cookiecutter-django/pull/5104))\n\n- Update django-upgrade to 1.18.0 ([#5105](https://github.com/cookiecutter/cookiecutter-django/pull/5105))\n\n## 2024.05.27\n\n\n### Changed\n\n- Rename SendInBlue ESP to Brevo ([#5094](https://github.com/cookiecutter/cookiecutter-django/pull/5094))\n\n### Updated\n\n- Update django-stubs to 5.0.2 ([#5100](https://github.com/cookiecutter/cookiecutter-django/pull/5100))\n\n- Update watchfiles to 0.22.0 ([#5099](https://github.com/cookiecutter/cookiecutter-django/pull/5099))\n\n- Update django-allauth to 0.63.2 ([#5092](https://github.com/cookiecutter/cookiecutter-django/pull/5092))\n\n- Update coverage to 7.5.2 ([#5095](https://github.com/cookiecutter/cookiecutter-django/pull/5095))\n\n- Update django-debug-toolbar to 4.4.2 ([#5098](https://github.com/cookiecutter/cookiecutter-django/pull/5098))\n\n## 2024.05.23\n\n\n### Updated\n\n- Update sentry-sdk to 2.3.1 ([#5091](https://github.com/cookiecutter/cookiecutter-django/pull/5091))\n\n- Auto-update pre-commit hooks ([#5087](https://github.com/cookiecutter/cookiecutter-django/pull/5087))\n\n- Update ruff to 0.4.5 ([#5086](https://github.com/cookiecutter/cookiecutter-django/pull/5086))\n\n## 2024.05.21\n\n\n### Updated\n\n- Update sentry-sdk to 2.2.1 ([#5083](https://github.com/cookiecutter/cookiecutter-django/pull/5083))\n\n## 2024.05.20\n\n\n### Fixed\n\n- Fix PyCharm Run Configurations After local.yml Rename ([#5080](https://github.com/cookiecutter/cookiecutter-django/pull/5080))\n\n### Updated\n\n- Update pytest to 8.2.1 ([#5079](https://github.com/cookiecutter/cookiecutter-django/pull/5079))\n\n## 2024.05.18\n\n\n### Fixed\n\n- Fix redirect error when forcing allauth login in admin site ([#5078](https://github.com/cookiecutter/cookiecutter-django/pull/5078))\n\n## 2024.05.17\n\n\n### Updated\n\n- Update django-allauth to 0.63.1 ([#5076](https://github.com/cookiecutter/cookiecutter-django/pull/5076))\n\n## 2024.05.16\n\n\n### Documentation\n\n- Update Two scoops of Django book link &amp; image ([#5073](https://github.com/cookiecutter/cookiecutter-django/pull/5073))\n\n### Updated\n\n- Update sentry-sdk to 2.2.0 ([#5074](https://github.com/cookiecutter/cookiecutter-django/pull/5074))\n\n- Update django-allauth to 0.63.0 ([#5070](https://github.com/cookiecutter/cookiecutter-django/pull/5070))\n\n## 2024.05.15\n\n\n### Fixed\n\n- Disable DDT profiling panel ([#5069](https://github.com/cookiecutter/cookiecutter-django/pull/5069))\n\n## 2024.05.13\n\n\n### Changed\n\n- Rename docker compose files to include &#39;docker-compose&#39; ([#4995](https://github.com/cookiecutter/cookiecutter-django/pull/4995))\n\n- Remove obsolete `version` element from docker compose files ([#5059](https://github.com/cookiecutter/cookiecutter-django/pull/5059))\n\n- Add Redis persistent storage when using celery ([#5063](https://github.com/cookiecutter/cookiecutter-django/pull/5063))\n\n### Fixed\n\n- Add noqa to ignore ruff false positive ([#5068](https://github.com/cookiecutter/cookiecutter-django/pull/5068))\n\n- Fix staticfile settings with cloud provider and whitenoise ([#5057](https://github.com/cookiecutter/cookiecutter-django/pull/5057))\n\n### Updated\n\n- Update djangorestframework-stubs to 3.15.0 ([#5041](https://github.com/cookiecutter/cookiecutter-django/pull/5041))\n\n- Update django-stubs to 5.0.0 ([#5040](https://github.com/cookiecutter/cookiecutter-django/pull/5040))\n\n- Update mypy to 1.10.0 ([#5022](https://github.com/cookiecutter/cookiecutter-django/pull/5022))\n\n- Update werkzeug to 3.0.3 ([#5050](https://github.com/cookiecutter/cookiecutter-django/pull/5050))\n\n## 2024.05.11\n\n\n### Updated\n\n- Update pre-commit to 3.7.1 ([#5066](https://github.com/cookiecutter/cookiecutter-django/pull/5066))\n\n- Auto-update pre-commit hooks ([#5067](https://github.com/cookiecutter/cookiecutter-django/pull/5067))\n\n## 2024.05.10\n\n\n### Updated\n\n- Update psycopg to 3.1.19 ([#5064](https://github.com/cookiecutter/cookiecutter-django/pull/5064))\n\n- Update django-upgrade to 1.17.0 ([#5065](https://github.com/cookiecutter/cookiecutter-django/pull/5065))\n\n- Auto-update pre-commit hooks ([#5062](https://github.com/cookiecutter/cookiecutter-django/pull/5062))\n\n- Update ruff to 0.4.4 ([#5061](https://github.com/cookiecutter/cookiecutter-django/pull/5061))\n\n## 2024.05.07\n\n\n### Updated\n\n- Update django to 4.2.13 ([#5058](https://github.com/cookiecutter/cookiecutter-django/pull/5058))\n\n## 2024.05.06\n\n\n### Fixed\n\n- Fix nginx image name in production.yml ([#5053](https://github.com/cookiecutter/cookiecutter-django/pull/5053))\n\n### Updated\n\n- Update django-model-utils to 4.5.1 ([#5044](https://github.com/cookiecutter/cookiecutter-django/pull/5044))\n\n- Update django to 4.2.12 ([#5056](https://github.com/cookiecutter/cookiecutter-django/pull/5056))\n\n- Update sentry-sdk to 2.1.1 ([#5055](https://github.com/cookiecutter/cookiecutter-django/pull/5055))\n\n- Update ruff to 0.4.3 ([#5049](https://github.com/cookiecutter/cookiecutter-django/pull/5049))\n\n## 2024.05.05\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5046](https://github.com/cookiecutter/cookiecutter-django/pull/5046))\n\n- Update django-storages to 1.14.3 ([#5047](https://github.com/cookiecutter/cookiecutter-django/pull/5047))\n\n- Update coverage to 7.5.1 ([#5048](https://github.com/cookiecutter/cookiecutter-django/pull/5048))\n\n## 2024.04.28\n\n\n### Updated\n\n- Update pytest to 8.2.0 ([#5034](https://github.com/cookiecutter/cookiecutter-django/pull/5034))\n\n## 2024.04.27\n\n\n### Updated\n\n- Update sentry-sdk to 2.0.1 ([#5030](https://github.com/cookiecutter/cookiecutter-django/pull/5030))\n\n## 2024.04.26\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5029](https://github.com/cookiecutter/cookiecutter-django/pull/5029))\n\n- Update ruff to 0.4.2 ([#5028](https://github.com/cookiecutter/cookiecutter-django/pull/5028))\n\n## 2024.04.25\n\n\n### Updated\n\n- Update coverage to 7.5.0 ([#5025](https://github.com/cookiecutter/cookiecutter-django/pull/5025))\n\n- Bump cssnano from 6.1.2 to 7.0.0 ([#5024](https://github.com/cookiecutter/cookiecutter-django/pull/5024))\n\n- Auto-update pre-commit hooks ([#5023](https://github.com/cookiecutter/cookiecutter-django/pull/5023))\n\n## 2024.04.24\n\n\n### Changed\n\n- Disable UP038 Ruff rule to avoid introducing slower code ([#5020](https://github.com/cookiecutter/cookiecutter-django/pull/5020))\n\n### Updated\n\n- Update django-allauth to 0.62.1 ([#5021](https://github.com/cookiecutter/cookiecutter-django/pull/5021))\n\n## 2024.04.23\n\n\n### Changed\n\n- Update link to djlint on pyproject.toml ([#5019](https://github.com/cookiecutter/cookiecutter-django/pull/5019))\n\n### Updated\n\n- Update redis to 5.0.4 ([#5018](https://github.com/cookiecutter/cookiecutter-django/pull/5018))\n\n- Update django-allauth to 0.62.0 ([#5016](https://github.com/cookiecutter/cookiecutter-django/pull/5016))\n\n## 2024.04.22\n\n\n### Fixed\n\n- Fix broken link for sphinx-doc in generated docs ([#5015](https://github.com/cookiecutter/cookiecutter-django/pull/5015))\n\n## 2024.04.20\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#5014](https://github.com/cookiecutter/cookiecutter-django/pull/5014))\n\n- Update pytest-xdist to 3.6.0 ([#5013](https://github.com/cookiecutter/cookiecutter-django/pull/5013))\n\n## 2024.04.19\n\n\n### Updated\n\n- Update ruff to 0.4.1 ([#5011](https://github.com/cookiecutter/cookiecutter-django/pull/5011))\n\n- Update ruff to 0.4.0 ([#5007](https://github.com/cookiecutter/cookiecutter-django/pull/5007))\n\n- Auto-update pre-commit hooks ([#5008](https://github.com/cookiecutter/cookiecutter-django/pull/5008))\n\n- Update sphinx to 7.3.7 ([#5010](https://github.com/cookiecutter/cookiecutter-django/pull/5010))\n\n## 2024.04.18\n\n\n### Updated\n\n- Update celery to 5.4.0 ([#5005](https://github.com/cookiecutter/cookiecutter-django/pull/5005))\n\n- Update sphinx to 7.3.6 ([#5004](https://github.com/cookiecutter/cookiecutter-django/pull/5004))\n\n## 2024.04.17\n\n\n### Updated\n\n- Update sphinx to 7.3.5 ([#5003](https://github.com/cookiecutter/cookiecutter-django/pull/5003))\n\n- Update gunicorn to 22.0.0 ([#5001](https://github.com/cookiecutter/cookiecutter-django/pull/5001))\n\n- Update sphinx to 7.3.3 ([#5000](https://github.com/cookiecutter/cookiecutter-django/pull/5000))\n\n## 2024.04.16\n\n\n### Changed\n\n- Add a prefix setting so that swagger tags are generated in a readable way ([#4975](https://github.com/cookiecutter/cookiecutter-django/pull/4975))\n\n### Fixed\n\n- Fix `runserver_plus` hot-reload when under Windows + Docker ([#4971](https://github.com/cookiecutter/cookiecutter-django/pull/4971))\n\n### Documentation\n\n- Update docs for `test_bare.sh` ([#4996](https://github.com/cookiecutter/cookiecutter-django/pull/4996))\n\n### Updated\n\n- Bump traefik from 2.11.0 to 2.11.2 ([#4993](https://github.com/cookiecutter/cookiecutter-django/pull/4993))\n\n- Update sphinx-autobuild to 2024.4.16 ([#4999](https://github.com/cookiecutter/cookiecutter-django/pull/4999))\n\n- Update sphinx-autobuild to 2024.4.13 ([#4991](https://github.com/cookiecutter/cookiecutter-django/pull/4991))\n\n- Update sentry-sdk to 1.45.0 ([#4982](https://github.com/cookiecutter/cookiecutter-django/pull/4982))\n\n- Update ruff to 0.3.7 ([#4989](https://github.com/cookiecutter/cookiecutter-django/pull/4989))\n\n- Auto-update pre-commit hooks ([#4988](https://github.com/cookiecutter/cookiecutter-django/pull/4988))\n\n## 2024.04.10\n\n\n### Updated\n\n- Bump python from 3.12.2 to 3.12.3 in docs ([#4979](https://github.com/cookiecutter/cookiecutter-django/pull/4979))\n\n- Bump python from 3.12.2 to 3.12.3 in local ([#4981](https://github.com/cookiecutter/cookiecutter-django/pull/4981))\n\n- Bump python from 3.12.2 to 3.12.3 in production ([#4980](https://github.com/cookiecutter/cookiecutter-django/pull/4980))\n\n## 2024.04.09\n\n\n### Documentation\n\n- Fix start command for docs ([#4978](https://github.com/cookiecutter/cookiecutter-django/pull/4978))\n\n## 2024.04.07\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4974](https://github.com/cookiecutter/cookiecutter-django/pull/4974))\n\n## 2024.04.06\n\n\n### Fixed\n\n- Fix syntax error in GitHub CI workflow  ([#4972](https://github.com/cookiecutter/cookiecutter-django/pull/4972))\n\n## 2024.04.05\n\n\n### Updated\n\n- Update django-webpack-loader to 3.1.0 ([#4965](https://github.com/cookiecutter/cookiecutter-django/pull/4965))\n\n## 2024.04.03\n\n\n### Changed\n\n- Update GH actions to resolve deprecation warnings ([#4964](https://github.com/cookiecutter/cookiecutter-django/pull/4964))\n\n### Updated\n\n- Update sentry-sdk to 1.44.1 ([#4963](https://github.com/cookiecutter/cookiecutter-django/pull/4963))\n\n## 2024.04.02\n\n\n### Changed\n\n- Change pytest import mode to importlib ([#4950](https://github.com/cookiecutter/cookiecutter-django/pull/4950))\n\n- Use main over master for branch name in deployment-on-heroku instruction ([#4954](https://github.com/cookiecutter/cookiecutter-django/pull/4954))\n\n- change obsolete docker image &#34;docker/compose:1.29.2&#34; to &#34;docker:25.0&#34; ([#4961](https://github.com/cookiecutter/cookiecutter-django/pull/4961))\n\n### Updated\n\n- Update sentry-sdk to 1.44.0 ([#4948](https://github.com/cookiecutter/cookiecutter-django/pull/4948))\n\n- Update ruff to 0.3.5 ([#4955](https://github.com/cookiecutter/cookiecutter-django/pull/4955))\n\n- Update gitpython to 3.1.43 ([#4951](https://github.com/cookiecutter/cookiecutter-django/pull/4951))\n\n- Update pillow to 10.3.0 ([#4953](https://github.com/cookiecutter/cookiecutter-django/pull/4953))\n\n- Update django-model-utils to 4.5.0 ([#4956](https://github.com/cookiecutter/cookiecutter-django/pull/4956))\n\n- Update drf-spectacular to 0.27.2 ([#4957](https://github.com/cookiecutter/cookiecutter-django/pull/4957))\n\n- Update werkzeug to 3.0.2 ([#4958](https://github.com/cookiecutter/cookiecutter-django/pull/4958))\n\n- Auto-update pre-commit hooks ([#4959](https://github.com/cookiecutter/cookiecutter-django/pull/4959))\n\n## 2024.03.29\n\n\n### Documentation\n\n- Add instruction for adding a django app ([#4944](https://github.com/cookiecutter/cookiecutter-django/pull/4944))\n\n## 2024.03.27\n\n\n### Updated\n\n- Update pre-commit to 3.7.0 ([#4943](https://github.com/cookiecutter/cookiecutter-django/pull/4943))\n\n- Update djangorestframework to 3.15.1 ([#4941](https://github.com/cookiecutter/cookiecutter-django/pull/4941))\n\n- Update ruff to 0.3.4 ([#4936](https://github.com/cookiecutter/cookiecutter-django/pull/4936))\n\n- Auto-update pre-commit hooks ([#4937](https://github.com/cookiecutter/cookiecutter-django/pull/4937))\n\n## 2024.03.26\n\n\n### Documentation\n\n- Update mentions of psycopg in comments ([#4947](https://github.com/cookiecutter/cookiecutter-django/pull/4947))\n\n## 2024.03.21\n\n\n### Changed\n\n- Add PostgreSQL 16, remove Postgres 10 and 11 ([#4935](https://github.com/cookiecutter/cookiecutter-django/pull/4935))\n\n### Updated\n\n- Update uvicorn to 0.29.0 ([#4933](https://github.com/cookiecutter/cookiecutter-django/pull/4933))\n\n- Update sentry-sdk to 1.43.0 ([#4934](https://github.com/cookiecutter/cookiecutter-django/pull/4934))\n\n## 2024.03.19\n\n\n### Changed\n\n- Add documentation to upgrade Postgres in Docker environment. Fix: #461 ([#4898](https://github.com/cookiecutter/cookiecutter-django/pull/4898))\n\n- Upgrade Python to version 3.12 ([#4930](https://github.com/cookiecutter/cookiecutter-django/pull/4930))\n\n## 2024.03.18\n\n\n### Changed\n\n- Split the docs from local.yml and build the service in CI ([#4909](https://github.com/cookiecutter/cookiecutter-django/pull/4909))\n\n### Updated\n\n- Update django-anymail to 10.3 ([#4919](https://github.com/cookiecutter/cookiecutter-django/pull/4919))\n\n- Update sentry-sdk to 1.42.0 ([#4921](https://github.com/cookiecutter/cookiecutter-django/pull/4921))\n\n- Update coverage to 7.4.4 ([#4926](https://github.com/cookiecutter/cookiecutter-django/pull/4926))\n\n- Update ruff to 0.3.3 ([#4927](https://github.com/cookiecutter/cookiecutter-django/pull/4927))\n\n- Auto-update pre-commit hooks ([#4928](https://github.com/cookiecutter/cookiecutter-django/pull/4928))\n\n## 2024.03.17\n\n\n### Updated\n\n- Update djangorestframework to 3.15.0 ([#4929](https://github.com/cookiecutter/cookiecutter-django/pull/4929))\n\n## 2024.03.10\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4912](https://github.com/cookiecutter/cookiecutter-django/pull/4912))\n\n- Update ruff to 0.3.2 ([#4911](https://github.com/cookiecutter/cookiecutter-django/pull/4911))\n\n- Update uvicorn to 0.28.0 ([#4913](https://github.com/cookiecutter/cookiecutter-django/pull/4913))\n\n- Update redis to 5.0.3 ([#4916](https://github.com/cookiecutter/cookiecutter-django/pull/4916))\n\n- Update pytest to 8.1.1 ([#4914](https://github.com/cookiecutter/cookiecutter-django/pull/4914))\n\n## 2024.03.07\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4907](https://github.com/cookiecutter/cookiecutter-django/pull/4907))\n\n- Update sentry-sdk to 1.41.0 ([#4908](https://github.com/cookiecutter/cookiecutter-django/pull/4908))\n\n## 2024.03.06\n\n\n### Fixed\n\n- Fix fully qualified docker images ([#4905](https://github.com/cookiecutter/cookiecutter-django/pull/4905))\n\n## 2024.03.04\n\n\n### Updated\n\n- Update pytest to 8.1.0 ([#4900](https://github.com/cookiecutter/cookiecutter-django/pull/4900))\n\n- Update django to 4.2.11 ([#4901](https://github.com/cookiecutter/cookiecutter-django/pull/4901))\n\n## 2024.03.03\n\n\n### Updated\n\n- Update django-celery-beat to 2.6.0 ([#4899](https://github.com/cookiecutter/cookiecutter-django/pull/4899))\n\n## 2024.03.01\n\n\n### Changed\n\n- Add a maintainer guide to the docs ([#4884](https://github.com/cookiecutter/cookiecutter-django/pull/4884))\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4897](https://github.com/cookiecutter/cookiecutter-django/pull/4897))\n\n- Update ruff to 0.3.0 ([#4896](https://github.com/cookiecutter/cookiecutter-django/pull/4896))\n\n## 2024.02.28\n\n\n### Fixed\n\n- Fix invalid HTML in django-allauth field element template ([#4894](https://github.com/cookiecutter/cookiecutter-django/pull/4894))\n\n- Fix permissions for media files when served by nginx ([#4889](https://github.com/cookiecutter/cookiecutter-django/pull/4889))\n\n### Documentation\n\n- Fix broken &#34;Two scoops of django&#34; link in FAQ ([#4892](https://github.com/cookiecutter/cookiecutter-django/pull/4892))\n\n### Updated\n\n- Update redis to 5.0.2 ([#4895](https://github.com/cookiecutter/cookiecutter-django/pull/4895))\n\n- Update sentry-sdk to 1.40.6 ([#4893](https://github.com/cookiecutter/cookiecutter-django/pull/4893))\n\n## 2024.02.26\n\n\n### Changed\n\n- Allauth elements &amp; MFA ([#4843](https://github.com/cookiecutter/cookiecutter-django/pull/4843))\n\n### Updated\n\n- Update pytest to 8.0.2 ([#4890](https://github.com/cookiecutter/cookiecutter-django/pull/4890))\n\n- Update crispy-bootstrap5 to 2024.2 ([#4891](https://github.com/cookiecutter/cookiecutter-django/pull/4891))\n\n## 2024.02.24\n\n\n### Updated\n\n- Update coverage to 7.4.3 ([#4888](https://github.com/cookiecutter/cookiecutter-django/pull/4888))\n\n## 2024.02.23\n\n\n### Changed\n\n- Switch to local imports within app ([#4883](https://github.com/cookiecutter/cookiecutter-django/pull/4883))\n\n- Install ruff extension in `devcontainer.json` ([#4887](https://github.com/cookiecutter/cookiecutter-django/pull/4887))\n\n### Updated\n\n- Bump webpack-dev-server to 5.0.2 ([#4875](https://github.com/cookiecutter/cookiecutter-django/pull/4875))\n\n## 2024.02.21\n\n\n### Changed\n\n- Switch to `celery.shared_task` to define tasks ([#4881](https://github.com/cookiecutter/cookiecutter-django/pull/4881))\n\n- Replace usages of `get_user_model` by importing model directly ([#4879](https://github.com/cookiecutter/cookiecutter-django/pull/4879))\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4873](https://github.com/cookiecutter/cookiecutter-django/pull/4873))\n\n- Update pre-commit to 3.6.2 ([#4874](https://github.com/cookiecutter/cookiecutter-django/pull/4874))\n\n- Update ruff to 0.2.2 ([#4871](https://github.com/cookiecutter/cookiecutter-django/pull/4871))\n\n## 2024.02.19\n\n\n### Updated\n\n- Update sentry-sdk to 1.40.5 ([#4876](https://github.com/cookiecutter/cookiecutter-django/pull/4876))\n\n## 2024.02.17\n\n\n### Updated\n\n- Update pytest to 8.0.1 ([#4870](https://github.com/cookiecutter/cookiecutter-django/pull/4870))\n\n## 2024.02.16\n\n\n### Changed\n\n- Speed up GitHub CI for Docker setup ([#4863](https://github.com/cookiecutter/cookiecutter-django/pull/4863))\n\n### Documentation\n\n- Add link to the ruff repository in requirements ([#4866](https://github.com/cookiecutter/cookiecutter-django/pull/4866))\n\n## 2024.02.13\n\n\n### Changed\n\n- Ruff linting &amp; formatting ([#4834](https://github.com/cookiecutter/cookiecutter-django/pull/4834))\n\n### Updated\n\n- Update uvicorn to 0.27.1 ([#4848](https://github.com/cookiecutter/cookiecutter-django/pull/4848))\n\n- Update sentry-sdk to 1.40.4 ([#4858](https://github.com/cookiecutter/cookiecutter-django/pull/4858))\n\n- Bump traefik to 2.11.0 ([#4857](https://github.com/cookiecutter/cookiecutter-django/pull/4857))\n\n- Auto-update pre-commit hooks ([#4855](https://github.com/cookiecutter/cookiecutter-django/pull/4855))\n\n- Update black to 24.2.0 ([#4853](https://github.com/cookiecutter/cookiecutter-django/pull/4853))\n\n## 2024.02.12\n\n\n### Updated\n\n- Update django-model-utils to 4.4.0 ([#4850](https://github.com/cookiecutter/cookiecutter-django/pull/4850))\n\n- Update pre-commit to 3.6.1 ([#4849](https://github.com/cookiecutter/cookiecutter-django/pull/4849))\n\n- Update django-upgrade to 1.16.0 ([#4851](https://github.com/cookiecutter/cookiecutter-django/pull/4851))\n\n- Auto-update pre-commit hooks ([#4852](https://github.com/cookiecutter/cookiecutter-django/pull/4852))\n\n## 2024.02.09\n\n\n### Updated\n\n- Update sentry-sdk to 1.40.3 ([#4847](https://github.com/cookiecutter/cookiecutter-django/pull/4847))\n\n- Update django-allauth to 0.61.1 ([#4846](https://github.com/cookiecutter/cookiecutter-django/pull/4846))\n\n- Update python-slugify to 8.0.4 ([#4844](https://github.com/cookiecutter/cookiecutter-django/pull/4844))\n\n## 2024.02.08\n\n\n### Updated\n\n- Bump python to 3.11.8 in compose/local/docs ([#4840](https://github.com/cookiecutter/cookiecutter-django/pull/4840))\n\n- Bump python to 3.11.8 in compose/local/django ([#4841](https://github.com/cookiecutter/cookiecutter-django/pull/4841))\n\n- Bump python to 3.11.8 in compose/production/django ([#4842](https://github.com/cookiecutter/cookiecutter-django/pull/4842))\n\n## 2024.02.07\n\n\n### Changed\n\n- Extend docker test with deploy check ([#4838](https://github.com/cookiecutter/cookiecutter-django/pull/4838))\n\n- Generic UserManager ([#4836](https://github.com/cookiecutter/cookiecutter-django/pull/4836))\n\n### Updated\n\n- Update django-allauth to 0.61.0 ([#4839](https://github.com/cookiecutter/cookiecutter-django/pull/4839))\n\n- Bump gulp-postcss to 10.0.0 ([#4835](https://github.com/cookiecutter/cookiecutter-django/pull/4835))\n\n- Update sentry-sdk to 1.40.2 ([#4837](https://github.com/cookiecutter/cookiecutter-django/pull/4837))\n\n- Update django to 4.2.10 ([#4833](https://github.com/cookiecutter/cookiecutter-django/pull/4833))\n\n## 2024.02.05\n\n\n### Updated\n\n- Update pytest to 8.0.0 ([#4813](https://github.com/cookiecutter/cookiecutter-django/pull/4813))\n\n- Update pytest-sugar to 1.0.0 ([#4828](https://github.com/cookiecutter/cookiecutter-django/pull/4828))\n\n- Update sphinx-autobuild to 2024.2.4 ([#4830](https://github.com/cookiecutter/cookiecutter-django/pull/4830))\n\n- Update django-debug-toolbar to 4.3.0 ([#4829](https://github.com/cookiecutter/cookiecutter-django/pull/4829))\n\n- Update psycopg to 3.1.18 ([#4831](https://github.com/cookiecutter/cookiecutter-django/pull/4831))\n\n## 2024.01.31\n\n\n### Updated\n\n- Update python-slugify to 8.0.3 ([#4826](https://github.com/cookiecutter/cookiecutter-django/pull/4826))\n\n## 2024.01.30\n\n\n### Updated\n\n- Update pytest-django to 4.8.0 ([#4823](https://github.com/cookiecutter/cookiecutter-django/pull/4823))\n\n- Update sentry-sdk to 1.40.0 ([#4822](https://github.com/cookiecutter/cookiecutter-django/pull/4822))\n\n- Update uvicorn to 0.27.0.post1 ([#4818](https://github.com/cookiecutter/cookiecutter-django/pull/4818))\n\n## 2024.01.29\n\n\n### Changed\n\n- Fix deprecation warning about renaming of `webpack_loader.loader` to `webpack_loader.loaders` ([#4815](https://github.com/cookiecutter/cookiecutter-django/pull/4815))\n\n### Documentation\n\n- Update mention of coverage config file to `pyproject.toml` in documentation ([#4816](https://github.com/cookiecutter/cookiecutter-django/pull/4816))\n\n### Updated\n\n- Update black to 24.1.1 ([#4814](https://github.com/cookiecutter/cookiecutter-django/pull/4814))\n\n- Auto-update pre-commit hooks ([#4817](https://github.com/cookiecutter/cookiecutter-django/pull/4817))\n\n## 2024.01.27\n\n\n### Changed\n\n- Do not show webpack devserver overlay for warnings ([#4809](https://github.com/cookiecutter/cookiecutter-django/pull/4809))\n\n### Updated\n\n- Update python-slugify to 8.0.2 ([#4805](https://github.com/cookiecutter/cookiecutter-django/pull/4805))\n\n- Update coverage to 7.4.1 ([#4807](https://github.com/cookiecutter/cookiecutter-django/pull/4807))\n\n## 2024.01.26\n\n\n### Updated\n\n- Update black to 24.1.0 ([#4806](https://github.com/cookiecutter/cookiecutter-django/pull/4806))\n\n## 2024.01.25\n\n\n### Changed\n\n- Replace custom static &amp; media storage classes by passing options in the `STORAGES` setting ([#4803](https://github.com/cookiecutter/cookiecutter-django/pull/4803))\n\n- Add registry to Docker images names ([#4804](https://github.com/cookiecutter/cookiecutter-django/pull/4804))\n\n## 2024.01.24\n\n\n### Changed\n\n- Migrate to the unified `STORAGES` setting added in Django 4.2 ([#4477](https://github.com/cookiecutter/cookiecutter-django/pull/4477))\n\n### Updated\n\n- Update uvicorn to 0.27.0 ([#4800](https://github.com/cookiecutter/cookiecutter-django/pull/4800))\n\n## 2024.01.21\n\n\n### Documentation\n\n- Update traefik doc links ([#4798](https://github.com/cookiecutter/cookiecutter-django/pull/4798))\n\n### Updated\n\n- Bump browser-sync from 2.29.3 to 3.0.2 in /{{cookiecutter.project_slug}} ([#4765](https://github.com/cookiecutter/cookiecutter-django/pull/4765))\n\n## 2024.01.19\n\n\n### Updated\n\n- Update drf-spectacular to 0.27.1 ([#4797](https://github.com/cookiecutter/cookiecutter-django/pull/4797))\n\n## 2024.01.17\n\n\n### Changed\n\n- Add a test to cover `DJANGO_ADMIN_FORCE_ALLAUTH` ([#4790](https://github.com/cookiecutter/cookiecutter-django/pull/4790))\n\n### Updated\n\n- Bump webpack-bundle-tracker to 3.0.1 ([#4781](https://github.com/cookiecutter/cookiecutter-django/pull/4781))\n\n- Update django-webpack-loader to 3.0.1 ([#4793](https://github.com/cookiecutter/cookiecutter-django/pull/4793))\n\n- Bump postcss-loader to 8.0.0 ([#4795](https://github.com/cookiecutter/cookiecutter-django/pull/4795))\n\n- Update uvicorn to 0.26.0 ([#4794](https://github.com/cookiecutter/cookiecutter-django/pull/4794))\n\n## 2024.01.16\n\n\n### Updated\n\n- Bump sass-loader from 13.3.3 to 14.0.0 in /{{cookiecutter.project_slug}} ([#4791](https://github.com/cookiecutter/cookiecutter-django/pull/4791))\n\n## 2024.01.15\n\n\n### Documentation\n\n- Update allauth documentation links ([#4786](https://github.com/cookiecutter/cookiecutter-django/pull/4786))\n\n### Updated\n\n- Update django-allauth to 0.60.1 ([#4787](https://github.com/cookiecutter/cookiecutter-django/pull/4787))\n\n## 2024.01.11\n\n\n### Updated\n\n- Update jinja2 to 3.1.3 ([#4784](https://github.com/cookiecutter/cookiecutter-django/pull/4784))\n\n## 2024.01.10\n\n\n### Updated\n\n- Update sentry-sdk to 1.39.2 ([#4782](https://github.com/cookiecutter/cookiecutter-django/pull/4782))\n\n## 2024.01.09\n\n\n### Documentation\n\n- Update allauth settings documentation links ([#4769](https://github.com/cookiecutter/cookiecutter-django/pull/4769))\n\n### Updated\n\n- Update django-allauth to 0.60.0 ([#4776](https://github.com/cookiecutter/cookiecutter-django/pull/4776))\n\n- Update psycopg to 3.1.17 ([#4777](https://github.com/cookiecutter/cookiecutter-django/pull/4777))\n\n## 2024.01.05\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4774](https://github.com/cookiecutter/cookiecutter-django/pull/4774))\n\n- Update flake8 to 7.0.0 ([#4775](https://github.com/cookiecutter/cookiecutter-django/pull/4775))\n\n## 2024.01.02\n\n\n### Updated\n\n- Update psycopg to 3.1.16 ([#4753](https://github.com/cookiecutter/cookiecutter-django/pull/4753))\n\n- Update djlint to 1.34.1 ([#4773](https://github.com/cookiecutter/cookiecutter-django/pull/4773))\n\n- Update uvicorn to 0.25.0 ([#4760](https://github.com/cookiecutter/cookiecutter-django/pull/4760))\n\n- Auto-update pre-commit hooks ([#4749](https://github.com/cookiecutter/cookiecutter-django/pull/4749))\n\n- Update black to 23.12.1 ([#4772](https://github.com/cookiecutter/cookiecutter-django/pull/4772))\n\n- Update pillow to 10.2.0 ([#4770](https://github.com/cookiecutter/cookiecutter-django/pull/4770))\n\n- Update django to 4.2.9 ([#4771](https://github.com/cookiecutter/cookiecutter-django/pull/4771))\n\n- Update pytest to 7.4.4 ([#4767](https://github.com/cookiecutter/cookiecutter-django/pull/4767))\n\n- Update coverage to 7.4.0 ([#4764](https://github.com/cookiecutter/cookiecutter-django/pull/4764))\n\n## 2023.12.19\n\n\n### Changed\n\n- Upgrade debian to 12 bookworm ([#4745](https://github.com/cookiecutter/cookiecutter-django/pull/4745))\n\n### Updated\n\n- Update hiredis to 2.3.2 ([#4750](https://github.com/cookiecutter/cookiecutter-django/pull/4750))\n\n## 2023.12.15\n\n\n### Updated\n\n- Update coverage to 7.3.3 ([#4748](https://github.com/cookiecutter/cookiecutter-django/pull/4748))\n\n- Update psycopg to 3.1.15 ([#4747](https://github.com/cookiecutter/cookiecutter-django/pull/4747))\n\n- Update sentry-sdk to 1.39.1 ([#4746](https://github.com/cookiecutter/cookiecutter-django/pull/4746))\n\n- Auto-update pre-commit hooks ([#4743](https://github.com/cookiecutter/cookiecutter-django/pull/4743))\n\n## 2023.12.13\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4740](https://github.com/cookiecutter/cookiecutter-django/pull/4740))\n\n## 2023.12.12\n\n\n### Updated\n\n- Update django-allauth to 0.59.0 ([#4739](https://github.com/cookiecutter/cookiecutter-django/pull/4739))\n\n- Update sentry-sdk to 1.39.0 ([#4738](https://github.com/cookiecutter/cookiecutter-django/pull/4738))\n\n- Update black to 23.12.0 ([#4737](https://github.com/cookiecutter/cookiecutter-django/pull/4737))\n\n- Auto-update pre-commit hooks ([#4736](https://github.com/cookiecutter/cookiecutter-django/pull/4736))\n\n- Update drf-spectacular to 0.27.0 ([#4735](https://github.com/cookiecutter/cookiecutter-django/pull/4735))\n\n## 2023.12.11\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4730](https://github.com/cookiecutter/cookiecutter-django/pull/4730))\n\n## 2023.12.10\n\n\n### Updated\n\n- Update pre-commit to 3.6.0 ([#4728](https://github.com/cookiecutter/cookiecutter-django/pull/4728))\n\n- Auto-update pre-commit hooks ([#4729](https://github.com/cookiecutter/cookiecutter-django/pull/4729))\n\n## 2023.12.09\n\n\n### Changed\n\n- Add missing __init__.py file to api module ([#4726](https://github.com/cookiecutter/cookiecutter-django/pull/4726))\n\n## 2023.12.07\n\n\n### Updated\n\n- Bump actions/setup-python from 4 to 5 ([#4723](https://github.com/cookiecutter/cookiecutter-django/pull/4723))\n\n- Auto-update pre-commit hooks ([#4709](https://github.com/cookiecutter/cookiecutter-django/pull/4709))\n\n- Bump traefik from 2.10.6 to 2.10.7 ([#4722](https://github.com/cookiecutter/cookiecutter-django/pull/4722))\n\n## 2023.12.06\n\n\n### Updated\n\n- Bump python from 3.11.6 to 3.11.7 ([#4719](https://github.com/cookiecutter/cookiecutter-django/pull/4719))\n\n- Update mypy to 1.7.1, django-stubs to 4.2.7 and djangorestframework-stubs to 3.14.5 ([#4694](https://github.com/cookiecutter/cookiecutter-django/pull/4694))\n\n## 2023.12.04\n\n\n### Updated\n\n- Update django to 4.2.8 ([#4713](https://github.com/cookiecutter/cookiecutter-django/pull/4713))\n\n- Bump node from 18 to 20 ([#4283](https://github.com/cookiecutter/cookiecutter-django/pull/4283))\n\n- Update psycopg to 3.1.14 ([#4711](https://github.com/cookiecutter/cookiecutter-django/pull/4711))\n\n## 2023.12.02\n\n\n### Updated\n\n-  Update mailpit to latest ([#4710](https://github.com/cookiecutter/cookiecutter-django/pull/4710))\n\n## 2023.11.30\n\n\n### Fixed\n\n- Removed tmp mount in devcontainer.json. Fix #4686 ([#4708](https://github.com/cookiecutter/cookiecutter-django/pull/4708))\n\n### Updated\n\n- Bump traefik from 2.10.5 to 2.10.6 ([#4706](https://github.com/cookiecutter/cookiecutter-django/pull/4706))\n\n## 2023.11.29\n\n\n### Updated\n\n- Update sentry-sdk to 1.38.0 ([#4705](https://github.com/cookiecutter/cookiecutter-django/pull/4705))\n\n## 2023.11.28\n\n\n### Fixed\n\n- Excludes devcontainer.json from the pre-commit ([#4702](https://github.com/cookiecutter/cookiecutter-django/pull/4702))\n\n### Updated\n\n- Update sphinx-rtd-theme to 2.0.0 ([#4700](https://github.com/cookiecutter/cookiecutter-django/pull/4700))\n\n## 2023.11.24\n\n\n### Updated\n\n- Update sentry-sdk to 1.37.1 ([#4696](https://github.com/cookiecutter/cookiecutter-django/pull/4696))\n\n- Update sentry-sdk to 1.37.0 ([#4695](https://github.com/cookiecutter/cookiecutter-django/pull/4695))\n\n## 2023.11.22\n\n\n### Updated\n\n- Update celery to 5.3.6 ([#4693](https://github.com/cookiecutter/cookiecutter-django/pull/4693))\n\n## 2023.11.21\n\n\n### Updated\n\n- Update sentry-sdk to 1.36.0 ([#4687](https://github.com/cookiecutter/cookiecutter-django/pull/4687))\n\n## 2023.11.20\n\n\n### Fixed\n\n- Fix bug with social account adapter name override, in very specific conditions ([#4650](https://github.com/cookiecutter/cookiecutter-django/pull/4650))\n\n### Updated\n\n- Update django-cors-headers to 4.3.1 ([#4684](https://github.com/cookiecutter/cookiecutter-django/pull/4684))\n\n- Update psycopg to 3.1.13 ([#4685](https://github.com/cookiecutter/cookiecutter-django/pull/4685))\n\n## 2023.11.14\n\n\n### Updated\n\n- Update sentry-sdk to 1.35.0 ([#4681](https://github.com/cookiecutter/cookiecutter-django/pull/4681))\n\n- Auto-update pre-commit hooks ([#4683](https://github.com/cookiecutter/cookiecutter-django/pull/4683))\n\n## 2023.11.11\n\n\n### Updated\n\n- Update celery to 5.3.5 ([#4678](https://github.com/cookiecutter/cookiecutter-django/pull/4678))\n\n## 2023.11.09\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4673](https://github.com/cookiecutter/cookiecutter-django/pull/4673))\n\n- Update black to 23.11.0 ([#4674](https://github.com/cookiecutter/cookiecutter-django/pull/4674))\n\n## 2023.11.08\n\n\n### Updated\n\n- Update pytest-django to 4.7.0 ([#4672](https://github.com/cookiecutter/cookiecutter-django/pull/4672))\n\n## 2023.11.06\n\n\n### Changed\n\n- Add `rmbackup` script to remove backups from `postgres/backups`. Fixes: #4663 ([#4664](https://github.com/cookiecutter/cookiecutter-django/pull/4664))\n\n### Updated\n\n- Update django-allauth to 0.58.2 ([#4667](https://github.com/cookiecutter/cookiecutter-django/pull/4667))\n\n- Update uvicorn to 0.24.0.post1 ([#4666](https://github.com/cookiecutter/cookiecutter-django/pull/4666))\n\n## 2023.11.04\n\n\n### Updated\n\n- Update uvicorn to 0.24.0 ([#4665](https://github.com/cookiecutter/cookiecutter-django/pull/4665))\n\n## 2023.11.03\n\n\n### Updated\n\n- Update flake8-isort to 6.1.1 ([#4662](https://github.com/cookiecutter/cookiecutter-django/pull/4662))\n\n## 2023.11.02\n\n\n### Updated\n\n- Update sentry-sdk to 1.34.0 ([#4660](https://github.com/cookiecutter/cookiecutter-django/pull/4660))\n\n## 2023.11.01\n\n\n### Updated\n\n- Update django to 4.2.7 ([#4658](https://github.com/cookiecutter/cookiecutter-django/pull/4658))\n\n- Update django-stubs to 4.2.6 ([#4657](https://github.com/cookiecutter/cookiecutter-django/pull/4657))\n\n## 2023.10.31\n\n\n### Updated\n\n- Update pytest-django to 4.6.0 ([#4656](https://github.com/cookiecutter/cookiecutter-django/pull/4656))\n\n- Update pytest to 7.4.3 ([#4654](https://github.com/cookiecutter/cookiecutter-django/pull/4654))\n\n- Update werkzeug to 3.0.1 ([#4655](https://github.com/cookiecutter/cookiecutter-django/pull/4655))\n\n- Update sentry-sdk to 1.33.1 ([#4653](https://github.com/cookiecutter/cookiecutter-django/pull/4653))\n\n- Update sentry-sdk to 1.33.0 ([#4652](https://github.com/cookiecutter/cookiecutter-django/pull/4652))\n\n- Update crispy-bootstrap5 to 2023.10 ([#4651](https://github.com/cookiecutter/cookiecutter-django/pull/4651))\n\n## 2023.10.26\n\n\n### Updated\n\n- Update django-anymail to 10.2 ([#4645](https://github.com/cookiecutter/cookiecutter-django/pull/4645))\n\n## 2023.10.24\n\n\n### Updated\n\n- Update black to 23.10.1 ([#4639](https://github.com/cookiecutter/cookiecutter-django/pull/4639))\n\n- Auto-update pre-commit hooks ([#4641](https://github.com/cookiecutter/cookiecutter-django/pull/4641))\n\n## 2023.10.23\n\n\n### Updated\n\n- Update pylint-django to 2.5.5 ([#4638](https://github.com/cookiecutter/cookiecutter-django/pull/4638))\n\n## 2023.10.19\n\n\n### Updated\n\n- Update mypy to 1.6.1 ([#4634](https://github.com/cookiecutter/cookiecutter-django/pull/4634))\n\n- Update djangorestframework-stubs to 3.14.4 ([#4637](https://github.com/cookiecutter/cookiecutter-django/pull/4637))\n\n- Update django-stubs to 4.2.5 ([#4636](https://github.com/cookiecutter/cookiecutter-django/pull/4636))\n\n## 2023.10.17\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4633](https://github.com/cookiecutter/cookiecutter-django/pull/4633))\n\n- Update black to 23.10.0 ([#4632](https://github.com/cookiecutter/cookiecutter-django/pull/4632))\n\n- Update pillow to 10.1.0 ([#4630](https://github.com/cookiecutter/cookiecutter-django/pull/4630))\n\n- Update django-crispy-forms to 2.1 ([#4629](https://github.com/cookiecutter/cookiecutter-django/pull/4629))\n\n## 2023.10.13\n\n\n### Updated\n\n- Update pre-commit to 3.5.0 ([#4628](https://github.com/cookiecutter/cookiecutter-django/pull/4628))\n\n- Update watchfiles to 0.21.0 ([#4627](https://github.com/cookiecutter/cookiecutter-django/pull/4627))\n\n## 2023.10.12\n\n\n### Updated\n\n- Update django-cors-headers to 4.3.0 ([#4625](https://github.com/cookiecutter/cookiecutter-django/pull/4625))\n\n- Update whitenoise to 6.6.0 ([#4624](https://github.com/cookiecutter/cookiecutter-django/pull/4624))\n\n- Update sentry-sdk to 1.32.0 ([#4623](https://github.com/cookiecutter/cookiecutter-django/pull/4623))\n\n- Bump traefik from 2.10.4 to 2.10.5 ([#4626](https://github.com/cookiecutter/cookiecutter-django/pull/4626))\n\n## 2023.10.09\n\n\n### Updated\n\n- Bump stefanzweifel/git-auto-commit-action from 4.16.0 to 5.0.0 ([#4621](https://github.com/cookiecutter/cookiecutter-django/pull/4621))\n\n- Update django-storages to 1.14.2 ([#4620](https://github.com/cookiecutter/cookiecutter-django/pull/4620))\n\n## 2023.10.08\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4619](https://github.com/cookiecutter/cookiecutter-django/pull/4619))\n\n## 2023.10.05\n\n\n### Updated\n\n- Update djangorestframework-stubs to 3.14.3 ([#4618](https://github.com/cookiecutter/cookiecutter-django/pull/4618))\n\n- Update django-stubs to 4.2.4 ([#4566](https://github.com/cookiecutter/cookiecutter-django/pull/4566))\n\n- Update mypy to 1.5.1 ([#4568](https://github.com/cookiecutter/cookiecutter-django/pull/4568))\n\n## 2023.10.04\n\n\n### Updated\n\n- Update django to 4.2.6 ([#4617](https://github.com/cookiecutter/cookiecutter-django/pull/4617))\n\n- Update coverage to 7.3.2 ([#4616](https://github.com/cookiecutter/cookiecutter-django/pull/4616))\n\n- Update werkzeug to 3.0.0 ([#4608](https://github.com/cookiecutter/cookiecutter-django/pull/4608))\n\n- Update django-redis to 5.4.0 ([#4609](https://github.com/cookiecutter/cookiecutter-django/pull/4609))\n\n- Bump docs Python docker image from 3.11.5 to 3.11.6 ([#4615](https://github.com/cookiecutter/cookiecutter-django/pull/4615))\n\n## 2023.10.03\n\n\n### Changed\n\n- [pre-commit.ci] pre-commit autoupdate ([#4613](https://github.com/cookiecutter/cookiecutter-django/pull/4613))\n\n### Updated\n\n- Bump prod Python docker image from 3.11.5 to 3.11.6 ([#4611](https://github.com/cookiecutter/cookiecutter-django/pull/4611))\n\n- Bump local Python docker image from 3.11.5 to 3.11.6 ([#4612](https://github.com/cookiecutter/cookiecutter-django/pull/4612))\n\n- Auto-update pre-commit hooks ([#4610](https://github.com/cookiecutter/cookiecutter-django/pull/4610))\n\n## 2023.09.29\n\n\n### Updated\n\n- Update django-storages to 1.14.1 ([#4604](https://github.com/cookiecutter/cookiecutter-django/pull/4604))\n\n## 2023.09.28\n\n\n### Updated\n\n- Update psycopg to 3.1.12 ([#4601](https://github.com/cookiecutter/cookiecutter-django/pull/4601))\n\n## 2023.09.27\n\n\n### Fixed\n\n- Fix ownership for /start-flower script in production Dockerfile ([#4603](https://github.com/cookiecutter/cookiecutter-django/pull/4603))\n\n## 2023.09.26\n\n\n### Updated\n\n- Update redis to 5.0.1 ([#4600](https://github.com/cookiecutter/cookiecutter-django/pull/4600))\n\n## 2023.09.25\n\n\n### Updated\n\n- Update django-upgrade to 1.15.0 ([#4598](https://github.com/cookiecutter/cookiecutter-django/pull/4598))\n\n- Update django-allauth to 0.57.0 ([#4597](https://github.com/cookiecutter/cookiecutter-django/pull/4597))\n\n- Auto-update pre-commit hooks ([#4596](https://github.com/cookiecutter/cookiecutter-django/pull/4596))\n\n## 2023.09.23\n\n\n### Updated\n\n- Update psycopg to 3.1.11 ([#4595](https://github.com/cookiecutter/cookiecutter-django/pull/4595))\n\n- Auto-update pre-commit hooks ([#4591](https://github.com/cookiecutter/cookiecutter-django/pull/4591))\n\n- Update drf-spectacular to 0.26.5 ([#4594](https://github.com/cookiecutter/cookiecutter-django/pull/4594))\n\n## 2023.09.21\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4589](https://github.com/cookiecutter/cookiecutter-django/pull/4589))\n\n- Update djlint to 1.34.0 ([#4590](https://github.com/cookiecutter/cookiecutter-django/pull/4590))\n\n## 2023.09.19\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4588](https://github.com/cookiecutter/cookiecutter-django/pull/4588))\n\n- Update djlint to 1.33.0 ([#4587](https://github.com/cookiecutter/cookiecutter-django/pull/4587))\n\n## 2023.09.16\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4586](https://github.com/cookiecutter/cookiecutter-django/pull/4586))\n\n## 2023.09.15\n\n\n### Updated\n\n- Update flake8-isort to 6.1.0 ([#4585](https://github.com/cookiecutter/cookiecutter-django/pull/4585))\n\n- Update pillow to 10.0.1 ([#4584](https://github.com/cookiecutter/cookiecutter-django/pull/4584))\n\n## 2023.09.14\n\n\n### Updated\n\n- Update sphinx to 7.2.6 ([#4583](https://github.com/cookiecutter/cookiecutter-django/pull/4583))\n\n## 2023.09.13\n\n\n### Updated\n\n- Update sentry-sdk to 1.31.0 ([#4582](https://github.com/cookiecutter/cookiecutter-django/pull/4582))\n\n## 2023.09.12\n\n\n### Updated\n\n- Update django-storages to 1.14 ([#4564](https://github.com/cookiecutter/cookiecutter-django/pull/4564))\n\n## 2023.09.11\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4579](https://github.com/cookiecutter/cookiecutter-django/pull/4579))\n\n- Update black to 23.9.1 ([#4580](https://github.com/cookiecutter/cookiecutter-django/pull/4580))\n\n- Update django-allauth to 0.56.1 ([#4576](https://github.com/cookiecutter/cookiecutter-django/pull/4576))\n\n## 2023.09.08\n\n\n### Updated\n\n- Update pytest to 7.4.2 ([#4573](https://github.com/cookiecutter/cookiecutter-django/pull/4573))\n\n## 2023.09.07\n\n\n### Updated\n\n- Update django-allauth to 0.56.0 ([#4571](https://github.com/cookiecutter/cookiecutter-django/pull/4571))\n\n## 2023.09.06\n\n\n### Changed\n\n- Replace Mailhog with Mailpit ([#4551](https://github.com/cookiecutter/cookiecutter-django/pull/4551))\n\n### Updated\n\n- Update sphinx to 7.2.5 ([#4569](https://github.com/cookiecutter/cookiecutter-django/pull/4569))\n\n- Bump actions/checkout from 3 to 4 ([#4565](https://github.com/cookiecutter/cookiecutter-django/pull/4565))\n\n- Update coverage to 7.3.1 ([#4567](https://github.com/cookiecutter/cookiecutter-django/pull/4567))\n\n## 2023.09.04\n\n\n### Updated\n\n- Update django to 4.2.5 ([#4563](https://github.com/cookiecutter/cookiecutter-django/pull/4563))\n\n## 2023.09.03\n\n\n### Updated\n\n- Update celery to 5.3.4 ([#4562](https://github.com/cookiecutter/cookiecutter-django/pull/4562))\n\n## 2023.09.02\n\n\n### Updated\n\n- Update pytest to 7.4.1 ([#4561](https://github.com/cookiecutter/cookiecutter-django/pull/4561))\n\n- Update pre-commit to 3.4.0 ([#4560](https://github.com/cookiecutter/cookiecutter-django/pull/4560))\n\n- Update django-environ to 0.11.2 ([#4558](https://github.com/cookiecutter/cookiecutter-django/pull/4558))\n\n## 2023.09.01\n\n\n## 2023.08.31\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4550](https://github.com/cookiecutter/cookiecutter-django/pull/4550))\n\n- Update django-allauth to 0.55.2 ([#4549](https://github.com/cookiecutter/cookiecutter-django/pull/4549))\n\n- Update celery to 5.3.3 ([#4553](https://github.com/cookiecutter/cookiecutter-django/pull/4553))\n\n## 2023.08.30\n\n\n### Updated\n\n- Update django-environ to 0.11.0 ([#4548](https://github.com/cookiecutter/cookiecutter-django/pull/4548))\n\n## 2023.08.29\n\n\n### Updated\n\n- Update sentry-sdk to 1.30.0 ([#4546](https://github.com/cookiecutter/cookiecutter-django/pull/4546))\n\n## 2023.08.28\n\n\n### Changed\n\n- Add French translations ([#4454](https://github.com/cookiecutter/cookiecutter-django/pull/4454))\n\n- Change `MEDIA_URL` to an absolute URL in tests ([#4460](https://github.com/cookiecutter/cookiecutter-django/pull/4460))\n\n### Fixed\n\n- Fix a small compatibility issue between black and flake8 ([#4541](https://github.com/cookiecutter/cookiecutter-django/pull/4541))\n\n### Updated\n\n- Update django-allauth to 0.55.0 ([#4535](https://github.com/cookiecutter/cookiecutter-django/pull/4535))\n\n- Update watchfiles to 0.20.0 ([#4537](https://github.com/cookiecutter/cookiecutter-django/pull/4537))\n\n- Update Python version from 3.11.4 to 3.11.5 ([#4542](https://github.com/cookiecutter/cookiecutter-django/pull/4542))\n\n## 2023.08.19\n\n\n### Changed\n\n- Override `_after_postgeneration` to force save in `UserFactory` ([#4534](https://github.com/cookiecutter/cookiecutter-django/pull/4534))\n\n## 2023.08.17\n\n\n### Updated\n\n- Update argon2-cffi to 23.1.0 ([#4527](https://github.com/cookiecutter/cookiecutter-django/pull/4527))\n\n- Auto-update pre-commit hooks ([#4530](https://github.com/cookiecutter/cookiecutter-django/pull/4530))\n\n## 2023.08.16\n\n\n### Updated\n\n- Update django-upgrade to 1.14.1 ([#4528](https://github.com/cookiecutter/cookiecutter-django/pull/4528))\n\n## 2023.08.15\n\n\n### Updated\n\n- Update redis to 5.0.0 ([#4526](https://github.com/cookiecutter/cookiecutter-django/pull/4526))\n\n## 2023.08.14\n\n\n### Changed\n\n- Install Django and DRF stubs with `compatible-mypy` extra (as per offical recommendation) ([#4361](https://github.com/cookiecutter/cookiecutter-django/pull/4361))\n\n-  Fix `overrideCommand` value in `devcontainer` so that the `django` container can run (#4517) ([#4517](https://github.com/cookiecutter/cookiecutter-django/pull/4517))\n\n### Fixed\n\n- Prevent error in data migration caused by long project name ([#4525](https://github.com/cookiecutter/cookiecutter-django/pull/4525))\n\n- Remove unused gulp-concat when Webpack is selected ([#4520](https://github.com/cookiecutter/cookiecutter-django/pull/4520))\n\n- Exclude env files from container image (add .envs/ to .dockerignore) ([#4476](https://github.com/cookiecutter/cookiecutter-django/pull/4476))\n\n### Updated\n\n- Update werkzeug to 2.3.7 ([#4521](https://github.com/cookiecutter/cookiecutter-django/pull/4521))\n\n- Update coverage to 7.3.0 ([#4516](https://github.com/cookiecutter/cookiecutter-django/pull/4516))\n\n- Update django-debug-toolbar to 4.2.0 ([#4511](https://github.com/cookiecutter/cookiecutter-django/pull/4511))\n\n- Update flower to 2.0.1 ([#4518](https://github.com/cookiecutter/cookiecutter-django/pull/4518))\n\n## 2023.08.10\n\n\n### Fixed\n\n- Corrected &#39;or&#39; translation to pt-br ([#4507](https://github.com/cookiecutter/cookiecutter-django/pull/4507))\n\n## 2023.08.04\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4503](https://github.com/cookiecutter/cookiecutter-django/pull/4503))\n\n## 2023.08.01\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4499](https://github.com/cookiecutter/cookiecutter-django/pull/4499))\n\n- Update django-anymail to 10.1 ([#4497](https://github.com/cookiecutter/cookiecutter-django/pull/4497))\n\n- Update sentry-sdk to 1.29.2 ([#4496](https://github.com/cookiecutter/cookiecutter-django/pull/4496))\n\n- Update django to 4.2.4 ([#4495](https://github.com/cookiecutter/cookiecutter-django/pull/4495))\n\n- Update flake8 to 6.1.0 ([#4489](https://github.com/cookiecutter/cookiecutter-django/pull/4489))\n\n- Update uvicorn to 0.23.2 ([#4490](https://github.com/cookiecutter/cookiecutter-django/pull/4490))\n\n- Update sentry-sdk to 1.29.1 ([#4494](https://github.com/cookiecutter/cookiecutter-django/pull/4494))\n\n## 2023.07.30\n\n\n### Fixed\n\n- Fix `README.md` file extension in `setup.py` ([#4488](https://github.com/cookiecutter/cookiecutter-django/pull/4488))\n\n## 2023.07.28\n\n\n### Changed\n\n- Add support for Drone CI ([#4382](https://github.com/cookiecutter/cookiecutter-django/pull/4382))\n\n## 2023.07.27\n\n\n### Documentation\n\n- Document that `docker exec` does not work for running management commands ([#4487](https://github.com/cookiecutter/cookiecutter-django/pull/4487))\n\n- Add Webpack instructions for developping locally with HTTPS ([#4486](https://github.com/cookiecutter/cookiecutter-django/pull/4486))\n\n## 2023.07.25\n\n\n### Updated\n\n- Upgrade to traefik 2.10.4 ([#4483](https://github.com/cookiecutter/cookiecutter-django/pull/4483))\n\n## 2023.07.24\n\n\n### Fixed\n\n- Add missing custom CRSF error page in prod ([#4464](https://github.com/cookiecutter/cookiecutter-django/pull/4464))\n\n### Documentation\n\n- Replace `docker-compose` by `docker compose` in docs ([#4463](https://github.com/cookiecutter/cookiecutter-django/pull/4463))\n\n### Updated\n\n- Update drf-spectacular to 0.26.4 ([#4481](https://github.com/cookiecutter/cookiecutter-django/pull/4481))\n\n## 2023.07.20\n\n\n### Updated\n\n- Update djlint to 1.32.1 ([#4475](https://github.com/cookiecutter/cookiecutter-django/pull/4475))\n\n## 2023.07.19\n\n\n### Updated\n\n- Update factory-boy to 3.3.0 ([#4472](https://github.com/cookiecutter/cookiecutter-django/pull/4472))\n\n- Update gunicorn to 21.2.0 ([#4473](https://github.com/cookiecutter/cookiecutter-django/pull/4473))\n\n- Update djlint to 1.32.0 ([#4471](https://github.com/cookiecutter/cookiecutter-django/pull/4471))\n\n## 2023.07.18\n\n\n### Updated\n\n- Update gunicorn to 21.1.0 ([#4470](https://github.com/cookiecutter/cookiecutter-django/pull/4470))\n\n- Update uvicorn to 0.23.1 ([#4468](https://github.com/cookiecutter/cookiecutter-django/pull/4468))\n\n- Update gunicorn to 21.0.1 ([#4466](https://github.com/cookiecutter/cookiecutter-django/pull/4466))\n\n## 2023.07.13\n\n\n### Updated\n\n- Update sentry-sdk to 1.28.1 ([#4458](https://github.com/cookiecutter/cookiecutter-django/pull/4458))\n\n## 2023.07.11\n\n\n### Changed\n\n- Improve type hints for `UserSerializer` ([#4429](https://github.com/cookiecutter/cookiecutter-django/pull/4429))\n\n- [pre-commit.ci] pre-commit autoupdate ([#4453](https://github.com/cookiecutter/cookiecutter-django/pull/4453))\n\n### Fixed\n\n- Fix `/tmp` bind mount in devcontainer config ([#4455](https://github.com/cookiecutter/cookiecutter-django/pull/4455))\n\n### Updated\n\n- Update black to 23.7.0 ([#4452](https://github.com/cookiecutter/cookiecutter-django/pull/4452))\n\n## 2023.07.10\n\n\n### Fixed\n\n- Prevent user&#39;s name being shown twice on user details page if username is set to email ([#4436](https://github.com/cookiecutter/cookiecutter-django/pull/4436))\n\n- Add missing trailing space in `EMAIL_SUBJECT_PREFIX` setting ([#4434](https://github.com/cookiecutter/cookiecutter-django/pull/4434))\n\n### Documentation\n\n- Clarify documentation on which port to use to access the application when using Webpack or Gulp ([#4413](https://github.com/cookiecutter/cookiecutter-django/pull/4413))\n\n### Updated\n\n- Update django-coverage-plugin to 3.1.0 ([#4446](https://github.com/cookiecutter/cookiecutter-django/pull/4446))\n\n- Update pillow to 10.0.0 ([#4432](https://github.com/cookiecutter/cookiecutter-django/pull/4432))\n\n- Update django-cors-headers to 4.2.0 ([#4445](https://github.com/cookiecutter/cookiecutter-django/pull/4445))\n\n- Update sentry-sdk to 1.28.0 ([#4444](https://github.com/cookiecutter/cookiecutter-django/pull/4444))\n\n## 2023.07.09\n\n\n### Fixed\n\n- Fix missing run configurations when PyCharm is selected ([#4441](https://github.com/cookiecutter/cookiecutter-django/pull/4441))\n\n## 2023.07.08\n\n\n### Updated\n\n- Update sentry-sdk to 1.27.1 ([#4440](https://github.com/cookiecutter/cookiecutter-django/pull/4440))\n\n## 2023.07.04\n\n\n### Changed\n\n- Add PostgreSQL 15 ([#4431](https://github.com/cookiecutter/cookiecutter-django/pull/4431))\n\n- [pre-commit.ci] pre-commit autoupdate ([#4438](https://github.com/cookiecutter/cookiecutter-django/pull/4438))\n\n### Updated\n\n- Update sentry-sdk to 1.27.0 ([#4439](https://github.com/cookiecutter/cookiecutter-django/pull/4439))\n\n- Update postcss-preset-env to 9.0.0 ([#4437](https://github.com/cookiecutter/cookiecutter-django/pull/4437))\n\n## 2023.07.03\n\n\n### Changed\n\n- Add a devcontainer configuration with Docker ([#4198](https://github.com/cookiecutter/cookiecutter-django/pull/4198))\n\n### Updated\n\n- Update django-stubs to 4.2.3 ([#4430](https://github.com/cookiecutter/cookiecutter-django/pull/4430))\n\n- Update django to 4.2.3 ([#4435](https://github.com/cookiecutter/cookiecutter-django/pull/4435))\n\n## 2023.06.30\n\n\n### Changed\n\n- Add option to use django-allauth workflow in the admin ([#1921](https://github.com/cookiecutter/cookiecutter-django/pull/1921))\n\n## 2023.06.29\n\n\n### Changed\n\n- Replace psycopg2 by psycopg3 ([#4421](https://github.com/cookiecutter/cookiecutter-django/pull/4421))\n\n## 2023.06.28\n\n\n### Changed\n\n- Upgrade to django 4.2 ([#4393](https://github.com/cookiecutter/cookiecutter-django/pull/4393))\n\n### Fixed\n\n- Fix PostgreSQL version in GitHub workflow ([#4423](https://github.com/cookiecutter/cookiecutter-django/pull/4423))\n\n### Updated\n\n- Update werkzeug to 2.3.6 ([#4427](https://github.com/cookiecutter/cookiecutter-django/pull/4427))\n\n- Update django-compressor to 4.4 ([#4422](https://github.com/cookiecutter/cookiecutter-django/pull/4422))\n\n## 2023.06.27\n\n\n### Changed\n\n- Populate User `name` field during social auth ([#3968](https://github.com/cookiecutter/cookiecutter-django/pull/3968))\n\n- Add djLint for HTML formatting and linting ([#4389](https://github.com/cookiecutter/cookiecutter-django/pull/4389))\n\n### Fixed\n\n- Only include prettier pre-commit hook with node-based front-end pipeline ([#4418](https://github.com/cookiecutter/cookiecutter-django/pull/4418))\n\n### Updated\n\n- Update djangorestframework-stubs to 3.14.2 ([#4420](https://github.com/cookiecutter/cookiecutter-django/pull/4420))\n\n- Update django-stubs to 4.2.2 ([#4419](https://github.com/cookiecutter/cookiecutter-django/pull/4419))\n\n## 2023.06.26\n\n\n### Updated\n\n- Update pytest to 7.4.0 ([#4412](https://github.com/cookiecutter/cookiecutter-django/pull/4412))\n\n- Update redis to 4.6.0 ([#4415](https://github.com/cookiecutter/cookiecutter-django/pull/4415))\n\n- Update mypy to 1.4.1 ([#4416](https://github.com/cookiecutter/cookiecutter-django/pull/4416))\n\n## 2023.06.22\n\n\n### Updated\n\n- Update pygithub to 1.59.0 ([#4410](https://github.com/cookiecutter/cookiecutter-django/pull/4410))\n\n- Update drf-spectacular to 0.26.3 ([#4411](https://github.com/cookiecutter/cookiecutter-django/pull/4411))\n\n- Update sentry-sdk to 1.26.0 ([#4409](https://github.com/cookiecutter/cookiecutter-django/pull/4409))\n\n## 2023.06.21\n\n\n### Updated\n\n- Upgrade traefik to 2.10.3 ([#4408](https://github.com/cookiecutter/cookiecutter-django/pull/4408))\n\n## 2023.06.19\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4405](https://github.com/cookiecutter/cookiecutter-django/pull/4405))\n\n- Update celery to 5.3.1 ([#4404](https://github.com/cookiecutter/cookiecutter-django/pull/4404))\n\n## 2023.06.18\n\n\n### Changed\n\n- Fix missing celery env variable when running compilemessages ([#4403](https://github.com/cookiecutter/cookiecutter-django/pull/4403))\n\n### Updated\n\n- Update flower to 2.0.0 ([#4402](https://github.com/cookiecutter/cookiecutter-django/pull/4402))\n\n## 2023.06.17\n\n\n## 2023.06.16\n\n\n### Updated\n\n- Update whitenoise to 6.5.0 ([#4400](https://github.com/cookiecutter/cookiecutter-django/pull/4400))\n\n- Update django-redis to 5.3.0 ([#4399](https://github.com/cookiecutter/cookiecutter-django/pull/4399))\n\n- Auto-update pre-commit hooks ([#4395](https://github.com/cookiecutter/cookiecutter-django/pull/4395))\n\n## 2023.06.14\n\n\n### Updated\n\n- Update django-cors-headers to 4.1.0 ([#4391](https://github.com/cookiecutter/cookiecutter-django/pull/4391))\n\n- Update django-upgrade to 1.14.0 ([#4394](https://github.com/cookiecutter/cookiecutter-django/pull/4394))\n\n- Update django-webpack-loader to 2.0.1 ([#4392](https://github.com/cookiecutter/cookiecutter-django/pull/4392))\n\n- Update pre-commit to 3.3.3 ([#4390](https://github.com/cookiecutter/cookiecutter-django/pull/4390))\n\n## 2023.06.11\n\n\n### Updated\n\n- Update pytest to 7.3.2 ([#4384](https://github.com/cookiecutter/cookiecutter-django/pull/4384))\n\n- Auto-update pre-commit hooks ([#4385](https://github.com/cookiecutter/cookiecutter-django/pull/4385))\n\n## 2023.06.09\n\n\n### Fixed\n\n- Fix missing `compilemessages` step before deploying to prod ([#4363](https://github.com/cookiecutter/cookiecutter-django/pull/4363))\n\n## 2023.06.08\n\n\n### Fixed\n\n- Fix failure in user view test caused by translations ([#4374](https://github.com/cookiecutter/cookiecutter-django/pull/4374))\n\n### Updated\n\n- Update to Python 3.11.4 in production Docker compose ([#4378](https://github.com/cookiecutter/cookiecutter-django/pull/4378))\n\n- Update to Python 3.11.4 in docs Docker compose ([#4379](https://github.com/cookiecutter/cookiecutter-django/pull/4379))\n\n- Update to Python 3.11.4 in local Docker compose ([#4380](https://github.com/cookiecutter/cookiecutter-django/pull/4380))\n\n- Update celery to 5.3.0 ([#4369](https://github.com/cookiecutter/cookiecutter-django/pull/4369))\n\n- Update werkzeug to 2.3.5 ([#4377](https://github.com/cookiecutter/cookiecutter-django/pull/4377))\n\n## 2023.06.07\n\n\n### Changed\n\n- Replace `runserver` with `runserver_plus` ([#4373](https://github.com/cookiecutter/cookiecutter-django/pull/4373))\n\n- Add translations for Brazilian Portuguese ([#4367](https://github.com/cookiecutter/cookiecutter-django/pull/4367))\n\n### Updated\n\n- Update sentry-sdk to 1.25.1 ([#4376](https://github.com/cookiecutter/cookiecutter-django/pull/4376))\n\n- Update django-extensions to 3.2.3 ([#4372](https://github.com/cookiecutter/cookiecutter-django/pull/4372))\n\n- Update djangorestframework-stubs to 3.14.1 ([#4366](https://github.com/cookiecutter/cookiecutter-django/pull/4366))\n\n- Update django-stubs to 4.2.1 ([#4365](https://github.com/cookiecutter/cookiecutter-django/pull/4365))\n\n- Update mypy to 1.3.0 ([#4327](https://github.com/cookiecutter/cookiecutter-django/pull/4327))\n\n## 2023.06.02\n\n\n### Updated\n\n- Update sentry-sdk to 1.25.0 ([#4364](https://github.com/cookiecutter/cookiecutter-django/pull/4364))\n\n## 2023.05.30\n\n\n### Updated\n\n- Update hiredis to 2.2.3 ([#4360](https://github.com/cookiecutter/cookiecutter-django/pull/4360))\n\n- Update django-debug-toolbar to 4.1.0 ([#4359](https://github.com/cookiecutter/cookiecutter-django/pull/4359))\n\n- Update redis to 4.5.5 ([#4358](https://github.com/cookiecutter/cookiecutter-django/pull/4358))\n\n- Update django-anymail to 10.0 ([#4357](https://github.com/cookiecutter/cookiecutter-django/pull/4357))\n\n- Update coverage to 7.2.7 ([#4356](https://github.com/cookiecutter/cookiecutter-django/pull/4356))\n\n## 2023.05.28\n\n\n## 2023.05.24\n\n\n### Fixed\n\n- Prevent Celery restarts on media file changes ([#4352](https://github.com/cookiecutter/cookiecutter-django/pull/4352))\n\n### Updated\n\n- Update coverage to 7.2.6 ([#4351](https://github.com/cookiecutter/cookiecutter-django/pull/4351))\n\n## 2023.05.23\n\n\n### Changed\n\n- Fix compatibility webpack-bundle-tracker&gt;=2.0.0 js library required after upgrade django-webpack-loader&gt;=2.0.0 ([#4350](https://github.com/cookiecutter/cookiecutter-django/pull/4350))\n\n### Updated\n\n- Update sphinx-rtd-theme to 1.2.1 ([#4348](https://github.com/cookiecutter/cookiecutter-django/pull/4348))\n\n- Update sentry-sdk to 1.24.0 ([#4349](https://github.com/cookiecutter/cookiecutter-django/pull/4349))\n\n- Bump webpack-bundle-tracker from 1.8.1 to 2.0.0 in /{{cookiecutter.project_slug}} ([#4347](https://github.com/cookiecutter/cookiecutter-django/pull/4347))\n\n- Update django-webpack-loader to 2.0.0 ([#4345](https://github.com/cookiecutter/cookiecutter-django/pull/4345))\n\n- Update pytest-xdist to 3.3.1 ([#4344](https://github.com/cookiecutter/cookiecutter-django/pull/4344))\n\n- Update requests to 2.31.0 ([#4346](https://github.com/cookiecutter/cookiecutter-django/pull/4346))\n\n## 2023.05.18\n\n\n### Updated\n\n- Update pre-commit to 3.3.2 ([#4342](https://github.com/cookiecutter/cookiecutter-django/pull/4342))\n\n## 2023.05.17\n\n\n### Updated\n\n- Update sentry-sdk to 1.23.1 ([#4341](https://github.com/cookiecutter/cookiecutter-django/pull/4341))\n\n## 2023.05.15\n\n\n### Updated\n\n- Update django-cors-headers to 4.0.0 ([#4329](https://github.com/cookiecutter/cookiecutter-django/pull/4329))\n\n- Update sentry-sdk to 1.23.0 ([#4337](https://github.com/cookiecutter/cookiecutter-django/pull/4337))\n\n## 2023.05.09\n\n\n### Updated\n\n- Update werkzeug to 2.3.4 ([#4325](https://github.com/cookiecutter/cookiecutter-django/pull/4325))\n\n## 2023.05.08\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4320](https://github.com/cookiecutter/cookiecutter-django/pull/4320))\n\n- Update sentry-sdk to 1.22.2 ([#4321](https://github.com/cookiecutter/cookiecutter-django/pull/4321))\n\n## 2023.05.04\n\n\n### Changed\n\n- Remove pytz from dependencies ([#4309](https://github.com/cookiecutter/cookiecutter-django/pull/4309))\n\n### Updated\n\n- Update django-anymail to 9.2 ([#4316](https://github.com/cookiecutter/cookiecutter-django/pull/4316))\n\n- Update pre-commit to 3.3.1 ([#4315](https://github.com/cookiecutter/cookiecutter-django/pull/4315))\n\n- Update coverage to 7.2.5 ([#4314](https://github.com/cookiecutter/cookiecutter-django/pull/4314))\n\n- Update django to 4.1.9 ([#4313](https://github.com/cookiecutter/cookiecutter-django/pull/4313))\n\n- Update sentry-sdk to 1.21.1 ([#4312](https://github.com/cookiecutter/cookiecutter-django/pull/4312))\n\n- Update requests to 2.30.0 ([#4311](https://github.com/cookiecutter/cookiecutter-django/pull/4311))\n\n## 2023.05.02\n\n\n### Updated\n\n- Upgrade traefik to 2.10.1 ([#4304](https://github.com/cookiecutter/cookiecutter-django/pull/4304))\n\n- Update uvicorn to 0.22.0 ([#4305](https://github.com/cookiecutter/cookiecutter-django/pull/4305))\n\n- Update werkzeug to 2.3.3 ([#4307](https://github.com/cookiecutter/cookiecutter-django/pull/4307))\n\n## 2023.04.28\n\n\n### Changed\n\n- Add django-upgrade to pre-commit hooks ([#4298](https://github.com/cookiecutter/cookiecutter-django/pull/4298))\n\n## 2023.04.27\n\n\n### Updated\n\n- Update djangorestframework-stubs to 3.14.0 ([#4303](https://github.com/cookiecutter/cookiecutter-django/pull/4303))\n\n- Update werkzeug to 2.3.1 ([#4302](https://github.com/cookiecutter/cookiecutter-django/pull/4302))\n\n- Update django-stubs to 4.2.0 ([#4301](https://github.com/cookiecutter/cookiecutter-django/pull/4301))\n\n## 2023.04.26\n\n\n### Updated\n\n- Upgrade cssnano to v6.0.0 ([#4233](https://github.com/cookiecutter/cookiecutter-django/pull/4233))\n\n- Upgrade concurrently to 8.0.1 ([#4237](https://github.com/cookiecutter/cookiecutter-django/pull/4237))\n\n- Upgrade to node v18 ([#4294](https://github.com/cookiecutter/cookiecutter-django/pull/4294))\n\n- Update coverage to 7.2.3 ([#4297](https://github.com/cookiecutter/cookiecutter-django/pull/4297))\n\n- Update mypy to 1.2.0 ([#4295](https://github.com/cookiecutter/cookiecutter-django/pull/4295))\n\n- Update werkzeug to 2.3.0 ([#4296](https://github.com/cookiecutter/cookiecutter-django/pull/4296))\n\n## 2023.04.25\n\n\n### Updated\n\n- Update sentry-sdk to 1.21.0 ([#4293](https://github.com/cookiecutter/cookiecutter-django/pull/4293))\n\n- Update sphinx to 6.2.1 ([#4292](https://github.com/cookiecutter/cookiecutter-django/pull/4292))\n\n- Bump traefik from 2.9.10 to 2.10.0 ([#4290](https://github.com/cookiecutter/cookiecutter-django/pull/4290))\n\n- Auto-update pre-commit hooks ([#4288](https://github.com/cookiecutter/cookiecutter-django/pull/4288))\n\n## 2023.04.24\n\n\n### Updated\n\n- Auto-update pre-commit hooks ([#4286](https://github.com/cookiecutter/cookiecutter-django/pull/4286))\n\n- Update sphinx to 6.2.0 ([#4285](https://github.com/cookiecutter/cookiecutter-django/pull/4285))\n\n## 2023.04.19\n\n\n### Updated\n\n- Update sentry-sdk to 1.20.0 ([#4282](https://github.com/cookiecutter/cookiecutter-django/pull/4282))\n\n## 2023.04.18\n\n\n### Documentation\n\n- Document how to add 3rd party packages with Docker ([#4279](https://github.com/cookiecutter/cookiecutter-django/pull/4279))\n\n## 2023.04.15\n\n\n### Changed\n\n- Add username_type option ([#3958](https://github.com/cookiecutter/cookiecutter-django/pull/3958))\n\n- Fix inconsistent line length and move configs to pyproject.toml ([#4276](https://github.com/cookiecutter/cookiecutter-django/pull/4276))\n\n- Relax rules for linting of pull requests on this template ([#4273](https://github.com/cookiecutter/cookiecutter-django/pull/4273))\n\n- Add more pre-commit hooks ([#4266](https://github.com/cookiecutter/cookiecutter-django/pull/4266))\n\n- Upgrade Python to version 3.11 (Faster CPython) ([#4256](https://github.com/cookiecutter/cookiecutter-django/pull/4256))\n\n### Updated\n\n- Update drf-spectacular to 0.26.2 ([#4277](https://github.com/cookiecutter/cookiecutter-django/pull/4277))\n\n- Update pytest to 7.3.1 ([#4272](https://github.com/cookiecutter/cookiecutter-django/pull/4272))\n\n## 2023.04.13\n\n### Updated\n- Update tox to 4.4.12 ([#4271](https://github.com/cookiecutter/cookiecutter-django/pull/4271))\n\n## 2023.04.10\n\n### Updated\n- Update pytest-sugar to 0.9.7 ([#4269](https://github.com/cookiecutter/cookiecutter-django/pull/4269))\n- Update pytest to 7.3.0 ([#4268](https://github.com/cookiecutter/cookiecutter-django/pull/4268))\n\n## 2023.04.07\n\n### Updated\n- Upgrade traefik to 2.9.10 ([#4267](https://github.com/cookiecutter/cookiecutter-django/pull/4267))\n\n## 2023.04.05\n\n### Changed\n- Update indent for nginx config file ([#4260](https://github.com/cookiecutter/cookiecutter-django/pull/4260))\n### Updated\n- Update tox to 4.4.11 ([#4262](https://github.com/cookiecutter/cookiecutter-django/pull/4262))\n- Update django to 4.1.8 ([#4258](https://github.com/cookiecutter/cookiecutter-django/pull/4258))\n- Update pre-commit to 3.2.2 ([#4259](https://github.com/cookiecutter/cookiecutter-django/pull/4259))\n\n## 2023.04.04\n\n### Changed\n- Upgrade to Django 4.1 ([#4028](https://github.com/cookiecutter/cookiecutter-django/pull/4028))\n- Remove deprecated security setting ([#4247](https://github.com/cookiecutter/cookiecutter-django/pull/4247))\n### Fixed\n- Replace `runserver_plus` with `runserver` ([#4255](https://github.com/cookiecutter/cookiecutter-django/pull/4255))\n- Fix traefik rule priority for media router ([#4244](https://github.com/cookiecutter/cookiecutter-django/pull/4244))\n### Updated\n- Update sentry-sdk to 1.19.0 ([#4254](https://github.com/cookiecutter/cookiecutter-django/pull/4254))\n- Update django-debug-toolbar to 4.0.0 ([#4251](https://github.com/cookiecutter/cookiecutter-django/pull/4251))\n\n## 2023.04.03\n\n### Changed\n- fix: Syntax for ignoring specific noqa errors ([#4250](https://github.com/cookiecutter/cookiecutter-django/pull/4250))\n### Updated\n- Update psycopg2-binary to 2.9.6 ([#4249](https://github.com/cookiecutter/cookiecutter-django/pull/4249))\n- Update psycopg2 to 2.9.6 ([#4248](https://github.com/cookiecutter/cookiecutter-django/pull/4248))\n\n## 2023.04.01\n\n### Updated\n- Update pytest-instafail to 0.5.0 ([#4240](https://github.com/cookiecutter/cookiecutter-django/pull/4240))\n- Update pillow to 9.5.0 ([#4242](https://github.com/cookiecutter/cookiecutter-django/pull/4242))\n- Update django-allauth to 0.54.0 ([#4241](https://github.com/cookiecutter/cookiecutter-django/pull/4241))\n\n## 2023.03.29\n\n### Updated\n- Update redis to 4.5.4 ([#4239](https://github.com/cookiecutter/cookiecutter-django/pull/4239))\n- Update pytz to 2023.3 ([#4238](https://github.com/cookiecutter/cookiecutter-django/pull/4238))\n- Update black to 23.3.0 ([#4236](https://github.com/cookiecutter/cookiecutter-django/pull/4236))\n\n## 2023.03.27\n\n### Updated\n- Update watchfiles to 0.19.0 ([#4232](https://github.com/cookiecutter/cookiecutter-django/pull/4232))\n\n## 2023.03.26\n\n### Updated\n- Update pre-commit to 3.2.1 ([#4229](https://github.com/cookiecutter/cookiecutter-django/pull/4229))\n\n## 2023.03.25\n\n### Updated\n- Update pytz to 2023.2 ([#4228](https://github.com/cookiecutter/cookiecutter-django/pull/4228))\n\n## 2023.03.23\n\n### Updated\n- Bump traefik from 2.9.8 to 2.9.9 ([#4225](https://github.com/cookiecutter/cookiecutter-django/pull/4225))\n\n## 2023.03.22\n\n### Updated\n- Update redis to 4.5.3 ([#4227](https://github.com/cookiecutter/cookiecutter-django/pull/4227))\n\n## 2023.03.20\n\n### Updated\n- Update django-allauth to 0.53.1 ([#4223](https://github.com/cookiecutter/cookiecutter-django/pull/4223))\n- Update redis to 4.5.2 ([#4222](https://github.com/cookiecutter/cookiecutter-django/pull/4222))\n\n## 2023.03.18\n\n### Updated\n- Update drf-spectacular to 0.26.1 ([#4221](https://github.com/cookiecutter/cookiecutter-django/pull/4221))\n- Update pygithub to 1.58.1 ([#4220](https://github.com/cookiecutter/cookiecutter-django/pull/4220))\n- Update pre-commit to 3.2.0 ([#4219](https://github.com/cookiecutter/cookiecutter-django/pull/4219))\n\n## 2023.03.16\n\n### Changed\n- Pin base Python Docker images to bugfix ([#4194](https://github.com/cookiecutter/cookiecutter-django/pull/4194))\n### Fixed\n- Trim leading and trailing space in `domain_name` and `email` ([#4163](https://github.com/cookiecutter/cookiecutter-django/pull/4163))\n### Updated\n- Update djangorestframework-stubs to 1.10.0 ([#4217](https://github.com/cookiecutter/cookiecutter-django/pull/4217))\n- Update django-stubs to 1.16.0 ([#4216](https://github.com/cookiecutter/cookiecutter-django/pull/4216))\n- Update coverage to 7.2.2 ([#4218](https://github.com/cookiecutter/cookiecutter-django/pull/4218))\n- Update sentry-sdk to 1.17.0 ([#4215](https://github.com/cookiecutter/cookiecutter-django/pull/4215))\n- Bump Docker python image from 3.10.9 to 3.10.10 on production Django ([#4214](https://github.com/cookiecutter/cookiecutter-django/pull/4214))\n- Bump Docker python image from 3.10.9-slim-bullseye to 3.10.10-slim-bullseye for docs ([#4213](https://github.com/cookiecutter/cookiecutter-django/pull/4213))\n- Bump Docker python image from 3.10.9-slim-bullseye to 3.10.10-slim-bullseye for local Django service ([#4212](https://github.com/cookiecutter/cookiecutter-django/pull/4212))\n- Update uvicorn to 0.21.1 ([#4211](https://github.com/cookiecutter/cookiecutter-django/pull/4211))\n- Update django-allauth to 0.53.0 ([#4210](https://github.com/cookiecutter/cookiecutter-django/pull/4210))\n\n## 2023.03.14\n\n### Updated\n- Update django-celery-beat to 2.5.0 ([#4208](https://github.com/cookiecutter/cookiecutter-django/pull/4208))\n\n## 2023.03.13\n\n### Updated\n- Update uvicorn to 0.21.0 ([#4203](https://github.com/cookiecutter/cookiecutter-django/pull/4203))\n- Update django-anymail to 9.1 ([#4206](https://github.com/cookiecutter/cookiecutter-django/pull/4206))\n- Update tox to 4.4.7 ([#4207](https://github.com/cookiecutter/cookiecutter-django/pull/4207))\n\n## 2023.03.09\n\n### Fixed\n- Fix the omit configuration for coverage ([#4201](https://github.com/cookiecutter/cookiecutter-django/pull/4201))\n### Updated\n- Update ipdb to 0.13.13 ([#4202](https://github.com/cookiecutter/cookiecutter-django/pull/4202))\n\n## 2023.03.07\n\n### Updated\n- Update mypy to 1.1.1 ([#4196](https://github.com/cookiecutter/cookiecutter-django/pull/4196))\n- Update django-environ to 0.10.0 ([#4195](https://github.com/cookiecutter/cookiecutter-django/pull/4195))\n\n## 2023.03.04\n\n### Changed\n- Add option to serve media files locally using nginx ([#2457](https://github.com/cookiecutter/cookiecutter-django/pull/2457))\n### Documentation\n- Include contributing page to the docs ([#4144](https://github.com/cookiecutter/cookiecutter-django/pull/4144))\n### Updated\n- Update myst-parser to 0.19.1 ([#4193](https://github.com/cookiecutter/cookiecutter-django/pull/4193))\n- Update pytest to 7.2.2 ([#4191](https://github.com/cookiecutter/cookiecutter-django/pull/4191))\n- Update drf-spectacular to 0.26.0 ([#4192](https://github.com/cookiecutter/cookiecutter-django/pull/4192))\n\n## 2023.02.28\n\n### Updated\n- Update pre-commit to 3.1.1 ([#4188](https://github.com/cookiecutter/cookiecutter-django/pull/4188))\n\n## 2023.02.27\n\n### Updated\n- Update sentry-sdk to 1.16.0 ([#4187](https://github.com/cookiecutter/cookiecutter-django/pull/4187))\n\n## 2023.02.26\n\n### Changed\n- Fix readthedocs config file for generated project ([#4172](https://github.com/cookiecutter/cookiecutter-django/pull/4172))\n### Updated\n- Bump traefik from v2.2.11 to 2.9.8 ([#4164](https://github.com/cookiecutter/cookiecutter-django/pull/4164))\n- Update coverage to 7.2.1 ([#4186](https://github.com/cookiecutter/cookiecutter-django/pull/4186))\n\n## 2023.02.25\n\n### Changed\n- Run linting with pre-commit on GitLab ([#4150](https://github.com/cookiecutter/cookiecutter-django/pull/4150))\n### Fixed\n- Disable caching for linter job on GitHub actions ([#4166](https://github.com/cookiecutter/cookiecutter-django/pull/4166))\n### Documentation\n- Add instuction to run celery beat ([#4162](https://github.com/cookiecutter/cookiecutter-django/pull/4162))\n### Updated\n- Bump garland/aws-cli-docker from 1.15.47 to 1.16.140 ([#4136](https://github.com/cookiecutter/cookiecutter-django/pull/4136))\n- Update djangorestframework-stubs to 1.9.1 ([#4184](https://github.com/cookiecutter/cookiecutter-django/pull/4184))\n- Update whitenoise to 6.4.0 ([#4180](https://github.com/cookiecutter/cookiecutter-django/pull/4180))\n- Update django-stubs to 1.15.0 ([#4183](https://github.com/cookiecutter/cookiecutter-django/pull/4183))\n- Update django-crispy-forms to 2.0 ([#4158](https://github.com/cookiecutter/cookiecutter-django/pull/4158))\n- Update django-cors-headers to 3.14.0 ([#4181](https://github.com/cookiecutter/cookiecutter-django/pull/4181))\n- Update python-slugify to 8.0.1 ([#4178](https://github.com/cookiecutter/cookiecutter-django/pull/4178))\n- Update pre-commit to 3.1.0 ([#4176](https://github.com/cookiecutter/cookiecutter-django/pull/4176))\n- Update mypy to 1.0.1 ([#4168](https://github.com/cookiecutter/cookiecutter-django/pull/4168))\n- Update werkzeug to 2.2.3 ([#4160](https://github.com/cookiecutter/cookiecutter-django/pull/4160))\n- Update coverage to 7.2.0 ([#4177](https://github.com/cookiecutter/cookiecutter-django/pull/4177))\n- Update django to 4.0.10 ([#4159](https://github.com/cookiecutter/cookiecutter-django/pull/4159))\n- Update hiredis to 2.2.2 ([#4156](https://github.com/cookiecutter/cookiecutter-django/pull/4156))\n\n## 2023.02.17\n\n### Changed\n- Update version of github actions on the template project ([#4167](https://github.com/cookiecutter/cookiecutter-django/pull/4167))\n\n## 2023.02.09\n\n### Changed\n- Remove unused pip cache paths in GHA &amp; add a note for pre-commit.ci ([#4151](https://github.com/cookiecutter/cookiecutter-django/pull/4151))\n### Updated\n- Update mypy to 0.991 ([#4106](https://github.com/cookiecutter/cookiecutter-django/pull/4106))\n\n## 2023.02.08\n\n### Updated\n- Update sphinx to 6.1.3 ([#4148](https://github.com/cookiecutter/cookiecutter-django/pull/4148))\n- Update redis to 4.5.1 ([#4147](https://github.com/cookiecutter/cookiecutter-django/pull/4147))\n\n## 2023.02.07\n\n### Updated\n- Bump postcss-preset-env from 7.8.3 to 8.0.1 ([#4115](https://github.com/cookiecutter/cookiecutter-django/pull/4115))\n- Bump sass-loader from 12.6.0 to 13.2.0 ([#4116](https://github.com/cookiecutter/cookiecutter-django/pull/4116))\n- Bump babel-loader from 8.3.0 to 9.1.2 ([#4117](https://github.com/cookiecutter/cookiecutter-django/pull/4117))\n- Bump postcss-loader from 6.2.1 to 7.0.2 ([#4114](https://github.com/cookiecutter/cookiecutter-django/pull/4114))\n- Bump webpack-cli from 4.10.0 to 5.0.1 ([#4118](https://github.com/cookiecutter/cookiecutter-django/pull/4118))\n- Update redis to 4.5.0 ([#4142](https://github.com/cookiecutter/cookiecutter-django/pull/4142))\n- Update sentry-sdk to 1.15.0 ([#4141](https://github.com/cookiecutter/cookiecutter-django/pull/4141))\n\n## 2023.02.06\n\n### Changed\n- Change `RequestFactory` to `APIRequestFactory` in tests for API views ([#4110](https://github.com/cookiecutter/cookiecutter-django/pull/4110))\n### Fixed\n- Fix django-webpack-loader setup when running tests ([#4128](https://github.com/cookiecutter/cookiecutter-django/pull/4128))\n### Documentation\n- Added AWS ECS Full Deployment Article to README ([#2630](https://github.com/cookiecutter/cookiecutter-django/pull/2630))\n### Updated\n- Update hiredis to 2.2.1 ([#4123](https://github.com/cookiecutter/cookiecutter-django/pull/4123))\n- Update tox to 4.4.4 ([#4133](https://github.com/cookiecutter/cookiecutter-django/pull/4133))\n- Update django to 4.0.9 ([#4134](https://github.com/cookiecutter/cookiecutter-django/pull/4134))\n- Update django-webpack-loader to 1.8.1 ([#4132](https://github.com/cookiecutter/cookiecutter-django/pull/4132))\n\n## 2023.02.05\n\n### Documentation\n- Add note about which service to request when running locally with Docker &amp; Webpack or Gulp ([#4130](https://github.com/cookiecutter/cookiecutter-django/pull/4130))\n\n## 2023.02.03\n\n### Updated\n- Update pre-commit to 3.0.4 ([#4127](https://github.com/cookiecutter/cookiecutter-django/pull/4127))\n\n## 2023.02.02\n\n### Updated\n- Update python-slugify to 8.0.0 ([#4111](https://github.com/cookiecutter/cookiecutter-django/pull/4111))\n- Update pre-commit to 3.0.3 ([#4121](https://github.com/cookiecutter/cookiecutter-django/pull/4121))\n- Update black to 23.1.0 ([#4120](https://github.com/cookiecutter/cookiecutter-django/pull/4120))\n- Update black pre-commit hook ([#4122](https://github.com/cookiecutter/cookiecutter-django/pull/4122))\n\n## 2023.01.29\n\n### Changed\n- Add Webpack support  ([#3623](https://github.com/cookiecutter/cookiecutter-django/pull/3623))\n- Remove `BrokenLinkEmailsMiddleware` ([#4112](https://github.com/cookiecutter/cookiecutter-django/pull/4112))\n\n## 2023.01.28\n\n### Changed\n- Refactor `merge_production_dotenvs_in_dotenv.py` ([#4105](https://github.com/cookiecutter/cookiecutter-django/pull/4105))\n### Updated\n- Update isort to 5.12.0 ([#4109](https://github.com/cookiecutter/cookiecutter-django/pull/4109))\n- Auto-update pre-commit hooks ([#4108](https://github.com/cookiecutter/cookiecutter-django/pull/4108))\n\n## 2023.01.27\n\n### Updated\n- Update django-stubs to 1.14.0 ([#4103](https://github.com/cookiecutter/cookiecutter-django/pull/4103))\n\n## 2023.01.26\n\n### Changed\n- Rename BASE_DIR_PATH to BASE_DIR ([#4102](https://github.com/cookiecutter/cookiecutter-django/pull/4102))\n### Updated\n- Update pre-commit to 3.0.1 ([#4104](https://github.com/cookiecutter/cookiecutter-django/pull/4104))\n- Update tox to 4.4.2 ([#4101](https://github.com/cookiecutter/cookiecutter-django/pull/4101))\n\n## 2023.01.25\n\n### Changed\n- Rename ROOT_DIR to BASE_DIR ([#4086](https://github.com/cookiecutter/cookiecutter-django/pull/4086))\n- Update postgres and redis to point to mini tiers ([#4099](https://github.com/cookiecutter/cookiecutter-django/pull/4099))\n### Updated\n- Update coverage to 7.1.0 ([#4100](https://github.com/cookiecutter/cookiecutter-django/pull/4100))\n\n## 2023.01.24\n\n### Updated\n- Update pre-commit to 3.0.0 ([#4098](https://github.com/cookiecutter/cookiecutter-django/pull/4098))\n\n## 2023.01.23\n\n### Updated\n- Update sentry-sdk to 1.14.0 ([#4096](https://github.com/cookiecutter/cookiecutter-django/pull/4096))\n\n## 2023.01.22\n\n### Updated\n- Update django-compressor to 4.3.1 ([#4094](https://github.com/cookiecutter/cookiecutter-django/pull/4094))\n\n## 2023.01.21\n\n### Updated\n- Update django-stubs to 1.13.2 ([#4093](https://github.com/cookiecutter/cookiecutter-django/pull/4093))\n\n## 2023.01.19\n\n### Fixed\n- Add sourcemaps support to Gulp ([#4089](https://github.com/cookiecutter/cookiecutter-django/pull/4089))\n### Updated\n- Update coverage to 7.0.5 ([#4092](https://github.com/cookiecutter/cookiecutter-django/pull/4092))\n- Update redis to 4.4.2 ([#4091](https://github.com/cookiecutter/cookiecutter-django/pull/4091))\n- Update requests to 2.28.2 ([#4090](https://github.com/cookiecutter/cookiecutter-django/pull/4090))\n- Update tox to 4.3.5 ([#4087](https://github.com/cookiecutter/cookiecutter-django/pull/4087))\n\n## 2023.01.17\n\n### Updated\n- Update tox to 4.3.3 ([#4081](https://github.com/cookiecutter/cookiecutter-django/pull/4081))\n\n## 2023.01.15\n\n### Updated\n- Update pytest to 7.2.1 ([#4077](https://github.com/cookiecutter/cookiecutter-django/pull/4077))\n- Update pytz to 2022.7.1 ([#4078](https://github.com/cookiecutter/cookiecutter-django/pull/4078))\n\n## 2023.01.12\n\n### Updated\n- Update sentry-sdk to 1.13.0 ([#4074](https://github.com/cookiecutter/cookiecutter-django/pull/4074))\n\n## 2023.01.11\n\n### Changed\n- Update Celery instructions in the documentation ([#4061](https://github.com/cookiecutter/cookiecutter-django/pull/4061))\n### Updated\n- Update tox to 4.2.7 ([#4073](https://github.com/cookiecutter/cookiecutter-django/pull/4073))\n\n## 2023.01.10\n\n### Changed\n- Add dump.rdb to gitignore ([#4062](https://github.com/cookiecutter/cookiecutter-django/pull/4062))\n### Fixed\n- Exclude `.venv` from code style checks ([#4069](https://github.com/cookiecutter/cookiecutter-django/pull/4069))\n### Updated\n- Update hiredis to 2.1.1 ([#4070](https://github.com/cookiecutter/cookiecutter-django/pull/4070))\n\n## 2023.01.08\n\n### Updated\n- Update redis to 4.4.1 ([#4068](https://github.com/cookiecutter/cookiecutter-django/pull/4068))\n- Update coverage to 7.0.4 ([#4067](https://github.com/cookiecutter/cookiecutter-django/pull/4067))\n\n## 2023.01.07\n\n### Updated\n- Update tox to 4.2.6 ([#4064](https://github.com/cookiecutter/cookiecutter-django/pull/4064))\n- Update django-storages to 1.13.2 ([#4057](https://github.com/cookiecutter/cookiecutter-django/pull/4057))\n- Update isort to 5.11.4 ([#4058](https://github.com/cookiecutter/cookiecutter-django/pull/4058))\n- Update rcssmin to 1.1.1 ([#4060](https://github.com/cookiecutter/cookiecutter-django/pull/4060))\n- Update django-compressor to 4.3 ([#4063](https://github.com/cookiecutter/cookiecutter-django/pull/4063))\n\n## 2023.01.06\n\n### Changed\n- Add `.git` to `.dockerignore` ([#4054](https://github.com/cookiecutter/cookiecutter-django/pull/4054))\n- Fix link and add non-Docker commands to testing page in the docs ([#4036](https://github.com/cookiecutter/cookiecutter-django/pull/4036))\n### Updated\n- Update tox to 4.2.3 ([#4051](https://github.com/cookiecutter/cookiecutter-django/pull/4051))\n\n## 2023.01.04\n\n### Changed\n- Fix typo on test settings ([#4049](https://github.com/cookiecutter/cookiecutter-django/pull/4049))\n### Updated\n- Update tox to 4.2.2 ([#4050](https://github.com/cookiecutter/cookiecutter-django/pull/4050))\n- Update tox to 4.2.1 ([#4046](https://github.com/cookiecutter/cookiecutter-django/pull/4046))\n- Update coverage to 7.0.3 ([#4047](https://github.com/cookiecutter/cookiecutter-django/pull/4047))\n\n## 2023.01.03\n\n### Updated\n- Update flake8-isort to 6.0.0 ([#4022](https://github.com/cookiecutter/cookiecutter-django/pull/4022))\n- Update tox to 4.1.3 ([#4041](https://github.com/cookiecutter/cookiecutter-django/pull/4041))\n- Update pillow to 9.4.0 ([#4040](https://github.com/cookiecutter/cookiecutter-django/pull/4040))\n- Update gitpython to 3.1.30 ([#4032](https://github.com/cookiecutter/cookiecutter-django/pull/4032))\n- Update coverage to 7.0.2 ([#4042](https://github.com/cookiecutter/cookiecutter-django/pull/4042))\n- Update whitenoise to 6.3.0 ([#4044](https://github.com/cookiecutter/cookiecutter-django/pull/4044))\n\n## 2022.12.29\n\n### Updated\n- Update tox to 4.1.0 ([#4035](https://github.com/cookiecutter/cookiecutter-django/pull/4035))\n- Update tox to 4.0.19 ([#4030](https://github.com/cookiecutter/cookiecutter-django/pull/4030))\n- Update django-allauth to 0.52.0 ([#4033](https://github.com/cookiecutter/cookiecutter-django/pull/4033))\n\n## 2022.12.26\n\n### Updated\n- Update tox to 4.0.17 ([#4027](https://github.com/cookiecutter/cookiecutter-django/pull/4027))\n- Update pre-commit to 2.21.0 ([#4026](https://github.com/cookiecutter/cookiecutter-django/pull/4026))\n\n## 2022.12.25\n\n### Updated\n- Auto-update pre-commit hooks ([#4021](https://github.com/cookiecutter/cookiecutter-django/pull/4021))\n\n## 2022.12.24\n\n### Updated\n- Update coverage to 7.0.1 ([#4024](https://github.com/cookiecutter/cookiecutter-django/pull/4024))\n\n## 2022.12.21\n\n### Changed\n- Retry when trying to store a Celery result in backend ([#3996](https://github.com/cookiecutter/cookiecutter-django/pull/3996))\n- Update image URL for build status shield badge ([#4018](https://github.com/cookiecutter/cookiecutter-django/pull/4018))\n### Updated\n- Update pytz to 2022.7 ([#4020](https://github.com/cookiecutter/cookiecutter-django/pull/4020))\n- Update ipdb to 0.13.11 ([#4019](https://github.com/cookiecutter/cookiecutter-django/pull/4019))\n- Update tox to 4.0.16 ([#4017](https://github.com/cookiecutter/cookiecutter-django/pull/4017))\n- Update sentry-sdk to 1.12.1 ([#4014](https://github.com/cookiecutter/cookiecutter-django/pull/4014))\n- Update coverage to 7.0.0 ([#4013](https://github.com/cookiecutter/cookiecutter-django/pull/4013))\n- Update django-anymail to 9.0 ([#4012](https://github.com/cookiecutter/cookiecutter-django/pull/4012))\n- Auto-update pre-commit hooks ([#4005](https://github.com/cookiecutter/cookiecutter-django/pull/4005))\n- Update isort to 5.11.3 ([#4010](https://github.com/cookiecutter/cookiecutter-django/pull/4010))\n- Update drf-spectacular to 0.25.1 ([#4009](https://github.com/cookiecutter/cookiecutter-django/pull/4009))\n- Update hiredis to 2.1.0 ([#4006](https://github.com/cookiecutter/cookiecutter-django/pull/4006))\n\n## 2022.12.13\n\n### Changed\n- Improve documentation for Getting started with Docker ([#4003](https://github.com/cookiecutter/cookiecutter-django/pull/4003))\n### Updated\n- Update isort to 5.11.1 ([#3999](https://github.com/cookiecutter/cookiecutter-django/pull/3999))\n- Auto-update pre-commit hooks ([#3998](https://github.com/cookiecutter/cookiecutter-django/pull/3998))\n- Update isort to 5.11.0 ([#3997](https://github.com/cookiecutter/cookiecutter-django/pull/3997))\n\n## 2022.12.10\n\n### Updated\n- Update tox to 4.0.5 ([#3993](https://github.com/cookiecutter/cookiecutter-django/pull/3993))\n- Auto-update pre-commit hooks ([#3991](https://github.com/cookiecutter/cookiecutter-django/pull/3991))\n\n## 2022.12.09\n\n### Changed\n- Remove bind option mounts for docker compose volumes ([#3981](https://github.com/cookiecutter/cookiecutter-django/pull/3981))\n### Updated\n- Update djangorestframework-stubs to 1.8.0 ([#3990](https://github.com/cookiecutter/cookiecutter-django/pull/3990))\n- Update black to 22.12.0 ([#3988](https://github.com/cookiecutter/cookiecutter-django/pull/3988))\n\n## 2022.12.08\n\n### Updated\n- Update tox to 4.0.3 ([#3987](https://github.com/cookiecutter/cookiecutter-django/pull/3987))\n- Update tox to 4.0.2 ([#3985](https://github.com/cookiecutter/cookiecutter-django/pull/3985))\n- Update django-stubs to 1.13.1 ([#3986](https://github.com/cookiecutter/cookiecutter-django/pull/3986))\n\n## 2022.12.07\n\n### Updated\n- Auto-update pre-commit hooks ([#3983](https://github.com/cookiecutter/cookiecutter-django/pull/3983))\n\n## 2022.12.06\n\n### Changed\n- Simplify production `DATABASES` setting to extend base definition ([#3969](https://github.com/cookiecutter/cookiecutter-django/pull/3969))\n### Fixed\n- Only set `SERVERS` for `drf-spectacular` in production ([#3609](https://github.com/cookiecutter/cookiecutter-django/pull/3609))\n### Updated\n- Update django-coverage-plugin to 3.0.0 ([#3979](https://github.com/cookiecutter/cookiecutter-django/pull/3979))\n- Bump stefanzweifel/git-auto-commit-action from 4.15.4 to 4.16.0 ([#3978](https://github.com/cookiecutter/cookiecutter-django/pull/3978))\n\n## 2022.12.04\n\n### Updated\n- Update redis to 4.4.0 ([#3977](https://github.com/cookiecutter/cookiecutter-django/pull/3977))\n- Update django-debug-toolbar to 3.8.1 ([#3976](https://github.com/cookiecutter/cookiecutter-django/pull/3976))\n\n## 2022.12.03\n\n### Updated\n- Auto-update pre-commit hooks ([#3975](https://github.com/cookiecutter/cookiecutter-django/pull/3975))\n\n## 2022.12.02\n\n### Updated\n- Update flake8 to 6.0.0 ([#3974](https://github.com/cookiecutter/cookiecutter-django/pull/3974))\n\n## 2022.11.30\n\n### Changed\n- Add Azure Storage as an option to serve static and media files ([#3967](https://github.com/cookiecutter/cookiecutter-django/pull/3967))\n### Updated\n- Auto-update pre-commit hooks ([#3970](https://github.com/cookiecutter/cookiecutter-django/pull/3970))\n\n## 2022.11.26\n\n### Changed\n- Fix typo in flower start for watching celery ([#3966](https://github.com/cookiecutter/cookiecutter-django/pull/3966))\n\n## 2022.11.24\n\n### Updated\n- Auto-update pre-commit hooks ([#3963](https://github.com/cookiecutter/cookiecutter-django/pull/3963))\n\n## 2022.11.23\n\n### Changed\n- Fix graceful shutdown of local dev containers and use watchfiles for beat + flower ([#3925](https://github.com/cookiecutter/cookiecutter-django/pull/3925))\n- feat(celery): Enable sending the sent task event by default ([#3961](https://github.com/cookiecutter/cookiecutter-django/pull/3961))\n### Updated\n- Bump stefanzweifel/git-auto-commit-action from 4.15.3 to 4.15.4 ([#3940](https://github.com/cookiecutter/cookiecutter-django/pull/3940))\n- Update django-model-utils to 4.3.1 ([#3948](https://github.com/cookiecutter/cookiecutter-django/pull/3948))\n- Update flake8-isort to 5.0.3 ([#3952](https://github.com/cookiecutter/cookiecutter-django/pull/3952))\n\n## 2022.11.22\n\n### Changed\n- Remove USE_L10N due to deprecation ([#3960](https://github.com/cookiecutter/cookiecutter-django/pull/3960))\n- Remove platform from compose file ([#3957](https://github.com/cookiecutter/cookiecutter-django/pull/3957))\n- feat(celery): Send task events for Celery by default ([#3959](https://github.com/cookiecutter/cookiecutter-django/pull/3959))\n### Updated\n- Update python-slugify to 7.0.0 ([#3950](https://github.com/cookiecutter/cookiecutter-django/pull/3950))\n- Update redis to 4.3.5 ([#3954](https://github.com/cookiecutter/cookiecutter-django/pull/3954))\n- Update sentry-sdk to 1.11.1 ([#3955](https://github.com/cookiecutter/cookiecutter-django/pull/3955))\n- Update uvicorn to 0.20.0 ([#3953](https://github.com/cookiecutter/cookiecutter-django/pull/3953))\n- Update tox to 3.27.1 ([#3945](https://github.com/cookiecutter/cookiecutter-django/pull/3945))\n\n## 2022.11.11\n\n### Updated\n- Auto-update pre-commit hooks ([#3942](https://github.com/cookiecutter/cookiecutter-django/pull/3942))\n\n## 2022.11.07\n\n### Updated\n- Update watchfiles to 0.18.1 ([#3938](https://github.com/cookiecutter/cookiecutter-django/pull/3938))\n\n## 2022.11.06\n\n### Changed\n- Store extended Celery task attributes in backend ([#3855](https://github.com/cookiecutter/cookiecutter-django/pull/3855))\n- add os requirements for Ubuntu 22.04 (Jammy) ([#3930](https://github.com/cookiecutter/cookiecutter-django/pull/3930))\n### Updated\n- Update pytest-sugar to 0.9.6 ([#3937](https://github.com/cookiecutter/cookiecutter-django/pull/3937))\n- Update pygithub to 1.57 ([#3936](https://github.com/cookiecutter/cookiecutter-django/pull/3936))\n- Update sphinx-rtd-theme to 1.1.1 ([#3935](https://github.com/cookiecutter/cookiecutter-django/pull/3935))\n\n## 2022.11.02\n\n### Changed\n- fix typo in CONTRIBUTING.md ([#3932](https://github.com/cookiecutter/cookiecutter-django/pull/3932))\n### Updated\n- Update crispy-bootstrap5 to 0.7 ([#3886](https://github.com/cookiecutter/cookiecutter-django/pull/3886))\n- Update django-coverage-plugin to 2.0.4 ([#3927](https://github.com/cookiecutter/cookiecutter-django/pull/3927))\n- Update pytz to 2022.6 ([#3928](https://github.com/cookiecutter/cookiecutter-django/pull/3928))\n- Update sphinx-rtd-theme to 1.1.0 ([#3929](https://github.com/cookiecutter/cookiecutter-django/pull/3929))\n- Update pillow to 9.3.0 ([#3922](https://github.com/cookiecutter/cookiecutter-django/pull/3922))\n\n## 2022.10.30\n\n### Updated\n- Auto-update pre-commit hooks ([#3924](https://github.com/cookiecutter/cookiecutter-django/pull/3924))\n\n## 2022.10.28\n\n### Updated\n- Bump stefanzweifel/git-auto-commit-action from 4.15.2 to 4.15.3 ([#3921](https://github.com/cookiecutter/cookiecutter-django/pull/3921))\n\n## 2022.10.26\n\n### Updated\n- Update uvicorn to 0.19.0 ([#3920](https://github.com/cookiecutter/cookiecutter-django/pull/3920))\n- Update pytest to 7.2.0 ([#3919](https://github.com/cookiecutter/cookiecutter-django/pull/3919))\n- Update tox to 3.27.0 ([#3917](https://github.com/cookiecutter/cookiecutter-django/pull/3917))\n- Update psycopg2 to 2.9.5 ([#3918](https://github.com/cookiecutter/cookiecutter-django/pull/3918))\n\n## 2022.10.24\n\n### Changed\n- Upgrade Python version from 3.9 to 3.10 ([#3913](https://github.com/cookiecutter/cookiecutter-django/pull/3913))\n### Updated\n- Update sentry-sdk to 1.10.1 ([#3911](https://github.com/cookiecutter/cookiecutter-django/pull/3911))\n- Bump stefanzweifel/git-auto-commit-action from 4.15.1 to 4.15.2 ([#3914](https://github.com/cookiecutter/cookiecutter-django/pull/3914))\n\n## 2022.10.19\n\n### Changed\n- Set AWS_S3_MAX_MEMORY_SIZE ([#3810](https://github.com/cookiecutter/cookiecutter-django/pull/3810))\n- Upgrade to Django 4.0 ([#3848](https://github.com/cookiecutter/cookiecutter-django/pull/3848))\n### Updated\n- Update pytz to 2022.5 ([#3906](https://github.com/cookiecutter/cookiecutter-django/pull/3906))\n- Update sphinx to 5.3.0 ([#3905](https://github.com/cookiecutter/cookiecutter-django/pull/3905))\n- Update django-celery-beat to 2.4.0 ([#3908](https://github.com/cookiecutter/cookiecutter-django/pull/3908))\n- Update watchfiles to 0.18.0 ([#3907](https://github.com/cookiecutter/cookiecutter-django/pull/3907))\n\n## 2022.10.13\n\n### Updated\n- Update pygithub to 1.56 ([#3904](https://github.com/cookiecutter/cookiecutter-django/pull/3904))\n\n## 2022.10.11\n\n### Updated\n- Auto-update pre-commit hooks ([#3899](https://github.com/cookiecutter/cookiecutter-django/pull/3899))\n- Update flake8-isort to 5.0.0 ([#3901](https://github.com/cookiecutter/cookiecutter-django/pull/3901))\n- Update gitpython to 3.1.29 ([#3902](https://github.com/cookiecutter/cookiecutter-django/pull/3902))\n- Update psycopg2 to 2.9.4 ([#3896](https://github.com/cookiecutter/cookiecutter-django/pull/3896))\n- Bump stefanzweifel/git-auto-commit-action from 4.15.0 to 4.15.1 ([#3903](https://github.com/cookiecutter/cookiecutter-django/pull/3903))\n- Update black to 22.10.0 ([#3898](https://github.com/cookiecutter/cookiecutter-django/pull/3898))\n\n## 2022.10.04\n\n### Updated\n- Update django to 3.2.16 ([#3895](https://github.com/cookiecutter/cookiecutter-django/pull/3895))\n- Update mypy to 0.982 ([#3893](https://github.com/cookiecutter/cookiecutter-django/pull/3893))\n- Auto-update pre-commit hooks ([#3894](https://github.com/cookiecutter/cookiecutter-django/pull/3894))\n\n## 2022.10.03\n\n### Updated\n- Update sentry-sdk to 1.9.10 ([#3892](https://github.com/cookiecutter/cookiecutter-django/pull/3892))\n\n## 2022.10.02\n\n### Updated\n- Update pytz to 2022.4 ([#3891](https://github.com/cookiecutter/cookiecutter-django/pull/3891))\n\n## 2022.09.30\n\n### Updated\n- Update coverage to 6.5.0 ([#3890](https://github.com/cookiecutter/cookiecutter-django/pull/3890))\n- Update mypy to 0.981 ([#3889](https://github.com/cookiecutter/cookiecutter-django/pull/3889))\n- Update sentry-sdk to 1.9.9 ([#3888](https://github.com/cookiecutter/cookiecutter-django/pull/3888))\n- Update sphinx to 5.2.3 ([#3887](https://github.com/cookiecutter/cookiecutter-django/pull/3887))\n\n## 2022.09.29\n\n### Changed\n- Remove outdated &amp; optional Sendgrid settings from production config ([#3885](https://github.com/cookiecutter/cookiecutter-django/pull/3885))\n\n## 2022.09.27\n\n### Updated\n- Update sphinx to 5.2.2 ([#3884](https://github.com/cookiecutter/cookiecutter-django/pull/3884))\n\n## 2022.09.26\n\n### Updated\n- Update drf-spectacular to 0.24.2 ([#3882](https://github.com/cookiecutter/cookiecutter-django/pull/3882))\n- Update djangorestframework to 3.14.0 ([#3881](https://github.com/cookiecutter/cookiecutter-django/pull/3881))\n- Update django-debug-toolbar to 3.7.0 ([#3878](https://github.com/cookiecutter/cookiecutter-django/pull/3878))\n- Auto-update pre-commit hooks ([#3877](https://github.com/cookiecutter/cookiecutter-django/pull/3877))\n- Bump stefanzweifel/git-auto-commit-action from 4.14.1 to 4.15.0 ([#3880](https://github.com/cookiecutter/cookiecutter-django/pull/3880))\n- Update sphinx to 5.2.1 ([#3879](https://github.com/cookiecutter/cookiecutter-django/pull/3879))\n\n## 2022.09.24\n\n### Fixed\n- Remove `--no-deps` in pip wheels command of docs Dockerfile ([#3875](https://github.com/cookiecutter/cookiecutter-django/pull/3875))\n\n## 2022.09.23\n\n### Changed\n- Reload uvicorn on html file change ([#3866](https://github.com/cookiecutter/cookiecutter-django/pull/3866))\n- Mailjet default api url does not work out of the box ([#3871](https://github.com/cookiecutter/cookiecutter-django/pull/3871))\n### Updated\n- Auto-update pre-commit hooks ([#3872](https://github.com/cookiecutter/cookiecutter-django/pull/3872))\n- Update django-extensions to 3.2.1 ([#3867](https://github.com/cookiecutter/cookiecutter-django/pull/3867))\n- Update tox to 3.26.0 ([#3864](https://github.com/cookiecutter/cookiecutter-django/pull/3864))\n- Update drf-spectacular to 0.24.1 ([#3874](https://github.com/cookiecutter/cookiecutter-django/pull/3874))\n\n## 2022.09.15\n\n### Updated\n- Update watchfiles to 0.17.0 ([#3869](https://github.com/cookiecutter/cookiecutter-django/pull/3869))\n- Update drf-spectacular to 0.24.0 ([#3870](https://github.com/cookiecutter/cookiecutter-django/pull/3870))\n\n## 2022.09.05\n\n### Updated\n- Update sentry-sdk to 1.9.8 ([#3861](https://github.com/cookiecutter/cookiecutter-django/pull/3861))\n\n## 2022.09.02\n\n### Updated\n- Update pytest to 7.1.3 ([#3860](https://github.com/cookiecutter/cookiecutter-django/pull/3860))\n- Update sentry-sdk to 1.9.7 ([#3859](https://github.com/cookiecutter/cookiecutter-django/pull/3859))\n\n## 2022.09.01\n\n### Changed\n- Add article to README about how to use a hosted DB ([#3844](https://github.com/cookiecutter/cookiecutter-django/pull/3844))\n### Updated\n- Update sentry-sdk to 1.9.6 ([#3856](https://github.com/cookiecutter/cookiecutter-django/pull/3856))\n- Auto-update pre-commit hooks ([#3858](https://github.com/cookiecutter/cookiecutter-django/pull/3858))\n- Update black to 22.8.0 ([#3857](https://github.com/cookiecutter/cookiecutter-django/pull/3857))\n\n## 2022.08.26\n\n### Changed\n- Fix formatting in docs ([#3850](https://github.com/cookiecutter/cookiecutter-django/pull/3850))\n\n## 2022.08.24\n\n### Updated\n- Update django-debug-toolbar to 3.6.0 ([#3847](https://github.com/cookiecutter/cookiecutter-django/pull/3847))\n- Update werkzeug to 2.2.2 ([#3846](https://github.com/cookiecutter/cookiecutter-django/pull/3846))\n- Update coverage to 6.4.4 ([#3842](https://github.com/cookiecutter/cookiecutter-django/pull/3842))\n- Update uvicorn to 0.18.3 ([#3845](https://github.com/cookiecutter/cookiecutter-django/pull/3845))\n- Update sentry-sdk to 1.9.5 ([#3841](https://github.com/cookiecutter/cookiecutter-django/pull/3841))\n- Update flower to 1.2.0 ([#3836](https://github.com/cookiecutter/cookiecutter-django/pull/3836))\n- Update django-storages to 1.13.1 ([#3833](https://github.com/cookiecutter/cookiecutter-django/pull/3833))\n\n## 2022.08.15\n\n### Updated\n- Update coverage to 6.4.3 ([#3835](https://github.com/cookiecutter/cookiecutter-django/pull/3835))\n- Update pytz to 2022.2.1 ([#3840](https://github.com/cookiecutter/cookiecutter-django/pull/3840))\n- Update sentry-sdk to 1.9.4 ([#3838](https://github.com/cookiecutter/cookiecutter-django/pull/3838))\n\n## 2022.08.09\n\n### Updated\n- Update sentry-sdk to 1.9.3 ([#3837](https://github.com/cookiecutter/cookiecutter-django/pull/3837))\n\n## 2022.08.05\n\n### Updated\n- Update sentry-sdk to 1.9.2 ([#3832](https://github.com/cookiecutter/cookiecutter-django/pull/3832))\n\n## 2022.08.04\n\n### Updated\n- Auto-update pre-commit hooks ([#3816](https://github.com/cookiecutter/cookiecutter-django/pull/3816))\n- Update flake8 to 5.0.4 ([#3829](https://github.com/cookiecutter/cookiecutter-django/pull/3829))\n- Update django-compressor to 4.1 ([#3823](https://github.com/cookiecutter/cookiecutter-django/pull/3823))\n- Update flake8-isort to 4.2.0 ([#3828](https://github.com/cookiecutter/cookiecutter-django/pull/3828))\n\n## 2022.08.03\n\n### Updated\n- Update django to 3.2.15 ([#3822](https://github.com/cookiecutter/cookiecutter-django/pull/3822))\n\n## 2022.07.29\n\n### Updated\n- Update sentry-sdk to 1.9.0 ([#3815](https://github.com/cookiecutter/cookiecutter-django/pull/3815))\n\n## 2022.07.28\n\n### Updated\n- Update werkzeug to 2.2.1 ([#3814](https://github.com/cookiecutter/cookiecutter-django/pull/3814))\n\n## 2022.07.27\n\n### Updated\n- Update werkzeug to 2.2.0 ([#3813](https://github.com/cookiecutter/cookiecutter-django/pull/3813))\n- Update sphinx to 5.1.1 ([#3811](https://github.com/cookiecutter/cookiecutter-django/pull/3811))\n- Update drf-spectacular to 0.23.1 ([#3812](https://github.com/cookiecutter/cookiecutter-django/pull/3812))\n\n## 2022.07.26\n\n### Changed\n- Switch from `watchgod` to `watchfiles` ([#3791](https://github.com/cookiecutter/cookiecutter-django/pull/3791))\n- Change Django settings file used by pylint ([#3806](https://github.com/cookiecutter/cookiecutter-django/pull/3806))\n- Simplify database access in tests ([#3807](https://github.com/cookiecutter/cookiecutter-django/pull/3807))\n- Provide more context when wating for PostgreSQL takes too long ([#3782](https://github.com/cookiecutter/cookiecutter-django/pull/3782))\n### Updated\n- Update django-compressor to 4.0 ([#3802](https://github.com/cookiecutter/cookiecutter-django/pull/3802))\n- Update flake8-isort to 4.1.2.post0 ([#3809](https://github.com/cookiecutter/cookiecutter-django/pull/3809))\n- Update sphinx to 5.1.0 ([#3808](https://github.com/cookiecutter/cookiecutter-django/pull/3808))\n- Update sh to 1.14.3 ([#3798](https://github.com/cookiecutter/cookiecutter-django/pull/3798))\n- Auto-update pre-commit hooks ([#3780](https://github.com/cookiecutter/cookiecutter-django/pull/3780))\n\n## 2022.07.22\n\n### Updated\n- Update pytest-sugar to 0.9.5 ([#3800](https://github.com/cookiecutter/cookiecutter-django/pull/3800))\n- Update sphinx to 5.0.2 ([#3801](https://github.com/cookiecutter/cookiecutter-django/pull/3801))\n- Update pillow to 9.2.0 ([#3799](https://github.com/cookiecutter/cookiecutter-django/pull/3799))\n- Update werkzeug to 2.1.2 ([#3797](https://github.com/cookiecutter/cookiecutter-django/pull/3797))\n\n## 2022.07.21\n\n### Changed\n- Set user to form instance in update user view test ([#3776](https://github.com/cookiecutter/cookiecutter-django/pull/3776))\n- Fix warning from django-coverage-plugin in tests ([#3790](https://github.com/cookiecutter/cookiecutter-django/pull/3790))\n- Always use `const` instead of `var` in `gulpfile.js` ([#3786](https://github.com/cookiecutter/cookiecutter-django/pull/3786))\n### Updated\n- Update flower to 1.1.0 ([#3796](https://github.com/cookiecutter/cookiecutter-django/pull/3796))\n- Update coverage to 6.4.2 ([#3783](https://github.com/cookiecutter/cookiecutter-django/pull/3783))\n- Update mypy to 0.971 ([#3788](https://github.com/cookiecutter/cookiecutter-django/pull/3788))\n- Update sentry-sdk to 1.8.0 ([#3792](https://github.com/cookiecutter/cookiecutter-django/pull/3792))\n- Update pre-commit to 2.20.0 ([#3779](https://github.com/cookiecutter/cookiecutter-django/pull/3779))\n- Update django-extensions to 3.2.0 ([#3774](https://github.com/cookiecutter/cookiecutter-django/pull/3774))\n- Update tox to 3.25.1 ([#3767](https://github.com/cookiecutter/cookiecutter-django/pull/3767))\n- Update uvicorn to 0.18.2 ([#3762](https://github.com/cookiecutter/cookiecutter-django/pull/3762))\n- Update redis to 4.3.4 ([#3763](https://github.com/cookiecutter/cookiecutter-django/pull/3763))\n- Update requests to 2.28.1 ([#3766](https://github.com/cookiecutter/cookiecutter-django/pull/3766))\n\n## 2022.07.10\n\n### Changed\n- Revert auto-update pre-commit hooks ([#3778](https://github.com/cookiecutter/cookiecutter-django/pull/3778))\n### Updated\n- Auto-update pre-commit hooks ([#3775](https://github.com/cookiecutter/cookiecutter-django/pull/3775))\n\n## 2022.07.06\n\n### Updated\n- Update django to 3.2.14 ([#3768](https://github.com/cookiecutter/cookiecutter-django/pull/3768))\n\n## 2022.06.28\n\n### Updated\n- Auto-update pre-commit hooks ([#3765](https://github.com/cookiecutter/cookiecutter-django/pull/3765))\n- Update black to 22.6.0 ([#3764](https://github.com/cookiecutter/cookiecutter-django/pull/3764))\n\n## 2022.06.23\n\n### Updated\n- Update django-debug-toolbar to 3.5.0 ([#3760](https://github.com/cookiecutter/cookiecutter-django/pull/3760))\n\n## 2022.06.22\n\n### Updated\n- Update django-stubs to 1.12.0 ([#3757](https://github.com/cookiecutter/cookiecutter-django/pull/3757))\n- Update sentry-sdk to 1.6.0 ([#3756](https://github.com/cookiecutter/cookiecutter-django/pull/3756))\n- Update djangorestframework-stubs to 1.7.0 ([#3754](https://github.com/cookiecutter/cookiecutter-django/pull/3754))\n\n## 2022.06.15\n\n### Updated\n- Update django-environ to 0.9.0 ([#3751](https://github.com/cookiecutter/cookiecutter-django/pull/3751))\n\n## 2022.06.13\n\n### Updated\n- Update cookiecutter to 2.1.1 ([#3727](https://github.com/cookiecutter/cookiecutter-django/pull/3727))\n\n## 2022.06.11\n\n### Updated\n- Update requests to 2.28.0 ([#3748](https://github.com/cookiecutter/cookiecutter-django/pull/3748))\n\n## 2022.06.09\n\n### Updated\n- Bump actions/setup-python from 3 to 4 ([#3746](https://github.com/cookiecutter/cookiecutter-django/pull/3746))\n\n## 2022.06.08\n\n### Updated\n- Auto-update pre-commit hooks ([#3744](https://github.com/cookiecutter/cookiecutter-django/pull/3744))\n\n## 2022.06.07\n\n### Updated\n- Update django-allauth to 0.51.0 ([#3743](https://github.com/cookiecutter/cookiecutter-django/pull/3743))\n- Auto-update pre-commit hooks ([#3742](https://github.com/cookiecutter/cookiecutter-django/pull/3742))\n\n## 2022.06.06\n\n### Updated\n- Bump pre-commit/action from 2.0.3 to 3.0.0 ([#3739](https://github.com/cookiecutter/cookiecutter-django/pull/3739))\n\n## 2022.06.05\n\n### Updated\n- Update whitenoise to 6.2.0 ([#3737](https://github.com/cookiecutter/cookiecutter-django/pull/3737))\n- Update django-cors-headers to 3.13.0 ([#3738](https://github.com/cookiecutter/cookiecutter-django/pull/3738))\n\n## 2022.06.04\n\n### Updated\n- Update django-cors-headers to 3.12.0 ([#3736](https://github.com/cookiecutter/cookiecutter-django/pull/3736))\n- Update djangorestframework-stubs to 1.6.0 ([#3718](https://github.com/cookiecutter/cookiecutter-django/pull/3718))\n- Update django-stubs to 1.11.0 ([#3734](https://github.com/cookiecutter/cookiecutter-django/pull/3734))\n- Update sphinx to 5.0.1 ([#3733](https://github.com/cookiecutter/cookiecutter-django/pull/3733))\n- Update sphinx to 5.0.0 ([#3724](https://github.com/cookiecutter/cookiecutter-django/pull/3724))\n- Update celery to 5.2.7 ([#3732](https://github.com/cookiecutter/cookiecutter-django/pull/3732))\n- Update django-celery-beat to 2.3.0 ([#3731](https://github.com/cookiecutter/cookiecutter-django/pull/3731))\n\n## 2022.06.02\n\n### Updated\n- Update coverage to 6.4.1 ([#3729](https://github.com/cookiecutter/cookiecutter-django/pull/3729))\n- Update redis to 4.3.3 ([#3728](https://github.com/cookiecutter/cookiecutter-django/pull/3728))\n\n## 2022.06.01\n\n### Updated\n- Update redis to 4.3.2 ([#3726](https://github.com/cookiecutter/cookiecutter-django/pull/3726))\n\n## 2022.05.24\n\n### Updated\n- Update coverage to 6.4 ([#3716](https://github.com/cookiecutter/cookiecutter-django/pull/3716))\n\n## 2022.05.18\n\n### Updated\n- Update pillow to 9.1.1 ([#3714](https://github.com/cookiecutter/cookiecutter-django/pull/3714))\n\n## 2022.05.16\n\n### Changed\n- Update postgres versions ([#3712](https://github.com/cookiecutter/cookiecutter-django/pull/3712))\n### Updated\n- Update django-anymail to 8.6 ([#3713](https://github.com/cookiecutter/cookiecutter-django/pull/3713))\n\n## 2022.05.14\n\n### Updated\n- Update coverage to 6.3.3 ([#3709](https://github.com/cookiecutter/cookiecutter-django/pull/3709))\n- Update whitenoise to 6.1.0 ([#3707](https://github.com/cookiecutter/cookiecutter-django/pull/3707))\n- Update sentry-sdk to 1.5.12 ([#3706](https://github.com/cookiecutter/cookiecutter-django/pull/3706))\n- Update redis to 4.3.1 ([#3704](https://github.com/cookiecutter/cookiecutter-django/pull/3704))\n\n## 2022.05.07\n\n### Changed\n- Add pyupgrade to pre-commit config ([#3702](https://github.com/cookiecutter/cookiecutter-django/pull/3702))\n- Set permissions for GitHub actions ([#3698](https://github.com/cookiecutter/cookiecutter-django/pull/3698))\n### Updated\n- Update jinja2 to 3.1.2 ([#3700](https://github.com/cookiecutter/cookiecutter-django/pull/3700))\n\n## 2022.05.06\n\n### Updated\n- Update pre-commit to 2.19.0 ([#3697](https://github.com/cookiecutter/cookiecutter-django/pull/3697))\n\n## 2022.05.04\n\n### Updated\n- Update django-coverage-plugin to 2.0.3 ([#3695](https://github.com/cookiecutter/cookiecutter-django/pull/3695))\n\n## 2022.05.03\n\n### Updated\n- Update django-debug-toolbar to 3.4.0 ([#3692](https://github.com/cookiecutter/cookiecutter-django/pull/3692))\n- Update sentry-sdk to 1.5.11 ([#3693](https://github.com/cookiecutter/cookiecutter-django/pull/3693))\n\n## 2022.05.01\n\n### Updated\n- Update django-debug-toolbar to 3.3.0 ([#3690](https://github.com/cookiecutter/cookiecutter-django/pull/3690))\n\n## 2022.04.28\n\n### Changed\n- Add the possibility to set a max django version on create_django_issue script ([#3680](https://github.com/cookiecutter/cookiecutter-django/pull/3680))\n\n## 2022.04.27\n\n### Updated\n- Update mypy to 0.950 ([#3687](https://github.com/cookiecutter/cookiecutter-django/pull/3687))\n- Update python-slugify to 6.1.2 ([#3686](https://github.com/cookiecutter/cookiecutter-django/pull/3686))\n- Update drf-spectacular to 0.22.1 ([#3684](https://github.com/cookiecutter/cookiecutter-django/pull/3684))\n\n## 2022.04.25\n\n### Updated\n- Update pytest to 7.1.2 ([#3683](https://github.com/cookiecutter/cookiecutter-django/pull/3683))\n\n## 2022.04.19\n\n### Updated\n- Update tox to 3.25.0 ([#3675](https://github.com/cookiecutter/cookiecutter-django/pull/3675))\n- Update sentry-sdk to 1.5.10 ([#3679](https://github.com/cookiecutter/cookiecutter-django/pull/3679))\n\n## 2022.04.13\n\n### Updated\n- Bump stefanzweifel/git-auto-commit-action from 4.14.0 to 4.14.1 ([#3677](https://github.com/cookiecutter/cookiecutter-django/pull/3677))\n\n## 2022.04.11\n\n### Updated\n- Update django to 3.2.13 ([#3676](https://github.com/cookiecutter/cookiecutter-django/pull/3676))\n\n## 2022.04.08\n\n### Updated\n- Auto-update pre-commit hooks ([#3673](https://github.com/cookiecutter/cookiecutter-django/pull/3673))\n\n## 2022.04.05\n\n### Updated\n- Update celery to 5.2.6 ([#3671](https://github.com/cookiecutter/cookiecutter-django/pull/3671))\n\n## 2022.04.04\n\n### Updated\n- Update redis to 4.2.2 ([#3670](https://github.com/cookiecutter/cookiecutter-django/pull/3670))\n- Update celery to 5.2.5 ([#3669](https://github.com/cookiecutter/cookiecutter-django/pull/3669))\n- Update pre-commit to 2.18.1 ([#3668](https://github.com/cookiecutter/cookiecutter-django/pull/3668))\n- Update pillow to 9.1.0 ([#3665](https://github.com/cookiecutter/cookiecutter-django/pull/3665))\n\n## 2022.04.01\n\n### Changed\n- Update domain for Celery docs ([#3663](https://github.com/cookiecutter/cookiecutter-django/pull/3663))\n### Updated\n- Update watchgod to 0.8.2 ([#3664](https://github.com/cookiecutter/cookiecutter-django/pull/3664))\n- Update redis to 4.2.1 ([#3660](https://github.com/cookiecutter/cookiecutter-django/pull/3660))\n\n## 2022.03.28\n\n### Changed\n- Update `black` version to `22.3.0` ([#3657](https://github.com/cookiecutter/cookiecutter-django/pull/3657))\n\n## 2022.03.27\n\n### Updated\n- Update sphinx to 4.5.0 ([#3654](https://github.com/cookiecutter/cookiecutter-django/pull/3654))\n- Update jinja2 to 3.1.1 ([#3652](https://github.com/cookiecutter/cookiecutter-django/pull/3652))\n- Update pylint-django to 2.5.3 ([#3650](https://github.com/cookiecutter/cookiecutter-django/pull/3650))\n- Update django-allauth to 0.50.0 ([#3649](https://github.com/cookiecutter/cookiecutter-django/pull/3649))\n- Update mypy to 0.942 ([#3648](https://github.com/cookiecutter/cookiecutter-django/pull/3648))\n- Update jinja2 to 3.1.0 ([#3647](https://github.com/cookiecutter/cookiecutter-django/pull/3647))\n- Update redis to 4.2.0 ([#3646](https://github.com/cookiecutter/cookiecutter-django/pull/3646))\n- Update watchgod to 0.8.1 ([#3643](https://github.com/cookiecutter/cookiecutter-django/pull/3643))\n- Bump stefanzweifel/git-auto-commit-action from 4.13.1 to 4.14.0 ([#3641](https://github.com/cookiecutter/cookiecutter-django/pull/3641))\n- Update drf-spectacular to 0.22.0 ([#3642](https://github.com/cookiecutter/cookiecutter-django/pull/3642))\n- Update pytz to 2022.1 ([#3639](https://github.com/cookiecutter/cookiecutter-django/pull/3639))\n- Update sentry-sdk to 1.5.8 ([#3638](https://github.com/cookiecutter/cookiecutter-django/pull/3638))\n- Update pytest to 7.1.1 ([#3637](https://github.com/cookiecutter/cookiecutter-django/pull/3637))\n- Update uvicorn to 0.17.6 ([#3627](https://github.com/cookiecutter/cookiecutter-django/pull/3627))\n\n## 2022.03.23\n\n### Updated\n- Bump peter-evans/create-pull-request from 3.14.0 to 4 ([#3645](https://github.com/cookiecutter/cookiecutter-django/pull/3645))\n\n## 2022.03.20\n\n### Changed\n- Unify compressor, gulp and custom bootstrap options ([#3535](https://github.com/cookiecutter/cookiecutter-django/pull/3535))\n\n## 2022.03.14\n\n### Fixed\n- Fix broken link in README of generated projects ([#3634](https://github.com/cookiecutter/cookiecutter-django/pull/3634))\n\n## 2022.03.13\n\n### Changed\n- Add DRF spectacular link in requirements ([#3630](https://github.com/cookiecutter/cookiecutter-django/pull/3630))\n\n## 2022.03.09\n\n### Changed\n- Fix a few typos in the documentation ([#3625](https://github.com/cookiecutter/cookiecutter-django/pull/3625))\n\n## 2022.03.08\n\n### Updated\n- Update sentry-sdk to 1.5.7 ([#3624](https://github.com/cookiecutter/cookiecutter-django/pull/3624))\n\n## 2022.03.03\n\n### Updated\n- Upgrade actions/setup-python to v3 ([#3621](https://github.com/cookiecutter/cookiecutter-django/pull/3621))\n\n## 2022.03.02\n\n### Updated\n- Bump actions/checkout from 2 to 3 ([#3619](https://github.com/cookiecutter/cookiecutter-django/pull/3619))\n\n## 2022.03.01\n\n### Updated\n- Bump actions/setup-python from 2 to 3 ([#3617](https://github.com/cookiecutter/cookiecutter-django/pull/3617))\n- Bump peter-evans/create-pull-request from 3.13.0 to 3.14.0 ([#3618](https://github.com/cookiecutter/cookiecutter-django/pull/3618))\n\n## 2022.02.28\n\n### Updated\n- Update python-slugify to 6.1.1 ([#3615](https://github.com/cookiecutter/cookiecutter-django/pull/3615))\n- Bump peter-evans/create-pull-request from 3.12.1 to 3.13.0 ([#3616](https://github.com/cookiecutter/cookiecutter-django/pull/3616))\n\n## 2022.02.25\n\n### Updated\n- Bump actions/setup-node from 2 to 3 ([#3614](https://github.com/cookiecutter/cookiecutter-django/pull/3614))\n\n## 2022.02.24\n\n### Updated\n- Update django-allauth to 0.49.0 ([#3613](https://github.com/cookiecutter/cookiecutter-django/pull/3613))\n- Update sentry-sdk to 1.5.6 ([#3611](https://github.com/cookiecutter/cookiecutter-django/pull/3611))\n- Update python-slugify to 6.1.0 ([#3612](https://github.com/cookiecutter/cookiecutter-django/pull/3612))\n\n## 2022.02.21\n\n### Changed\n- Cancel previous CI runs on successive PR pushes with GitHub actions ([#3575](https://github.com/cookiecutter/cookiecutter-django/pull/3575))\n### Updated\n- Update coverage to 6.3.2 ([#3610](https://github.com/cookiecutter/cookiecutter-django/pull/3610))\n- Update gitpython to 3.1.27 ([#3607](https://github.com/cookiecutter/cookiecutter-django/pull/3607))\n- Update pylint-django to 2.5.2 ([#3602](https://github.com/cookiecutter/cookiecutter-django/pull/3602))\n- Update python-slugify to 6.0.1 ([#3599](https://github.com/cookiecutter/cookiecutter-django/pull/3599))\n- Update uvicorn to 0.17.5 ([#3596](https://github.com/cookiecutter/cookiecutter-django/pull/3596))\n- Update redis to 4.1.4 ([#3595](https://github.com/cookiecutter/cookiecutter-django/pull/3595))\n\n## 2022.02.20\n\n### Changed\n- Fix incorrect createdb instruction in documentation ([#3606](https://github.com/cookiecutter/cookiecutter-django/pull/3606))\n\n## 2022.02.16\n\n### Fixed\n- Fix Swagger schema API endpoint &amp; add a test for it ([#3592](https://github.com/cookiecutter/cookiecutter-django/pull/3592))\n\n## 2022.02.15\n\n### Changed\n- Update the drf-spectacular local dev server url to use http instead of https ([#3591](https://github.com/cookiecutter/cookiecutter-django/pull/3591))\n\n## 2022.02.13\n\n### Changed\n- Change docs port from 7000 to 9000 ([#3590](https://github.com/cookiecutter/cookiecutter-django/pull/3590))\n\n## 2022.02.12\n\n### Updated\n- Update pytest to 7.0.1 ([#3588](https://github.com/cookiecutter/cookiecutter-django/pull/3588))\n\n## 2022.02.11\n\n### Updated\n- Update sentry-sdk to 1.5.5 ([#3586](https://github.com/cookiecutter/cookiecutter-django/pull/3586))\n\n## 2022.02.10\n\n### Fixed\n- Fix GitLab CI error caused by Docker Compose&#39;s `platform` option ([#3585](https://github.com/cookiecutter/cookiecutter-django/pull/3585))\n### Updated\n- Update whitenoise to 6.0.0 ([#3583](https://github.com/cookiecutter/cookiecutter-django/pull/3583))\n\n## 2022.02.08\n\n### Fixed\n- Fixed some typos in drf-spectacular description and comments ([#3579](https://github.com/cookiecutter/cookiecutter-django/pull/3579))\n### Updated\n- Update redis to 4.1.3 ([#3577](https://github.com/cookiecutter/cookiecutter-django/pull/3577))\n- Update werkzeug to 2.0.3 ([#3576](https://github.com/cookiecutter/cookiecutter-django/pull/3576))\n\n## 2022.02.07\n\n### Changed\n- Update black to 22.1.0 ([#3572](https://github.com/cookiecutter/cookiecutter-django/pull/3572))\n### Fixed\n- Fix docker-compose config on Apple silicon ([#3562](https://github.com/cookiecutter/cookiecutter-django/pull/3562))\n### Updated\n- Update uvicorn to 0.17.4 ([#3574](https://github.com/cookiecutter/cookiecutter-django/pull/3574))\n- Update django-allauth to 0.48.0 ([#3573](https://github.com/cookiecutter/cookiecutter-django/pull/3573))\n- Update pytest to 7.0.0 ([#3567](https://github.com/cookiecutter/cookiecutter-django/pull/3567))\n- Update coverage to 6.3.1 ([#3561](https://github.com/cookiecutter/cookiecutter-django/pull/3561))\n- Update pillow to 9.0.1 ([#3571](https://github.com/cookiecutter/cookiecutter-django/pull/3571))\n- Bump peter-evans/create-pull-request from 3.12.0 to 3.12.1 ([#3558](https://github.com/cookiecutter/cookiecutter-django/pull/3558))\n- Update drf-spectacular to 0.21.2 ([#3560](https://github.com/cookiecutter/cookiecutter-django/pull/3560))\n- Update django to 3.2.12 ([#3559](https://github.com/cookiecutter/cookiecutter-django/pull/3559))\n\n## 2022.01.27\n\n### Updated\n- Update redis to 4.1.2 ([#3551](https://github.com/cookiecutter/cookiecutter-django/pull/3551))\n\n## 2022.01.26\n\n### Updated\n- Update coverage to 6.3 ([#3550](https://github.com/cookiecutter/cookiecutter-django/pull/3550))\n- Update sentry-sdk to 1.5.4 ([#3549](https://github.com/cookiecutter/cookiecutter-django/pull/3549))\n- Update django-crispy-forms to 1.14.0 ([#3548](https://github.com/cookiecutter/cookiecutter-django/pull/3548))\n- Update uvicorn to 0.17.0.post1 ([#3547](https://github.com/cookiecutter/cookiecutter-django/pull/3547))\n\n## 2022.01.21\n\n### Changed\n- mysql support link ([#3544](https://github.com/cookiecutter/cookiecutter-django/pull/3544))\n### Updated\n- Update sentry-sdk to 1.5.3 ([#3543](https://github.com/cookiecutter/cookiecutter-django/pull/3543))\n- Update django-anymail to 8.5 ([#3542](https://github.com/cookiecutter/cookiecutter-django/pull/3542))\n\n## 2022.01.19\n\n### Changed\n- Add swagger API documentation when DRF is enabled  ([#3536](https://github.com/cookiecutter/cookiecutter-django/pull/3536))\n### Updated\n- Update pre-commit to 2.17.0 ([#3541](https://github.com/cookiecutter/cookiecutter-django/pull/3541))\n\n## 2022.01.17\n\n### Changed\n- Avoid docker image/volume collision by prefixing with project slug ([#3528](https://github.com/cookiecutter/cookiecutter-django/pull/3528))\n### Updated\n- Update redis to 4.1.1 ([#3540](https://github.com/cookiecutter/cookiecutter-django/pull/3540))\n- Update sphinx to 4.4.0 ([#3537](https://github.com/cookiecutter/cookiecutter-django/pull/3537))\n\n## 2022.01.14\n\n### Updated\n- Update uvicorn to 0.17.0 ([#3534](https://github.com/cookiecutter/cookiecutter-django/pull/3534))\n- Bump stefanzweifel/git-auto-commit-action from 4.13.0 to 4.13.1 ([#3532](https://github.com/cookiecutter/cookiecutter-django/pull/3532))\n\n## 2022.01.13\n\n### Changed\n- Add UserSignupForm and UserSocialSignupForm ([#3515](https://github.com/cookiecutter/cookiecutter-django/pull/3515))\n### Fixed\n- Fix high CPU usage when running `runserver_plus` in Docker ([#3531](https://github.com/cookiecutter/cookiecutter-django/pull/3531))\n- Fix out-of-sync sequence for Site ID ([#3511](https://github.com/cookiecutter/cookiecutter-django/pull/3511))\n\n## 2022.01.11\n\n### Updated\n- Bump stefanzweifel/git-auto-commit-action from 4.12.0 to 4.13.0 ([#3527](https://github.com/cookiecutter/cookiecutter-django/pull/3527))\n\n## 2022.01.10\n\n### Updated\n- Update django-cors-headers to 3.11.0 ([#3526](https://github.com/cookiecutter/cookiecutter-django/pull/3526))\n- Update sentry-sdk to 1.5.2 ([#3525](https://github.com/cookiecutter/cookiecutter-django/pull/3525))\n- Update gitpython to 3.1.26 ([#3524](https://github.com/cookiecutter/cookiecutter-django/pull/3524))\n\n## 2022.01.09\n\n### Changed\n- Fix broken center align of image links in README  ([#3522](https://github.com/cookiecutter/cookiecutter-django/pull/3522))\n\n## 2022.01.07\n\n### Fixed\n- Fix cache dependency path for linter job in CI workflow ([#3520](https://github.com/cookiecutter/cookiecutter-django/pull/3520))\n- Fix `open` option for `initBrowserSync` when using Docker ([#3519](https://github.com/cookiecutter/cookiecutter-django/pull/3519))\n### Updated\n- Update mypy to 0.931 ([#3521](https://github.com/cookiecutter/cookiecutter-django/pull/3521))\n- Update gitpython to 3.1.25 ([#3518](https://github.com/cookiecutter/cookiecutter-django/pull/3518))\n\n## 2022.01.06\n\n### Changed\n- Update output example in README ([#3512](https://github.com/cookiecutter/cookiecutter-django/pull/3512))\n\n## 2022.01.05\n\n### Changed\n- Update references to Bootstrap from v4 to v5 in README ([#3513](https://github.com/cookiecutter/cookiecutter-django/pull/3513))\n### Updated\n- Update requests to 2.27.1 ([#3516](https://github.com/cookiecutter/cookiecutter-django/pull/3516))\n\n## 2022.01.04\n\n### Changed\n- Double quote array expansions to avoid re-splitting elements ([#3514](https://github.com/cookiecutter/cookiecutter-django/pull/3514))\n### Updated\n- Update django to 3.2.11 ([#3510](https://github.com/cookiecutter/cookiecutter-django/pull/3510))\n\n## 2022.01.03\n\n### Changed\n- Convert top level RST files to Markdown ([#3489](https://github.com/cookiecutter/cookiecutter-django/pull/3489))\n### Updated\n- Update requests to 2.27.0 ([#3509](https://github.com/cookiecutter/cookiecutter-django/pull/3509))\n- Update pillow to 9.0.0 ([#3508](https://github.com/cookiecutter/cookiecutter-django/pull/3508))\n- Update pylint-django to 2.5.0 ([#3505](https://github.com/cookiecutter/cookiecutter-django/pull/3505))\n\n## 2021.12.29\n\n### Fixed\n- Add generated files to `.gitignore` when selecting Gulp ([#3500](https://github.com/cookiecutter/cookiecutter-django/pull/3500))\n### Updated\n- Update psycopg2-binary to 2.9.3 ([#3504](https://github.com/cookiecutter/cookiecutter-django/pull/3504))\n- Update psycopg2 to 2.9.3 ([#3503](https://github.com/cookiecutter/cookiecutter-django/pull/3503))\n- Update celery to 5.2.3 ([#3502](https://github.com/cookiecutter/cookiecutter-django/pull/3502))\n- Update tox to 3.24.5 ([#3501](https://github.com/cookiecutter/cookiecutter-django/pull/3501))\n\n## 2021.12.28\n\n### Changed\n- Build the HTML for the documentation as part of the CI ([#3498](https://github.com/cookiecutter/cookiecutter-django/pull/3498))\n\n## 2021.12.27\n\n### Changed\n- Hides &#39;sign up&#39; elements when ACCOUNT_ALLOW_REGISTRATION is disabled ([#1914](https://github.com/cookiecutter/cookiecutter-django/pull/1914))\n\n## 2021.12.26\n\n### Fixed\n- Fix missing psycopg2 dependency in docs Docker image ([#3494](https://github.com/cookiecutter/cookiecutter-django/pull/3494))\n### Updated\n- Update celery to 5.2.2 ([#3496](https://github.com/cookiecutter/cookiecutter-django/pull/3496))\n- Update redis to 4.1.0 ([#3495](https://github.com/cookiecutter/cookiecutter-django/pull/3495))\n\n## 2021.12.25\n\n### Changed\n- Automatically add Django version label to issue ([#3492](https://github.com/cookiecutter/cookiecutter-django/pull/3492))\n### Updated\n- Auto-update pre-commit hooks ([#3493](https://github.com/cookiecutter/cookiecutter-django/pull/3493))\n\n## 2021.12.24\n\n### Changed\n- Simplify `TEMPLATES` settings with `APP_DIRS=True` ([#3488](https://github.com/cookiecutter/cookiecutter-django/pull/3488))\n- Fix docs not building ([#3491](https://github.com/cookiecutter/cookiecutter-django/pull/3491))\n- Remove pylint-django from VITAL_BUT_UNKNOWN ([#3490](https://github.com/cookiecutter/cookiecutter-django/pull/3490))\n- Making docs image 40% smaller and also making python version upgrades easier for multi-stage builds. ([#2836](https://github.com/cookiecutter/cookiecutter-django/pull/2836))\n- Added Django&#39;s current language to the lang attribute of the html tag ([#3174](https://github.com/cookiecutter/cookiecutter-django/pull/3174))\n### Updated\n- Update uvicorn to 0.16.0 ([#3454](https://github.com/cookiecutter/cookiecutter-django/pull/3454))\n\n## 2021.12.22\n\n### Changed\n- Use built-in pip caching from actions/setup-python in generated project ([#3481](https://github.com/cookiecutter/cookiecutter-django/pull/3481))\n- Speed up CI tests on macOS ([#3480](https://github.com/cookiecutter/cookiecutter-django/pull/3480))\n### Updated\n- Update mypy to 0.930 ([#3487](https://github.com/cookiecutter/cookiecutter-django/pull/3487))\n- Update redis to 4.0.2 ([#3486](https://github.com/cookiecutter/cookiecutter-django/pull/3486))\n- Update django-redis to 5.2.0 ([#3485](https://github.com/cookiecutter/cookiecutter-django/pull/3485))\n\n## 2021.12.20\n\n### Changed\n- Add a PyCharm run configuration for docker-compose ([#3462](https://github.com/cookiecutter/cookiecutter-django/pull/3462))\n\n## 2021.12.19\n\n### Updated\n- Update mypy to 0.920 ([#3478](https://github.com/cookiecutter/cookiecutter-django/pull/3478))\n- Update django-compressor to 3.1 ([#3476](https://github.com/cookiecutter/cookiecutter-django/pull/3476))\n- Update sphinx to 4.3.2 ([#3477](https://github.com/cookiecutter/cookiecutter-django/pull/3477))\n\n## 2021.12.17\n\n### Fixed\n- Fix BrowserSync config on non-Docker setup ([#3461](https://github.com/cookiecutter/cookiecutter-django/pull/3461))\n\n## 2021.12.16\n\n### Fixed\n- Fix carriage return in `.gitignore` on Windows ([#3456](https://github.com/cookiecutter/cookiecutter-django/pull/3456))\n### Updated\n- Update django-debug-toolbar to 3.2.4 ([#3473](https://github.com/cookiecutter/cookiecutter-django/pull/3473))\n\n## 2021.12.15\n\n### Updated\n- Update djangorestframework to 3.13.1 ([#3472](https://github.com/cookiecutter/cookiecutter-django/pull/3472))\n\n## 2021.12.14\n\n### Changed\n- Update rcssmin &amp; django-compressor ([#3470](https://github.com/cookiecutter/cookiecutter-django/pull/3470))\n### Updated\n- Update pytest-django to 4.5.2 ([#3471](https://github.com/cookiecutter/cookiecutter-django/pull/3471))\n- Bump peter-evans/create-pull-request from 3.11.0 to 3.12.0 ([#3469](https://github.com/cookiecutter/cookiecutter-django/pull/3469))\n\n## 2021.12.13\n\n### Updated\n- Update djangorestframework to 3.13.0 ([#3468](https://github.com/cookiecutter/cookiecutter-django/pull/3468))\n- Update sentry-sdk to 1.5.1 ([#3467](https://github.com/cookiecutter/cookiecutter-django/pull/3467))\n- Update django-debug-toolbar to 3.2.3 ([#3466](https://github.com/cookiecutter/cookiecutter-django/pull/3466))\n- Update argon2-cffi to 21.3.0 ([#3464](https://github.com/cookiecutter/cookiecutter-django/pull/3464))\n- Update django-allauth to 0.47.0 ([#3459](https://github.com/cookiecutter/cookiecutter-django/pull/3459))\n\n## 2021.12.09\n\n### Updated\n- Auto-update pre-commit hooks ([#3457](https://github.com/cookiecutter/cookiecutter-django/pull/3457))\n\n## 2021.12.08\n\n### Changed\n- Reword introduction in documentation ([#3452](https://github.com/cookiecutter/cookiecutter-django/pull/3452))\n### Updated\n- Update argon2-cffi to 21.2.0 ([#3453](https://github.com/cookiecutter/cookiecutter-django/pull/3453))\n\n## 2021.12.07\n\n### Changed\n- Add docker, pip and npm to GitHub&#39;s Dependabot ([#3401](https://github.com/cookiecutter/cookiecutter-django/pull/3401))\n- Configure Dependabot for npm packages at the template level ([#3436](https://github.com/cookiecutter/cookiecutter-django/pull/3436))\n### Updated\n- Update django to 3.2.10 ([#3451](https://github.com/cookiecutter/cookiecutter-django/pull/3451))\n\n## 2021.12.06\n\n### Updated\n- Auto-update pre-commit hooks ([#3449](https://github.com/cookiecutter/cookiecutter-django/pull/3449))\n- Update black to 21.12b0 ([#3448](https://github.com/cookiecutter/cookiecutter-django/pull/3448))\n- Update django-cors-headers to 3.10.1 ([#3447](https://github.com/cookiecutter/cookiecutter-django/pull/3447))\n\n## 2021.12.04\n\n### Changed\n- Removed mention of Foundation fork from readme ([#3445](https://github.com/cookiecutter/cookiecutter-django/pull/3445))\n### Updated\n- Update pytest-django to 4.5.1 ([#3443](https://github.com/cookiecutter/cookiecutter-django/pull/3443))\n\n## 2021.12.01\n\n### Updated\n- Update pre-commit to 2.16.0 ([#3442](https://github.com/cookiecutter/cookiecutter-django/pull/3442))\n\n## 2021.11.30\n\n### Updated\n- Update django-redis to 5.1.0 ([#3440](https://github.com/cookiecutter/cookiecutter-django/pull/3440))\n- Update django-stubs to 1.9.0 ([#3439](https://github.com/cookiecutter/cookiecutter-django/pull/3439))\n\n## 2021.11.29\n\n### Fixed\n- Fix pre-commit config ([#3435](https://github.com/cookiecutter/cookiecutter-django/pull/3435))\n### Updated\n- Update sphinx to 4.3.1 ([#3438](https://github.com/cookiecutter/cookiecutter-django/pull/3438))\n\n## 2021.11.27\n\n### Updated\n- Update coverage to 6.2 ([#3437](https://github.com/cookiecutter/cookiecutter-django/pull/3437))\n\n## 2021.11.26\n\n### Changed\n- Setup pre-commit for the template files ([#3433](https://github.com/cookiecutter/cookiecutter-django/pull/3433))\n\n## 2021.11.25\n\n### Changed\n- Add an assertion to fix mypy type error ([#3150](https://github.com/cookiecutter/cookiecutter-django/pull/3150))\n- Make `django` depend on `redis` in local Docker  ([#3265](https://github.com/cookiecutter/cookiecutter-django/pull/3265))\n\n## 2021.11.24\n\n### Changed\n- Cache Python dependencies on our CI ([#3434](https://github.com/cookiecutter/cookiecutter-django/pull/3434))\n- Small formatting fixes to Deploy to PythonAnywhere page ([#3432](https://github.com/cookiecutter/cookiecutter-django/pull/3432))\n### Updated\n- Upgrade to Django 3.2 ([#3425](https://github.com/cookiecutter/cookiecutter-django/pull/3425))\n\n## 2021.11.22\n\n### Changed\n- Removed unnecessary custom context processor exposing the DEBUG Template Context Variable ([#3042](https://github.com/cookiecutter/cookiecutter-django/pull/3042))\n- Clean up trailing whitespace ([#3430](https://github.com/cookiecutter/cookiecutter-django/pull/3430))\n### Updated\n- Update redis to 4.0.2 ([#3431](https://github.com/cookiecutter/cookiecutter-django/pull/3431))\n- Bump Postgres to 13.5 12.9 11.14 10.19; add 14.1 ([#3428](https://github.com/cookiecutter/cookiecutter-django/pull/3428))\n\n## 2021.11.20\n\n### Fixed\n- Update repos for pre-commit hooks ([#3424](https://github.com/cookiecutter/cookiecutter-django/pull/3424))\n### Updated\n- Bump pre-commit/action to 2.0.3 ([#3426](https://github.com/cookiecutter/cookiecutter-django/pull/3426))\n\n## 2021.11.19\n\n### Updated\n- Update celery to 5.2.1 ([#3423](https://github.com/cookiecutter/cookiecutter-django/pull/3423))\n- Auto-update pre-commit hooks ([#3420](https://github.com/cookiecutter/cookiecutter-django/pull/3420))\n\n## 2021.11.18\n\n### Changed\n- Switch template to calendar versioning &amp; automate releases ([#3415](https://github.com/cookiecutter/cookiecutter-django/pull/3415))\n### Updated\n- Update black to 21.11b1 ([#3421](https://github.com/cookiecutter/cookiecutter-django/pull/3421))\n- Update redis to 4.0.1 ([#3416](https://github.com/cookiecutter/cookiecutter-django/pull/3416))\n\n## [2021-11-17]\n### Updated\n- Update sentry-sdk to 1.5.0 ([#3417](https://github.com/cookiecutter/cookiecutter-django/pull/3417))\n- Update black to 21.11b0 ([#3414](https://github.com/cookiecutter/cookiecutter-django/pull/3414))\n\n## [2021-11-16]\n### Changed\n- Upgrade JS dependencies and upgrade to node 16 ([#3400](https://github.com/cookiecutter/cookiecutter-django/pull/3400))\n### Fixed\n- Fix ungraceful Celery workers shutdown in container ([#3405](https://github.com/cookiecutter/cookiecutter-django/pull/3405))\n### Updated\n- Update psycopg2-binary to 2.9.2 ([#3411](https://github.com/cookiecutter/cookiecutter-django/pull/3411))\n- Update psycopg2 to 2.9.2 ([#3410](https://github.com/cookiecutter/cookiecutter-django/pull/3410))\n- Update redis to 4.0.0 ([#3406](https://github.com/cookiecutter/cookiecutter-django/pull/3406))\n- Update django-coverage-plugin to 2.0.2 ([#3409](https://github.com/cookiecutter/cookiecutter-django/pull/3409))\n- Update black to 21.10b0 ([#3408](https://github.com/cookiecutter/cookiecutter-django/pull/3408))\n\n## [2021-11-15]\n### Updated\n- Update django-allauth to 0.46.0 ([#3407](https://github.com/cookiecutter/cookiecutter-django/pull/3407))\n\n## [2021-11-13]\n### Fixed\n- Fix incorrect node version in `package.json` ([#3399](https://github.com/cookiecutter/cookiecutter-django/pull/3399))\n\n## [2021-11-12]\n### Changed\n- Add Django major/minor release table maker in GitHub issues ([#3288](https://github.com/cookiecutter/cookiecutter-django/pull/3288))\n- Upgrade to Bootstrap 5 ([#3276](https://github.com/cookiecutter/cookiecutter-django/pull/3276))\n### Updated\n- Update requests to 2.26.0 ([#3397](https://github.com/cookiecutter/cookiecutter-django/pull/3397))\n- Update crispy-bootstrap5 to 0.6 ([#3396](https://github.com/cookiecutter/cookiecutter-django/pull/3396))\n\n## [2021-11-11]\n### Changed\n- Build all images on CI ([#3394](https://github.com/cookiecutter/cookiecutter-django/pull/3394))\n### Updated\n- Update coverage to 6.1.2 ([#3393](https://github.com/cookiecutter/cookiecutter-django/pull/3393))\n\n## [2021-11-10]\n### Changed\n- Update sphinx to 4.3.0 ([#3392](https://github.com/cookiecutter/cookiecutter-django/pull/3392))\n### Updated\n- Auto-update pre-commit hooks ([#3389](https://github.com/cookiecutter/cookiecutter-django/pull/3389))\n- Update jinja2 to 3.0.3 ([#3388](https://github.com/cookiecutter/cookiecutter-django/pull/3388))\n\n## [2021-11-09]\n### Changed\n- refactor: remove user API methods parameter ([#3385](https://github.com/cookiecutter/cookiecutter-django/pull/3385))\n- Get GitHub repo from environment ([#3387](https://github.com/cookiecutter/cookiecutter-django/pull/3387))\n### Updated\n- Update celery to 5.2.0 ([#3384](https://github.com/cookiecutter/cookiecutter-django/pull/3384))\n- Update isort to 5.10.1 ([#3386](https://github.com/cookiecutter/cookiecutter-django/pull/3386))\n\n## [2021-11-08]\n### Changed\n- Update docker and non-docker configs to Debian 11 (bullseye) ([#3372](https://github.com/cookiecutter/cookiecutter-django/pull/3372))\n\n## [2021-11-07]\n### Updated\n- Update django-extensions to 3.1.5 ([#3383](https://github.com/cookiecutter/cookiecutter-django/pull/3383))\n\n## [2021-11-04]\n### Changed\n- change path in docs Makefile to use APP variable ([#3379](https://github.com/cookiecutter/cookiecutter-django/pull/3379))\n### Fixed\n- fix help in docs Makefile ([#3380](https://github.com/cookiecutter/cookiecutter-django/pull/3380))\n### Updated\n- Bump peter-evans/create-pull-request from 3.10.1 to 3.11.0 ([#3382](https://github.com/cookiecutter/cookiecutter-django/pull/3382))\n- Auto-update pre-commit hooks ([#3381](https://github.com/cookiecutter/cookiecutter-django/pull/3381))\n- Update isort to 5.10.0 ([#3378](https://github.com/cookiecutter/cookiecutter-django/pull/3378))\n\n## [2021-11-02]\n### Updated\n- Auto-update pre-commit hooks ([#3377](https://github.com/cookiecutter/cookiecutter-django/pull/3377))\n\n## [2021-11-01]\n### Updated\n- Update django-storages to 1.12.3 ([#3374](https://github.com/cookiecutter/cookiecutter-django/pull/3374))\n- Update coverage to 6.1.1 ([#3376](https://github.com/cookiecutter/cookiecutter-django/pull/3376))\n\n## [2021-10-28]\n### Updated\n- Update factory-boy to 3.2.1 ([#3373](https://github.com/cookiecutter/cookiecutter-django/pull/3373))\n\n## [2021-10-26]\n### Changed\n- use Wayback Machine to fix dead link for postgres user setup ([#3363](https://github.com/cookiecutter/cookiecutter-django/pull/3363))\n- Fix pull request links to correct repo URL on CHANGELOG.md  ([#3370](https://github.com/cookiecutter/cookiecutter-django/pull/3370))\n### Updated\n- Update pyyaml to 6.0 ([#3362](https://github.com/cookiecutter/cookiecutter-django/pull/3362))\n- Update pillow to 8.4.0 ([#3364](https://github.com/cookiecutter/cookiecutter-django/pull/3364))\n- Update django-storages to 1.12.2 ([#3365](https://github.com/cookiecutter/cookiecutter-django/pull/3365))\n- Update django-environ to 0.8.1 ([#3368](https://github.com/cookiecutter/cookiecutter-django/pull/3368))\n\n## [2021-10-22]\n### Changed\n- Move repo under cookiecutter organisation ([#3357](https://github.com/cookiecutter/cookiecutter-django/pull/3357))\n\n## [2021-10-18]\n### Updated\n- Update django-environ to 0.8.0 ([#3367](https://github.com/cookiecutter/cookiecutter-django/pull/3367))\n\n## [2021-10-14]\n### Updated\n- Update flake8 to 4.0.1 ([#3361](https://github.com/cookiecutter/cookiecutter-django/pull/3361))\n- Update flake8-isort to 4.1.1 ([#3360](https://github.com/cookiecutter/cookiecutter-django/pull/3360))\n- Update django-model-utils to 4.2.0 ([#3359](https://github.com/cookiecutter/cookiecutter-django/pull/3359))\n\n## [2021-10-13]\n### Changed\n- Add drf stubs ([#3353](https://github.com/cookiecutter/cookiecutter-django/pull/3353))\n\n## [2021-10-12]\n### Updated\n- Update coverage to 6.0.2 ([#3356](https://github.com/cookiecutter/cookiecutter-django/pull/3356))\n\n## [2021-10-11]\n### Updated\n- Update werkzeug to 2.0.2 ([#3344](https://github.com/cookiecutter/cookiecutter-django/pull/3344))\n- Update coverage to 6.0.1 ([#3348](https://github.com/cookiecutter/cookiecutter-django/pull/3348))\n- Update django-coverage-plugin to 2.0.1 ([#3349](https://github.com/cookiecutter/cookiecutter-django/pull/3349))\n- Update django-cors-headers to 3.10.0 ([#3345](https://github.com/cookiecutter/cookiecutter-django/pull/3345))\n- Update jinja2 to 3.0.2 ([#3343](https://github.com/cookiecutter/cookiecutter-django/pull/3343))\n- Update django-storages to 1.12.1 ([#3355](https://github.com/cookiecutter/cookiecutter-django/pull/3355))\n\n## [2021-10-03]\n### Updated\n- Update pytz to 2021.3 ([#3340](https://github.com/cookiecutter/cookiecutter-django/pull/3340))\n\n## [2021-10-01]\n### Changed\n- Fix the wrong pre-commit hyperlink in Prerequisites section ([#3338](https://github.com/cookiecutter/cookiecutter-django/pull/3338))\n\n## [2021-09-30]\n### Updated\n- Update sentry-sdk to 1.4.3 ([#3334](https://github.com/cookiecutter/cookiecutter-django/pull/3334))\n\n## [2021-09-29]\n### Updated\n- Update django-cors-headers to 3.9.0 ([#3332](https://github.com/cookiecutter/cookiecutter-django/pull/3332))\n\n## [2021-09-27]\n### Updated\n- Update sentry-sdk to 1.4.2 ([#3329](https://github.com/cookiecutter/cookiecutter-django/pull/3329))\n\n## [2021-09-26]\n### Updated\n- Update django-crispy-forms to 1.13.0 ([#3327](https://github.com/cookiecutter/cookiecutter-django/pull/3327))\n\n## [2021-09-24]\n### Changed\n- Add django-settings-module to .pylintrc ([#3326](https://github.com/cookiecutter/cookiecutter-django/pull/3326))\n\n## [2021-09-23]\n### Updated\n- Update sentry-sdk to 1.4.1 ([#3325](https://github.com/cookiecutter/cookiecutter-django/pull/3325))\n\n## [2021-09-22]\n### Updated\n- Update sentry-sdk to 1.4.0 ([#3324](https://github.com/cookiecutter/cookiecutter-django/pull/3324))\n\n## [2021-09-16]\n### Updated\n- Update tox to 3.24.4 ([#3323](https://github.com/cookiecutter/cookiecutter-django/pull/3323))\n\n## [2021-09-15]\n### Updated\n- Auto-update pre-commit hooks ([#3322](https://github.com/cookiecutter/cookiecutter-django/pull/3322))\n\n## [2021-09-14]\n### Updated\n- Update black to 21.9b0 ([#3321](https://github.com/cookiecutter/cookiecutter-django/pull/3321))\n\n## [2021-09-13]\n### Updated\n- Bump stefanzweifel/git-auto-commit-action from 4.11.0 to 4.12.0 ([#3320](https://github.com/cookiecutter/cookiecutter-django/pull/3320))\n- Update sphinx to 4.2.0 ([#3319](https://github.com/cookiecutter/cookiecutter-django/pull/3319))\n\n## [2021-09-11]\n### Changed\n- Removing pycharm docs if app does not use pycharm ([#3139](https://github.com/cookiecutter/cookiecutter-django/pull/3139))\n### Updated\n- Update django-environ to 0.7.0 ([#3317](https://github.com/cookiecutter/cookiecutter-django/pull/3317))\n\n## [2021-09-06]\n### Changed\n- Update Celery to v5 ([#3280](https://github.com/cookiecutter/cookiecutter-django/pull/3280))\n\n## [2021-09-05]\n### Updated\n- Update django-environ to 0.6.0 ([#3314](https://github.com/cookiecutter/cookiecutter-django/pull/3314))\n\n## [2021-09-03]\n### Changed\n- Update available postgres versions ([#3297](https://github.com/cookiecutter/cookiecutter-django/pull/3297))\n### Updated\n- Update pre-commit to 2.15.0 ([#3313](https://github.com/cookiecutter/cookiecutter-django/pull/3313))\n- Auto-update pre-commit hooks ([#3307](https://github.com/cookiecutter/cookiecutter-django/pull/3307))\n- Update pillow to 8.3.2 ([#3312](https://github.com/cookiecutter/cookiecutter-django/pull/3312))\n- Update django-environ to 0.5.0 ([#3311](https://github.com/cookiecutter/cookiecutter-django/pull/3311))\n- Update pytest to 6.2.5 ([#3310](https://github.com/cookiecutter/cookiecutter-django/pull/3310))\n- Update black to 21.8b0 ([#3308](https://github.com/cookiecutter/cookiecutter-django/pull/3308))\n- Update argon2-cffi to 21.1.0 ([#3306](https://github.com/cookiecutter/cookiecutter-django/pull/3306))\n- Bump peter-evans/create-pull-request from 3.10.0 to 3.10.1 ([#3303](https://github.com/cookiecutter/cookiecutter-django/pull/3303))\n- Update django-debug-toolbar to 3.2.2 ([#3296](https://github.com/cookiecutter/cookiecutter-django/pull/3296))\n- Update django-cors-headers to 3.8.0 ([#3295](https://github.com/cookiecutter/cookiecutter-django/pull/3295))\n- Update uvicorn to 0.15.0 ([#3294](https://github.com/cookiecutter/cookiecutter-django/pull/3294))\n\n## [2021-08-27]\n### Updated\n- Update tox to 3.24.3 ([#3302](https://github.com/cookiecutter/cookiecutter-django/pull/3302))\n\n## [2021-08-20]\n### Changed\n- Fix Jinja2 break line control on Procfile ([#3300](https://github.com/cookiecutter/cookiecutter-django/pull/3300))\n\n## [2021-08-19]\n### Changed\n- Fix several minor typos ([#3301](https://github.com/cookiecutter/cookiecutter-django/pull/3301))\n\n## [2021-08-13]\n### Changed\n- Upgrade to Redis 6 ([#3255](https://github.com/cookiecutter/cookiecutter-django/pull/3255))\n### Fixed\n- Fix RTD build image to support Python 3.9 ([#3293](https://github.com/cookiecutter/cookiecutter-django/pull/3293))\n\n## [2021-08-12]\n### Changed\n- Add documentation for automating backups ([#3268](https://github.com/cookiecutter/cookiecutter-django/pull/3268))\n- Add missing step to getting started locally in docs ([#3291](https://github.com/cookiecutter/cookiecutter-django/pull/3291))\n- Moved isort config from `.editorconfig` to `setup.cfg` ([#3290](https://github.com/cookiecutter/cookiecutter-django/pull/3290))\n- How to pre-commit in Docker Development ([#3287](https://github.com/cookiecutter/cookiecutter-django/pull/3287))\n### Updated\n- Update sentry-sdk to 1.3.1 ([#3281](https://github.com/cookiecutter/cookiecutter-django/pull/3281))\n- Update tox to 3.24.1 ([#3285](https://github.com/cookiecutter/cookiecutter-django/pull/3285))\n- Update pre-commit to 2.14.0 ([#3289](https://github.com/cookiecutter/cookiecutter-django/pull/3289))\n\n## [2021-07-30]\n### Updated\n- Auto-update pre-commit hooks ([#3283](https://github.com/cookiecutter/cookiecutter-django/pull/3283))\n- Update isort to 5.9.3 ([#3282](https://github.com/cookiecutter/cookiecutter-django/pull/3282))\n\n## [2021-07-27]\n### Changed\n- Convert trans to translate in templates ([#3277](https://github.com/cookiecutter/cookiecutter-django/pull/3277))\n### Updated\n- Update hiredis to 2.0.0 ([#3110](https://github.com/cookiecutter/cookiecutter-django/pull/3110))\n- Update mypy to 0.910 ([#3237](https://github.com/cookiecutter/cookiecutter-django/pull/3237))\n- Update whitenoise to 5.3.0 ([#3273](https://github.com/cookiecutter/cookiecutter-django/pull/3273))\n- Update tox to 3.24.0 ([#3269](https://github.com/cookiecutter/cookiecutter-django/pull/3269))\n- Update django-allauth to 0.45.0 ([#3267](https://github.com/cookiecutter/cookiecutter-django/pull/3267))\n- Update sentry-sdk to 1.3.0 ([#3262](https://github.com/cookiecutter/cookiecutter-django/pull/3262))\n- Update sphinx to 4.1.2 ([#3278](https://github.com/cookiecutter/cookiecutter-django/pull/3278))\n- Auto-update pre-commit hooks ([#3264](https://github.com/cookiecutter/cookiecutter-django/pull/3264))\n- Update isort to 5.9.2 ([#3279](https://github.com/cookiecutter/cookiecutter-django/pull/3279))\n- Update pillow to 8.3.1 ([#3259](https://github.com/cookiecutter/cookiecutter-django/pull/3259))\n- Update black to 21.7b0 ([#3272](https://github.com/cookiecutter/cookiecutter-django/pull/3272))\n\n## [2021-07-12]\n### Changed\n- Define REMAP_SIGTERM=SIGQUIT on Profile of Celery on Heroku ([#3263](https://github.com/cookiecutter/cookiecutter-django/pull/3263))\n\n## [2021-07-08]\n### Updated\n- Update django to 3.1.13 ([#3247](https://github.com/cookiecutter/cookiecutter-django/pull/3247))\n\n## [2021-06-29]\n### Changed\n- Improve github bug report template ([#3243](https://github.com/cookiecutter/cookiecutter-django/pull/3243))\n\n## [2021-06-28]\n### Changed\n- Revert &#34;Fix Celery ports error on local Docker&#34; ([#3242](https://github.com/cookiecutter/cookiecutter-django/pull/3242))\n### Fixed\n- Fix Celery ports error on local Docker ([#3241](https://github.com/cookiecutter/cookiecutter-django/pull/3241))\n\n## [2021-06-25]\n### Changed\n- Update `.gitignore` file for VSCode ([#3238](https://github.com/cookiecutter/cookiecutter-django/pull/3238))\n### Fixed\n- Wrap jQuery call in `DOMContentLoaded` event listener on account email page ([#3239](https://github.com/cookiecutter/cookiecutter-django/pull/3239))\n\n## [2021-06-22]\n### Changed\n- Update docs/howto.rst ([#3230](https://github.com/cookiecutter/cookiecutter-django/pull/3230))\n- Add support for PG 13. Drop PG 9. Update all minor versions ([#3154](https://github.com/cookiecutter/cookiecutter-django/pull/3154))\n### Updated\n- Update isort to 5.9.1 ([#3236](https://github.com/cookiecutter/cookiecutter-django/pull/3236))\n- Auto-update pre-commit hooks ([#3235](https://github.com/cookiecutter/cookiecutter-django/pull/3235))\n\n## [2021-06-21]\n### Updated\n- Update isort to 5.9.0 ([#3234](https://github.com/cookiecutter/cookiecutter-django/pull/3234))\n- Update django-anymail to 8.4 ([#3225](https://github.com/cookiecutter/cookiecutter-django/pull/3225))\n- Update django-redis to 5.0.0 ([#3205](https://github.com/cookiecutter/cookiecutter-django/pull/3205))\n- Update pylint-django to 2.4.4 ([#3233](https://github.com/cookiecutter/cookiecutter-django/pull/3233))\n- Auto-update pre-commit hooks ([#3220](https://github.com/cookiecutter/cookiecutter-django/pull/3220))\n- Bump peter-evans/create-pull-request from 3.9.2 to 3.10.0 ([#3197](https://github.com/cookiecutter/cookiecutter-django/pull/3197))\n- Update black to 21.6b0 ([#3232](https://github.com/cookiecutter/cookiecutter-django/pull/3232))\n- Update pytest to 6.2.4 ([#3231](https://github.com/cookiecutter/cookiecutter-django/pull/3231))\n- Update django-crispy-forms to 1.12.0 ([#3221](https://github.com/cookiecutter/cookiecutter-django/pull/3221))\n- Update mypy to 0.902 ([#3219](https://github.com/cookiecutter/cookiecutter-django/pull/3219))\n- Update django-coverage-plugin to 2.0.0 ([#3217](https://github.com/cookiecutter/cookiecutter-django/pull/3217))\n- Update ipdb to 0.13.9 ([#3210](https://github.com/cookiecutter/cookiecutter-django/pull/3210))\n- Update uvicorn to 0.14.0 ([#3207](https://github.com/cookiecutter/cookiecutter-django/pull/3207))\n- Update pytest-cookies to 0.6.1 ([#3196](https://github.com/cookiecutter/cookiecutter-django/pull/3196))\n- Update sphinx to 4.0.2 ([#3193](https://github.com/cookiecutter/cookiecutter-django/pull/3193))\n- Update jinja2 to 3.0.1 ([#3189](https://github.com/cookiecutter/cookiecutter-django/pull/3189))\n\n## [2021-06-19]\n### Updated\n- Update psycopg2 to 2.9.1 ([#3227](https://github.com/cookiecutter/cookiecutter-django/pull/3227))\n- Update psycopg2-binary to 2.9.1 ([#3228](https://github.com/cookiecutter/cookiecutter-django/pull/3228))\n\n## [2021-06-14]\n### Changed\n- Update black GitHub link in requirements ([#3222](https://github.com/cookiecutter/cookiecutter-django/pull/3222))\n\n## [2021-06-09]\n### Changed\n- Fix link format in developing-locally.rst ([#3214](https://github.com/cookiecutter/cookiecutter-django/pull/3214))\n### Updated\n- Update pre-commit to 2.13.0 ([#3195](https://github.com/cookiecutter/cookiecutter-django/pull/3195))\n- Update pytest-django to 4.4.0 ([#3212](https://github.com/cookiecutter/cookiecutter-django/pull/3212))\n- Update mypy to 0.901 ([#3215](https://github.com/cookiecutter/cookiecutter-django/pull/3215))\n- Auto-update pre-commit hooks ([#3206](https://github.com/cookiecutter/cookiecutter-django/pull/3206))\n- Update black to 21.5b2 ([#3204](https://github.com/cookiecutter/cookiecutter-django/pull/3204))\n\n## [2021-06-06]\n### Changed\n- Updated .pre-commit-config.yaml to self-update its dependencies ([#3208](https://github.com/cookiecutter/cookiecutter-django/pull/3208))\n\n## [2021-06-05]\n### Changed\n- Shorthand for the officially supported buildpack ([#3211](https://github.com/cookiecutter/cookiecutter-django/pull/3211))\n\n## [2021-06-02]\n### Updated\n- Update django to 3.1.12 ([#3209](https://github.com/cookiecutter/cookiecutter-django/pull/3209))\n\n## [2021-05-18]\n### Changed\n- Move ARG PYTHON_VERSION=3.9-slim-buster to the global scope ([#3188](https://github.com/cookiecutter/cookiecutter-django/pull/3188))\n\n## [2021-05-17]\n### Updated\n- Bump tiangolo/issue-manager from 0.3.0 to 0.4.0 ([#3186](https://github.com/cookiecutter/cookiecutter-django/pull/3186))\n- Auto-update pre-commit hooks ([#3185](https://github.com/cookiecutter/cookiecutter-django/pull/3185))\n\n## [2021-05-15]\n### Changed\n- Update watchgod to 0.7 ([#3177](https://github.com/cookiecutter/cookiecutter-django/pull/3177))\n### Updated\n- Auto-update pre-commit hooks ([#3184](https://github.com/cookiecutter/cookiecutter-django/pull/3184))\n- Update black to 21.5b1 ([#3167](https://github.com/cookiecutter/cookiecutter-django/pull/3167))\n- Update flake8 to 3.9.2 ([#3164](https://github.com/cookiecutter/cookiecutter-django/pull/3164))\n- Update pytest-django to 4.3.0 ([#3182](https://github.com/cookiecutter/cookiecutter-django/pull/3182))\n- Auto-update pre-commit hooks ([#3157](https://github.com/cookiecutter/cookiecutter-django/pull/3157))\n- Update python-slugify to 5.0.2 ([#3161](https://github.com/cookiecutter/cookiecutter-django/pull/3161))\n- Bump stefanzweifel/git-auto-commit-action from 4.10.0 to 4.11.0 ([#3171](https://github.com/cookiecutter/cookiecutter-django/pull/3171))\n- Update sentry-sdk to 1.1.0 ([#3163](https://github.com/cookiecutter/cookiecutter-django/pull/3163))\n- Bump actions/setup-python from 2 to 2.2.2 ([#3173](https://github.com/cookiecutter/cookiecutter-django/pull/3173))\n- Update tox to 3.23.1 ([#3160](https://github.com/cookiecutter/cookiecutter-django/pull/3160))\n- Update pytest to 6.2.4 ([#3156](https://github.com/cookiecutter/cookiecutter-django/pull/3156))\n- Bump peter-evans/create-pull-request from 3.8.2 to 3.9.2 ([#3179](https://github.com/cookiecutter/cookiecutter-django/pull/3179))\n- Update sphinx to 4.0.1 ([#3169](https://github.com/cookiecutter/cookiecutter-django/pull/3169))\n- Update cookiecutter to 1.7.3 ([#3180](https://github.com/cookiecutter/cookiecutter-django/pull/3180))\n- Update django to 3.1.11 ([#3178](https://github.com/cookiecutter/cookiecutter-django/pull/3178))\n\n## [2021-05-06]\n### Updated\n- Update django to 3.1.10 ([#3162](https://github.com/cookiecutter/cookiecutter-django/pull/3162))\n\n## [2021-05-04]\n### Updated\n- Update django to 3.1.9 ([#3155](https://github.com/cookiecutter/cookiecutter-django/pull/3155))\n\n## [2021-04-30]\n### Fixed\n- Fix linting error in production.py ([#3148](https://github.com/cookiecutter/cookiecutter-django/pull/3148))\n\n## [2021-04-29]\n### Updated\n- Update black to 21.4b2 ([#3147](https://github.com/cookiecutter/cookiecutter-django/pull/3147))\n- Auto-update pre-commit hooks ([#3146](https://github.com/cookiecutter/cookiecutter-django/pull/3146))\n\n## [2021-04-28]\n### Changed\n- Fix README link ([#3144](https://github.com/cookiecutter/cookiecutter-django/pull/3144))\n### Updated\n- Auto-update pre-commit hooks ([#3145](https://github.com/cookiecutter/cookiecutter-django/pull/3145))\n\n## [2021-04-27]\n### Updated\n- Update pygithub to 1.55 ([#3141](https://github.com/cookiecutter/cookiecutter-django/pull/3141))\n- Update black to 21.4b1 ([#3143](https://github.com/cookiecutter/cookiecutter-django/pull/3143))\n\n## [2021-04-26]\n### Updated\n- Update black to 21.4b0 ([#3138](https://github.com/cookiecutter/cookiecutter-django/pull/3138))\n- Auto-update pre-commit hooks ([#3137](https://github.com/cookiecutter/cookiecutter-django/pull/3137))\n\n## [2021-04-21]\n### Updated\n- Auto-update pre-commit hooks ([#3133](https://github.com/cookiecutter/cookiecutter-django/pull/3133))\n- Update django-extensions to 3.1.3 ([#3136](https://github.com/cookiecutter/cookiecutter-django/pull/3136))\n- Update django-compressor to 2.4.1 ([#3135](https://github.com/cookiecutter/cookiecutter-django/pull/3135))\n- Update pre-commit to 2.12.1 ([#3134](https://github.com/cookiecutter/cookiecutter-django/pull/3134))\n- Update flake8 to 3.9.1 ([#3131](https://github.com/cookiecutter/cookiecutter-django/pull/3131))\n- Update django-stubs to 1.8.0 ([#3127](https://github.com/cookiecutter/cookiecutter-django/pull/3127))\n- Update sphinx to 3.5.4 ([#3126](https://github.com/cookiecutter/cookiecutter-django/pull/3126))\n\n## [2021-04-15]\n### Updated\n- Update django-debug-toolbar to 3.2.1 ([#3129](https://github.com/cookiecutter/cookiecutter-django/pull/3129))\n\n## [2021-04-14]\n### Updated\n- Bump stefanzweifel/git-auto-commit-action from v4.9.2 to v4.10.0 ([#3128](https://github.com/cookiecutter/cookiecutter-django/pull/3128))\n\n## [2021-04-11]\n### Updated\n- Update pytest-django to 4.2.0 ([#3125](https://github.com/cookiecutter/cookiecutter-django/pull/3125))\n- Update pylint-django to 2.4.3 ([#3122](https://github.com/cookiecutter/cookiecutter-django/pull/3122))\n\n## [2021-04-09]\n### Changed\n- Update from Python 3.8 to Python 3.9 ([#3023](https://github.com/cookiecutter/cookiecutter-django/pull/3023))\n\n## [2021-04-08]\n### Changed\n- Switch .dockerignore to explicit list ([#3121](https://github.com/cookiecutter/cookiecutter-django/pull/3121))\n- Change Docker image to multi-stage build for Django ([#2815](https://github.com/cookiecutter/cookiecutter-django/pull/2815))\n- Fix deprecated warning in middleware tests ([#3038](https://github.com/cookiecutter/cookiecutter-django/pull/3038))\n### Updated\n- Update pre-commit to 2.12.0 ([#3120](https://github.com/cookiecutter/cookiecutter-django/pull/3120))\n\n## [2021-04-07]\n### Changed\n- Update django to 3.1.8 ([#3117](https://github.com/cookiecutter/cookiecutter-django/pull/3117))\n### Fixed\n- Fix linting via pre-commit on Github CI ([#3077](https://github.com/cookiecutter/cookiecutter-django/pull/3077))\n- Fix gitlab-ci using duplicate key name for image ([#3112](https://github.com/cookiecutter/cookiecutter-django/pull/3112))\n### Updated\n- Update sentry-sdk to 1.0.0 ([#3080](https://github.com/cookiecutter/cookiecutter-django/pull/3080))\n- Update gunicorn to 20.1.0 ([#3108](https://github.com/cookiecutter/cookiecutter-django/pull/3108))\n- Update pre-commit to 2.12.0 ([#3118](https://github.com/cookiecutter/cookiecutter-django/pull/3118))\n- Update django-extensions to 3.1.2 ([#3116](https://github.com/cookiecutter/cookiecutter-django/pull/3116))\n- Update pillow to 8.2.0 ([#3113](https://github.com/cookiecutter/cookiecutter-django/pull/3113))\n- Update pytest to 6.2.3 ([#3115](https://github.com/cookiecutter/cookiecutter-django/pull/3115))\n\n## [2021-03-26]\n### Updated\n- Update djangorestframework to 3.12.4 ([#3107](https://github.com/cookiecutter/cookiecutter-django/pull/3107))\n\n## [2021-03-25]\n### Updated\n- Update djangorestframework to 3.12.3 ([#3105](https://github.com/cookiecutter/cookiecutter-django/pull/3105))\n\n## [2021-03-22]\n### Updated\n- Update django-crispy-forms to 1.11.2 ([#3104](https://github.com/cookiecutter/cookiecutter-django/pull/3104))\n- Update sphinx to 3.5.3 ([#3103](https://github.com/cookiecutter/cookiecutter-django/pull/3103))\n- Update ipdb to 0.13.7 ([#3102](https://github.com/cookiecutter/cookiecutter-django/pull/3102))\n- Update sphinx-autobuild to 2021.3.14 ([#3101](https://github.com/cookiecutter/cookiecutter-django/pull/3101))\n- Update isort to 5.8.0 ([#3100](https://github.com/cookiecutter/cookiecutter-django/pull/3100))\n- Update pre-commit to 2.11.1 ([#3089](https://github.com/cookiecutter/cookiecutter-django/pull/3089))\n- Update flake8 to 3.9.0 ([#3096](https://github.com/cookiecutter/cookiecutter-django/pull/3096))\n- Update pillow to 8.1.2 ([#3084](https://github.com/cookiecutter/cookiecutter-django/pull/3084))\n- Auto-update pre-commit hooks ([#3095](https://github.com/cookiecutter/cookiecutter-django/pull/3095))\n\n## [2021-03-05]\n### Changed\n- Updated test_urls.py and views.py to re-use User.get_absolute_url() ([#3070](https://github.com/cookiecutter/cookiecutter-django/pull/3070))\n### Updated\n- Bump stefanzweifel/git-auto-commit-action from v4.9.1 to v4.9.2 ([#3082](https://github.com/cookiecutter/cookiecutter-django/pull/3082))\n\n## [2021-03-03]\n### Updated\n- Update tox to 3.23.0 ([#3079](https://github.com/cookiecutter/cookiecutter-django/pull/3079))\n- Update ipdb to 0.13.5 ([#3078](https://github.com/cookiecutter/cookiecutter-django/pull/3078))\n\n## [2021-03-02]\n### Fixed\n- Fixes for pytest job in Github CI workflow ([#3076](https://github.com/cookiecutter/cookiecutter-django/pull/3076))\n### Updated\n- Update pillow to 8.1.1 ([#3075](https://github.com/cookiecutter/cookiecutter-django/pull/3075))\n- Update coverage to 5.5 ([#3074](https://github.com/cookiecutter/cookiecutter-django/pull/3074))\n\n## [2021-02-24]\n### Updated\n- Bump stefanzweifel/git-auto-commit-action from v4.9.0 to v4.9.1 ([#3069](https://github.com/cookiecutter/cookiecutter-django/pull/3069))\n\n## [2021-02-23]\n### Changed\n- Update to Django 3.1 ([#3043](https://github.com/cookiecutter/cookiecutter-django/pull/3043))\n- Lint with pre-commit on CI with Github actions ([#3066](https://github.com/cookiecutter/cookiecutter-django/pull/3066))\n- Use exception var in status code pages if available ([#2992](https://github.com/cookiecutter/cookiecutter-django/pull/2992))\n\n## [2021-02-22]\n### Changed\n- refactor: remove default cache settings in test.py ([#3064](https://github.com/cookiecutter/cookiecutter-django/pull/3064))\n- Update django to 3.0.13 ([#3060](https://github.com/cookiecutter/cookiecutter-django/pull/3060))\n### Fixed\n- Fix missing Django Debug toolbar with node container ([#2865](https://github.com/cookiecutter/cookiecutter-django/pull/2865))\n- Remove Email from User API ([#3055](https://github.com/cookiecutter/cookiecutter-django/pull/3055))\n### Updated\n- Bump stefanzweifel/git-auto-commit-action from v4.8.0 to v4.9.0 ([#3065](https://github.com/cookiecutter/cookiecutter-django/pull/3065))\n- Update django-crispy-forms to 1.11.1 ([#3063](https://github.com/cookiecutter/cookiecutter-django/pull/3063))\n- Update uvicorn to 0.13.4 ([#3062](https://github.com/cookiecutter/cookiecutter-django/pull/3062))\n- Update mypy to 0.812 ([#3061](https://github.com/cookiecutter/cookiecutter-django/pull/3061))\n- Update sentry-sdk to 0.20.3 ([#3059](https://github.com/cookiecutter/cookiecutter-django/pull/3059))\n- Update tox to 3.22.0 ([#3057](https://github.com/cookiecutter/cookiecutter-django/pull/3057))\n- Update sphinx to 3.5.1 ([#3056](https://github.com/cookiecutter/cookiecutter-django/pull/3056))\n\n## [2021-02-16]\n### Updated\n- Update sentry-sdk to 0.20.2 ([#3054](https://github.com/cookiecutter/cookiecutter-django/pull/3054))\n- Update sphinx to 3.5.0 ([#3053](https://github.com/cookiecutter/cookiecutter-django/pull/3053))\n\n## [2021-02-13]\n### Updated\n- Update sentry-sdk to 0.20.1 ([#3052](https://github.com/cookiecutter/cookiecutter-django/pull/3052))\n\n## [2021-02-12]\n### Updated\n- Update pre-commit to 2.10.1 ([#3045](https://github.com/cookiecutter/cookiecutter-django/pull/3045))\n- Update sentry-sdk to 0.20.0 ([#3051](https://github.com/cookiecutter/cookiecutter-django/pull/3051))\n\n## [2021-02-10]\n### Updated\n- Bump peter-evans/create-pull-request from v3.8.1 to v3.8.2 ([#3049](https://github.com/cookiecutter/cookiecutter-django/pull/3049))\n\n## [2021-02-08]\n### Updated\n- Update django-extensions to 3.1.1 ([#3047](https://github.com/cookiecutter/cookiecutter-django/pull/3047))\n- Bump peter-evans/create-pull-request from v3.8.0 to v3.8.1 ([#3046](https://github.com/cookiecutter/cookiecutter-django/pull/3046))\n\n## [2021-02-06]\n### Changed\n- Removed Redundant test_case_sensitivity() and made test_not_authenticated() get the LOGIN_URL dynamically. ([#3041](https://github.com/cookiecutter/cookiecutter-django/pull/3041))\n- Refactored users.forms to make the code more readeable ([#3029](https://github.com/cookiecutter/cookiecutter-django/pull/3029))\n- Update django to 3.0.12 ([#3037](https://github.com/cookiecutter/cookiecutter-django/pull/3037))\n### Updated\n- Update tox to 3.21.4 ([#3044](https://github.com/cookiecutter/cookiecutter-django/pull/3044))\n\n## [2021-02-01]\n### Updated\n- Update pytz to 2021.1 ([#3035](https://github.com/cookiecutter/cookiecutter-django/pull/3035))\n- Update jinja2 to 2.11.3 ([#3033](https://github.com/cookiecutter/cookiecutter-django/pull/3033))\n- Bump peter-evans/create-pull-request from v3.7.0 to v3.8.0 ([#3034](https://github.com/cookiecutter/cookiecutter-django/pull/3034))\n\n## [2021-01-31]\n### Changed\n- Adding local celery instructions to developing-locally ([#3031](https://github.com/cookiecutter/cookiecutter-django/pull/3031))\n### Updated\n- Update django-crispy-forms to 1.11.0 ([#3032](https://github.com/cookiecutter/cookiecutter-django/pull/3032))\n\n## [2021-01-28]\n### Updated\n- Update pre-commit to 2.10.0 ([#3028](https://github.com/cookiecutter/cookiecutter-django/pull/3028))\n- Update django-anymail to 8.2 ([#3027](https://github.com/cookiecutter/cookiecutter-django/pull/3027))\n- Update tox to 3.21.3 ([#3026](https://github.com/cookiecutter/cookiecutter-django/pull/3026))\n\n## [2021-01-26]\n### Changed\n- Bump peter-evans/create-pull-request from v3.6.0 to v3.7.0 ([#3022](https://github.com/cookiecutter/cookiecutter-django/pull/3022))\n- Using SuccessMessageMixin to send success message to django template ([#3021](https://github.com/cookiecutter/cookiecutter-django/pull/3021))\n### Fixed\n- Update admin to ignore *_name User attributes ([#3018](https://github.com/cookiecutter/cookiecutter-django/pull/3018))\n### Updated\n- Update coverage to 5.4 ([#3024](https://github.com/cookiecutter/cookiecutter-django/pull/3024))\n- Update pytest to 6.2.2 ([#3020](https://github.com/cookiecutter/cookiecutter-django/pull/3020))\n- Update django-cors-headers to 3.7.0 ([#3019](https://github.com/cookiecutter/cookiecutter-django/pull/3019))\n\n## [2021-01-24]\n### Changed\n- Use defer for script tags (Fix #2922) ([#2927](https://github.com/cookiecutter/cookiecutter-django/pull/2927))\n- Made Traefik conf much easier to understand and improved redirect res… ([#2838](https://github.com/cookiecutter/cookiecutter-django/pull/2838))\n- Sentry Redis integration enabled by default in production. ([#2989](https://github.com/cookiecutter/cookiecutter-django/pull/2989))\n- Add test for UserUpdateView.form_valid() ([#2949](https://github.com/cookiecutter/cookiecutter-django/pull/2949))\n### Fixed\n- Omit first_name and last_name in User model ([#2998](https://github.com/cookiecutter/cookiecutter-django/pull/2998))\n### Updated\n- Update django-celery-beat to 2.2.0 ([#3009](https://github.com/cookiecutter/cookiecutter-django/pull/3009))\n- Update pyyaml to 5.4.1 ([#3011](https://github.com/cookiecutter/cookiecutter-django/pull/3011))\n- Update mypy to 0.800 ([#3013](https://github.com/cookiecutter/cookiecutter-django/pull/3013))\n- Update factory-boy to 3.2.0 ([#2986](https://github.com/cookiecutter/cookiecutter-django/pull/2986))\n- Update tox to 3.21.2 ([#3010](https://github.com/cookiecutter/cookiecutter-django/pull/3010))\n\n## [2021-01-22]\n### Changed\n- Use self.request.user instead of second query ([#3012](https://github.com/cookiecutter/cookiecutter-django/pull/3012))\n\n## [2021-01-14]\n### Updated\n- Update tox to 3.21.1 ([#3006](https://github.com/cookiecutter/cookiecutter-django/pull/3006))\n\n## [2021-01-10]\n### Updated\n- Update pylint-django to 2.4.2 ([#3003](https://github.com/cookiecutter/cookiecutter-django/pull/3003))\n- Update tox to 3.21.0 ([#3002](https://github.com/cookiecutter/cookiecutter-django/pull/3002))\n\n## [2021-01-08]\n### Changed\n- Upgrade Travis to Focal ([#2999](https://github.com/cookiecutter/cookiecutter-django/pull/2999))\n### Updated\n- Update pylint-django to 2.4.1 ([#3001](https://github.com/cookiecutter/cookiecutter-django/pull/3001))\n- Update sphinx to 3.4.3 ([#3000](https://github.com/cookiecutter/cookiecutter-django/pull/3000))\n- Update pylint-django to 2.4.0 ([#2996](https://github.com/cookiecutter/cookiecutter-django/pull/2996))\n\n## [2021-01-04]\n### Updated\n- Update isort to 5.7.0 ([#2988](https://github.com/cookiecutter/cookiecutter-django/pull/2988))\n- Update uvicorn to 0.13.3 ([#2987](https://github.com/cookiecutter/cookiecutter-django/pull/2987))\n- Auto-update pre-commit hooks ([#2990](https://github.com/cookiecutter/cookiecutter-django/pull/2990))\n- Update sphinx to 3.4.2 ([#2995](https://github.com/cookiecutter/cookiecutter-django/pull/2995))\n- Update pillow to 8.1.0 ([#2993](https://github.com/cookiecutter/cookiecutter-django/pull/2993))\n\n## [2020-12-29]\n### Updated\n- Update pygithub to 1.54.1 ([#2982](https://github.com/cookiecutter/cookiecutter-django/pull/2982))\n- Update django-storages to 1.11.1 ([#2981](https://github.com/cookiecutter/cookiecutter-django/pull/2981))\n\n## [2020-12-26]\n### Updated\n- Update sphinx to 3.4.1 ([#2985](https://github.com/cookiecutter/cookiecutter-django/pull/2985))\n- Update pytz to 2020.5 ([#2984](https://github.com/cookiecutter/cookiecutter-django/pull/2984))\n\n## [2020-12-23]\n### Changed\n- Bump peter-evans/create-pull-request from v3.5.2 to v3.6.0 ([#2980](https://github.com/cookiecutter/cookiecutter-django/pull/2980))\n### Updated\n- Update flower to 0.9.7 ([#2979](https://github.com/cookiecutter/cookiecutter-django/pull/2979))\n- Update sphinx to 3.4.0 ([#2978](https://github.com/cookiecutter/cookiecutter-django/pull/2978))\n- Update coverage to 5.3.1 ([#2977](https://github.com/cookiecutter/cookiecutter-django/pull/2977))\n- Update uvicorn to 0.13.2 ([#2976](https://github.com/cookiecutter/cookiecutter-django/pull/2976))\n\n## [2020-12-18]\n### Changed\n- Bump stefanzweifel/git-auto-commit-action from v4.7.2 to v4.8.0 ([#2972](https://github.com/cookiecutter/cookiecutter-django/pull/2972))\n### Updated\n- Update django-storages to 1.11 ([#2973](https://github.com/cookiecutter/cookiecutter-django/pull/2973))\n- Update pytest to 6.2.1 ([#2971](https://github.com/cookiecutter/cookiecutter-django/pull/2971))\n- Auto-update pre-commit hooks ([#2970](https://github.com/cookiecutter/cookiecutter-django/pull/2970))\n\n## [2020-12-14]\n### Updated\n- Update pytest to 6.2.0 ([#2968](https://github.com/cookiecutter/cookiecutter-django/pull/2968))\n- Update django-cors-headers to 3.6.0 ([#2967](https://github.com/cookiecutter/cookiecutter-django/pull/2967))\n- Update uvicorn to 0.13.1 ([#2966](https://github.com/cookiecutter/cookiecutter-django/pull/2966))\n\n## [2020-12-10]\n### Changed\n- Hot-reload support to celery ([#2554](https://github.com/cookiecutter/cookiecutter-django/pull/2554))\n### Updated\n- Update uvicorn to 0.13.0 ([#2962](https://github.com/cookiecutter/cookiecutter-django/pull/2962))\n- Update sentry-sdk to 0.19.5 ([#2965](https://github.com/cookiecutter/cookiecutter-django/pull/2965))\n\n## [2020-12-09]\n### Changed\n- Bump peter-evans/create-pull-request from v3.5.1 to v3.5.2 ([#2964](https://github.com/cookiecutter/cookiecutter-django/pull/2964))\n\n## [2020-12-08]\n### Updated\n- Update pre-commit to 2.9.3 ([#2961](https://github.com/cookiecutter/cookiecutter-django/pull/2961))\n\n## [2020-12-04]\n### Updated\n- Update django-debug-toolbar to 3.2 ([#2959](https://github.com/cookiecutter/cookiecutter-django/pull/2959))\n\n## [2020-12-02]\n### Updated\n- Update django-model-utils to 4.1.1 ([#2957](https://github.com/cookiecutter/cookiecutter-django/pull/2957))\n- Update pygithub to 1.54 ([#2958](https://github.com/cookiecutter/cookiecutter-django/pull/2958))\n\n## [2020-11-26]\n### Updated\n- Update django-extensions to 3.1.0 ([#2947](https://github.com/cookiecutter/cookiecutter-django/pull/2947))\n- Update pre-commit to 2.9.2 ([#2948](https://github.com/cookiecutter/cookiecutter-django/pull/2948))\n- Update django-allauth to 0.44.0 ([#2945](https://github.com/cookiecutter/cookiecutter-django/pull/2945))\n\n## [2020-11-25]\n### Changed\n- Bump peter-evans/create-pull-request from v3.5.0 to v3.5.1 ([#2944](https://github.com/cookiecutter/cookiecutter-django/pull/2944))\n\n## [2020-11-23]\n### Updated\n- Update uvicorn to 0.12.3 ([#2943](https://github.com/cookiecutter/cookiecutter-django/pull/2943))\n- Update pre-commit to 2.9.0 ([#2942](https://github.com/cookiecutter/cookiecutter-django/pull/2942))\n\n## [2020-11-21]\n### Changed\n- Fix after uvicorn 0.12.0 - Ship extra dependencies ([#2939](https://github.com/cookiecutter/cookiecutter-django/pull/2939))\n\n## [2020-11-20]\n### Updated\n- Update sentry-sdk to 0.19.4 ([#2938](https://github.com/cookiecutter/cookiecutter-django/pull/2938))\n\n## [2020-11-19]\n### Updated\n- Update django-crispy-forms to 1.10.0 ([#2937](https://github.com/cookiecutter/cookiecutter-django/pull/2937))\n\n## [2020-11-17]\n### Changed\n- Bump peter-evans/create-pull-request from v2 to v3.5.0 ([#2936](https://github.com/cookiecutter/cookiecutter-django/pull/2936))\n\n## [2020-11-15]\n### Changed\n- Fix formatting in docs ([#2935](https://github.com/cookiecutter/cookiecutter-django/pull/2935))\n\n## [2020-11-13]\n### Changed\n- Upgrade factory-boy to 3.1.0 ([#2932](https://github.com/cookiecutter/cookiecutter-django/pull/2932))\n### Updated\n- Update sentry-sdk to 0.19.3 ([#2933](https://github.com/cookiecutter/cookiecutter-django/pull/2933))\n- Update sphinx to 3.3.1 ([#2934](https://github.com/cookiecutter/cookiecutter-django/pull/2934))\n\n## [2020-11-12]\n### Changed\n- Migrate CI to Github Actions ([#2931](https://github.com/cookiecutter/cookiecutter-django/pull/2931))\n\n## [2020-11-06]\n### Updated\n- Update djangorestframework to 3.12.2 ([#2930](https://github.com/cookiecutter/cookiecutter-django/pull/2930))\n\n## [2020-11-04]\n### Changed\n- Fix docs service and add RTD support ([#2920](https://github.com/cookiecutter/cookiecutter-django/pull/2920))\n- Bump stefanzweifel/git-auto-commit-action from v4.6.0 to v4.7.2 ([#2914](https://github.com/cookiecutter/cookiecutter-django/pull/2914))\n### Updated\n- Auto-update pre-commit hooks ([#2908](https://github.com/cookiecutter/cookiecutter-django/pull/2908))\n- Update mypy to 0.790 ([#2886](https://github.com/cookiecutter/cookiecutter-django/pull/2886))\n- Update django-stubs to 1.7.0 ([#2916](https://github.com/cookiecutter/cookiecutter-django/pull/2916))\n\n## [2020-11-03]\n### Updated\n- Update sentry-sdk to 0.19.2 ([#2926](https://github.com/cookiecutter/cookiecutter-django/pull/2926))\n- Update sphinx to 3.3.0 ([#2925](https://github.com/cookiecutter/cookiecutter-django/pull/2925))\n- Update django to 3.0.11 ([#2924](https://github.com/cookiecutter/cookiecutter-django/pull/2924))\n- Update pytz to 2020.4 ([#2923](https://github.com/cookiecutter/cookiecutter-django/pull/2923))\n- Update pre-commit to 2.8.2 ([#2919](https://github.com/cookiecutter/cookiecutter-django/pull/2919))\n- Update pytest to 6.1.2 ([#2917](https://github.com/cookiecutter/cookiecutter-django/pull/2917))\n- Update sh to 1.14.1 ([#2912](https://github.com/cookiecutter/cookiecutter-django/pull/2912))\n- Update pytest-django to 4.1.0 ([#2911](https://github.com/cookiecutter/cookiecutter-django/pull/2911))\n- Update pillow to 8.0.1 ([#2910](https://github.com/cookiecutter/cookiecutter-django/pull/2910))\n- Update django-celery-beat to 2.1.0 ([#2907](https://github.com/cookiecutter/cookiecutter-django/pull/2907))\n- Update uvicorn to 0.12.2 ([#2906](https://github.com/cookiecutter/cookiecutter-django/pull/2906))\n\n## [2020-10-19]\n### Updated\n- Update sentry-sdk to 0.19.1 ([#2905](https://github.com/cookiecutter/cookiecutter-django/pull/2905))\n\n## [2020-10-17]\n### Updated\n- Update django-allauth to 0.43.0 ([#2901](https://github.com/cookiecutter/cookiecutter-django/pull/2901))\n- Update pytest-django to 4.0.0 ([#2903](https://github.com/cookiecutter/cookiecutter-django/pull/2903))\n\n## [2020-10-15]\n### Updated\n- Update pillow to 8.0.0 ([#2898](https://github.com/cookiecutter/cookiecutter-django/pull/2898))\n\n## [2020-10-14]\n### Updated\n- Auto-update pre-commit hooks ([#2897](https://github.com/cookiecutter/cookiecutter-django/pull/2897))\n- Update sentry-sdk to 0.19.0 ([#2896](https://github.com/cookiecutter/cookiecutter-django/pull/2896))\n\n## [2020-10-13]\n### Updated\n- Update isort to 5.6.4 ([#2895](https://github.com/cookiecutter/cookiecutter-django/pull/2895))\n\n## [2020-10-12]\n### Changed\n- Bump stefanzweifel/git-auto-commit-action from v4.5.1 to v4.6.0 ([#2893](https://github.com/cookiecutter/cookiecutter-django/pull/2893))\n### Updated\n- Auto-update pre-commit hooks ([#2892](https://github.com/cookiecutter/cookiecutter-django/pull/2892))\n\n## [2020-10-11]\n### Updated\n- Auto-update pre-commit hooks ([#2890](https://github.com/cookiecutter/cookiecutter-django/pull/2890))\n- Update isort to 5.6.3 ([#2891](https://github.com/cookiecutter/cookiecutter-django/pull/2891))\n- Update django-anymail to 8.1 ([#2887](https://github.com/cookiecutter/cookiecutter-django/pull/2887))\n- Update tox to 3.20.1 ([#2885](https://github.com/cookiecutter/cookiecutter-django/pull/2885))\n\n## [2020-10-09]\n### Updated\n- Auto-update pre-commit hooks ([#2884](https://github.com/cookiecutter/cookiecutter-django/pull/2884))\n- Update isort to 5.6.1 ([#2883](https://github.com/cookiecutter/cookiecutter-django/pull/2883))\n\n## [2020-10-08]\n### Changed\n- Add dedicated websockets package ([#2881](https://github.com/cookiecutter/cookiecutter-django/pull/2881))\n### Updated\n- Update isort to 5.6.0 ([#2882](https://github.com/cookiecutter/cookiecutter-django/pull/2882))\n\n## [2020-10-04]\n### Updated\n- Update pytest to 6.1.1 ([#2880](https://github.com/cookiecutter/cookiecutter-django/pull/2880))\n- Update mypy and django-stubs ([#2874](https://github.com/cookiecutter/cookiecutter-django/pull/2874))\n- Auto-update pre-commit hooks ([#2876](https://github.com/cookiecutter/cookiecutter-django/pull/2876))\n- Update flake8 to 3.8.4 ([#2877](https://github.com/cookiecutter/cookiecutter-django/pull/2877))\n\n## [2020-10-01]\n### Changed\n- Bump actions/setup-python from v2.1.2 to v2.1.3 ([#2869](https://github.com/cookiecutter/cookiecutter-django/pull/2869))\n### Updated\n- Update ipdb to 0.13.4 ([#2873](https://github.com/cookiecutter/cookiecutter-django/pull/2873))\n- Auto-update pre-commit hooks ([#2867](https://github.com/cookiecutter/cookiecutter-django/pull/2867))\n- Update uvicorn to 0.12.1 ([#2866](https://github.com/cookiecutter/cookiecutter-django/pull/2866))\n- Update isort to 5.5.4 ([#2864](https://github.com/cookiecutter/cookiecutter-django/pull/2864))\n- Update sentry-sdk to 0.18.0 ([#2863](https://github.com/cookiecutter/cookiecutter-django/pull/2863))\n- Update djangorestframework to 3.12.1 ([#2862](https://github.com/cookiecutter/cookiecutter-django/pull/2862))\n- Update pytest to 6.1.0 ([#2859](https://github.com/cookiecutter/cookiecutter-django/pull/2859))\n- Update django-debug-toolbar to 3.1.1 ([#2855](https://github.com/cookiecutter/cookiecutter-django/pull/2855))\n\n## [2020-09-23]\n### Updated\n- Update sentry-sdk to 0.17.7 ([#2847](https://github.com/cookiecutter/cookiecutter-django/pull/2847))\n- Update django-debug-toolbar to 3.1 ([#2846](https://github.com/cookiecutter/cookiecutter-django/pull/2846))\n\n## [2020-09-21]\n### Changed\n- Adding GitHub-Action CI Option ([#2837](https://github.com/cookiecutter/cookiecutter-django/pull/2837))\n### Updated\n- Update django-debug-toolbar to 3.0 ([#2842](https://github.com/cookiecutter/cookiecutter-django/pull/2842))\n- Auto-update pre-commit hooks ([#2843](https://github.com/cookiecutter/cookiecutter-django/pull/2843))\n- Update isort to 5.5.3 ([#2844](https://github.com/cookiecutter/cookiecutter-django/pull/2844))\n\n## [2020-09-18]\n### Updated\n- Update django-extensions to 3.0.9 ([#2839](https://github.com/cookiecutter/cookiecutter-django/pull/2839))\n\n## [2020-09-16]\n### Updated\n- Update sentry-sdk to 0.17.6 ([#2833](https://github.com/cookiecutter/cookiecutter-django/pull/2833))\n- Update pytest-django to 3.10.0 ([#2832](https://github.com/cookiecutter/cookiecutter-django/pull/2832))\n\n## [2020-09-14]\n### Fixed\n- Downgrade Celery to 4.4.6 ([#2829](https://github.com/cookiecutter/cookiecutter-django/pull/2829))\n### Updated\n- Update sentry-sdk to 0.17.5 ([#2828](https://github.com/cookiecutter/cookiecutter-django/pull/2828))\n- Update coverage to 5.3 ([#2826](https://github.com/cookiecutter/cookiecutter-django/pull/2826))\n- Update django-storages to 1.10.1 ([#2825](https://github.com/cookiecutter/cookiecutter-django/pull/2825))\n\n## [2020-09-12]\n### Updated\n- Updating Traefik version from 2.0 to 2.2.11 ([#2814](https://github.com/cookiecutter/cookiecutter-django/pull/2814))\n- Update pytest to 6.0.2 ([#2819](https://github.com/cookiecutter/cookiecutter-django/pull/2819))\n- Update django-anymail to 8.0 ([#2818](https://github.com/cookiecutter/cookiecutter-django/pull/2818))\n\n## [2020-09-11]\n### Updated\n- Auto-update pre-commit hooks ([#2809](https://github.com/cookiecutter/cookiecutter-django/pull/2809))\n\n## [2020-09-10]\n### Updated\n- Update isort to 5.5.2 ([#2807](https://github.com/cookiecutter/cookiecutter-django/pull/2807))\n- Update sentry-sdk to 0.17.4 ([#2805](https://github.com/cookiecutter/cookiecutter-django/pull/2805))\n\n## [2020-09-09]\n### Changed\n- Update actions/setup-python requirement to v2.1.2 ([#2804](https://github.com/cookiecutter/cookiecutter-django/pull/2804))\n- Clean up nested venv files from `.gitignore` ([#2800](https://github.com/cookiecutter/cookiecutter-django/pull/2800))\n\n## [2020-09-08]\n### Changed\n- Traeffik and Django dockerfile changes ([#2801](https://github.com/cookiecutter/cookiecutter-django/pull/2801))\n\n## [2020-09-07]\n### Changed\n- Add :z/:Z to mounted volumes in {local,production}.yml ([#2663](https://github.com/cookiecutter/cookiecutter-django/pull/2663))\n- Remove --no-binary option for psycopg2 ([#2798](https://github.com/cookiecutter/cookiecutter-django/pull/2798))\n- Updated Gitlab CI to use Python 3.8 instead of Python 3.7 ([#2794](https://github.com/cookiecutter/cookiecutter-django/pull/2794))\n### Fixed\n- Fix options for sphinx-autobuild in docs Makefile ([#2799](https://github.com/cookiecutter/cookiecutter-django/pull/2799))\n### Updated\n- Update psycopg2-binary to 2.8.6 ([#2797](https://github.com/cookiecutter/cookiecutter-django/pull/2797))\n\n## [2020-09-05]\n### Updated\n- Auto-update pre-commit hooks ([#2793](https://github.com/cookiecutter/cookiecutter-django/pull/2793))\n\n## [2020-09-04]\n### Updated\n- Update django-extensions to 3.0.8 ([#2792](https://github.com/cookiecutter/cookiecutter-django/pull/2792))\n- Update isort to 5.5.1 ([#2791](https://github.com/cookiecutter/cookiecutter-django/pull/2791))\n- Auto-update pre-commit hooks ([#2790](https://github.com/cookiecutter/cookiecutter-django/pull/2790))\n- Update isort to 5.5.0 ([#2789](https://github.com/cookiecutter/cookiecutter-django/pull/2789))\n\n## [2020-09-02]\n### Changed\n- Add environment and traces_sample_rate keyword to sentry_sdk.init ([#2777](https://github.com/cookiecutter/cookiecutter-django/pull/2777))\n### Updated\n- Update sentry-sdk to 0.17.3 ([#2788](https://github.com/cookiecutter/cookiecutter-django/pull/2788))\n- Update django-extensions to 3.0.7 ([#2787](https://github.com/cookiecutter/cookiecutter-django/pull/2787))\n\n## [2020-09-01]\n### Changed\n- Exclude venv directory and update document link ([#2780](https://github.com/cookiecutter/cookiecutter-django/pull/2780))\n### Updated\n- Update tox to 3.20.0 ([#2786](https://github.com/cookiecutter/cookiecutter-django/pull/2786))\n- Update django-storages to 1.10 ([#2781](https://github.com/cookiecutter/cookiecutter-django/pull/2781))\n- Update sentry-sdk to 0.17.2 ([#2784](https://github.com/cookiecutter/cookiecutter-django/pull/2784))\n- Update django to 3.0.10 ([#2785](https://github.com/cookiecutter/cookiecutter-django/pull/2785))\n- Update sphinx-autobuild to 2020.9.1 ([#2782](https://github.com/cookiecutter/cookiecutter-django/pull/2782))\n- Update django-extensions to 3.0.6 ([#2783](https://github.com/cookiecutter/cookiecutter-django/pull/2783))\n\n## [2020-08-31]\n### Updated\n- Update sh to 1.14.0 ([#2779](https://github.com/cookiecutter/cookiecutter-django/pull/2779))\n- Update sentry-sdk to 0.17.1 ([#2778](https://github.com/cookiecutter/cookiecutter-django/pull/2778))\n\n## [2020-04-13]\n### Changed\n- Updated to Python 3.8 (@codnee)\n- Moved coverage config in setup.cfg (@danihodovic)\n\n## [2020-04-08]\n### Fixed\n- Internal IPs for debug toolbar (@dudanogueira)\n\n## [2020-04-04]\n### Fixed\n- Added compress command with Django compressor (@gwiskur)\n\n## [2020-03-23]\n### Changed\n- Updated project to Django 3.0\n\n## [2020-03-17]\n### Changed\n- Handle paths using Pathlib (@jules-ch)\n\n### Fixed\n- Pre-commit hook regex (@demestav)\n\n## [2020-03-16]\n### Added\n- Support for all Anymail providers (@Andrew-Chen-Wang)\n### Fixed\n- Django compressor setup (@jameswilliams1)\n\n## [2020-01-23]\n### Changed\n- Fix UserFactory to set the password if provided (@BoPeng)\n- Update documentation files with latest Sphinx (@howiezhao)\n\n## [2020-01-12]\n### Changed\n- Fix mypy setup and added django-stubs (@danifus)\n- Add Gitlab CI as option (@ikhomutov)\n\n## [2020-01-11]\n### Changed\n- Speed up & reduce size for production Django image (@maxp)\n- Bumped runtime version for Heroku (@Isaac12x)\n- Added Debian 10 (Buster) OS dependencies (@ddiazpinto)\n- Update Traefik to v2 (@blaxpy)\n- Switched Docker images from Alpine based to Debian based (@trungdong)\n\n## [2019-10-06]\n### Changed\n- Default Python version is now 3.7 (@nicolas471)\n\n## [2019-10-04]\n### Fixed\n- Fix static files handling on GCP (@caioariede)\n\n## [2019-10-03]\n### Fixed\n- Fix incompatible combination between Whitenoise and no cloud provider (@caioariede)\n\n## [2019-07-09]\n### Fixed\n- Always use test settings in pytest (@danihodovic)\n- Remove gunicorn from `INSTALLED_APPS` (@danihodovic)\n- Remove `EMAIL_HOST` and `EMAIL_PORT` with locmem backend (@danihodovic)\n\n### Added\n- Add `EMAIL_TIMEOUT` (@danihodovic)\n\n## [2019-06-22]\n### Fixed\n- Remove redundant template debug setting (@danihodovic)\n\n## [2019-06-19]\n### Fixed\n- Fix removal carriage returns in docker scripts (@timclaessens)\n\n## [2019-06-15]\n### Fixed\n- Issue with Pycharm setup for running things in Docker compose (@foarsitter)\n\n## [2019-06-06]\n### Changed\n- Update generated Travis config (@browniebroke)\n\n## [2019-06-03]\n### Added\n- Installed `django-celery-beat` to keep scheduled tasks in DB (@keyvanm)\n\n## [2019-05-28]\n### Changed\n- Use GCP acronym rather than inconsistent GCE/GCS (@tanoabeleyra)\n\n## [2019-05-27]\n### Changed\n- Made cloud provider optional (@tanoabeleyra)\n- Updated to Django 2.2.1 (@browniebroke)\n\n### Fixed\n- Celery worker-related setting names (@browniebroke)\n\n## [2019-05-18]\n### Removed\n- Remove the user list view (@browniebroke)\n\n### Fixed\n- Static storage default ACL (@browniebroke)\n\n## [2019-05-17]\n### Fixed\n- Added `LocaleMiddleware` to the list of middlewares (@tanoabeleyra)\n- Added `LOCALE_PATH` to settings (@tanoabeleyra)\n\n## [2019-05-16]\n### Changed\n- Users app to have a translated verbose name (@tanoabeleyra)\n- Logging configuration for local (@browniebroke)\n\n## [2019-05-08]\n### Changed\n- Upgraded to Django 2.1 (@browniebroke)\n\n## [2019-04-07]\n### Added\n- Support for Google Cloud Storage (@ahhda)\n\n## [2019-04-03]\n### Added\n- Command to backup Db to AWS S3 (@foarsitter)\n\n## [2019-03-25]\n### Added\n- Node image to run Gulp with Docker (@browniebroke)\n\n## [2019-03-19]\n### Changed\n- Replaced Caddy with Traefik (@demestav)\n\n## [2019-03-11]\n### Changed\n- Sentry integration from Raven to Sentry-SDK (@gfabricio)\n- Made Redis config conditional on Celery locally (@demestav)\n\n## [2019-03-11]\n### Added\n- Automatic migrations on Heroku (@yunti)\n\n## [2019-03-06]\n### Fixed\n- Missing script tag in Travis config (@btknu)\n\n## [2019-03-02]\n### Changed\n- Celery eager setting in local setting with Docker (@keithjeb)\n\n## [2019-03-01]\n### Updated\n- All NPM dependencies (@takkaria)\n\n## [2018-11-13]\n### Changed\n- Security settings in Dev (@carlmjohnson)\n\n## [2018-11-20]\n### Fixed\n- Passing the CSRF header from the reverse proxy to Django server for DRF (@hpbruna)\n\n## [2018-11-12]\n### Fixed\n- Initialisation of Celery app (@glasslion)\n\n## [2018-10-24]\n### Fixed\n- Persisting of iPython history between sessions (@davitovmasyan)\n\n### Added\n- Postgres 10.5 option (@jleclanche)\n\n## [2018-09-18]\n### Added\n- Included `mypy` in dependencies and run it in tests (@apirobot)\n\n## [2018-09-18]\n### Fixed\n- Avoid `$` in environment variables to workaround a bug from django-environ (@browniebroke)\n\n## [2018-09-16]\n### Fixed\n- Bug in ordering of Middleware for production config (@ChrisPappalardo)\n\n## [2018-09-12]\n### Fixed\n- URLs for Static and Media for S3 buckets in regions other than N. Virginia (@umrashrf)\n\n## [2018-09-09]\n### Changed\n- Name of static and media storage classes (@sfdye)\n\n## [2018-09-01]\n### Changed\n- Make static and media storage fully-fledged classes (@erfaan)\n\n## [2018-08-28]\n### Fixed\n- Running tests in docker test script (@apirobot)\n\n## [2018-07-23]\n### Changed\n- Test commands to use pytest (@jcass77)\n\n### Removed\n- Some hacks leftovers from Bootstrap v4 beta in `project.js` (@hendrikschneider)\n\n## [2018-07-12]\n### Changed\n- Upgraded to Bootstrap 4.1.1 (@mostaszewski)\n\n## [2018-06-25]\n### Added\n- Flower integration with Docker (@webyneter)\n\n## [2018-06-25]\n### Changed\n- Rewrite user app test to use a pytest style (@webyneter)\n\n## [2018-06-21]\n### Added\n- Extend & update Celery config (@webyneter & @apirobot)\n\n## [2018-05-25]\n### Fixed\n- Build issues due to incompatibility between libressl & openssl (@SassanoM)\n\n## [2018-05-21]\n### Changed\n- Updated Caddy to 0.11 and pin its version (@webyneter)\n\n## [2018-05-14]\n### Changed\n- Replace `awesome-slugify` by `python-slugify` (@hongquan)\n- Migrate to Django 2.0+ URL style (@saschalalala)\n\n## [2018-05-05]\n### Fixed\n- Postgres backup & restore commands (@webyneter)\n\n## [2018-04-10]\n### Changed\n- Simplify configuration (@danidee10)\n\n## [2018-04-08]\n### Added\n- Adopt Black code style (@pydanny)\n\n## [2018-03-27]\n### Fixed\n- Simplified extra Celery config generated when opted out (@webyneter)\n\n## [2018-03-21]\n### Removed\n- Remove Opbeat support (@sfdye)\n\n## [2018-03-16]\n### Fixed\n- Install `psycopg2-binary` when using Docker locally (@browniebroke)\n\n## [2018-03-14]\n### Fixed\n- Fixed and improved Postgres backup & restore scripts (@webyneter)\n\n## [2018-03-10]\n### Changed\n- Simplify Mailgun setting (@browniebroke)\n\n## [2018-03-06]\n### Changed\n- Convert string formatting to f-strings (@sfdye)\n\n## [2018-03-01]\n### Changed\n- Celery to use JSON serialization by default (@adammsteele)\n- Use Docker version from Travis to run tests (@browniebroke)\n\n## [2018-02-16]\n### Changed\n- Upgraded to Django 2.0 (@epicwhale)\n\n## [2018-01-15]\n### Changed\n- Removed Elastic Beanstalk support (@pydanny)\n\n## [2017-12-28]\n### Changed\n- Upgraded to Django 1.11 (@pydanny)\n\n## [2017-10-08]\n### Changed\n- Elastic Beanstalk: Added --noinput to migrate command (@MightySCollins )\n\n## [2017-10-07]\n### Added\n- Finished first pass at Elastic Beanstalk docs (@pydanny & @audreyr)\n### Deleted\n- Removed Heroku instant deploy button (@pydanny)\n\n\n##[2016-09-29]\n### Added\n- Added default `AUTH_PASSWORD_VALIDATORS` configuration, generated by django 1.10 startproject. See [Password Validation docs](https://docs.djangoproject.com/en/1.10/topics/auth/passwords/#module-django.contrib.auth.password_validation\") (@luzfcb)\n- Rename `MIDDLEWARE_CLASSES` to `MIDDLEWARE` to enable support to [new style middleware](https://github.com/django/deps/blob/master/final/0005-improved-middleware.rst) introduced in Django 1.10 (@luzfcb)\n- New setting `MAILGUN_SENDER_DOMAIN` to allow sending mail from any domain other than those registered with mailgun (@jangeador)\n- add `urlpatterns` configuration to django-debug-toolbar, because the automatic configuration of `urlpatterns` was removed from django-debug-toolbar (@luzfcb)\n- Added Temporary workaround on `requirements/local.txt` to fix django-debug-toolbar issue: https://github.com/cookiecutter/cookiecutter-django/issues/827 (@luzfcb)\n\n### Changed\n- Upgrade to Django 1.10.1 (@luzfcb)\n- Upgrade django-model-utils to 2.6, django-redis to 4.5.0, redis to 2.10.5, Sphinx to 1.4.6, pytest-django to 3.0.0, django-anymail to 0.5, raven to 5.27.1, whitenoise to 3.2.2 (@luzfcb)\n- Upgrade to Bootstrap 4 Alpha 4, jQuery to 3.1.1, tether.js to 1.3.7 (@luzfcb)\n- Update `manage.py` to use same code of `manage.py` from Django 1.10 (@luzfcb)\n- Sync `sites` app migrations with django 1.10, and fix aditional migrations to `sites` and `user` app (@luzfcb)\nd changed 'admin' url on `config/urls.py`, to stay the same as generated by django 1.10 (@luzfcb)\n- Make test_docker.sh tests pass by passing new password auth rules (@ssteinerx)\n\n### Removed\n- Removed django-autoslug because not support django 1.10 at this date (@luzfcb)\n\n\n##[2016-09-10]\n### Changed\n- Use app registry instead of INSTALLED_APPS to discover celery tasks (@dhepper)\n- PEP8 imports fix (@aleprovencio)\n\n### Removed\n- Removed django-floppyforms (@pydanny)\n\n##[2016-09-08]\n### Removed\n- Webpack support, see #774 (@ssteinerx)\n\n##[2016-08-10]\n## Added\n- PostgreSQL versions are now selectable, instead of defaulting to 9.5; the minimum version is 9.2, which is supported by [Heroku](https://devcenter.heroku.com/articles/heroku-postgresql#version-support-and-legacy-infrastructure) and Django (@burhan)\n- Fixed minor issue in the README.rst (@burhan)\n\n##[2016-08-03]\n## Changed\n- Upgrade to Bootstrap 4 Alpha 3 and its dependencies, including jQuery (@audreyr)\n\n##[2016-06-25]\n## Changed\n- use `https` instead `ssh` to clone [cookiecutter-webpack](https://github.com/hzdg/cookiecutter-webpack) if `Webpack` is selected as `JS Task Runner` - fix issue #647 (@luzfcb and @resakse)\n\n##[2016-06-24]\n## Added\n- Settings file for running tests faster (@audreyr)\n- Add GPLv3 licence support (@cgaspoz)\n\n## Changed\n- Makes the database backups compressed. restores compressed backups (@jangeador)\n- Review and edit django-allauth templates (@kappataumu)\n\n##[2016-06-19]\n## Added\n- Webpack as an option (@goldhand)\n\n##[2016-06-17]\n## Added\n- django-compressor support (@andresgz)\n- Debian Jessie OS Requirements (@ddiazpinto)\n\n##[2016-06-14]\n### Changed\n- Move Docker backups to their own section (@pydanny)\n\n##[2016-06-13]\n### Changed\n- Use latest redis image in Docker (@pydanny)\n- Documentation cleanup and corrections (@audreyr)\n\n##[2016-06-12]\n### Changed\n- Documentation cleanup and corrections (@kappataumu)\n\n##[2016-06-11]\n### Changed\n- Enhancements to the developing locally docs (@antoniablair)\n\n##[2016-06-06]\n### Changed\n- Pin Bootstrap CSS and JS to v4.0.0-alpha.2, use minified versions\n\n##[2016-06-05]\n### Added\n- Configurable admin for users (@pydanny, @jayfk, @dezoito)\n\n##[2016-06-04]\n### Added\n- Let's Encrypt automation and instruction (@mjsisley and @chrisdev)\n\n##[2016-06-03]\n### Added\n- Documentation for debugging with Docker (@mjsisley)\n- Apache 2 License option in `cookiecutter.json` (@dot2dotseurat)\n- Removed unnecessary version check from `pre_gen_project.py` (@suledev)\n- Add gulp alternative as a js task runner and fix navbar style issue (@viviangb and @xpostudio4)\n\n### Deleted\n- AngularJS (@pydanny)\n- django-secure (@xpostudio4)\n\n##[2016-06-02]\n### Added\n- Added better instructions for installing postgres on Mac OS X (@dot2dotseurat )\n\n##[2016-05-22]\n### Added\n- Added instructions for copying backups from docker to host (@phiberjenz)\n- Added mailhog docker container (@noisy)\n\n##[2016-05-15]\n### Added\n- Added GitLab continuous integration article to README.rst (@dezoito)\n\n## [2016-05-13]\n### Changed\n- Update version of pyflakes to 1.2.3, django-extensions to 1.6.7 and gunicorn to 19.5.0 (@luzfcb)\n- Update version of AngularJS to 1.5.5 (@luzfcb)\n\n### Removed\n- Remove Raven 404 catch middleware. Fix #367 (@pydanny)\n\n## [2016-05-09]\n### Changed\n- Improved mailhog usage documentation on `developing-locally.rst`  (@shireenrao)\n- Replaced all `readthedocs.org` referencies to point to the new domain `readthedocs.io` (@luzfcb)\n- Update version of pyflakes (@luzfcb)\n\n## [2016-05-08]\n### Changed\n- Updated whitenoise configuration to match changes in version 3.0 (@trungdong)\n\n## [2016-05-07]\n### Added\n- Added Ubuntu 16.04 dependencies on a new dependency file `requirements.apt.xenial` (@raonyguimaraes)\n\n### Changed\n- Small improvements in ``install_os_dependencies.sh`` support new dependency file (@raonyguimaraes)\n\n## [2016-05-06]\n### Changed\n- Update version of pyflakes (@pydanny)\n\n## [2016-05-03]\n### Changed\n- Update version of Django, django-extensions, django-mailgun (@luzfcb)\n\n### [2016-05-01]\n### Changed\n- Restored the Pycharm project configuration files, that was accidentally removed in [15f350f](https://github.com/cookiecutter/cookiecutter-django/commit/15f350f05e2b49b4bdff0bdaa2b2ff260606e0f6) (@luzfcb @Newton715)\n\n### [2016-04-30]\n### Changed\n- Small fixes to utility scripts (@scast)\n\n### [2016-04-26]\n### Added\n- Instructions on how to install PythonAnywhere. (@hjwp)\n\n### [2016-04-25]\n### Added\n- Check to confirm that the user has a modern version of Cookiecutter. (@pydanny)\n\n### Removed\n- Removed hitch per #529 (@pydanny)\n\n### [2016-04-20]\n### Changed\n- Default to today's date in cookiecutter.json. (@audreyr)\n- Change repo_name to project_slug for clarity. (@audreyr)\n- Transform project name to lowercase for slug. (@audreyr)\n\n### [2016-04-19]\n### Added\n- \"Got Questions?\" section in our README.rst. Yes, there is now a cookiecutter-django tag on Stack Overflow! (@pydanny)\n\n### Changed\n- Update usage instructions with new prompts, minor cleanup (@audreyr)\n\n### [2016-04-18]\n### Added\n- removing duplication of depends_on in docker-compose.yml (@noisy)\n\n### [2016-04-17]\n### Added\n- \"Built with Cookiecutter Django\" badge to generated project README (@audreyr)\n- New introductory article (@krzysztofzuraw)\n\n### Changed\n- Quote consistency, single quotes everywhere! (@blopker)\n\n### [2016-04-15]\n### Changed\n- Major project generation cleanup (@jayfk)\n\n### Removed\n- Deleting unnecessary .idea dir from MAIN directory (@noisy)\n\n### [2016-04-14]\n### Added\n- Added typecheck in .pylintrc to fix pylint-django gets \"no-member\" error (@solvire)\n\n### Changed\n- Downgrading python-dateutil to version 2.4.2 because pykwalify==1.5.0 (required by HitchTest) uses a [pinned version of python-dateutil](https://github.com/Grokzen/pykwalify/blob/1.5.0/setup.py#L31) (@noisy)\n- Update Pillow version to 3.2.0 (security fix) (@luzfcb)\n\n### [2016-04-12]\n### Changed\n- celeryworker and celerybeat missing the correct dockerfile (@jayfk)\n\n### [2016-04-08]\n### Changed\n- Move to named docker volumes (@jayfk)\n\n### [2016-04-07]\n### Changed\n- Pycharm Support (including debugging in Docker) @noisy\n- Set the correct License @epileptic-fish\n\n### [2016-03-23]\n### Changed\n- Fixed issue on LICENSE file generation (@romanosipenko)\n- In install_python_dependencies.sh file, Fixed wrong reference to python3 if use_python2 was set to y (@luzfcb @noisy)\n\n### [2016-03-16]\n### Changed\n- Set the correct postgres username in dev.yml (@calculuscowboy)\n\n## [2016-03-14]\n### Changed\n- Enforce `repo_name` as proper python module (@catherinedevlin)\n\n## [2016-03-08]\n### Changed\n- Docker configuration now uses docker-compose format v2 (@aeikenberry)\n- Make sure that STATIC_URL != MEDIA_URL (@cdvv7788)\n- fix minor typos in project README (@menzenski)\n- Updated docker docs (@jayfk)\n\n### Added\n- Added database controls for docker (@jayfk)\n\n\n## [2016-03-05]\n### Changed\n- Update version of Django, celery, django-test-plus (@luzfcb)\n- Update version of Hitch tests dependencies: jupyter_client (@luzfcb)\n- Update 'now' date in cookiecutter.json (@luzfcb)\n- Update the usage example in README (@luzfcb)\n\n## [2016-03-01]\n### Changed\n- Update version of Django, flake8, pyflakes, pytest, factory_boy, ipdb, Werkzeug, gevent (@luzfcb)\n- Update version of Hitch tests dependencies: click, hitchserve, hitchsystem, hitchtest, ipython, psutil, python-dateutil(@luzfcb)\n- Update Tether (JS) version to 1.2.0 (@luzfcb)\n\n## [2016-02-24]\n### Added\n- Beginning support for `py.test` (@pydanny)\n\n### Changed\n- Fixed missing div closing tag for \"container\" on user_list.html (@Eraldo)\n\n## [2016-02-18]\n### Changed\n- The status of the registration (open or closed) is now read from the project environment instead of hardcoded in the common settings file. (@Eraldo)\n- Renamed the adapter.py file to adapters.py to match the django naming convention. (@Eraldo)\n\n\n\n## [2016-02-15]\n### Changed\n- In `users` app adapter, fix `is_open_for_signup` missing parameter (@oryx2)\n- Fixes and improvements in Hitch tests , see [#485](https://github.com/cookiecutter/cookiecutter-django/pull/485) (@crdoconnor)\n\n\n## [2016-02-12]\n### Changed\n- Fixed typo (@yunti)\n\n## [2016-02-07]\n### Changed\n- In `users` app, use Django 1.9 `LoginRequiredMixin` instead of django-braces implementation (@yunti)\n- Update native OS libraries of Hitch Test, because [unixpackage](https://github.com/unixpackage/unixpackage) now supports multiple versions of same Linux distribution (@crdoconnor)\n- Update AngularJS version to 1.5.0 (@luzfcb)\n- Update version of wheel, Pillow, django_coverage_plugin (@luzfcb)\n- Update version of Hitch tests dependencies: decorator, hitchselenium, ipython, ptyprocess, selenium (@luzfcb)\n- Provided options for FOSS license choices, or for private efforts, no written license (@pydanny)\n\n## [2016-02-01]\n### Changed\n- Update version of Django and django-floppyforms (@luzfcb)\n- Update version of Hitch tests dependencies: hitchpython and selenium (@luzfcb)\n\n## [2016-01-30]\n### Changed\n- Update flake8 to 2.5.2 (@luzfcb)\n\n## [2016-01-29]\n### Changed\n- Update AngularJS version to 1.4.9 (@luzfcb)\n- Update jQuery version to 2.2.0 (@luzfcb)\n- Update 'now' date in cookiecutter.json (@luzfcb)\n- Update version of boto, celery, django_coverage_plugin, django-storages-redux, flake8, gevent, gunicorn, pep8, pytest, tox, Werkzeug (@luzfcb)\n- Update version of Hitch tests dependencies: colorama, decorator, hitchpostgres, hitchpython, hitchredis, hitchselenium, hitchserve, hitchsystem, hitchtest, ipython, patool, pickleshare, psutil, python-build, requests, selenium, tblib, traitlets (@luzfcb)\n\n\n## [2016-01-26]\n### Changed\n- Fixed NEW_RELIC_APP_NAME environment variable (@jayfk)\n\n## [2016-1-18]\n### Added\n- Added .dockerignore file (@bogdal)\n- Docker tests for travis (@jayfk)\n\n### Changed\n- Removed the $-sign from allowed chars to generate the secret key (@jayfk)\n\n## [2016-01-17]\n### Added\n- Adding a section on third party articles referencing `cookiecutter-django` (@mjheo)\n\n### Changed\n- Add celerybeat db to gitignore (@originell)\n\n## [2016-01-16]\n### Added\n- Adding an explanation for having `django.contrib.sites`. (@pydanny)\n\n\n## [2016-01-13]\n### Changed\n- Update setup.py version to 1.9.1 to match Django version. (@Collederas)\n- Require Wheel 0.26.0. Needed to install certain packages on CPython 3.5+ like Pillow and psycopg2 (@audreyr)\n\n## [2016-01-09]\n### Changed\n- Upgraded django-extensions to 1.6.1 as it fixes a [JSONField bug](https://github.com/django-extensions/django-extensions/blob/master/CHANGELOG.md#161) (@burhan)\n- Upgraded Pillow to version 3.1.0 ([upstream changelog](https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst#310-2016-01-04)) (@burhan)\n- Upgraded django to 1.9.1 to integrate various [bugfixes](https://docs.djangoproject.com/en/1.9/releases/1.9.1/) (@burhan)\n- Upgraded django-crispy-forms to 1.6 for [BS4 and django 1.9 compatibility fixes](https://github.com/maraujop/django-crispy-forms/blob/dev/CHANGELOG.md#160-201617) (@burhan)\n- Upgraded django-model-utils to 2.4, to enable [support for django 1.9](https://github.com/carljm/django-model-utils/blob/master/CHANGES.rst#24-2015-12-03) (@burhan)\n\n## [2016-01-08]\n### Changed\n- Fixed redis url on docker (@jayfk)\n- Fixed docker on windows (@burhan)\n\n## [2016-01-06]\n### Added\n- You can now enable or disable user registration using the ACCOUNT_ALLOW_REGISTRATION setting. (@ddiazpinto)\n\n### Changed\n- Use Postgres 9.5 on docker (@jayfk)\n\n## [2016-01-04]\n### Added\n- Add Tether.js because [is needed](http://v4-alpha.getbootstrap.com/components/tooltips/#overview) for proper positioning of Bootstrap tooltips (@EricZaporzan)\n\n### Changed\n- Minor fixes in the docker documentation (@jayfk)\n- Made @burhan a core committer (@pydanny)\n\n## [2015-12-30]\n### Changed\n- Fixed a bug where the navbar was not displayed correctly (@jvanbrug)\n\n## [2015-12-21]\n### Changed\n- Added sentry logger to celery config (@jayfk)\n\n## [2015-12-16]\n- Update preview 4xx error pages to accept `exception` argument (@theskumar)\n\n## [2015-12-15]\n### Changed\n- Fix celery worker app name in Procfile (@stepmr)\n\n## [2015-12-13]\n### Changed\n- Bumped Django to 1.9 (@areski)\n- Support opbeat logging with celery (@stepmr)\n- Update runtime.txt with PY2 support (@stepmr)\n\n## [2015-12-12]\n### Added\n- Celery worker to Heroku procfile (@stepmr)\n\n## [2015-12-11]\n### Changed\n- Fixed issue #436 - cookiecutter variable name was renamed from `celery_support` to `use_celery` in `tests/engine.py` (@luzfcb @otakucode)\n- Updated Heroku runtime.txt for python 3.5.1 (@yunti)\n\n## [2015-12-06]\n### Changed\n- Reorganization of contributors (@burhan)\n\n## [2015-12-01]\n### Changed\n- Update documentation to include the installation os dependencies before development requirements (@failsafe86)\n\n## [2015-11-29]\n### Changed\n- Update version of click and python-build (@luzfcb)\n\n## [2015-11-25]\n### Changed\n- Update version of psutil, ipython (@luzfcb)\n- Update version of gunicorn (@audreyr)\n- Remove debugging tools from non-generated part of cookiecutter-django, since those are personal prefs (@audreyr)\n- Update version of Django in setup.py (@luzfcb)\n\n## [2015-11-24]\n### Changed\n- Update version of Django, coverage and click (@luzfcb)\n- Fixed configuration for Celery in local.py. (@luzfcb @hackebrot)\n\n## [2015-11-23]\n### Changed\n- Update AngularJS version to 1.4.8 (@luzfcb)\n- Update version of cookiecutter, pytest, tox, whitenoise, django-test-plus, django_coverage_plugin, Werkzeug, hitchserve, tornado, unixpackage (@luzfcb)\n- Update 'now' date in cookiecutter.json (@luzfcb)\n- `sh` package version pinned to `1.11` (@luzfcb)\n\n## [2015-11-22]\n### Changed\n- Move div class unquote outside the django if tag (@jvanbrug)\n- Changed gevent to `1.1rc1` for python 3 users (@jondelmil / @jayfk)\n\n## [2015-11-20]\n### Changed\n- Using python 3.5 on Heroku/Travis (@bogdal)\n- Fixed typo in README (@tedmiston)\n\n## [2015-11-18]\n### Added\n- Mailhog as a replacement for Maildump (@keybits)\n\n### Removed\n- Maildump because it didn't support Python 3 (@keybits)\n\n## [2015-11-17]\n### Added\n- initial configuration to support opbeat (@burhan)\n\n### Removed\n- Took `*.pyc` out of .gitignore, because it's already covered by `*.py[cod]` (@audreyr)\n\n## [2015-11-16]\n### Changed\n- Cleanup of main README (@burhan)\n\n## [2015-11-15]\n### Added\n- Added `UserFactory` for users.User tests (@ad-m)\n\n## [2015-11-12]\n### Changed\n- Update version of django-allauth (@yunti)\n- Added a warning in README.rst: ```repo_name must be a valid Python module``` @cdvv7788\n\n### Removed\n- remove ```{% load url from future %}``` in templates - deprecated in django 1.9 (@yunti)\n\n## [2015-11-11]\n### Added\n- Added django_coverage_plugin to measure Django template coverage (@audreyr)\n\n## [2015-11-09]\n### Changed\n- Now using py.test for our test suite!! (@hackebrot)\n- Python version in travis.yml is now correct for the selected version of Django (@show0k)\n\n## [2015-11-08]\n### Changed\n- bump django-extensions version (@garrypolley)\n\n## [2015-11-07]\n### Added\n- newrelic support (@amjith)\n- DJANGO_SENTRY_DSN to env.example (@jayfk)\n\n### Changed\n- Made `post_gen_hook.set_secret_key()` only changes one CHANGEME!!! at a time. (@pydanny)\n- Fixed an error where celery couldn't load the sentry DSN from settings (@jayfk)\n- Renamed ADMIN_URL to DJANGO_ADMIN_URL in env.example (@ChrisPappalardo)\n\n## [2015-11-06]\n### Added\n- \\*tests\\* to `.coveragerc`, because including it is cheating! (@pydanny)\n- Binaryornot to cookiecutter-django's own tests because otherwise Python 3 blows up (@audreyr)\n\n### Changed\n- `.travis.yml` configuration to support Python 3.4 and 3.5 (@pydanny)\n- `.gitignore` configuration so py.test cache files don't show up in git status.\n\n## [2015-11-05]\n### Changed\n- Update version of django-extensions (@luzfcb)\n- Fix gevent requirement for Python 3 (@mcho421)\n\n## [2015-11-04]\n### Changed\n- Update version of Django, cookiecutter, celery, coverage, django-mailgun, django-redis, factory_boy, flake8, pytest and pytz (@luzfcb)\n- Update AngularJS version to 1.4.7 (@luzfcb)\n- Update 'now' date in cookiecutter.json (@luzfcb)\n\n## [2015-10-28]\n### Changed\n- Update deployment-on-heroku.rst for ADMIN_URL (@yunti)\n\n## [2015-10-27]\n### Added\n- Added sudo: true to the travis file (@MathijsHoogland)\n\n## [2015-10-25]\n### Added\n- Move current logging config into production.py since it's not useful locally anyway. Used only if not using Sentry. (@audreyr)\n- `setup.py` so we can list it on PyPI and therefore displayed on djangopackages.com as compatible with Python 3. (@pydanny)\n- Versioning and tagging policy (@pydanny)\n- Fixed flake8 issue (@pydanny)\n\n## [2015-10-24]\n### Changed\n- Update nav in base template to latest Bootstrap 4 version (@audreyr)\n- Replaced ADD with COPY in dockerfiles (@audreyr)\n- Simplified development dockerfile (@jayfk)\n- Moved the docker postgres volume on the development environment to it's own subfolder (@jayfk)\n- Renamed DJANGO_CACHE_URL to REDIS_URL (@jayfk / proposed by @pydanny)\n\n## [2015-10-22]\n### Removed\n- Remove unnecessary .gitkeep in static/images/ (@audreyr)\n\n## [2015-10-21]\n### Changed\n- Updated requirements (@theskumar)\n### Removed\n- editorconfig comment that was just a isort settings link (@pydanny)\n\n## [2015-10-19]\n### Changed\n- On Windows, don't install psycopg2 locally. Still install it in test/prod which are assumed to be Unix. (@audreyr)\n\n## [2015-10-15]\n### Changed\n- Made `post_gen_hook` function to change secret keys in files more generic (@pydanny)\n- Set cryptographically randomized value to `DJANGO_SECRET_KEY` in `env.example` (@pydanny)\n\n## [2015-10-14]\n### Added\n- Documention of project options (@audreyr)\n### Changed\n- Added clarification on building for local or production (@MathijsHoogland)\n- Whitespace correction in dev.yml (@MathijsHoogland)\n\n## [2015-10-13]\n### Changed\n- Requirements update (@theskumar)\n\n## [2015-10-11]\n### Changed\n- Fixed raven issue on development (#302) (@jazztpt)\n\n## [2015-10-05]\n### Changed\n- Update version of Django, Pillow, hitchselenium, psutil (@luzfcb)\n\n## [2015-10-04]\n### Changed\n- Remove stray closing tags and fix navbar margin in in base.html (@hairychris)\n- Docker docs to be functional and more understandable (@audreyr)\n\n## [2015-09-30]\n### Changed\n- Fixed Sentry logging with celery (@jayfk)\n- Added pep8 and pyflakes to requirements (@jayfk)\n- Fixed url() arguments in urls.py because String view arguments to url() is deprecated in django 1.9 (@siauPatrick)\n- Update version of cookiecutter, coverage, django-environ, django-extensions, hitchpython, hitchselenium, hitchserve, pytest, pytz, whitenoise (@luzfcb)\n- Update the usage example in README (@luzfcb)\n- Update 'now' date in cookiecutter.json (@luzfcb)\n\n## [2015-09-29]\n### Changed\n- Fix RST in Docker docs (@andor-pierdelacabeza)\n\n## [2015-09-27]\n### Added\n- Added advice on how to persist changes with boot2docker (@jayfk)\n\n###Changed\n- Removed duplicate from `CONTRIBUTORS.rst` (@jayfk)\n\n## [2015-09-26]\n### Added\n- Add .pylintrc and .pep8 (@kaidokert)\n\n### Changed\n- Move pep8 rules to setup.cfg (@audreyr)\n- Better pep8 rules for exclusion (@audreyr)\n- Document all linters (@audreyr)\n- Sass linting and improvements to alerts (@audreyr)\n\n## [2015-09-25]\n### Changed\n- django-mailgun requirement to 0.7.2 (@pydanny)\n- Remove commented-out flake8 ignore rule. (@audreyr)\n\n## [2015-09-24]\n### Changed\n- Add user-uploaded media dir to .gitignore (@audreyr)\n- Update .editorconfig to use 2 spaces for html, css, scss, json (@audreyr)\n- Have flake8 ignore node_modules dir (@audreyr)\n\n## [2015-09-23]\n### Changed\n- Add workaround for django-debug-toolbar conflict with Bootstrap 4 (@audreyr)\n\n## [2015-09-22]\n### Added\n- Add Python version option for deployment (@yunti)\n\n## [2015-09-21]\n### Changed\n- django-mailgun-redux to django-mailgun, because @pydanny now has commit rights\n### Removed\n- Excess \"loggers\" from LOGGING setting (@siauPatrick)\n\n## [2015-09-18]\n### Changed\n- Major reorganization of docs (@pydanny)\n- Fix expanded navbar on mobile (@jayfk)\n- Update various requirements (@audreyr)\n\n## [2015-09-17]\n### Added\n- Fix for wsgi.py for Raven in dev (@yunti)\n\n## [2015-09-15]\n### Added\n- whitespace to allow proper rendering of RST (@IanLee1521 )\n\n## [2015-09-14]\n### Added\n- Functionality to delete taskapp if celery isn't going to be used (@pydanny)\n\n### Removed\n- Remove unused generated CSS styles (@audreyr)\n\n### Changed\n- Use Bootstrap margin utility class `m-b-lg` and remove our custom `navbar-header` class (@audreyr)\n- Update Hitch requirements (@audreyr)\n\n## [2015-09-13]\n### Removed\n- Styles that already exist in Bootstrap 4 (or 3) (@audreyr)\n\n### Changed\n- Fix issue #296 - change login.html to use [get_providers](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/templatetags/socialaccount.py#L84-L93) templatetag because ``allauth.socialaccount`` context processor now is [deprecated](http://django-allauth.readthedocs.io/en/latest/changelog.html#from-0-21-0) (@luzfcb)\n\n## [2015-09-09]\n### Added\n- post_gen_hook to generate a secret key for use in locals.py. You should define your own for production (@pydanny)\n\n## [2015-09-09]\n### Added\n- htmlcov to gitignore (@pydanny)\n\n## [2015-09-04]\n### Added\n- Easy deploy Heroku button and app.json file (@bogdal)\n\n## [2015-09-03]\n### Added\n- For security reasons, we set explicitly the list of allowed hosts (@bogdal)\n\n## [2015-08-31]\n### Removed\n- Dokku in favor of docker-compose and other modern Django tools (@pydanny)\n\n## [2015-08-30]\n### Changed\n- Moved from Bootstrap 3 to Bootstrap 4 (@audreyr)\n- Slight Reorganization of the README docs (@pydanny)\n- Dokku docs are out of the README and in the docs folder (@pydanny)\n- Small improvements in ``install_python_dependencies.sh`` and ``install_os_dependencies.sh`` scripts (@luzfcb)\n- Update version of django-crispy-forms, django-extensions, django-test-plus, gevent, coverage, hitchpython and hitchtest (@luzfcb)\n- Update AngularJS version to 1.4.4 (@luzfcb)\n- Update the usage example on README (@luzfcb)\n\n## [2015-08-28]\n### Changed\n- Switched to django-mailgun-redux so mail doesn't blow up on Python 3 (@pydanny)\n\n\n## [2015-08-27]\n### Changed\n- Grunt Updates: use libsass, add postcss (@288)\n\n## [2015-08-20]\n### Changed\n- requirements files to match current dependency versions (@pydanny)\n\n## [2015-08-18]\n### Added\n- Docker support and docker-compose (@jayfk)\n\n## [2015-08-12]\n### Added\n- hitch for end-to-end testing functionality (@crdoconnor)\n\n## [2015-08-09]\n### Added\n- test coverage, bringing it to 100% (@pydanny)\n\n## 2015-08-08\n### Added\n- Gitter badge (@pydanny)\n### Changed\n- Refactor of cookiecutter-django render tests (@burhan)\n\n## [2015-08-06]\n### Added\n- More test coverage, up to 97% (@pydanny)\n- Slight optimization to celery configuration (@jayfk)\n\n## [2015-08-05]\n### Added\n- Sentry support (@burhan)\n\n### Changed\n- Made the user object python 2 and 3 friendly (@pydanny)\n- When using maildump, pin gevent. (@audreyr)\n- Updated coverage version. (@audreyr)\n\n\n## [2015-08-04]\n### Added\n- Better specification of migrations in .coveragerc. (@audreyr)\n\n## [2015-08-03]\n### Added\n- Instructions for using coverage and generating reports (@audreyr)\n- Coverage project-level config file (@audreyr)\n- factory-boy package for improved testing  (@pydanny)\n- Error message for duplicate usernames in `users.admin.MyUserCreationForm` (@pydanny)\n- Tests on `users.admin.MyUserCreationForm` (@pydanny)\n\n### Changed\n- update django-all-auth to 0.23.0  (@pydanny)\n- update django-test-plus to 1.0.7  (@pydanny)\n\n### Removed\n- Unnecessary users/forms.py module (@pydanny)\n\n## [2015-07-30]\n### Changed\n- update django-floppyforms version to 1.5.2\n\n## [2015-07-29]\n### Removed\n- Removed legacy permalink decorator from the users.User model. (@pydanny)\n\n## [2015-07-27]\n### Removed\n- removed django-allauth template context processors because is deprecated now. see: https://github.com/pennersr/django-allauth/commit/634f4fe60e67c266aadcfba2981074f005db340c (@burhan)\n\n### Changed\n- update version of ipython, django-allauth (@luzfcb)\n- update version of django-braces, django-floppyforms, django-model-utils (#287)(@burhan)\n\n## [2015-07-21]\n### Changed\n- memcached is as a cache is replace with redis (#258)(@burhan)\n\n## [2015-07-18]\n### Changed\n- Heroku deployment docs (@stepmr)\n    - Heroku's free postgres tier is now \"hobby-dev\"\n    - pg:backups require a scheduled time\n    - add missing Mailgun API key\n    - Django recommends setting the PYTHONHASHSEED environment variable to random. See: https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/#python-options\n    - Use openssl to generate a secure, random secret_key\n\n\n## [2015-07-17]\n### Added\n- @models.permalink decorator to User.get_absolute_url() method\n\n### Fixed\n- Broken user_form.html (@pydanny)\n\n## [2015-07-16]\n### Added\n- django-test-plus (@pydanny)\n- option use maildump instead of ConsoleEmailHandler (@burhan)\n- Changelog.md (@pydanny)\n\n### Fixed\n- where 'DEFAULT_FROM_EMAIL' was used to cast the value (@jayfk)\n\n### Removed\n- unnecessary header block tag and 'user:' prefix. (@pydanny)\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "## Code of Conduct\n\nEveryone who interacts in the Cookiecutter project's codebase, issue trackers, chat rooms, and mailing lists is expected to follow the [PSF Code of Conduct](https://www.python.org/psf/conduct/)\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to Contribute\n\nAlways happy to get issues identified and pull requests!\n\n## General considerations\n\n1. Keep it small. The smaller the change, the more likely we are to accept.\n2. Changes that fix a current issue get priority for review.\n3. Check out [GitHub guide][submit-a-pr] if you've never created a pull request before.\n\n## Getting started\n\n1. Fork the repo\n2. Clone your fork\n3. Create a branch for your changes\n\nThis last step is very important, don't start developing from main, it'll cause pain if you need to send another change later.\n\n## Testing\n\nYou'll need to run the tests using Python 3.13. We recommend using [tox](https://tox.readthedocs.io/en/latest/) to run the tests. It will automatically create a fresh virtual environment and install our test dependencies, such as [pytest-cookies](https://pypi.python.org/pypi/pytest-cookies/) and [flake8](https://pypi.python.org/pypi/flake8/).\n\nWe'll also run the tests on GitHub actions when you send your pull request, but it's a good idea to run them locally before you send it.\n\n### Installation\n\nWe use uv to manage our environment and manage our Python installation. You can install it following the instructions at https://docs.astral.sh/uv/getting-started/installation/\n\n### Run the template's test suite\n\nTo run the tests of the template using the current Python version:\n\n```bash\n$ uv run tox run -e py\n```\n\nThis uses `pytest `under the hood, and you can pass options to it after a `--`. So to run a particular test:\n\n```bash\n$ uv run tox run -e py -- -k test_default_configuration\n```\n\nFor further information, please consult the [pytest usage docs](https://pytest.org/en/latest/how-to/usage.html#specifying-which-tests-to-run).\n\n### Run the generated project tests\n\nThe template tests are checking that the generated project is fully rendered and that it passes `flake8`. We also have some test scripts which generate a specific project combination, install the dependencies, run the tests of the generated project, install FE dependencies and generate the docs. They will install the template dependencies, so make sure you create and activate a virtual environment first.\n\n```bash\n$ python -m venv venv\n$ source venv/bin/activate\n```\n\nThese tests are slower and can be run with or without Docker:\n\n- Without Docker: `tests/test_bare.sh` (for bare metal)\n- With Docker: `tests/test_docker.sh`\n\nAll arguments to these scripts will be passed to the `cookiecutter` CLI, letting you set options, for example:\n\n```bash\n$ tests/test_bare.sh use_celery=y\n```\n\n## Submitting a pull request\n\nOnce you're happy with your changes and they look ok locally, push and send [a pull request][submit-a-pr] to the main repo, which will trigger the tests on GitHub actions. If they fail, try to fix them. A maintainer should take a look at your change and give you feedback or merge it.\n\n[submit-a-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request\n"
  },
  {
    "path": "CONTRIBUTORS.md",
    "content": "# Contributors\n\n## Core Developers\n\nThese contributors have commit flags for the repository, and are able to\naccept and merge pull requests.\n\n<table>\n  <tr>\n    <th>Name</th>\n    <th>Github</th>\n    <th>Twitter</th>\n  </tr>\n  <tr>\n    <td>Daniel Roy Greenfeld</td>\n    <td>\n      <a href=\"https://github.com/pydanny\">pydanny</a>\n    </td>\n    <td>pydanny</td>\n  </tr>\n  <tr>\n    <td>Audrey Roy Greenfeld</td>\n    <td>\n      <a href=\"https://github.com/audreyr\">audreyr</a>\n    </td>\n    <td>audreyr</td>\n  </tr>\n  <tr>\n    <td>Fábio C. Barrionuevo da Luz</td>\n    <td>\n      <a href=\"https://github.com/luzfcb\">luzfcb</a>\n    </td>\n    <td>luzfcb</td>\n  </tr>\n  <tr>\n    <td>Saurabh Kumar</td>\n    <td>\n      <a href=\"https://github.com/theskumar\">theskumar</a>\n    </td>\n    <td>_theskumar</td>\n  </tr>\n  <tr>\n    <td>Jannis Gebauer</td>\n    <td>\n      <a href=\"https://github.com/jayfk\">jayfk</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Burhan Khalid</td>\n    <td>\n      <a href=\"https://github.com/burhan\">burhan</a>\n    </td>\n    <td>burhan</td>\n  </tr>\n  <tr>\n    <td>Shupeyko Nikita</td>\n    <td>\n      <a href=\"https://github.com/webyneter\">webyneter</a>\n    </td>\n    <td>webyneter</td>\n  </tr>\n  <tr>\n    <td>Bruno Alla</td>\n    <td>\n      <a href=\"https://github.com/browniebroke\">browniebroke</a>\n    </td>\n    <td>_BrunoAlla</td>\n  </tr>\n  <tr>\n    <td>Wan Liuyang</td>\n    <td>\n      <a href=\"https://github.com/sfdye\">sfdye</a>\n    </td>\n    <td>sfdye</td>\n  </tr>\n  <tr>\n    <td>Jelmer Draaijer</td>\n    <td>\n      <a href=\"https://github.com/foarsitter\">foarsitter</a>\n    </td>\n    <td></td>\n  </tr>\n</table>\n\n_Audrey is also the creator of Cookiecutter. Audrey and Daniel are on\nthe Cookiecutter core team._\n\n## Other Contributors\n\nListed in alphabetical order.\n\n<table>\n  <tr>\n    <th>Name</th>\n    <th>Github</th>\n    <th>Twitter</th>\n  </tr>\n  <tr>\n    <td>18</td>\n    <td>\n      <a href=\"https://github.com/dezoito\">dezoito</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>2O4</td>\n    <td>\n      <a href=\"https://github.com/2O4\">2O4</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>a7p</td>\n    <td>\n      <a href=\"https://github.com/a7p\">a7p</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Aadith PM</td>\n    <td>\n      <a href=\"https://github.com/aadithpm\">aadithpm</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Aaron Eikenberry</td>\n    <td>\n      <a href=\"https://github.com/aeikenberry\">aeikenberry</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Abdul Qoyyuum</td>\n    <td>\n      <a href=\"https://github.com/Qoyyuum\">Qoyyuum</a>\n    </td>\n    <td>Qoyyuum</td>\n  </tr>\n  <tr>\n    <td>Abdullah Adeel</td>\n    <td>\n      <a href=\"https://github.com/mabdullahadeel\">mabdullahadeel</a>\n    </td>\n    <td>abdadeel_</td>\n  </tr>\n  <tr>\n    <td>Abe Hanoka</td>\n    <td>\n      <a href=\"https://github.com/abe-101\">abe-101</a>\n    </td>\n    <td>abe__101</td>\n  </tr>\n  <tr>\n    <td>Adam Bogdał</td>\n    <td>\n      <a href=\"https://github.com/bogdal\">bogdal</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Adam Dobrawy</td>\n    <td>\n      <a href=\"https://github.com/ad-m\">ad-m</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Adam Steele</td>\n    <td>\n      <a href=\"https://github.com/adammsteele\">adammsteele</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Adin Hodovic</td>\n    <td>\n      <a href=\"https://github.com/adinhodovic\">adinhodovic</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Agam Dua</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Agustín Scaramuzza</td>\n    <td>\n      <a href=\"https://github.com/scaramagus\">scaramagus</a>\n    </td>\n    <td>scaramagus</td>\n  </tr>\n  <tr>\n    <td>aiden</td>\n    <td>\n      <a href=\"https://github.com/anyidea\">anyidea</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Aidos Kanapyanov</td>\n    <td>\n      <a href=\"https://github.com/aidoskanapyanov\">aidoskanapyanov</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Alan Cyment</td>\n    <td>\n      <a href=\"https://github.com/acyment\">acyment</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Alberto Sanchez</td>\n    <td>\n      <a href=\"https://github.com/alb3rto\">alb3rto</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Alex Kanavos</td>\n    <td>\n      <a href=\"https://github.com/alexkanavos\">alexkanavos</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Alex Tsai</td>\n    <td>\n      <a href=\"https://github.com/caffodian\">caffodian</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Alexandr Artemyev</td>\n    <td>\n      <a href=\"https://github.com/Mogost\">Mogost</a>\n    </td>\n    <td>MOGOST</td>\n  </tr>\n  <tr>\n    <td>Ali Shamakhi</td>\n    <td>\n      <a href=\"https://github.com/ali-shamakhi\">ali-shamakhi</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Alvaro [Andor]</td>\n    <td>\n      <a href=\"https://github.com/andor-pierdelacabeza\">andor-pierdelacabeza</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Amjith Ramanujam</td>\n    <td>\n      <a href=\"https://github.com/amjith\">amjith</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Andreas Meistad</td>\n    <td>\n      <a href=\"https://github.com/ameistad\">ameistad</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Andres Gonzalez</td>\n    <td>\n      <a href=\"https://github.com/andresgz\">andresgz</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Andrew Chen Wang</td>\n    <td>\n      <a href=\"https://github.com/Andrew-Chen-Wang\">Andrew-Chen-Wang</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Andrew Mikhnevich</td>\n    <td>\n      <a href=\"https://github.com/zcho\">zcho</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Andy Rose</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Anna Callahan</td>\n    <td>\n      <a href=\"https://github.com/jazztpt\">jazztpt</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Anna Sidwell</td>\n    <td>\n      <a href=\"https://github.com/takkaria\">takkaria</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Antonia Blair</td>\n    <td>\n      <a href=\"https://github.com/antoniablair\">antoniablair</a>\n    </td>\n    <td>antoniablairart</td>\n  </tr>\n  <tr>\n    <td>Anuj Bansal</td>\n    <td>\n      <a href=\"https://github.com/ahhda\">ahhda</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Arcuri Davide</td>\n    <td>\n      <a href=\"https://github.com/dadokkio\">dadokkio</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Areski Belaid</td>\n    <td>\n      <a href=\"https://github.com/areski\">areski</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Arkadiusz Michał Ryś</td>\n    <td>\n      <a href=\"https://github.com/arrys\">arrys</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Arnav Choudhury</td>\n    <td>\n      <a href=\"https://github.com/arnav13081994\">arnav13081994</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Artur Barseghyan</td>\n    <td>\n      <a href=\"https://github.com/barseghyanartur\">barseghyanartur</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>AsheKR</td>\n    <td>\n      <a href=\"https://github.com/ashekr\">ashekr</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Ashley Camba</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>asmo</td>\n    <td>\n      <a href=\"https://github.com/a5m0\">a5m0</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Barclay Gauld</td>\n    <td>\n      <a href=\"https://github.com/yunti\">yunti</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Bartek</td>\n    <td>\n      <a href=\"https://github.com/btknu\">btknu</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Ben Lopatin</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Ben Warren</td>\n    <td>\n      <a href=\"https://github.com/bwarren2\">bwarren2</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Benjamin Abel</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Bert de Miranda</td>\n    <td>\n      <a href=\"https://github.com/bertdemiranda\">bertdemiranda</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Birtibu</td>\n    <td>\n      <a href=\"https://github.com/Birtibu\">Birtibu</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Bo Lopker</td>\n    <td>\n      <a href=\"https://github.com/blopker\">blopker</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Bo Peng</td>\n    <td>\n      <a href=\"https://github.com/BoPeng\">BoPeng</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Bogdan Mateescu</td>\n    <td>\n      <a href=\"https://github.com/mateesville93\">mateesville93</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Bouke Haarsma</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Brandon Rumiser</td>\n    <td>\n      <a href=\"https://github.com/brumiser1550\">brumiser1550</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Brent Payne</td>\n    <td>\n      <a href=\"https://github.com/brentpayne\">brentpayne</a>\n    </td>\n    <td>brentpayne</td>\n  </tr>\n  <tr>\n    <td>Bruce Olivier</td>\n    <td>\n      <a href=\"https://github.com/bolivierjr\">bolivierjr</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Caio Ariede</td>\n    <td>\n      <a href=\"https://github.com/caioariede\">caioariede</a>\n    </td>\n    <td>caioariede</td>\n  </tr>\n  <tr>\n    <td>Carl Johnson</td>\n    <td>\n      <a href=\"https://github.com/carlmjohnson\">carlmjohnson</a>\n    </td>\n    <td>carlmjohnson</td>\n  </tr>\n  <tr>\n    <td>Catherine Devlin</td>\n    <td>\n      <a href=\"https://github.com/catherinedevlin\">catherinedevlin</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Cebrail Yılmaz</td>\n    <td>\n      <a href=\"https://github.com/b1sar\">b1sar</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Chao Yang Wu</td>\n    <td>\n      <a href=\"https://github.com/goatwu1993\">goatwu1993</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Charlie Macfarlane Brodie</td>\n    <td>\n      <a href=\"https://github.com/tannart\">tannart</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Charlie Smith</td>\n    <td>\n      <a href=\"https://github.com/chuckus\">chuckus</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Chris Curvey</td>\n    <td>\n      <a href=\"https://github.com/ccurvey\">ccurvey</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Chris Franklin</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Chris Franklin</td>\n    <td>\n      <a href=\"https://github.com/hairychris\">hairychris</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Chris Pappalardo</td>\n    <td>\n      <a href=\"https://github.com/ChrisPappalardo\">ChrisPappalardo</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Christian González</td>\n    <td>\n      <a href=\"https://github.com/nerdoc\">nerdoc</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Christian Jauvin</td>\n    <td>\n      <a href=\"https://github.com/cjauvin\">cjauvin</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Christian Jensen</td>\n    <td>\n      <a href=\"https://github.com/jensenbox\">jensenbox</a>\n    </td>\n    <td>cjensen</td>\n  </tr>\n  <tr>\n    <td>Christopher Clarke</td>\n    <td>\n      <a href=\"https://github.com/chrisdev\">chrisdev</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Cole Mackenzie</td>\n    <td>\n      <a href=\"https://github.com/cmackenzie1\">cmackenzie1</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Cole Maclean</td>\n    <td>\n      <a href=\"https://github.com/cole\">cole</a>\n    </td>\n    <td>cole</td>\n  </tr>\n  <tr>\n    <td>Collederas</td>\n    <td>\n      <a href=\"https://github.com/Collederas\">Collederas</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Corey Garvey</td>\n    <td>\n      <a href=\"https://github.com/coreygarvey\">coreygarvey</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Craig Margieson</td>\n    <td>\n      <a href=\"https://github.com/cmargieson\">cmargieson</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Cristian Vargas</td>\n    <td>\n      <a href=\"https://github.com/cdvv7788\">cdvv7788</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Cullen Rhodes</td>\n    <td>\n      <a href=\"https://github.com/c-rhodes\">c-rhodes</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Curtis St Pierre</td>\n    <td>\n      <a href=\"https://github.com/curtisstpierre\">curtisstpierre</a>\n    </td>\n    <td>cstpierre1388</td>\n  </tr>\n  <tr>\n    <td>Cédric Gaspoz</td>\n    <td>\n      <a href=\"https://github.com/cgaspoz\">cgaspoz</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>dalrrard</td>\n    <td>\n      <a href=\"https://github.com/dalrrard\">dalrrard</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Dan Shultz</td>\n    <td>\n      <a href=\"https://github.com/shultz\">shultz</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Dani Hodovic</td>\n    <td>\n      <a href=\"https://github.com/danihodovic\">danihodovic</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Daniel Hepper</td>\n    <td>\n      <a href=\"https://github.com/dhepper\">dhepper</a>\n    </td>\n    <td>danielhepper</td>\n  </tr>\n  <tr>\n    <td>Daniel Hillier</td>\n    <td>\n      <a href=\"https://github.com/danifus\">danifus</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Daniel Sears</td>\n    <td>\n      <a href=\"https://github.com/highpost\">highpost</a>\n    </td>\n    <td>highpost</td>\n  </tr>\n  <tr>\n    <td>Daniele Tricoli</td>\n    <td>\n      <a href=\"https://github.com/eriol\">eriol</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>David</td>\n    <td>\n      <a href=\"https://github.com/buckldav\">buckldav</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>David Díaz</td>\n    <td>\n      <a href=\"https://github.com/ddiazpinto\">ddiazpinto</a>\n    </td>\n    <td>DavidDiazPinto</td>\n  </tr>\n  <tr>\n    <td>David Păcioianu</td>\n    <td>\n      <a href=\"https://github.com/DavidPacioianu\">DavidPacioianu</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Davit Tovmasyan</td>\n    <td>\n      <a href=\"https://github.com/davitovmasyan\">davitovmasyan</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Davur Clementsen</td>\n    <td>\n      <a href=\"https://github.com/dsclementsen\">dsclementsen</a>\n    </td>\n    <td>davur</td>\n  </tr>\n  <tr>\n    <td>Delio Castillo</td>\n    <td>\n      <a href=\"https://github.com/jangeador\">jangeador</a>\n    </td>\n    <td>jangeador</td>\n  </tr>\n  <tr>\n    <td>Delphine LEMIRE</td>\n    <td>\n      <a href=\"https://github.com/DelphineLemire\">DelphineLemire</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Demetris Stavrou</td>\n    <td>\n      <a href=\"https://github.com/demestav\">demestav</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Denis Bobrov</td>\n    <td>\n      <a href=\"https://github.com/delneg\">delneg</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Denis Darii</td>\n    <td>\n      <a href=\"https://github.com/DNX\">DNX</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Denis Orehovsky</td>\n    <td>\n      <a href=\"https://github.com/apirobot\">apirobot</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Denis Savran</td>\n    <td>\n      <a href=\"https://github.com/blaxpy\">blaxpy</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>DevForsure</td>\n    <td>\n      <a href=\"https://github.com/DevForsure\">DevForsure</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Diane Chen</td>\n    <td>\n      <a href=\"https://github.com/purplediane\">purplediane</a>\n    </td>\n    <td>purplediane88</td>\n  </tr>\n  <tr>\n    <td>Diego Montes</td>\n    <td>\n      <a href=\"https://github.com/d57montes\">d57montes</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Dominique Plante</td>\n    <td>\n      <a href=\"https://github.com/dominiqueplante\">dominiqueplante</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Dong Huynh</td>\n    <td>\n      <a href=\"https://github.com/trungdong\">trungdong</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Donghoon Nam</td>\n    <td>\n      <a href=\"https://github.com/codenamenam\">codenamenam</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Douglas</td>\n    <td>\n      <a href=\"https://github.com/douglascdev\">douglascdev</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Duda Nogueira</td>\n    <td>\n      <a href=\"https://github.com/dudanogueira\">dudanogueira</a>\n    </td>\n    <td>dudanogueira</td>\n  </tr>\n  <tr>\n    <td>duffn</td>\n    <td>\n      <a href=\"https://github.com/duffn\">duffn</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Dónal Adams</td>\n    <td>\n      <a href=\"https://github.com/epileptic-fish\">epileptic-fish</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Ed Morley</td>\n    <td>\n      <a href=\"https://github.com/edmorley\">edmorley</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Emanuel Calso</td>\n    <td>\n      <a href=\"https://github.com/bloodpet\">bloodpet</a>\n    </td>\n    <td>bloodpet</td>\n  </tr>\n  <tr>\n    <td>enchance</td>\n    <td>\n      <a href=\"https://github.com/enchance\">enchance</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Eraldo Energy</td>\n    <td>\n      <a href=\"https://github.com/eraldo\">eraldo</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Eric Groom</td>\n    <td>\n      <a href=\"https://github.com/ericgroom\">ericgroom</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Ernesto Cedeno</td>\n    <td>\n      <a href=\"https://github.com/codnee\">codnee</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Eyad Al Sibai</td>\n    <td>\n      <a href=\"https://github.com/eyadsibai\">eyadsibai</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Fabian Affolter</td>\n    <td>\n      <a href=\"https://github.com/fabaff\">fabaff</a>\n    </td>\n    <td>fabaff</td>\n  </tr>\n  <tr>\n    <td>farwill</td>\n    <td>\n      <a href=\"https://github.com/farwill\">farwill</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Fateme Fouladkar</td>\n    <td>\n      <a href=\"https://github.com/FatemeFouladkar\">FatemeFouladkar</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Felipe Arruda</td>\n    <td>\n      <a href=\"https://github.com/arruda\">arruda</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Filipe Nascimento</td>\n    <td>\n      <a href=\"https://github.com/FilipeNas\">FilipeNas</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Florian Idelberger</td>\n    <td>\n      <a href=\"https://github.com/step21\">step21</a>\n    </td>\n    <td>windrush</td>\n  </tr>\n  <tr>\n    <td>Floyd Hightower</td>\n    <td>\n      <a href=\"https://github.com/fhightower\">fhightower</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Francisco Navarro Morales </td>\n    <td>\n      <a href=\"https://github.com/spothound\">spothound</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Freddy</td>\n    <td>\n      <a href=\"https://github.com/Hraesvelg\">Hraesvelg</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Fuzzwah</td>\n    <td>\n      <a href=\"https://github.com/Fuzzwah\">Fuzzwah</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Gabriel Mejia</td>\n    <td>\n      <a href=\"https://github.com/elgartoinf\">elgartoinf</a>\n    </td>\n    <td>elgartoinf</td>\n  </tr>\n  <tr>\n    <td>Garry Cairns</td>\n    <td>\n      <a href=\"https://github.com/garry-cairns\">garry-cairns</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Garry Polley</td>\n    <td>\n      <a href=\"https://github.com/garrypolley\">garrypolley</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Geo Maciolek</td>\n    <td>\n      <a href=\"https://github.com/GeoMaciolek\">GeoMaciolek</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>ghazi-git</td>\n    <td>\n      <a href=\"https://github.com/ghazi-git\">ghazi-git</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Gilbishkosma</td>\n    <td>\n      <a href=\"https://github.com/Gilbishkosma\">Gilbishkosma</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>GitBib</td>\n    <td>\n      <a href=\"https://github.com/GitBib\">GitBib</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Glenn Wiskur</td>\n    <td>\n      <a href=\"https://github.com/gwiskur\">gwiskur</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Grant McLean</td>\n    <td>\n      <a href=\"https://github.com/grantm\">grantm</a>\n    </td>\n    <td>grantmnz</td>\n  </tr>\n  <tr>\n    <td>Guilherme Guy</td>\n    <td>\n      <a href=\"https://github.com/guilherme1guy\">guilherme1guy</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>GvS</td>\n    <td>\n      <a href=\"https://github.com/GvS666\">GvS666</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Hamish Durkin</td>\n    <td>\n      <a href=\"https://github.com/durkode\">durkode</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Hana Belay</td>\n    <td>\n      <a href=\"https://github.com/earthcomfy\">earthcomfy</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Hana Quadara</td>\n    <td>\n      <a href=\"https://github.com/hanaquadara\">hanaquadara</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Hannah Lazarus</td>\n    <td>\n      <a href=\"https://github.com/hanhanhan\">hanhanhan</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Harry Moreno</td>\n    <td>\n      <a href=\"https://github.com/morenoh149\">morenoh149</a>\n    </td>\n    <td>morenoh149</td>\n  </tr>\n  <tr>\n    <td>Harry Percival</td>\n    <td>\n      <a href=\"https://github.com/hjwp\">hjwp</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Harshit Ranjan</td>\n    <td>\n      <a href=\"https://github.com/HarshitR2004\">HarshitR2004</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Haseeb ur Rehman</td>\n    <td>\n      <a href=\"https://github.com/professorhaseeb\">professorhaseeb</a>\n    </td>\n    <td>professorhaseeb</td>\n  </tr>\n  <tr>\n    <td>Hendrik Schneider</td>\n    <td>\n      <a href=\"https://github.com/hendrikschneider\">hendrikschneider</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>henningbra</td>\n    <td>\n      <a href=\"https://github.com/henningbra\">henningbra</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Henrique G. G. Pereira</td>\n    <td>\n      <a href=\"https://github.com/ikkebr\">ikkebr</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>hleroy</td>\n    <td>\n      <a href=\"https://github.com/hleroy\">hleroy</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Hoai-Thu Vuong</td>\n    <td>\n      <a href=\"https://github.com/thuvh\">thuvh</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Howie Zhao</td>\n    <td>\n      <a href=\"https://github.com/howiezhao\">howiezhao</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Ian Lee</td>\n    <td>\n      <a href=\"https://github.com/IanLee1521\">IanLee1521</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Igor Jerosimić</td>\n    <td>\n      <a href=\"https://github.com/igor-wl\">igor-wl</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Imran Rahman</td>\n    <td>\n      <a href=\"https://github.com/infraredCoding\">infraredCoding</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>innicoder</td>\n    <td>\n      <a href=\"https://github.com/innicoder\">innicoder</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Irfan Ahmad</td>\n    <td>\n      <a href=\"https://github.com/erfaan\">erfaan</a>\n    </td>\n    <td>erfaan</td>\n  </tr>\n  <tr>\n    <td>Isaac12x</td>\n    <td>\n      <a href=\"https://github.com/Isaac12x\">Isaac12x</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>itisnotyourenv</td>\n    <td>\n      <a href=\"https://github.com/itisnotyourenv\">itisnotyourenv</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Ivan Khomutov</td>\n    <td>\n      <a href=\"https://github.com/ikhomutov\">ikhomutov</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>JAEGYUN JUNG</td>\n    <td>\n      <a href=\"https://github.com/TGoddessana\">TGoddessana</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jakub Boukal</td>\n    <td>\n      <a href=\"https://github.com/SukiCZ\">SukiCZ</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jakub Musko</td>\n    <td>\n      <a href=\"https://github.com/umgelurgel\">umgelurgel</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>James Williams</td>\n    <td>\n      <a href=\"https://github.com/jameswilliams1\">jameswilliams1</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jan Fabry</td>\n    <td>\n      <a href=\"https://github.com/janfabry\">janfabry</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jan Van Bruggen</td>\n    <td>\n      <a href=\"https://github.com/jvanbrug\">jvanbrug</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jason Mok</td>\n    <td>\n      <a href=\"https://github.com/jasonmokk\">jasonmokk</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jeff Foster</td>\n    <td>\n      <a href=\"https://github.com/jeffpfoster\">jeffpfoster</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jens Kaeske</td>\n    <td>\n      <a href=\"https://github.com/jkaeske\">jkaeske</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jens Nilsson</td>\n    <td>\n      <a href=\"https://github.com/phiberjenz\">phiberjenz</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jeongseok Kang</td>\n    <td>\n      <a href=\"https://github.com/rapsealk\">rapsealk</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jerome Caisip</td>\n    <td>\n      <a href=\"https://github.com/jeromecaisip\">jeromecaisip</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jerome Leclanche</td>\n    <td>\n      <a href=\"https://github.com/jleclanche\">jleclanche</a>\n    </td>\n    <td>Adys</td>\n  </tr>\n  <tr>\n    <td>Jimmy Gitonga</td>\n    <td>\n      <a href=\"https://github.com/Afrowave\">Afrowave</a>\n    </td>\n    <td>afrowave</td>\n  </tr>\n  <tr>\n    <td>jlitrell</td>\n    <td>\n      <a href=\"https://github.com/jlitrell\">jlitrell</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>John</td>\n    <td>\n      <a href=\"https://github.com/thorrak\">thorrak</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>John Cass</td>\n    <td>\n      <a href=\"https://github.com/jcass77\">jcass77</a>\n    </td>\n    <td>cass_john</td>\n  </tr>\n  <tr>\n    <td>Johnny Metz</td>\n    <td>\n      <a href=\"https://github.com/johnnymetz\">johnnymetz</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jonathan Thompson</td>\n    <td>\n      <a href=\"https://github.com/nojanath\">nojanath</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jorge Valdez</td>\n    <td>\n      <a href=\"https://github.com/jorgeavaldez\">jorgeavaldez</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Joseph Hanna</td>\n    <td>\n      <a href=\"https://github.com/sanchimenea\">sanchimenea</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Josh596</td>\n    <td>\n      <a href=\"https://github.com/Josh596\">Josh596</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>jugglinmike</td>\n    <td>\n      <a href=\"https://github.com/jugglinmike\">jugglinmike</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Jules Cheron</td>\n    <td>\n      <a href=\"https://github.com/jules-ch\">jules-ch</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Julien Almarcha</td>\n    <td>\n      <a href=\"https://github.com/sladinji\">sladinji</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Julio Castillo</td>\n    <td>\n      <a href=\"https://github.com/juliocc\">juliocc</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Kaido Kert</td>\n    <td>\n      <a href=\"https://github.com/kaidokert\">kaidokert</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>kappataumu</td>\n    <td>\n      <a href=\"https://github.com/kappataumu\">kappataumu</a>\n    </td>\n    <td>kappataumu</td>\n  </tr>\n  <tr>\n    <td>Kaveh</td>\n    <td>\n      <a href=\"https://github.com/ka7eh\">ka7eh</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Kawsar Alam Foysal</td>\n    <td>\n      <a href=\"https://github.com/iamfoysal\">iamfoysal</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Keith Bailey</td>\n    <td>\n      <a href=\"https://github.com/keithjeb\">keithjeb</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Keith Callenberg</td>\n    <td>\n      <a href=\"https://github.com/keithcallenberg\">keithcallenberg</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Keith Webber</td>\n    <td>\n      <a href=\"https://github.com/townie\">townie</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Kevin A. Stone</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Kevin Mills</td>\n    <td>\n      <a href=\"https://github.com/millsks\">millsks</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Kevin Ndung&#39;u</td>\n    <td>\n      <a href=\"https://github.com/kevgathuku\">kevgathuku</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Keyvan Mosharraf</td>\n    <td>\n      <a href=\"https://github.com/keyvanm\">keyvanm</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>krati yadav</td>\n    <td>\n      <a href=\"https://github.com/krati5\">krati5</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Krzysztof Szumny</td>\n    <td>\n      <a href=\"https://github.com/noisy\">noisy</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Krzysztof Żuraw</td>\n    <td>\n      <a href=\"https://github.com/krzysztofzuraw\">krzysztofzuraw</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Kuo Chao Cheng</td>\n    <td>\n      <a href=\"https://github.com/wwwtony5488\">wwwtony5488</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>lcd1232</td>\n    <td>\n      <a href=\"https://github.com/lcd1232\">lcd1232</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>LECbg</td>\n    <td>\n      <a href=\"https://github.com/LECbg\">LECbg</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Leifur Halldor Asgeirsson</td>\n    <td>\n      <a href=\"https://github.com/leifurhauks\">leifurhauks</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Leo won</td>\n    <td>\n      <a href=\"https://github.com/leollon\">leollon</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Leo Zhou</td>\n    <td>\n      <a href=\"https://github.com/glasslion\">glasslion</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Leon Kim</td>\n    <td>\n      <a href=\"https://github.com/PilhwanKim\">PilhwanKim</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Leonardo Jimenez</td>\n    <td>\n      <a href=\"https://github.com/xpostudio4\">xpostudio4</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Liam Brenner</td>\n    <td>\n      <a href=\"https://github.com/SableWalnut\">SableWalnut</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Lin Xianyi</td>\n    <td>\n      <a href=\"https://github.com/iynaix\">iynaix</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>LJFP</td>\n    <td>\n      <a href=\"https://github.com/ljfp\">ljfp</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Lucas Klasa</td>\n    <td>\n      <a href=\"https://github.com/lucaskbr\">lucaskbr</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Luis Nell</td>\n    <td>\n      <a href=\"https://github.com/originell\">originell</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Lukas Klein</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Lyla Fischer</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Malik Sulaimanov</td>\n    <td>\n      <a href=\"https://github.com/flyudvik\">flyudvik</a>\n    </td>\n    <td>flyudvik</td>\n  </tr>\n  <tr>\n    <td>Manas Mallick</td>\n    <td>\n      <a href=\"https://github.com/ManDun\">ManDun</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Manjit Pardeshi</td>\n    <td>\n      <a href=\"https://github.com/Manjit2003\">Manjit2003</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Marcio Mazza</td>\n    <td>\n      <a href=\"https://github.com/marciomazza\">marciomazza</a>\n    </td>\n    <td>marciomazza</td>\n  </tr>\n  <tr>\n    <td>Marios Frixou</td>\n    <td>\n      <a href=\"https://github.com/frixou89\">frixou89</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Mariot Tsitoara</td>\n    <td>\n      <a href=\"https://github.com/mariot\">mariot</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Marlon Castillo</td>\n    <td>\n      <a href=\"https://github.com/mcastle\">mcastle</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Martin Blech</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Martin Saizar</td>\n    <td>\n      <a href=\"https://github.com/msaizar\">msaizar</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Martín Blech</td>\n    <td>\n      <a href=\"https://github.com/martinblech\">martinblech</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>masavini</td>\n    <td>\n      <a href=\"https://github.com/masavini\">masavini</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Mateusz Ostaszewski</td>\n    <td>\n      <a href=\"https://github.com/mostaszewski\">mostaszewski</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Matheus Jardim Bernardes</td>\n    <td>\n      <a href=\"https://github.com/matheusjardimb\">matheusjardimb</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Mathijs Hoogland</td>\n    <td>\n      <a href=\"https://github.com/MathijsHoogland\">MathijsHoogland</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Matt Braymer-Hayes</td>\n    <td>\n      <a href=\"https://github.com/mattayes\">mattayes</a>\n    </td>\n    <td>mattayes</td>\n  </tr>\n  <tr>\n    <td>Matt Knapper</td>\n    <td>\n      <a href=\"https://github.com/mknapper1\">mknapper1</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Matt Linares</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Matt Menzenski</td>\n    <td>\n      <a href=\"https://github.com/menzenski\">menzenski</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Matt Warren</td>\n    <td>\n      <a href=\"https://github.com/mfwarren\">mfwarren</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Matthew Foster Walsh</td>\n    <td>\n      <a href=\"https://github.com/mfosterw\">mfosterw</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Matthew Sisley</td>\n    <td>\n      <a href=\"https://github.com/mjsisley\">mjsisley</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Matthias Sieber</td>\n    <td>\n      <a href=\"https://github.com/manonthemat\">manonthemat</a>\n    </td>\n    <td>MatzeOne</td>\n  </tr>\n  <tr>\n    <td>Maurício Gioachini</td>\n    <td>\n      <a href=\"https://github.com/MauGx3\">MauGx3</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Meghan Heintz</td>\n    <td>\n      <a href=\"https://github.com/dot2dotseurat\">dot2dotseurat</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Meraj </td>\n    <td>\n      <a href=\"https://github.com/ichbinmeraj\">ichbinmeraj</a>\n    </td>\n    <td>merajsafari</td>\n  </tr>\n  <tr>\n    <td>Mesut Yılmaz</td>\n    <td>\n      <a href=\"https://github.com/myilmaz\">myilmaz</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Michael Gecht</td>\n    <td>\n      <a href=\"https://github.com/mimischi\">mimischi</a>\n    </td>\n    <td>_mischi</td>\n  </tr>\n  <tr>\n    <td>Michael Samoylov</td>\n    <td>\n      <a href=\"https://github.com/msamoylov\">msamoylov</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Michael V. Battista</td>\n    <td>\n      <a href=\"https://github.com/mvbattista\">mvbattista</a>\n    </td>\n    <td>mvbattista</td>\n  </tr>\n  <tr>\n    <td>Mike97M</td>\n    <td>\n      <a href=\"https://github.com/Mike97M\">Mike97M</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>milvagox</td>\n    <td>\n      <a href=\"https://github.com/milvagox\">milvagox</a>\n    </td>\n    <td>milvagox</td>\n  </tr>\n  <tr>\n    <td>Min ho Kim</td>\n    <td>\n      <a href=\"https://github.com/minho42\">minho42</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>MinWoo Sung</td>\n    <td>\n      <a href=\"https://github.com/SungMinWoo\">SungMinWoo</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Mohamed Feddad</td>\n    <td>\n      <a href=\"https://github.com/mrf345\">mrf345</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>monosans</td>\n    <td>\n      <a href=\"https://github.com/monosans\">monosans</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Morten Kaae</td>\n    <td>\n      <a href=\"https://github.com/MortenKaae\">MortenKaae</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Mounir</td>\n    <td>\n      <a href=\"https://github.com/mounirmesselmeni\">mounirmesselmeni</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>mozillazg</td>\n    <td>\n      <a href=\"https://github.com/mozillazg\">mozillazg</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>mpoli</td>\n    <td>\n      <a href=\"https://github.com/mpoli\">mpoli</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>mpsantos</td>\n    <td>\n      <a href=\"https://github.com/mpsantos\">mpsantos</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Nadav Peretz</td>\n    <td>\n      <a href=\"https://github.com/nadavperetz\">nadavperetz</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Naveen</td>\n    <td>\n      <a href=\"https://github.com/naveensrinivasan\">naveensrinivasan</a>\n    </td>\n    <td>snaveen</td>\n  </tr>\n  <tr>\n    <td>Nico Stefani</td>\n    <td>\n      <a href=\"https://github.com/nicolas471\">nicolas471</a>\n    </td>\n    <td>moby_dick91</td>\n  </tr>\n  <tr>\n    <td>Nikita Sobolev</td>\n    <td>\n      <a href=\"https://github.com/sobolevn\">sobolevn</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Nix Siow</td>\n    <td>\n      <a href=\"https://github.com/nixsiow\">nixsiow</a>\n    </td>\n    <td>nixsiow</td>\n  </tr>\n  <tr>\n    <td>Noah H</td>\n    <td>\n      <a href=\"https://github.com/nthall\">nthall</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Oleg Russkin</td>\n    <td>\n      <a href=\"https://github.com/rolep\">rolep</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Omer-5</td>\n    <td>\n      <a href=\"https://github.com/Omer-5\">Omer-5</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Pablo</td>\n    <td>\n      <a href=\"https://github.com/oubiga\">oubiga</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Pamela Fox</td>\n    <td>\n      <a href=\"https://github.com/pamelafox\">pamelafox</a>\n    </td>\n    <td>pamelafox</td>\n  </tr>\n  <tr>\n    <td>Param Kapur</td>\n    <td>\n      <a href=\"https://github.com/paramkpr\">paramkpr</a>\n    </td>\n    <td>ParamKapur</td>\n  </tr>\n  <tr>\n    <td>Parbhat Puri</td>\n    <td>\n      <a href=\"https://github.com/parbhat\">parbhat</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Patrick Tran</td>\n    <td>\n      <a href=\"https://github.com/theptrk\">theptrk</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Patrick Zhang</td>\n    <td>\n      <a href=\"https://github.com/PatDuJour\">PatDuJour</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Paul Wulff</td>\n    <td>\n      <a href=\"https://github.com/mtmpaulwulff\">mtmpaulwulff</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Pawan Chaurasia</td>\n    <td>\n      <a href=\"https://github.com/rjsnh1522\">rjsnh1522</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Pedro Campos</td>\n    <td>\n      <a href=\"https://github.com/pcampos119104\">pcampos119104</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Pepa</td>\n    <td>\n      <a href=\"https://github.com/07pepa\">07pepa</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Peter Bittner</td>\n    <td>\n      <a href=\"https://github.com/bittner\">bittner</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Peter Coles</td>\n    <td>\n      <a href=\"https://github.com/mrcoles\">mrcoles</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Philipp Matthies</td>\n    <td>\n      <a href=\"https://github.com/canonnervio\">canonnervio</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Pierre Chiquet</td>\n    <td>\n      <a href=\"https://github.com/pchiquet\">pchiquet</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>PJ Hoberman</td>\n    <td>\n      <a href=\"https://github.com/pjhoberman\">pjhoberman</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Plurific</td>\n    <td>\n      <a href=\"https://github.com/paulschwenn\">paulschwenn</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Pulse-Mind</td>\n    <td>\n      <a href=\"https://github.com/pulse-mind\">pulse-mind</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>quroom</td>\n    <td>\n      <a href=\"https://github.com/quroom\">quroom</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>qwerrrqw</td>\n    <td>\n      <a href=\"https://github.com/qwerrrqw\">qwerrrqw</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Raony Guimarães Corrêa</td>\n    <td>\n      <a href=\"https://github.com/raonyguimaraes\">raonyguimaraes</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Raphael Pierzina</td>\n    <td>\n      <a href=\"https://github.com/hackebrot\">hackebrot</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Ray Besiga</td>\n    <td>\n      <a href=\"https://github.com/raybesiga\">raybesiga</a>\n    </td>\n    <td>raybesiga</td>\n  </tr>\n  <tr>\n    <td>Reggie Riser</td>\n    <td>\n      <a href=\"https://github.com/reggieriser\">reggieriser</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>René Muhl</td>\n    <td>\n      <a href=\"https://github.com/rm--\">rm--</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>rguptar</td>\n    <td>\n      <a href=\"https://github.com/rguptar\">rguptar</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Richard Hajdu</td>\n    <td>\n      <a href=\"https://github.com/Tusky\">Tusky</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Robin</td>\n    <td>\n      <a href=\"https://github.com/Kaffeetasse\">Kaffeetasse</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Roman Afanaskin</td>\n    <td>\n      <a href=\"https://github.com/siauPatrick\">siauPatrick</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Roman Osipenko</td>\n    <td>\n      <a href=\"https://github.com/romanosipenko\">romanosipenko</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Russell Davies</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>rxm7706</td>\n    <td>\n      <a href=\"https://github.com/rxm7706\">rxm7706</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Ryan Fitch</td>\n    <td>\n      <a href=\"https://github.com/ryfi\">ryfi</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Sadra Yahyapour</td>\n    <td>\n      <a href=\"https://github.com/lnxpy\">lnxpy</a>\n    </td>\n    <td>lnxpylnxpy</td>\n  </tr>\n  <tr>\n    <td>Sam Collins</td>\n    <td>\n      <a href=\"https://github.com/MightySCollins\">MightySCollins</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Sascha</td>\n    <td>\n      <a href=\"https://github.com/saschalalala\">saschalalala</a>\n    </td>\n    <td>saschalalala</td>\n  </tr>\n  <tr>\n    <td>Sebastian Reyes Espinosa</td>\n    <td>\n      <a href=\"https://github.com/sebastian-code\">sebastian-code</a>\n    </td>\n    <td>sebastianreyese</td>\n  </tr>\n  <tr>\n    <td>Shayan Karimi</td>\n    <td>\n      <a href=\"https://github.com/shywn-mrk\">shywn-mrk</a>\n    </td>\n    <td>shywn_mrk</td>\n  </tr>\n  <tr>\n    <td>Simeon Emanuilov</td>\n    <td>\n      <a href=\"https://github.com/s-emanuilov\">s-emanuilov</a>\n    </td>\n    <td>s_emanuilov</td>\n  </tr>\n  <tr>\n    <td>Simon Rey</td>\n    <td>\n      <a href=\"https://github.com/eqqe\">eqqe</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Soldatov Serhii</td>\n    <td>\n      <a href=\"https://github.com/soldatov-ss\">soldatov-ss</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Sorasful</td>\n    <td>\n      <a href=\"https://github.com/sorasful\">sorasful</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Srinivas Nyayapati</td>\n    <td>\n      <a href=\"https://github.com/shireenrao\">shireenrao</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>stepmr</td>\n    <td>\n      <a href=\"https://github.com/stepmr\">stepmr</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Steve Steiner</td>\n    <td>\n      <a href=\"https://github.com/ssteinerX\">ssteinerX</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Sudarshan Wadkar</td>\n    <td>\n      <a href=\"https://github.com/wadkar\">wadkar</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Sule Marshall</td>\n    <td>\n      <a href=\"https://github.com/suledev\">suledev</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Sławek Ehlert</td>\n    <td>\n      <a href=\"https://github.com/slafs\">slafs</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>TAKAHASHI Shuuji</td>\n    <td>\n      <a href=\"https://github.com/shuuji3\">shuuji3</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Tames McTigue</td>\n    <td>\n      <a href=\"https://github.com/Tamerz\">Tamerz</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Tano Abeleyra</td>\n    <td>\n      <a href=\"https://github.com/tanoabeleyra\">tanoabeleyra</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Taylor Baldwin</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Tharushan</td>\n    <td>\n      <a href=\"https://github.com/Tharushan\">Tharushan</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Thibault J.</td>\n    <td>\n      <a href=\"https://github.com/thibault\">thibault</a>\n    </td>\n    <td>thibault</td>\n  </tr>\n  <tr>\n    <td>Thomas Booij</td>\n    <td>\n      <a href=\"https://github.com/ThomasBooij95\">ThomasBooij95</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Théo Segonds</td>\n    <td>\n      <a href=\"https://github.com/show0k\">show0k</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>tildebox</td>\n    <td>\n      <a href=\"https://github.com/tildebox\">tildebox</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Tim Claessens</td>\n    <td>\n      <a href=\"https://github.com/timclaessens\">timclaessens</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Tim Freund</td>\n    <td>\n      <a href=\"https://github.com/timfreund\">timfreund</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Timm Simpkins</td>\n    <td>\n      <a href=\"https://github.com/PoDuck\">PoDuck</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>tmajerech</td>\n    <td>\n      <a href=\"https://github.com/tmajerech\">tmajerech</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Tom Atkins</td>\n    <td>\n      <a href=\"https://github.com/knitatoms\">knitatoms</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Tom Offermann</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Tosinibikunle</td>\n    <td>\n      <a href=\"https://github.com/Tosinibikunle\">Tosinibikunle</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Travis McNeill</td>\n    <td>\n      <a href=\"https://github.com/Travistock\">Travistock</a>\n    </td>\n    <td>tavistock_esq</td>\n  </tr>\n  <tr>\n    <td>Tubo Shi</td>\n    <td>\n      <a href=\"https://github.com/Tubo\">Tubo</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Umair Ashraf</td>\n    <td>\n      <a href=\"https://github.com/umrashrf\">umrashrf</a>\n    </td>\n    <td>fabumair</td>\n  </tr>\n  <tr>\n    <td>Vadim Iskuchekov</td>\n    <td>\n      <a href=\"https://github.com/Egregors\">Egregors</a>\n    </td>\n    <td>egregors</td>\n  </tr>\n  <tr>\n    <td>Vageeshan Mankala</td>\n    <td>\n      <a href=\"https://github.com/vagi8\">vagi8</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>vascop</td>\n    <td>\n      <a href=\"https://github.com/vascop\">vascop</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Vicente G. Reyes</td>\n    <td>\n      <a href=\"https://github.com/reyesvicente\">reyesvicente</a>\n    </td>\n    <td>highcenburg</td>\n  </tr>\n  <tr>\n    <td>Vikas Yadav</td>\n    <td>\n      <a href=\"https://github.com/vik-y\">vik-y</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>villancikos</td>\n    <td>\n      <a href=\"https://github.com/villancikos\">villancikos</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Vincent Leduc</td>\n    <td>\n      <a href=\"https://github.com/leducvin\">leducvin</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Vitaly Babiy</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Vivian Guillen</td>\n    <td>\n      <a href=\"https://github.com/viviangb\">viviangb</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Vlad Doster</td>\n    <td>\n      <a href=\"https://github.com/vladdoster\">vladdoster</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Wes Turner</td>\n    <td>\n      <a href=\"https://github.com/westurner\">westurner</a>\n    </td>\n    <td>westurner</td>\n  </tr>\n  <tr>\n    <td>Will</td>\n    <td>\n      <a href=\"https://github.com/novucs\">novucs</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Will Farley</td>\n    <td>\n      <a href=\"https://github.com/goldhand\">goldhand</a>\n    </td>\n    <td>g01dhand</td>\n  </tr>\n  <tr>\n    <td>Will Gordon</td>\n    <td>\n      <a href=\"https://github.com/wgordon17\">wgordon17</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>William Archinal</td>\n    <td>\n      <a href=\"https://github.com/archinal\">archinal</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Xaver Y.R. Chen</td>\n    <td>\n      <a href=\"https://github.com/yrchen\">yrchen</a>\n    </td>\n    <td>yrchen</td>\n  </tr>\n  <tr>\n    <td>Yaroslav Halchenko</td>\n    <td>\n      <a href=\"https://github.com/\"></a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Yotam Tal</td>\n    <td>\n      <a href=\"https://github.com/yotamtal\">yotamtal</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Yuchen Xie</td>\n    <td>\n      <a href=\"https://github.com/mapx\">mapx</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>Zach Borboa</td>\n    <td>\n      <a href=\"https://github.com/zachborboa\">zachborboa</a>\n    </td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>zhaoruibing</td>\n    <td>\n      <a href=\"https://github.com/zhaoruibing\">zhaoruibing</a>\n    </td>\n    <td></td>\n  </tr>\n</table>\n\n### Special Thanks\n\nThe following haven't provided code directly, but have provided\nguidance and advice.\n\n- Jannis Leidel\n- Nate Aune\n- Barry Morrison"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2013-2020, Daniel Roy Greenfeld\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice, this\n  list of conditions and the following disclaimer in the documentation and/or\n  other materials provided with the distribution.\n\n* Neither the name of Cookiecutter Django nor the names of its contributors may\n  be used to endorse or promote products derived from this software without\n  specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\nOF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# Cookiecutter Django\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/cookiecutter/cookiecutter-django/ci.yml?branch=main)](https://github.com/cookiecutter/cookiecutter-django/actions/workflows/ci.yml?query=branch%3Amain)\n[![Documentation Status](https://readthedocs.org/projects/cookiecutter-django/badge/?version=latest)](https://cookiecutter-django.readthedocs.io/en/latest/?badge=latest)\n[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/cookiecutter/cookiecutter-django/main.svg)](https://results.pre-commit.ci/latest/github/cookiecutter/cookiecutter-django/main)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\n[![Updates](https://pyup.io/repos/github/cookiecutter/cookiecutter-django/shield.svg)](https://pyup.io/repos/github/cookiecutter/cookiecutter-django/)\n[![Join our Discord](https://img.shields.io/badge/Discord-cookiecutter-5865F2?style=flat&logo=discord&logoColor=white)](https://discord.gg/rAWFUP47d2)\n[![Code Helpers Badge](https://www.codetriage.com/cookiecutter/cookiecutter-django/badges/users.svg)](https://www.codetriage.com/cookiecutter/cookiecutter-django)\n\nPowered by [Cookiecutter](https://github.com/cookiecutter/cookiecutter), Cookiecutter Django is a framework for jumpstarting\nproduction-ready Django projects quickly.\n\n- Documentation: <https://cookiecutter-django.readthedocs.io/en/latest/>\n- See [Troubleshooting](https://cookiecutter-django.readthedocs.io/en/latest/5-help/troubleshooting.html) for common errors and obstacles\n- If you have problems with Cookiecutter Django, please open [issues](https://github.com/cookiecutter/cookiecutter-django/issues/new) don't send\n  emails to the maintainers.\n\n## Features\n\n- For Django 6.0\n- Works with Python 3.13\n- Renders Django projects with 100% starting test coverage\n- Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5\n- [12-Factor](https://12factor.net) based settings via [django-environ](https://github.com/joke2k/django-environ)\n- Secure by default. We believe in SSL.\n- Optimized development and production settings\n- Registration via [django-allauth](https://github.com/pennersr/django-allauth)\n- Comes with custom user model ready to go\n- Optional basic ASGI setup for Websockets\n- Optional custom static build using Gulp or Webpack\n- Send emails via [Anymail](https://github.com/anymail/django-anymail) (using [Mailgun](http://www.mailgun.com/) by default or Amazon SES if AWS is selected cloud provider, but switchable)\n- Media storage using Amazon S3, Google Cloud Storage, Azure Storage or nginx\n- Docker support using [docker-compose](https://github.com/docker/compose) for development and production (using [Traefik](https://traefik.io/) with [LetsEncrypt](https://letsencrypt.org/) support)\n- [Procfile](https://devcenter.heroku.com/articles/procfile) for deploying to Heroku\n- Instructions for deploying to [PythonAnywhere](https://www.pythonanywhere.com/)\n- Run tests with unittest or pytest\n- Customizable PostgreSQL version\n- Default integration with [pre-commit](https://github.com/pre-commit/pre-commit) for identifying simple issues before submission to code review\n\n## Optional Integrations\n\n_These features can be enabled during initial project setup._\n\n- Serve static files from Amazon S3, Google Cloud Storage, Azure Storage or [Whitenoise](https://whitenoise.readthedocs.io/)\n- Configuration for [Celery](https://docs.celeryq.dev) and [Flower](https://github.com/mher/flower) (the latter in Docker setup only)\n- Integration with [Mailpit](https://github.com/axllent/mailpit/) for local email testing\n- Integration with [Sentry](https://sentry.io/welcome/) for error logging\n\n## Constraints\n\n- Only maintained 3rd party libraries are used.\n- Uses PostgreSQL everywhere: 14 - 18 ([MySQL fork](https://github.com/mabdullahadeel/cookiecutter-django-mysql) also available).\n- Environment variables for configuration (This won't work with Apache/mod_wsgi).\n\n## Support this Project!\n\nThis project is an open source project run by volunteers. You can sponsor us via [OpenCollective](https://opencollective.com/cookiecutter-django) or individually via GitHub Sponsors:\n\n- Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB.\n- Fabio C. Barrionuevo, Core Developer ([GitHub](https://github.com/luzfcb)): expertise in Python/Django, hands-on DevOps and frontend experience.\n- Bruno Alla, Core Developer ([GitHub](https://github.com/browniebroke)): expertise in Python/Django and DevOps.\n- Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience.\n\nProjects that provide financial support to the maintainers:\n\n### Two Scoops of Django\n\n[![Cover of the book \"Two Scoops of Django 3.x\"](https://f004.backblazeb2.com/file/feldroycom/images/book-TSD3-800.jpg)](https://www.feldroy.com/two-scoops-of-django)\n\nTwo Scoops of Django 3.x is the best ice cream-themed Django reference in the universe!\n\n### PyUp\n\n[![PyUp Logo](https://pyup.io/static/images/logo.png)](https://pyup.io)\n\nPyUp brings you automated security and dependency updates used by Google and other organizations. Free for open source projects!\n\n## Usage\n\nLet's pretend you want to create a Django project called \"redditclone\". Rather than using `startproject`\nand then editing the results to include your name, email, and various configuration issues that always get forgotten until the worst possible moment, get [cookiecutter](https://github.com/cookiecutter/cookiecutter) to do all the work.\n\nFirst, get Cookiecutter. Trust me, it's awesome:\n\n    uv tool install \"cookiecutter>=1.7.0\"\n\nNow run it against this repo:\n\n    uvx cookiecutter https://github.com/cookiecutter/cookiecutter-django\n\nYou'll be prompted for some values. Provide them, then a Django project will be created for you.\n\n**Warning**: After this point, change 'Daniel Greenfeld', 'pydanny', etc to your own information.\n\nAnswer the prompts with your own desired [options](http://cookiecutter-django.readthedocs.io/en/latest/1-getting-started/project-generation-options.html). For example:\n\n    Cloning into 'cookiecutter-django'...\n    remote: Counting objects: 550, done.\n    remote: Compressing objects: 100% (310/310), done.\n    remote: Total 550 (delta 283), reused 479 (delta 222)\n    Receiving objects: 100% (550/550), 127.66 KiB | 58 KiB/s, done.\n    Resolving deltas: 100% (283/283), done.\n    project_name [My Awesome Project]: Reddit Clone\n    project_slug [reddit_clone]: reddit\n    description [Behold My Awesome Project!]: A reddit clone.\n    author_name [Daniel Roy Greenfeld]: Daniel Greenfeld\n    domain_name [example.com]: myreddit.com\n    email [daniel-greenfeld@example.com]: pydanny@gmail.com\n    version [0.1.0]: 0.0.1\n    Select open_source_license:\n    1 - MIT\n    2 - BSD\n    3 - GPLv3\n    4 - Apache Software License 2.0\n    5 - Not open source\n    Choose from 1, 2, 3, 4, 5 [1]: 1\n    Select username_type:\n    1 - username\n    2 - email\n    Choose from 1, 2 [1]: 1\n    timezone [UTC]: America/Los_Angeles\n    windows [n]: n\n    Select an editor to use. The choices are:\n    1 - None\n    2 - PyCharm\n    3 - VS Code\n    Choose from 1, 2, 3 [1]: 1\n    use_docker [n]: n\n    Select postgresql_version:\n    1 - 18\n    2 - 17\n    3 - 16\n    4 - 15\n    5 - 14\n    Choose from 1, 2, 3, 4 [1]: 1\n    Select cloud_provider:\n    1 - AWS\n    2 - GCP\n    3 - None\n    Choose from 1, 2, 3 [1]: 1\n    Select mail_service:\n    1 - Mailgun\n    2 - Amazon SES\n    3 - Mailjet\n    4 - Mandrill\n    5 - Postmark\n    6 - Sendgrid\n    7 - Brevo (formerly SendinBlue)\n    8 - SparkPost\n    9 - Other SMTP\n    Choose from 1, 2, 3, 4, 5, 6, 7, 8, 9 [1]: 1\n    Select rest_api [None]:\n    1 - None\n    2 - DRF\n    3 - Django Ninja\n    Choose from 1, 2, 3 [1]: 1\n    use_async [n]: n\n    Select frontend_pipeline:\n    1 - None\n    2 - Django Compressor\n    3 - Gulp\n    4 - Webpack\n    Choose from 1, 2, 3, 4 [1]: 1\n    use_celery [n]: y\n    use_mailpit [n]: n\n    use_sentry [n]: y\n    use_whitenoise [n]: n\n    use_heroku [n]: y\n    Select ci_tool:\n    1 - None\n    2 - Travis\n    3 - Gitlab\n    4 - Github\n    Choose from 1, 2, 3, 4 [1]: 4\n    keep_local_envs_in_vcs [y]: y\n    debug [n]: n\n\nEnter the project and take a look around:\n\n    cd reddit/\n    ls\n\nCreate a git repo and push it there:\n\n    git init\n    git add .\n    git commit -m \"first awesome commit\"\n    git remote add origin git@github.com:pydanny/redditclone.git\n    git push -u origin main\n\nNow take a look at your repo. Don't forget to carefully look at the generated README. Awesome, right?\n\nFor local development, see the following:\n\n- [Developing locally](https://cookiecutter-django.readthedocs.io/en/latest/2-local-development/developing-locally.html)\n- [Developing locally using docker](https://cookiecutter-django.readthedocs.io/en/latest/2-local-development/developing-locally-docker.html)\n\n## Community\n\n- Have questions? **Before you ask questions anywhere else**, please post your question on [Stack Overflow](http://stackoverflow.com/questions/tagged/cookiecutter-django) under the _cookiecutter-django_ tag. We check there periodically for questions.\n- If you think you found a bug or want to request a feature, please open an [issue](https://github.com/cookiecutter/cookiecutter-django/issues).\n- For anything else, you can chat with us on [Discord](https://discord.gg/uFXweDQc5a).\n\n<img src=\"https://opencollective.com/cookiecutter-django/contributors.svg?width=890&button=false\" alt=\"Contributors\">\n\n## For Readers of Two Scoops of Django\n\nYou may notice that some elements of this project do not exactly match what we describe in chapter 3. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.\n\n## For PyUp Users\n\nIf you are using [PyUp](https://pyup.io) to keep your dependencies updated and secure, use the code _cookiecutter_ during checkout to get 15% off every month.\n\n## \"Your Stuff\"\n\nScattered throughout the Python and HTML of this project are places marked with \"your stuff\". This is where third-party libraries are to be integrated with your project.\n\n## For MySQL users\n\nTo get full MySQL support in addition to the default Postgresql, you can use this fork of the cookiecutter-django:\nhttps://github.com/mabdullahadeel/cookiecutter-django-mysql\n\n## Releases\n\nNeed a stable release? You can find them at <https://github.com/cookiecutter/cookiecutter-django/releases>\n\n## Not Exactly What You Want?\n\nThis is what I want. _It might not be what you want._ Don't worry, you have options:\n\n### Fork This\n\nIf you have differences in your preferred setup, I encourage you to fork this to create your own version.\nOnce you have your fork working, let me know and I'll add it to a '_Similar Cookiecutter Templates_' list here.\nIt's up to you whether to rename your fork.\n\nIf you do rename your fork, I encourage you to submit it to the following places:\n\n- [cookiecutter](https://github.com/cookiecutter/cookiecutter) so it gets listed in the README as a template.\n- The cookiecutter [grid](https://www.djangopackages.com/grids/g/cookiecutters/) on Django Packages.\n\n### Submit a Pull Request\n\nWe accept pull requests if they're small, atomic, and make our own project development\nexperience better.\n\n## Articles\n\n- [Why cookiecutter-django is Essential for Your Next Django Project](https://medium.com/@millsks/why-cookiecutter-django-is-essential-for-your-next-django-project-7d3c00cdce51) - Aug. 4, 2024\n- [How to Make Your Own Django Cookiecutter Template!](https://medium.com/@FatemeFouladkar/how-to-make-your-own-django-cookiecutter-template-a753d4cbb8c2) - Aug. 10, 2023\n- [Cookiecutter Django With Amazon RDS](https://haseeburrehman.com/posts/cookiecutter-django-with-amazon-rds/) - Apr, 2, 2021\n- [Complete Walkthrough: Blue/Green Deployment to AWS ECS using GitHub actions](https://github.com/Andrew-Chen-Wang/cookiecutter-django-ecs-github) - June 10, 2020\n- [Using cookiecutter-django with Google Cloud Storage](https://ahhda.github.io/cloud/gce/django/2019/03/12/using-django-cookiecutter-cloud-storage.html) - Mar. 12, 2019\n- [cookiecutter-django with Nginx, Route 53 and ELB](https://msaizar.com/blog/cookiecutter-django-nginx-route-53-and-elb/) - Feb. 12, 2018\n- [cookiecutter-django and Amazon RDS](https://msaizar.com/blog/cookiecutter-django-and-amazon-rds/) - Feb. 7, 2018\n- [Using Cookiecutter to Jumpstart a Django Project on Windows with PyCharm](https://joshuahunter.com/posts/using-cookiecutter-to-jumpstart-a-django-project-on-windows-with-pycharm/) - May 19, 2017\n- [Exploring with Cookiecutter](http://www.snowboardingcoder.com/django/2016/12/03/exploring-with-cookiecutter/) - Dec. 3, 2016\n- [Introduction to Cookiecutter-Django](http://krzysztofzuraw.com/blog/2016/django-cookiecutter.html) - Feb. 19, 2016\n- [Django and GitLab - Running Continuous Integration and tests with your FREE account](http://dezoito.github.io/2016/05/11/django-gitlab-continuous-integration-phantomjs.html) - May. 11, 2016\n- [Development and Deployment of Cookiecutter-Django on Fedora](https://realpython.com/blog/python/development-and-deployment-of-cookiecutter-django-on-fedora/) - Jan. 18, 2016\n- [Development and Deployment of Cookiecutter-Django via Docker](https://realpython.com/blog/python/development-and-deployment-of-cookiecutter-django-via-docker/) - Dec. 29, 2015\n- [How to create a Django Application using Cookiecutter and Django 1.8](https://www.swapps.io/blog/how-to-create-a-django-application-using-cookiecutter-and-django-1-8/) - Sept. 12, 2015\n\nHave a blog or online publication? Write about your cookiecutter-django tips and tricks, then send us a pull request with the link.\n"
  },
  {
    "path": "cookiecutter.json",
    "content": "{\n  \"project_name\": \"My Awesome Project\",\n  \"project_slug\": \"{{ cookiecutter.project_name.lower()|replace(' ', '_')|replace('-', '_')|replace('.', '_')|trim() }}\",\n  \"description\": \"Behold My Awesome Project!\",\n  \"author_name\": \"Daniel Roy Greenfeld\",\n  \"domain_name\": \"example.com\",\n  \"email\": \"{{ cookiecutter.author_name.lower() | trim() |replace(' ', '-') }}@{{ cookiecutter.domain_name.lower() | trim() }}\",\n  \"version\": \"0.1.0\",\n  \"open_source_license\": [\n    \"MIT\",\n    \"BSD\",\n    \"GPLv3\",\n    \"Apache Software License 2.0\",\n    \"Not open source\"\n  ],\n  \"username_type\": [\"username\", \"email\"],\n  \"timezone\": \"UTC\",\n  \"windows\": \"n\",\n  \"editor\": [\"None\", \"PyCharm\", \"VS Code\"],\n  \"use_docker\": \"n\",\n  \"postgresql_version\": [\"18\", \"17\", \"16\", \"15\", \"14\"],\n  \"cloud_provider\": [\"AWS\", \"GCP\", \"Azure\", \"None\"],\n  \"mail_service\": [\n    \"Mailgun\",\n    \"Amazon SES\",\n    \"Mailjet\",\n    \"Mandrill\",\n    \"Postmark\",\n    \"Sendgrid\",\n    \"Brevo\",\n    \"SparkPost\",\n    \"Other SMTP\"\n  ],\n  \"rest_api\": [\"None\", \"DRF\", \"Django Ninja\"],\n  \"use_async\": \"n\",\n  \"frontend_pipeline\": [\"None\", \"Django Compressor\", \"Gulp\", \"Webpack\"],\n  \"use_celery\": \"n\",\n  \"use_mailpit\": \"n\",\n  \"use_sentry\": \"n\",\n  \"use_whitenoise\": \"n\",\n  \"use_heroku\": \"n\",\n  \"ci_tool\": [\"None\", \"Travis\", \"Gitlab\", \"Github\", \"Drone\"],\n  \"keep_local_envs_in_vcs\": \"y\",\n  \"debug\": \"n\"\n}\n"
  },
  {
    "path": "docs/1-getting-started/project-generation-options.rst",
    "content": ".. _template-options:\n\nProject Generation Options\n==========================\n\nThis page describes all the template options that will be prompted by the `cookiecutter CLI`_ prior to generating your project.\n\n.. _cookiecutter CLI: https://github.com/cookiecutter/cookiecutter\n\nproject_name:\n    Your project's human-readable name, capitals and spaces allowed.\n\nproject_slug:\n    Your project's slug without dashes or spaces. Used to name your repo\n    and in other places where a Python-importable version of your project name\n    is needed.\n\ndescription:\n    Describes your project and gets used in places like ``README.rst`` and such.\n\nauthor_name:\n    This is you! The value goes into places like ``LICENSE`` and such.\n\nemail:\n    The email address you want to identify yourself in the project.\n\nusername_type:\n    The type of username you want to use in the project. This can be either\n    ``username`` or ``email``. If you choose ``username``, the ``email`` field\n    will be included. If you choose ``email``, the ``username`` field will be\n    excluded. It is best practice to always include an email field, so there is\n    no option for having just the ``username`` field.\n\ndomain_name:\n    The domain name you plan to use for your project once it goes live.\n    Note that it can be safely changed later on whenever you need to.\n\nversion:\n    The version of the project at its inception.\n\nopen_source_license:\n    A software license for the project. The choices are:\n\n    1. MIT_\n    2. BSD_\n    3. GPLv3_\n    4. `Apache Software License 2.0`_\n    5. Not open source\n\ntimezone:\n    The value to be used for the ``TIME_ZONE`` setting of the project.\n\nwindows:\n    Indicates whether the project should be configured for development on Windows.\n\neditor:\n    Select an editor to use. The choices are:\n\n    1. None\n    2. PyCharm_\n    3. `VS Code`_\n\nuse_docker:\n    Indicates whether the project should be configured to use Docker_, `Docker Compose`_ and `devcontainer`_.\n\npostgresql_version:\n    Select a PostgreSQL_ version to use. The choices are:\n\n    1. 18\n    2. 17\n    3. 16\n    4. 15\n    5. 14\n\ncloud_provider:\n    Select a cloud provider for static & media files. The choices are:\n\n    1. AWS_\n    2. GCP_\n    3. Azure_\n    4. None\n\n    If you choose no cloud provider and docker, the production stack will serve the media files via an nginx Docker service. Without Docker, the media files won't work.\n\nmail_service:\n    Select an email service that Django-Anymail provides\n\n    1. Mailgun_\n    2. `Amazon SES`_\n    3. Mailjet_\n    4. Mandrill_\n    5. Postmark_\n    6. SendGrid_\n    7. `Brevo (formerly SendinBlue)`_\n    8. SparkPost_\n    9. `Other SMTP`_\n\nrest_api:\n    Select a REST API framework to use. The choices are:\n\n    1. None\n    2. `Django Rest Framework`_\n    3. `Django Ninja`_\n\nuse_async:\n    Indicates whether the project should use web sockets with Uvicorn + Gunicorn.\n\nfrontend_pipeline:\n    Select a pipeline to compile and optimise frontend assets (JS, CSS, ...):\n\n    1. None\n    2. `Django Compressor`_\n    3. `Gulp`_\n    4. `Webpack`_\n\nBoth Gulp and Webpack support Bootstrap recompilation with real-time variables alteration.\n\nuse_celery:\n    Indicates whether the project should be configured to use Celery_.\n\nuse_mailpit:\n    Indicates whether the project should be configured to use Mailpit_.\n\nuse_sentry:\n    Indicates whether the project should be configured to use Sentry_.\n\nuse_whitenoise:\n    Indicates whether the project should be configured to use WhiteNoise_.\n\nuse_heroku:\n    Indicates whether the project should be configured so as to be deployable\n    to Heroku_.\n\nci_tool:\n    Select a CI tool for running tests. The choices are:\n\n    1. None\n    2. `Travis CI`_\n    3. `Gitlab CI`_\n    4. `Github Actions`_\n    5. `Drone CI`_\n\nkeep_local_envs_in_vcs:\n\nIndicates whether the project’s .envs/.local/ should be kept in VCS (comes in handy when working in teams where local environment reproducibility is strongly encouraged).\n\ndebug:\n    Indicates whether the project should be configured for debugging.\n    This option is relevant for Cookiecutter Django developers only.\n\n\n.. _MIT: https://opensource.org/licenses/MIT\n.. _BSD: https://opensource.org/licenses/BSD-3-Clause\n.. _GPLv3: https://www.gnu.org/licenses/gpl.html\n.. _Apache Software License 2.0: https://www.apache.org/licenses/LICENSE-2.0\n\n.. _PyCharm: https://www.jetbrains.com/pycharm/\n.. _VS Code: https://github.com/microsoft/vscode\n\n.. _Docker: https://github.com/docker/docker\n.. _Docker Compose: https://docs.docker.com/compose/\n.. _devcontainer: https://containers.dev/\n\n.. _PostgreSQL: https://www.postgresql.org/docs/\n\n.. _Gulp: https://github.com/gulpjs/gulp\n.. _Webpack: https://webpack.js.org\n\n.. _AWS: https://aws.amazon.com/s3/\n.. _GCP: https://cloud.google.com/storage/\n.. _Azure: https://azure.microsoft.com/en-us/products/storage/blobs/\n\n.. _Amazon SES: https://aws.amazon.com/ses/\n.. _Mailgun: https://www.mailgun.com\n.. _Mailjet: https://www.mailjet.com\n.. _Mandrill: http://mandrill.com\n.. _Postmark: https://postmarkapp.com\n.. _SendGrid: https://sendgrid.com\n.. _Brevo (formerly SendinBlue): https://www.brevo.com\n.. _SparkPost: https://www.sparkpost.com\n.. _Other SMTP: https://anymail.readthedocs.io/en/stable/\n\n.. _Django Rest Framework: https://github.com/encode/django-rest-framework/\n.. _Django Ninja: https://github.com/vitalik/django-ninja\n\n.. _Django Compressor: https://github.com/django-compressor/django-compressor\n\n.. _Celery: https://github.com/celery/celery\n\n.. _Mailpit: https://github.com/axllent/mailpit\n\n.. _Sentry: https://github.com/getsentry/sentry\n\n.. _WhiteNoise: https://github.com/evansd/whitenoise\n\n.. _Heroku: https://github.com/heroku/heroku-buildpack-python\n\n.. _Travis CI: https://travis-ci.org/\n\n.. _GitLab CI: https://docs.gitlab.com/ee/ci/\n\n.. _Drone CI: https://docs.drone.io/pipeline/overview/\n\n.. _Github Actions: https://docs.github.com/en/actions\n"
  },
  {
    "path": "docs/1-getting-started/settings.rst",
    "content": ".. _settings:\n\nSettings\n========\n\nThis project relies extensively on environment settings which **will not work with Apache/mod_wsgi setups**. It has been deployed successfully with both Gunicorn/Nginx and even uWSGI/Nginx.\n\nFor configuration purposes, the following table maps environment variables to their Django setting and project settings:\n\n\n======================================= =========================== ============================================== ======================================================================\nEnvironment Variable                    Django Setting              Development Default                            Production Default\n======================================= =========================== ============================================== ======================================================================\nDJANGO_READ_DOT_ENV_FILE                READ_DOT_ENV_FILE           False                                          False\n======================================= =========================== ============================================== ======================================================================\n\n\n======================================= =========================== ============================================== ======================================================================\nEnvironment Variable                    Django Setting              Development Default                            Production Default\n======================================= =========================== ============================================== ======================================================================\nDATABASE_URL                            DATABASES                   auto w/ Docker; postgres://project_slug w/o    raises error\nDJANGO_ADMIN_URL                        n/a                         'admin/'                                       raises error\nDJANGO_DEBUG                            DEBUG                       True                                           False\nDJANGO_SECRET_KEY                       SECRET_KEY                  auto-generated                                 raises error\nDJANGO_SECURE_SSL_REDIRECT              SECURE_SSL_REDIRECT         n/a                                            True\nDJANGO_SECURE_CONTENT_TYPE_NOSNIFF      SECURE_CONTENT_TYPE_NOSNIFF n/a                                            True\nDJANGO_SECURE_FRAME_DENY                SECURE_FRAME_DENY           n/a                                            True\nDJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS   HSTS_INCLUDE_SUBDOMAINS     n/a                                            True\nDJANGO_SESSION_COOKIE_HTTPONLY          SESSION_COOKIE_HTTPONLY     n/a                                            True\nDJANGO_SESSION_COOKIE_SECURE            SESSION_COOKIE_SECURE       n/a                                            False\nDJANGO_DEFAULT_FROM_EMAIL               DEFAULT_FROM_EMAIL          n/a                                            \"your_project_name <noreply@your_domain_name>\"\nDJANGO_SERVER_EMAIL                     SERVER_EMAIL                n/a                                            \"your_project_name <noreply@your_domain_name>\"\nDJANGO_EMAIL_SUBJECT_PREFIX             EMAIL_SUBJECT_PREFIX        n/a                                            \"[your_project_name] \"\nDJANGO_ALLOWED_HOSTS                    ALLOWED_HOSTS               ['*']                                          ['your_domain_name']\n======================================= =========================== ============================================== ======================================================================\n\nThe following table lists settings and their defaults for third-party applications, which may or may not be part of your project:\n\n======================================= =========================== ============================================== ======================================================================\nEnvironment Variable                    Django Setting              Development Default                            Production Default\n======================================= =========================== ============================================== ======================================================================\nDJANGO_AWS_ACCESS_KEY_ID                AWS_ACCESS_KEY_ID           n/a                                            raises error\nDJANGO_AWS_SECRET_ACCESS_KEY            AWS_SECRET_ACCESS_KEY       n/a                                            raises error\nDJANGO_AWS_STORAGE_BUCKET_NAME          AWS_STORAGE_BUCKET_NAME     n/a                                            raises error\nDJANGO_AWS_S3_REGION_NAME               AWS_S3_REGION_NAME          n/a                                            None\nDJANGO_AWS_S3_CUSTOM_DOMAIN             AWS_S3_CUSTOM_DOMAIN        n/a                                            None\nDJANGO_AWS_S3_MAX_MEMORY_SIZE           AWS_S3_MAX_MEMORY_SIZE      n/a                                            100_000_000\nDJANGO_GCP_STORAGE_BUCKET_NAME          GS_BUCKET_NAME              n/a                                            raises error\nGOOGLE_APPLICATION_CREDENTIALS          n/a                         n/a                                            raises error\nDJANGO_AZURE_ACCOUNT_KEY                AZURE_ACCOUNT_KEY           n/a                                            raises error\nDJANGO_AZURE_ACCOUNT_NAME               AZURE_ACCOUNT_NAME          n/a                                            raises error\nDJANGO_AZURE_CONTAINER_NAME             AZURE_CONTAINER             n/a                                            raises error\nSENTRY_DSN                              SENTRY_DSN                  n/a                                            raises error\nSENTRY_ENVIRONMENT                      n/a                         n/a                                            production\nSENTRY_TRACES_SAMPLE_RATE               n/a                         n/a                                            0.0\nDJANGO_SENTRY_LOG_LEVEL                 SENTRY_LOG_LEVEL            n/a                                            logging.INFO\nMAILGUN_API_KEY                         MAILGUN_API_KEY             n/a                                            raises error\nMAILGUN_DOMAIN                          MAILGUN_SENDER_DOMAIN       n/a                                            raises error\nMAILGUN_API_URL                         n/a                         n/a                                            \"https://api.mailgun.net/v3\"\nMAILJET_API_KEY                         MAILJET_API_KEY             n/a                                            raises error\nMAILJET_SECRET_KEY                      MAILJET_SECRET_KEY          n/a                                            raises error\nMAILJET_API_URL                         n/a                         n/a                                            \"https://api.mailjet.com/v3\"\nMANDRILL_API_KEY                        MANDRILL_API_KEY            n/a                                            raises error\nMANDRILL_API_URL                        n/a                         n/a                                            \"https://mandrillapp.com/api/1.0\"\nPOSTMARK_SERVER_TOKEN                   POSTMARK_SERVER_TOKEN       n/a                                            raises error\nPOSTMARK_API_URL                        n/a                         n/a                                            \"https://api.postmarkapp.com/\"\nSENDGRID_API_KEY                        SENDGRID_API_KEY            n/a                                            raises error\nSENDGRID_GENERATE_MESSAGE_ID            True                        n/a                                            raises error\nSENDGRID_MERGE_FIELD_FORMAT             None                        n/a                                            raises error\nSENDGRID_API_URL                        n/a                         n/a                                            \"https://api.sendgrid.com/v3/\"\nBREVO_API_KEY                           BREVO_API_KEY               n/a                                            raises error\nBREVO_API_URL                           n/a                         n/a                                            \"https://api.brevo.com/v3/\"\nSPARKPOST_API_KEY                       SPARKPOST_API_KEY           n/a                                            raises error\nSPARKPOST_API_URL                       n/a                         n/a                                            \"https://api.sparkpost.com/api/v1\"\n======================================= =========================== ============================================== ======================================================================\n\n--------------------------\nOther Environment Settings\n--------------------------\n\nDJANGO_ACCOUNT_ALLOW_REGISTRATION (=True)\n    Allow enable or disable user registration through `django-allauth` without disabling other characteristics like authentication and account management. (Django Setting: ACCOUNT_ALLOW_REGISTRATION)\n\nDJANGO_ADMIN_FORCE_ALLAUTH (=False)\n    Force the `admin` sign in process to go through the `django-allauth` workflow.\n"
  },
  {
    "path": "docs/2-local-development/developing-locally-docker.rst",
    "content": "Getting Up and Running Locally With Docker\n==========================================\n\n.. index:: Docker\n\n.. note::\n\n    If you're new to Docker, please be aware that some resources are cached system-wide\n    and might reappear if you generate a project multiple times with the same name (e.g.\n    :ref:`this issue with Postgres <docker-postgres-auth-failed>`).\n\n\nPrerequisites\n-------------\n\n* Docker; if you don't have it yet, follow the `installation instructions`_;\n* Docker Compose; refer to the official documentation for the `installation guide`_.\n* Pre-commit; refer to the official documentation for the `pre-commit`_.\n* Cookiecutter; refer to the official GitHub repository of `Cookiecutter`_\n\n.. _`installation instructions`: https://docs.docker.com/install/\n.. _`installation guide`: https://docs.docker.com/compose/install/\n.. _`pre-commit`: https://pre-commit.com/#install\n.. _`Cookiecutter`: https://github.com/cookiecutter/cookiecutter\n\nBefore Getting Started\n----------------------\n.. include:: generate-project-block.rst\n\nBuild the Stack\n---------------\n\nThis can take a while, especially the first time you run this particular command on your development system::\n\n    docker compose -f docker-compose.local.yml build\n\nGenerally, if you want to emulate production environment use ``docker-compose.production.yml`` instead. And this is true for any other actions you might need to perform: whenever a switch is required, just do it!\n\nAfter we have created our initial image we nee to generate a lockfile for our dependencies.\nDocker cannot write to the host system during builds, so we have to run the command to generate the lockfile in the container.\nThis is important for reproducible builds and to ensure that the dependencies are installed correctly in the container.\nUpdating the lockfile manually is normally not necessary when you add packages through `uv add <package_name>`.\n\n    docker compose -f docker-compose.local.yml run --rm django uv lock\n\nThis is done by running the following command: ::\n\n    docker compose -f docker-compose.local.yml run --rm django uv lock\n\nTo be sure we are on the right track we need to build our image again: ::\n\n    docker compose -f docker-compose.local.yml build\n\n\n\n\nBefore doing any git commit, `pre-commit`_ should be installed globally on your local machine, and then::\n\n    git init\n    pre-commit install\n\nFailing to do so will result with a bunch of CI and Linter errors that can be avoided with pre-commit.\n\nRun the Stack\n-------------\n\nThis brings up both Django and PostgreSQL. The first time it is run it might take a while to get started, but subsequent runs will occur quickly.\n\nOpen a terminal at the project root and run the following for local development::\n\n    docker compose -f docker-compose.local.yml up\n\nYou can also set the environment variable ``COMPOSE_FILE`` pointing to ``docker-compose.local.yml`` like this::\n\n    export COMPOSE_FILE=docker-compose.local.yml\n\nAnd then run::\n\n    docker compose up\n\nTo run in a detached (background) mode, just::\n\n    docker compose up -d\n\nThese commands don't run the docs service. In order to run docs service you can run::\n\n    docker compose -f docker-compose.docs.yml up\n\nTo run the docs with local services just use::\n\n    docker compose -f docker-compose.local.yml -f docker-compose.docs.yml up\n\nThe site should start and be accessible at http://localhost:3000 if you selected Webpack or Gulp as frontend pipeline and http://localhost:8000 otherwise.\n\nExecute Management Commands\n---------------------------\n\nAs with any shell command that we wish to run in our container, this is done using the ``docker compose -f docker-compose.local.yml run --rm`` command: ::\n\n    docker compose -f docker-compose.local.yml run --rm django python manage.py migrate\n    docker compose -f docker-compose.local.yml run --rm django python manage.py createsuperuser\n\nHere, ``django`` is the target service we are executing the commands against.\nAlso, please note that the ``docker exec`` does not work for running management commands.\n\n(Optionally) Designate your Docker Development Server IP\n--------------------------------------------------------\n\nWhen ``DEBUG`` is set to ``True``, the host is validated against ``['localhost', '127.0.0.1', '[::1]']``. This is adequate when running a ``virtualenv``. For Docker, in the ``config.settings.local``, add your host development server IP to ``INTERNAL_IPS`` or ``ALLOWED_HOSTS`` if the variable exists.\n\n.. _envs:\n\nConfiguring the Environment\n---------------------------\n\nThis is the excerpt from your project's ``docker-compose.local.yml``: ::\n\n  # ...\n\n  postgres:\n    build:\n      context: .\n      dockerfile: ./compose/production/postgres/Dockerfile\n    volumes:\n      - local_postgres_data:/var/lib/postgresql/data\n      - local_postgres_data_backups:/backups\n    env_file:\n      - ./.envs/.local/.postgres\n\n  # ...\n\nThe most important thing for us here now is ``env_file`` section enlisting ``./.envs/.local/.postgres``. Generally, the stack's behavior is governed by a number of environment variables (`env(s)`, for short) residing in ``envs/``, for instance, this is what we generate for you: ::\n\n    .envs\n    ├── .local\n    │   ├── .django\n    │   └── .postgres\n    └── .production\n        ├── .django\n        └── .postgres\n\nBy convention, for any service ``sI`` in environment ``e`` (you know ``someenv`` is an environment when there is a ``someenv.yml`` file in the project root), given ``sI`` requires configuration, a ``.envs/.e/.sI`` `service configuration` file exists.\n\nConsider the aforementioned ``.envs/.local/.postgres``: ::\n\n    # PostgreSQL\n    # ------------------------------------------------------------------------------\n    POSTGRES_HOST=postgres\n    POSTGRES_DB=<your project slug>\n    POSTGRES_USER=XgOWtQtJecsAbaIyslwGvFvPawftNaqO\n    POSTGRES_PASSWORD=jSljDz4whHuwO3aJIgVBrqEml5Ycbghorep4uVJ4xjDYQu0LfuTZdctj7y0YcCLu\n\nThe three envs we are presented with here are ``POSTGRES_DB``, ``POSTGRES_USER``, and ``POSTGRES_PASSWORD`` (by the way, their values have also been generated for you). You might have figured out already where these definitions will end up; it's all the same with ``django`` service container envs.\n\nOne final touch: should you ever need to merge ``.envs/.production/*`` in a single ``.env`` run the ``merge_production_dotenvs_in_dotenv.py``: ::\n\n    python merge_production_dotenvs_in_dotenv.py\n\nThe ``.env`` file will then be created, with all your production envs residing beside each other.\n\n\nTips & Tricks\n-------------\n\nActivate a Docker Machine\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis tells our computer that all future commands are specifically for the dev1 machine. Using the ``eval`` command we can switch machines as needed.::\n\n    eval \"$(docker-machine env dev1)\"\n\nAdd 3rd party python packages\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo install a new 3rd party python package, you cannot use ``uv add <package_name>``, that would only add the package to the container. The container is ephemeral, so that new library won't be persisted if you run another container. Instead, you should modify the Docker image:\nYou have to modify pyproject.toml and either add it to project.dependencies or to tool.uv.dev-dependencies by adding: ::\n\n    \"<package_name>==<package_version>\"\n\nTo get this change picked up, you'll need to rebuild the image(s) and restart the running container: ::\n\n    docker compose -f docker-compose.local.yml build\n    docker compose -f docker-compose.local.yml up\n\nDebugging\n~~~~~~~~~\n\nipdb\n\"\"\"\"\"\n\nIf you are using the following within your code to debug: ::\n\n    import ipdb; ipdb.set_trace()\n\nThen you may need to run the following for it to work as desired: ::\n\n    docker compose -f docker-compose.local.yml run --rm --service-ports django\n\n\ndjango-debug-toolbar\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nIn order for ``django-debug-toolbar`` to work designate your Docker Machine IP with ``INTERNAL_IPS`` in ``local.py``.\n\n\ndocker\n\"\"\"\"\"\"\n\nThe ``container_name`` from the yml file can be used to check on containers with docker commands, for example: ::\n\n    docker logs <project_slug>_local_celeryworker\n    docker top <project_slug>_local_celeryworker\n\nNotice that the ``container_name`` is generated dynamically using your project slug as a prefix\n\nMailpit\n~~~~~~~\n\nWhen developing locally you can go with Mailpit_ for email testing provided ``use_mailpit`` was set to ``y`` on setup. To proceed,\n\n#. make sure ``<project_slug>_local_mailpit`` container is up and running;\n\n#. open up ``http://127.0.0.1:8025``.\n\n.. _Mailpit: https://github.com/axllent/mailpit/\n\n.. _`CeleryTasks`:\n\nCelery tasks in local development\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nWhen not using docker Celery tasks are set to run in Eager mode, so that a full stack is not needed. When using docker the task scheduler will be used by default.\n\nIf you need tasks to be executed on the main thread during development set ``CELERY_TASK_ALWAYS_EAGER = True`` in ``config/settings/local.py``.\n\nPossible uses could be for testing, or ease of profiling with DJDT.\n\n.. _`CeleryFlower`:\n\nCelery Flower\n~~~~~~~~~~~~~\n\n`Flower`_ is a \"real-time monitor and web admin for Celery distributed task queue\".\n\nPrerequisites:\n\n* ``use_docker`` was set to ``y`` on project initialization;\n* ``use_celery`` was set to ``y`` on project initialization.\n\nBy default, it's enabled both in local and production environments (``docker-compose.local.yml`` and ``docker-compose.production.yml`` Docker Compose configs, respectively) through a ``flower`` service. For added security, ``flower`` requires its clients to provide authentication credentials specified as the corresponding environments' ``.envs/.local/.django`` and ``.envs/.production/.django`` ``CELERY_FLOWER_USER`` and ``CELERY_FLOWER_PASSWORD`` environment variables. Check out ``localhost:5555`` and see for yourself.\n\n.. _`Flower`: https://github.com/mher/flower\n\nUsing Webpack or Gulp\n~~~~~~~~~~~~~~~~~~~~~\n\nIf you've opted for Gulp or Webpack as front-end pipeline, the project comes configured with `Sass`_ compilation and `live reloading`_. As you change your Sass/JS source files, the task runner will automatically rebuild the corresponding CSS and JS assets and reload them in your browser without refreshing the page.\n\nThe stack comes with a dedicated node service to build the static assets, watch for changes and proxy requests to the Django app with live reloading scripts injected in the response. For everything to work smoothly, you need to access the application at the port served by the node service, which is http://localhost:3000 by default.\n\n.. _Sass: https://sass-lang.com/\n.. _live reloading: https://browsersync.io\n\n\nUsing Just for Docker Commands\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWe have included a ``justfile`` to simplify the use of frequent Docker commands for local development.\n\n.. warning::\n    Currently, \"Just\" does not reliably handle signals or forward them to its subprocesses. As a result,\n    pressing CTRL+C (or sending other signals like SIGTERM, SIGINT, or SIGHUP) may only interrupt\n    \"Just\" itself rather than its subprocesses.\n    For more information, see `this GitHub issue <https://github.com/casey/just/issues/2473>`_.\n\nFirst, install Just using one of the methods described in the `official documentation <https://just.systems/man/en/packages.html>`_.\n\nHere are the available commands:\n\n- ``just build``\n  Builds the Python image using the local Docker Compose file.\n\n- ``just up``\n  Starts the containers in detached mode and removes orphaned containers.\n\n- ``just down``\n  Stops the running containers.\n\n- ``just prune``\n  Stops and removes containers along with their volumes. You can optionally pass an argument with the service name to prune a single container.\n\n- ``just logs``\n  Shows container logs. You can optionally pass an argument with the service name to view logs for a specific service.\n\n- ``just manage <command>``\n  Runs Django management commands within the container. Replace ``<command>`` with any valid Django management command, such as ``migrate``, ``createsuperuser``, or ``shell``.\n\n\n(Optionally) Developing locally with HTTPS\n------------------------------------------\n\nNginx\n~~~~~\n\nIf you want to add some sort of social authentication with a OAuth provider such as Facebook, securing your communication to the local development environment will be necessary. These providers usually require that you use an HTTPS URL for the OAuth redirect URL for the Facebook login to work appropriately.\n\nHere is a link to an article on `how to add HTTPS using Nginx`_ to your local docker installation. This also includes how to serve files from the ``media`` location, in the event that you are want to serve user-uploaded content.\n\n.. _`how to add HTTPS using Nginx`: https://afroshok.com/cookiecutter-https\n\nWebpack\n~~~~~~~\n\nIf you are using Webpack, first install `mkcert`_. It is a simple by design tool that hides all the arcane knowledge required to generate valid TLS certificates. It works for any hostname or IP, including localhost. It supports macOS, Linux, and Windows, and Firefox, Chrome and Java. It even works on mobile devices with a couple manual steps. See https://blog.filippo.io/mkcert-valid-https-certificates-for-localhost/\n\n.. _`mkcert`:  https://github.com/FiloSottile/mkcert/blob/master/README.md#supported-root-stores\n\nThese are the places that you should configure to secure your local environment. Take the certificates that you generated and place them in a folder called ``certs`` in the project's root folder. Configure an ``nginx`` reverse-proxy server as a ``service`` in the ``docker-compose.local.yml``. This makes sure that it does not interfere with our ``traefik`` configuration that is reserved for production environments.\n\nAssuming that you registered your local hostname as ``my-dev-env.local``, the certificates you will put in the folder should have the names ``my-dev-env.local.crt`` and ``my-dev-env.local.key``.\n\n1. Add the ``nginx-proxy`` service to the ``docker-compose.local.yml``. ::\n\n    nginx-proxy:\n      image: jwilder/nginx-proxy:alpine\n      container_name: nginx-proxy\n      ports:\n        - \"80:80\"\n        - \"443:443\"\n      volumes:\n        - /var/run/docker.sock:/tmp/docker.sock:ro\n        - ./certs:/etc/nginx/certs\n      restart: always\n      depends_on:\n        - node\n      environment:\n        - VIRTUAL_HOST=my-dev-env.local\n        - VIRTUAL_PORT=3000\n\n2. Add the local secure domain to the ``config/settings/local.py``. You should allow the new hostname ::\n\n    ALLOWED_HOSTS = [\"localhost\", \"0.0.0.0\", \"127.0.0.1\", \"my-dev-env.local\"]\n\n3. Add the following configuration to the ``devServer`` section of ``webpack/dev.config.js`` ::\n\n    client: {\n      webSocketURL: 'auto://0.0.0.0:0/ws', // note the `:0` after `0.0.0.0`\n    },\n\n\nRebuild your ``docker`` application. ::\n\n    docker compose -f docker-compose.local.yml up -d --build\n\nGo to your browser and type in your URL bar ``https://my-dev-env.local``.\n\nFor more on this configuration, see `https with nginx`_.\n\n.. _`https with nginx`: https://codewithhugo.com/docker-compose-local-https/\n"
  },
  {
    "path": "docs/2-local-development/developing-locally.rst",
    "content": "Getting Up and Running Locally\n==============================\n\n.. index:: PostgreSQL\n\n\nSetting Up Development Environment\n----------------------------------\n\nMake sure to have the following on your host:\n\n* uv https://docs.astral.sh/uv/getting-started/installation/\n* PostgreSQL_.\n* Redis_, if using Celery\n* Cookiecutter_\n\n#. .. include:: generate-project-block.rst\n\n#. Install development requirements: ::\n\n    cd <what you have entered as the project_slug at setup stage>\n    uv sync\n    git init # A git repo is required for pre-commit to install\n    uv run pre-commit install\n\n   .. note::\n\n       the `pre-commit` hook exists in the generated project as default.\n       For the details of `pre-commit`, follow the `pre-commit`_ site.\n\n#. Create a new PostgreSQL database using createdb_: ::\n\n    createdb --username=postgres <project_slug>\n\n   ``project_slug`` is what you have entered as the project_slug at the setup stage.\n\n   .. note::\n\n       if this is the first time a database is created on your machine you might need an\n       `initial PostgreSQL set up`_ to allow local connections & set a password for\n       the ``postgres`` user. The `postgres documentation`_ explains the syntax of the config file\n       that you need to change.\n\n\n#. Set the environment variables for your database(s): ::\n\n    export DATABASE_URL=postgres://postgres:<password>@127.0.0.1:5432/<DB name given to createdb>\n\n   .. note::\n\n       Check out the :ref:`settings` page for a comprehensive list of the environments variables.\n\n   .. seealso::\n\n       To help setting up your environment variables, you have a few options:\n\n       * create an ``.env`` file in the root of your project and define all the variables you need in it.\n         Then you just need to have ``DJANGO_READ_DOT_ENV_FILE=True`` in your machine and all the variables\n         will be read.\n       * Use a local environment manager like `direnv`_\n\n#. Apply migrations: ::\n\n    uv run python manage.py migrate\n\n#. If you're running synchronously, see the application being served through Django development server: ::\n\n    uv run python manage.py runserver 0.0.0.0:8000\n\n   or if you're running asynchronously: ::\n\n    uv run uvicorn config.asgi:application --host 0.0.0.0 --reload --reload-include '*.html'\n\n   If you've opted for Webpack or Gulp as frontend pipeline, please see the :ref:`dedicated section <bare-metal-webpack-gulp>` below.\n\n.. _PostgreSQL: https://www.postgresql.org/download/\n.. _Redis: https://redis.io/download\n.. _CookieCutter: https://github.com/cookiecutter/cookiecutter\n.. _createdb: https://www.postgresql.org/docs/current/static/app-createdb.html\n.. _initial PostgreSQL set up: https://web.archive.org/web/20190303010033/http://suite.opengeo.org/docs/latest/dataadmin/pgGettingStarted/firstconnect.html\n.. _postgres documentation: https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html\n.. _pre-commit: https://pre-commit.com/\n.. _direnv: https://direnv.net/\n\n\nCreating Your First Django App\n-------------------------------\n\nAfter setting up your environment, you're ready to add your first app. This project uses the setup from \"Two Scoops of Django\" with a two-tier layout:\n\n- **Top Level Repository Root** has config files, documentation, `manage.py`, and more.\n- **Second Level Django Project Root** is where your Django apps live.\n- **Second Level Configuration Root** holds settings and URL configurations.\n\nThe project layout looks something like this: ::\n\n    <repository_root>/\n    ├── config/\n    │   ├── settings/\n    │   │   ├── __init__.py\n    │   │   ├── base.py\n    │   │   ├── local.py\n    │   │   └── production.py\n    │   ├── urls.py\n    │   └── wsgi.py\n    ├── <django_project_root>/\n    │   ├── <name_of_the_app>/\n    │   │   ├── migrations/\n    │   │   ├── admin.py\n    │   │   ├── apps.py\n    │   │   ├── models.py\n    │   │   ├── tests.py\n    │   │   └── views.py\n    │   ├── __init__.py\n    │   └── ...\n    ├── requirements/\n    │   ├── base.txt\n    │   ├── local.txt\n    │   └── production.txt\n    ├── manage.py\n    ├── README.md\n    └── ...\n\n\nFollowing this structured approach, here's how to add a new app:\n\n#. **Create the app** using Django's ``startapp`` command, replacing ``<name-of-the-app>`` with your desired app name: ::\n\n    uv run python manage.py startapp <name-of-the-app>\n\n#. **Move the app** to the Django Project Root, maintaining the project's two-tier structure: ::\n\n    mv <name-of-the-app> <django_project_root>/\n\n#. **Edit the app's apps.py** change ``name = '<name-of-the-app>'`` to ``name = '<django_project_root>.<name-of-the-app>'``.\n\n#. **Register the new app** by adding it to the ``LOCAL_APPS`` list in ``config/settings/base.py``, integrating it as an official component of your project.\n\n\n\nSetup Email Backend\n-------------------\n\nMailpit\n~~~~~~~\n\n.. note:: In order for the project to support Mailpit_ it must have been bootstrapped with ``use_mailpit`` set to ``y``.\n\nMailpit is used to receive emails during development, it is written in Go and has no external dependencies.\n\nFor instance, one of the packages we depend upon, ``django-allauth`` sends verification emails to new users signing up as well as to the existing ones who have not yet verified themselves.\n\n#. `Download the latest Mailpit release`_ for your OS.\n\n#. Copy the binary file to the project root.\n\n#. Make it executable: ::\n\n    chmod +x mailpit\n\n#. Spin up another terminal window and start it there: ::\n\n    ./mailpit\n\n#. Check out `<http://127.0.0.1:8025/>`_ to see how it goes.\n\nNow you have your own mail server running locally, ready to receive whatever you send it.\n\n.. _`Download the latest Mailpit release`: https://github.com/axllent/mailpit\n\nConsole\n~~~~~~~\n\n.. note:: If you have generated your project with ``use_mailpit`` set to ``n`` this will be a default setup.\n\nAlternatively, deliver emails over console via ``EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'``.\n\nIn production, we have Mailgun_ configured to have your back!\n\n.. _Mailgun: https://www.mailgun.com/\n\n\nCelery\n------\n\nIf the project is configured to use Celery as a task scheduler then, by default, tasks are set to run on the main thread when developing locally instead of getting sent to a broker. However, if you have Redis setup on your local machine, you can set the following in ``config/settings/local.py``::\n\n    CELERY_TASK_ALWAYS_EAGER = False\n\nNext, make sure `redis-server` is installed (per the `Getting started with Redis`_ guide) and run the server in one terminal::\n\n    redis-server\n\nStart the Celery worker by running the following command in another terminal::\n\n    uv run celery -A config.celery_app worker --loglevel=info\n\nThat Celery worker should be running whenever your app is running, typically as a background process,\nso that it can pick up any tasks that get queued. Learn more from the `Celery Workers Guide`_.\n\nThe project comes with a simple task for manual testing purposes, inside `<project_slug>/users/tasks.py`. To queue that task locally, start the Django shell, import the task, and call `delay()` on it::\n\n    uv run python manage.py shell\n    >> from <project_slug>.users.tasks import get_users_count\n    >> get_users_count.delay()\n\nYou can also use Django admin to queue up tasks, thanks to the `django-celerybeat`_ package.\n\n.. _Getting started with Redis: https://redis.io/docs/latest/get-started/\n.. _Celery Workers Guide: https://docs.celeryq.dev/en/stable/userguide/workers.html\n.. _django-celerybeat: https://django-celery-beat.readthedocs.io/en/latest/\n\n\n.. _bare-metal-webpack-gulp:\n\nUsing Webpack or Gulp\n---------------------\n\nIf you've opted for Gulp or Webpack as front-end pipeline, the project comes configured with `Sass`_ compilation and `live reloading`_. As you change your Sass/JS source files, the task runner will automatically rebuild the corresponding CSS and JS assets and reload them in your browser without refreshing the page.\n\n#. Make sure that `Node.js`_ v18 is installed on your machine.\n#. In the project root, install the JS dependencies with::\n\n    npm install\n\n#. Now - with your virtualenv activated - start the application by running::\n\n    npm run dev\n\n   This will start 2 processes in parallel: the static assets build loop on one side, and the Django server on the other.\n\n#. Access your application at the address of the ``node`` service in order to see your correct styles. This is http://localhost:3000 by default.\n\n   .. note:: Do NOT access the application using the Django port (8000 by default), as it will result in broken styles and 404s when accessing static assets.\n\n\n.. _Node.js: http://nodejs.org/download/\n.. _Sass: https://sass-lang.com/\n.. _live reloading: https://browsersync.io\n\nSummary\n-------\n\nCongratulations, you have made it! Keep on reading to unleash full potential of Cookiecutter Django.\n"
  },
  {
    "path": "docs/2-local-development/generate-project-block.rst",
    "content": "Generate a new cookiecutter-django project: ::\n\n    $ cookiecutter gh:cookiecutter/cookiecutter-django\n\nFor more information refer to\n:ref:`Project Generation Options <template-options>`.\n"
  },
  {
    "path": "docs/3-deployment/deployment-on-heroku.rst",
    "content": "Deployment on Heroku\n====================\n\n.. index:: Heroku\n\nScript\n------\n\nRun these commands to deploy the project to Heroku:\n\n.. code-block:: bash\n\n    heroku create --buildpack heroku/python\n\n    # Note: this is not a free plan\n    heroku addons:create heroku-postgresql:essential-0\n\n    # On Windows use double quotes for the time zone, e.g.\n    # heroku pg:backups schedule --at \"02:00 America/Los_Angeles\" DATABASE_URL\n    heroku pg:backups schedule --at '02:00 America/Los_Angeles' DATABASE_URL\n    heroku pg:promote DATABASE_URL\n\n    heroku addons:create heroku-redis:mini\n\n    # Assuming you chose Mailgun as mail service (see below for others)\n    heroku addons:create mailgun:starter\n\n    heroku config:set DJANGO_DEBUG=False\n    heroku config:set DJANGO_SETTINGS_MODULE=config.settings.production\n    heroku config:set DJANGO_SECRET_KEY=\"$(openssl rand -base64 64)\"\n\n    # Generating a 32 character-long random string without any of the visually similar characters \"IOl01\":\n    heroku config:set DJANGO_ADMIN_URL=\"$(openssl rand -base64 4096 | tr -dc 'A-HJ-NP-Za-km-z2-9' | head -c 32)/\"\n\n    # Set this to your Heroku app url, e.g. 'bionic-beaver-28392.herokuapp.com'\n    heroku config:set DJANGO_ALLOWED_HOSTS=\n\n    # Assign with AWS_ACCESS_KEY_ID\n    heroku config:set DJANGO_AWS_ACCESS_KEY_ID=\n\n    # Assign with AWS_SECRET_ACCESS_KEY\n    heroku config:set DJANGO_AWS_SECRET_ACCESS_KEY=\n\n    # Assign with AWS_STORAGE_BUCKET_NAME\n    heroku config:set DJANGO_AWS_STORAGE_BUCKET_NAME=\n\n    git push heroku main\n\n    heroku run python manage.py createsuperuser\n\n    heroku run python manage.py check --deploy\n\n    heroku open\n\nNotes\n-----\n\nEmail Service\n+++++++++++++\n\nThe script above assumes that you've chose Mailgun as email service. If you want to use another one, check the `documentation for django-anymail <https://anymail.readthedocs.io>`_ to know which environment variables to set. Heroku provides other `add-ons for emails <https://elements.heroku.com/addons#email-sms>`_ (e.g. Sendgrid) which can be configured with a similar one line command.\n\n.. warning::\n\n    .. include:: ../includes/mailgun.rst\n\nHeroku & Docker\n+++++++++++++++\n\nAlthough Heroku has some sort of `Docker support`_, it's not supported by cookiecutter-django.\nWe invite you to follow Heroku documentation about it.\n\n.. _Docker support: https://devcenter.heroku.com/articles/build-docker-images-heroku-yml\n\nOptional actions\n----------------\n\nCelery\n++++++\n\nCelery requires a few extra environment variables to be ready operational. Also, the worker is created,\nit's in the ``Procfile``, but is turned off by default:\n\n.. code-block:: bash\n\n    # Scale dyno to 1 instance\n    heroku ps:scale worker=1\n\nSentry\n++++++\n\nIf you're opted for Sentry error tracking, you can either install it through the `Sentry add-on`_:\n\n.. code-block:: bash\n\n    heroku addons:create sentry:f1\n\n\nOr add the DSN for your account, if you already have one:\n\n.. code-block:: bash\n\n    heroku config:set SENTRY_DSN=https://xxxx@sentry.io/12345\n\n.. _Sentry add-on: https://elements.heroku.com/addons/sentry\n\n\nGulp or Webpack\n+++++++++++++++\n\nIf you've opted for Gulp or Webpack as frontend pipeline, you'll most likely need to setup\nyour app to use `multiple buildpacks`_: one for Python & one for Node.js:\n\n.. code-block:: bash\n\n    heroku buildpacks:add --index 1 heroku/nodejs\n\nAt time of writing, this should do the trick: during deployment,\nthe Heroku should run ``npm install`` and then ``npm build``,\nwhich run the SASS compilation & JS bundling.\n\nIf things don't work, please refer to the Heroku docs.\n\n.. _multiple buildpacks: https://devcenter.heroku.com/articles/managing-buildpacks\n"
  },
  {
    "path": "docs/3-deployment/deployment-on-pythonanywhere.rst",
    "content": "Deployment on PythonAnywhere\n============================\n\n.. index:: PythonAnywhere\n\n\nOverview\n--------\n\nFull instructions follow, but here's a high-level view.\n\n**First time config**:\n\n1. Pull your code down to PythonAnywhere using a *Bash console* and install your dependencies\n\n2. Set your config variables in the *postactivate* script\n\n3. Run the *manage.py* ``migrate`` and ``collectstatic`` commands. If you've opted for django-compressor, also run ``compress``\n\n4. Add an entry to the PythonAnywhere *Web tab*\n\n5. Set your config variables in the PythonAnywhere *WSGI config file*\n\nOnce you've been through this one-off config, future deployments are much simpler: just ``git pull`` and then hit the \"Reload\" button :)\n\n\nGetting your code and dependencies installed on PythonAnywhere\n--------------------------------------------------------------\n\nMake sure your project is fully committed and pushed up to Github, GitLab or wherever it may be. Then, log into your PythonAnywhere account, open up a **Bash** console, clone your repo, and install your project:\n\n.. code-block:: bash\n\n    git clone <my-repo-url>\n    cd my-project-name\n    uv sync --locked --no-dev  # may take a few minutes\n\n\nSetting environment variables\n-----------------------------\n\nGenerate a secret key for yourself, e.g. like this:\n\n.. code-block:: bash\n\n    uv run python -c 'import secrets;import string; print(\"\".join(secrets.choice(string.digits + string.ascii_letters + string.punctuation) for _ in range(50)))'\n\nMake a note of it, since we'll need it here in the console and later on in the web app config tab.\n\nSet environment variables via the ``.env`` file:\n\n.. code-block:: bash\n\n    vi .env\n\n.. note:: If you don't like vi, you can also edit this file via the PythonAnywhere \"Files\" menu.\n\nAdd these env variables:\n\n.. code-block:: bash\n\n    WEB_CONCURRENCY=4\n    DJANGO_SETTINGS_MODULE='config.settings.production'\n    DJANGO_SECRET_KEY='<secret key goes here>'\n    DJANGO_ALLOWED_HOSTS='<www.your-domain.com>'\n    DJANGO_ADMIN_URL='<not admin/>'\n    MAILGUN_API_KEY='<mailgun key>'\n    MAILGUN_DOMAIN='<mailgun sender domain (e.g. mg.yourdomain.com)>'\n    DJANGO_AWS_ACCESS_KEY_ID=\n    DJANGO_AWS_SECRET_ACCESS_KEY=\n    DJANGO_AWS_STORAGE_BUCKET_NAME=\n    DATABASE_URL='<see Database setup section below>'\n    REDIS_URL='<see Redis section below>'\n\n.. note:: The AWS details are not required if you're using whitenoise or the built-in PythonAnywhere static files service, but you do need to set them to blank, as above.\n\n\nDatabase setup\n--------------\n\nGo to the PythonAnywhere **Databases tab** and configure your database. Using Postgres, setup your superuser password, then open a Postgres console and run a ``CREATE DATABASE my-db-name``.  You should probably also set up a specific role and permissions for your app, rather than using the superuser credentials.  Make a note of the address and port of your postgres server.\n\nNow go back to the ``.env`` file and set the ``DATABASE_URL`` environment variable:\n\n.. code-block:: bash\n\n    DATABASE_URL='postgres://<postgres-username>:<postgres-password>@<postgres-address>:<postgres-port>/<database-name>'\n\nNow run the migration, and collectstatic:\n\n.. code-block:: bash\n\n    export UV_ENV_FILE=.env\n    export UV_NO_DEV=1\n    uv run python manage.py migrate\n    uv run python manage.py compress  # optional, if using django-compressor\n    uv run python manage.py collectstatic\n    # and, optionally\n    uv run python manage.py createsuperuser\n\n\nRedis\n-----\n\nPythonAnywhere does NOT `offer a built-in solution <https://www.pythonanywhere.com/forums/topic/1666/>`_ for Redis, however the production setup from Cookiecutter Django uses Redis as cache and requires one.\n\nWe recommend to signup to a separate service offering hosted Redis (e.g. `Redislab <https://redis.com/>`_) and use the URL they provide.\n\n\nConfigure the PythonAnywhere Web Tab\n------------------------------------\n\nGo to the PythonAnywhere **Web tab**, hit **Add new web app**, and choose **Manual Config**, and then the Python 3.13.\n\n.. note:: If you're using a custom domain (not on \\*.pythonanywhere.com), then you'll need to set up a CNAME with your domain registrar.\n\nWhen you're redirected back to the web app config screen, set the **path to your virtualenv**, which should be something like ``/home/<your-username>/<your-project-directory>/.venv``.\n\nClick through to the **WSGI configuration file** link (near the top) and edit the wsgi file. Make it look something like this, repeating the environment variables you used earlier:\n\n.. code-block:: python\n\n    import os\n    import sys\n    PROJECT_PATH = '/home/<your-username>/<your-project-directory>'\n    if PROJECT_PATH not in sys.path:\n        sys.path.append(PROJECT_PATH)\n\n    os.environ['DJANGO_SETTINGS_MODULE='] = 'config.settings.production'\n    os.environ['DJANGO_READ_DOT_ENV_FILE'] = '1'\n\n    from django.core.wsgi import get_wsgi_application\n    application = get_wsgi_application()\n\nBack on the Web tab, hit **Reload**, and your app should be live!\n\n.. note:: You may see security warnings until you set up your SSL certificates. If you want to suppress them temporarily, set ``DJANGO_SECURE_SSL_REDIRECT`` to blank. Follow `these instructions <https://help.pythonanywhere.com/pages/HTTPSSetup>`_ to get SSL set up.\n\n\nOptional: static files\n----------------------\n\nIf you want to use the PythonAnywhere static files service instead of using whitenoise or S3, you'll find its configuration section on the Web tab.  Essentially you'll need an entry to match your ``STATIC_URL`` and ``STATIC_ROOT`` settings.  There's more info `in this article <https://help.pythonanywhere.com/pages/DjangoStaticFiles>`_.\n\n\nFuture deployments\n------------------\n\nFor subsequent deployments, the procedure is much simpler.  In a Bash console:\n\n.. code-block:: bash\n\n    cd project-directory\n    git pull\n    uv run python manage.py migrate\n    uv run python manage.py compress  # optional, if using django-compressor\n    uv run python manage.py collectstatic\n\nAnd then go to the Web tab and hit **Reload**\n\n.. note:: If you're really keen, you can set up git-push based deployments:  https://blog.pythonanywhere.com/87/\n"
  },
  {
    "path": "docs/3-deployment/deployment-with-docker.rst",
    "content": "Deployment with Docker\n======================\n\n.. index:: deployment, docker, docker compose, compose\n\n\nPrerequisites\n-------------\n\n* Docker 17.05+.\n* Docker Compose 1.17+\n\n\nUnderstanding the Docker Compose Setup\n--------------------------------------\n\nBefore you begin, check out the ``docker-compose.production.yml`` file in the root of this project. Keep note of how it provides configuration for the following services:\n\n* ``django``: your application running behind ``Gunicorn``;\n* ``postgres``: PostgreSQL database with the application's relational data;\n* ``redis``: Redis instance for caching;\n* ``traefik``: Traefik reverse proxy with HTTPS on by default.\n\nProvided you have opted for Celery (via setting ``use_celery`` to ``y``) there are three more services:\n\n* ``celeryworker`` running a Celery worker process;\n* ``celerybeat`` running a Celery beat process;\n* ``flower`` running Flower_.\n\nThe ``flower`` service is served by Traefik over HTTPS, through the port ``5555``. For more information about Flower and its login credentials, check out :ref:`CeleryFlower` instructions for local environment.\n\n.. _`Flower`: https://github.com/mher/flower\n\n\nConfiguring the Stack\n---------------------\n\nThe majority of services above are configured through the use of environment variables. Just check out :ref:`envs` and you will know the drill.\n\nTo obtain logs and information about crashes in a production setup, make sure that you have access to an external Sentry instance (e.g. by creating an account with `sentry.io`_), and set the ``SENTRY_DSN`` variable. Logs of level `logging.ERROR` are sent as Sentry events. Therefore, in order to send a Sentry event use:\n\n.. code-block:: python\n\n    import logging\n    logging.error(\"This event is sent to Sentry\", extra={\"<example_key>\": \"<example_value>\"})\n\nThe `extra` parameter allows you to send additional information about the context of this error.\n\n\nYou will probably also need to setup the Mail backend, for example by adding a `Mailgun`_ API key and a `Mailgun`_ sender domain, otherwise, the account creation view will crash and result in a 500 error when the backend attempts to send an email to the account owner.\n\n.. _sentry.io: https://sentry.io/welcome\n.. _Mailgun: https://mailgun.com\n\n\n.. warning::\n\n    .. include:: ../includes/mailgun.rst\n\n\nOptional: Use AWS IAM Role for EC2 instance\n-------------------------------------------\n\nIf you are deploying to AWS, you can use the IAM role to substitute AWS credentials, after which it's safe to remove the ``AWS_ACCESS_KEY_ID`` AND ``AWS_SECRET_ACCESS_KEY`` from ``.envs/.production/.django``. To do it, create an `IAM role`_ and `attach`_ it to the existing EC2 instance or create a new EC2 instance with that role. The role should assume, at minimum, the ``AmazonS3FullAccess`` permission.\n\n.. _IAM role: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html\n.. _attach: https://aws.amazon.com/blogs/security/easily-replace-or-attach-an-iam-role-to-an-existing-ec2-instance-by-using-the-ec2-console/\n\n\nHTTPS is On by Default\n----------------------\n\nSSL (Secure Sockets Layer) is a standard security technology for establishing an encrypted link between a server and a client, typically in this case, a web server (website) and a browser. Not having HTTPS means that malicious network users can sniff authentication credentials between your website and end users' browser.\n\nIt is always better to deploy a site behind HTTPS and will become crucial as the web services extend to the IoT (Internet of Things). For this reason, we have set up a number of security defaults to help make your website secure:\n\n* If you are not using a subdomain of the domain name set in the project, then remember to put your staging/production IP address in the ``DJANGO_ALLOWED_HOSTS`` environment variable (see :ref:`settings`) before you deploy your website. Failure to do this will mean you will not have access to your website through the HTTP protocol.\n\n* Access to the Django admin is set up by default to require HTTPS in production or once *live*.\n\nThe Traefik reverse proxy used in the default configuration will get you a valid certificate from Lets Encrypt and update it automatically. All you need to do to enable this is to make sure that your DNS records are pointing to the server Traefik runs on.\n\nYou can read more about this feature and how to configure it, at `Automatic HTTPS`_ in the Traefik docs.\n\n.. _Automatic HTTPS: https://docs.traefik.io/https/acme/\n\n.. _webpack-whitenoise-limitation:\n\nWebpack without Whitenoise limitation\n-------------------------------------\n\nIf you opt for Webpack without Whitenoise, Webpack needs to know the static URL at build time, when running ``docker compose build`` (See ``webpack/prod.config.js``). Depending on your setup, this URL may come from the following environment variables:\n\n- ``AWS_STORAGE_BUCKET_NAME``\n- ``DJANGO_AWS_S3_CUSTOM_DOMAIN``\n- ``DJANGO_GCP_STORAGE_BUCKET_NAME``\n- ``DJANGO_AZURE_CONTAINER_NAME``\n\nThe Django settings are getting these values at runtime via the ``.envs/.production/.django`` file , but Docker does not read this file at build time, it only look for a ``.env`` in the root of the project. Failing to pass the values correctly will result in a page without CSS styles nor javascript.\n\nTo solve this, you can either:\n\n1. merge all the env files into ``.env`` by running::\n\n     merge_production_dotenvs_in_dotenv.py\n\n2. create a ``.env`` file in the root of the project with just variables you need. You'll need to also define them in ``.envs/.production/.django`` (hence duplicating them).\n3. set these variables when running the build command::\n\n     DJANGO_AWS_S3_CUSTOM_DOMAIN=example.com docker compose -f docker-compose.production.yml build``.\n\nNone of these options are ideal, we're open to suggestions on how to improve this. If you think you have one, please open an issue or a pull request.\n\n(Optional) Postgres Data Volume Modifications\n---------------------------------------------\n\nPostgres is saving its database files to the ``production_postgres_data`` volume by default. Change that if you want something else and make sure to make backups since this is not done automatically.\n\n\nBuilding & Running Production Stack\n-----------------------------------\n\nYou will need to build the stack first. To do that, run::\n\n    docker compose -f docker-compose.production.yml build\n\nOnce this is ready, you can run it with::\n\n    docker compose -f docker-compose.production.yml up\n\nTo run the stack and detach the containers, run::\n\n    docker compose -f docker-compose.production.yml up -d\n\nTo run a migration, open up a second terminal and run::\n\n   docker compose -f docker-compose.production.yml run --rm django python manage.py migrate\n\nTo create a superuser, run::\n\n   docker compose -f docker-compose.production.yml run --rm django python manage.py createsuperuser\n\nIf you need a shell, run::\n\n   docker compose -f docker-compose.production.yml run --rm django python manage.py shell\n\nTo check the logs out, run::\n\n   docker compose -f docker-compose.production.yml logs\n\nIf you want to scale your application, run::\n\n   docker compose -f docker-compose.production.yml up --scale django=4\n   docker compose -f docker-compose.production.yml up --scale celeryworker=2\n\n.. warning:: don't try to scale ``postgres``, ``celerybeat``, or ``traefik``.\n\nTo see how your containers are doing run::\n\n    docker compose -f docker-compose.production.yml ps\n\n\nExample: Supervisor\n-------------------\n\nOnce you are ready with your initial setup, you want to make sure that your application is run by a process manager to\nsurvive reboots and auto restarts in case of an error. You can use the process manager you are most familiar with. All\nit needs to do is to run ``docker compose -f docker-compose.production.yml up`` in your projects root directory.\n\nIf you are using ``supervisor``, you can use this file as a starting point::\n\n    [program:{{cookiecutter.project_slug}}]\n    command=docker compose -f docker-compose.production.yml up\n    directory=/path/to/{{cookiecutter.project_slug}}\n    redirect_stderr=true\n    autostart=true\n    autorestart=true\n    priority=10\n\nMove it to ``/etc/supervisor/conf.d/{{cookiecutter.project_slug}}.conf`` and run::\n\n    supervisorctl reread\n    supervisorctl update\n    supervisorctl start {{cookiecutter.project_slug}}\n\nFor status check, run::\n\n    supervisorctl status\n\nMedia files without cloud provider\n----------------------------------\n\nIf you chose no cloud provider and Docker, the media files will be served by an nginx service, from a ``production_django_media`` volume. Make sure to keep this around to avoid losing any media files.\n"
  },
  {
    "path": "docs/4-guides/docker-postgres-backups.rst",
    "content": "PostgreSQL Backups with Docker\n==============================\n\n.. note:: For brevity it is assumed that you will be running the below commands against local environment, however, this is by no means mandatory so feel free to switch to ``docker-compose.production.yml`` when needed.\n\n\nPrerequisites\n-------------\n\n#. the project was generated with ``use_docker`` set to ``y``;\n#. the stack is up and running: ``docker compose -f docker-compose.local.yml up -d postgres``.\n\n\nCreating a Backup\n-----------------\n\nTo create a backup, run::\n\n    $ docker compose -f docker-compose.local.yml exec postgres backup\n\nAssuming your project's database is named ``my_project`` here is what you will see: ::\n\n    Backing up the 'my_project' database...\n    SUCCESS: 'my_project' database backup 'backup_2018_03_13T09_05_07.sql.gz' has been created and placed in '/backups'.\n\nKeep in mind that ``/backups`` is the ``postgres`` container directory.\n\n\nViewing the Existing Backups\n----------------------------\n\nTo list existing backups, ::\n\n    $ docker compose -f docker-compose.local.yml exec postgres backups\n\nThese are the sample contents of ``/backups``: ::\n\n    These are the backups you have got:\n    total 24K\n    -rw-r--r-- 1 root root 5.2K Mar 13 09:05 backup_2018_03_13T09_05_07.sql.gz\n    -rw-r--r-- 1 root root 5.2K Mar 12 21:13 backup_2018_03_12T21_13_03.sql.gz\n    -rw-r--r-- 1 root root 5.2K Mar 12 21:12 backup_2018_03_12T21_12_58.sql.gz\n\n\nCopying Backups Locally\n-----------------------\n\nIf you want to copy backups from your ``postgres`` container locally, ``docker cp`` command_ will help you on that.\n\nFor example, given ``9c5c3f055843`` is the container ID copying all the backups over to a local directory is as simple as ::\n\n    $ docker cp 9c5c3f055843:/backups ./backups\n\nWith a single backup file copied to ``.`` that would be ::\n\n    $ docker cp 9c5c3f055843:/backups/backup_2018_03_13T09_05_07.sql.gz .\n\nYou can also get the container ID using ``docker compose -f docker-compose.local.yml ps -q postgres`` so if you want to automate your backups, you don't have to check the container ID manually every time. Here is the full command ::\n\n    $ docker cp $(docker compose -f docker-compose.local.yml ps -q postgres):/backups ./backups\n\n.. _`command`: https://docs.docker.com/engine/reference/commandline/cp/\n\nRestoring from the Existing Backup\n----------------------------------\n\nTo restore from one of the backups you have already got (take the ``backup_2018_03_13T09_05_07.sql.gz`` for example), ::\n\n    $ docker compose -f docker-compose.local.yml exec postgres restore backup_2018_03_13T09_05_07.sql.gz\n\nYou will see something like ::\n\n    Restoring the 'my_project' database from the '/backups/backup_2018_03_13T09_05_07.sql.gz' backup...\n    INFO: Dropping the database...\n    INFO: Creating a new database...\n    INFO: Applying the backup to the new database...\n    SET\n    SET\n    SET\n    SET\n    SET\n     set_config\n    ------------\n\n    (1 row)\n\n    SET\n    # ...\n    ALTER TABLE\n    SUCCESS: The 'my_project' database has been restored from the '/backups/backup_2018_03_13T09_05_07.sql.gz' backup.\n\n\nBackup to Amazon S3\n----------------------------------\n\nFor uploading your backups to Amazon S3 you can use the aws cli container. There is an upload command for uploading the postgres /backups directory recursively and there is a download command for downloading a specific backup. The default S3 environment variables are used. ::\n\n    $ docker compose -f docker-compose.production.yml run --rm awscli upload\n    $ docker compose -f docker-compose.production.yml run --rm awscli download backup_2018_03_13T09_05_07.sql.gz\n\nRemove Backup\n----------------------------------\n\nTo remove backup you can use the ``rmbackup`` command. This will remove the backup from the ``/backups`` directory. ::\n\n    $ docker compose -f docker-compose.local.yml exec postgres rmbackup backup_2018_03_13T09_05_07.sql.gz\n\n\nUpgrading PostgreSQL\n----------------------------------\n\nUpgrading PostgreSQL in your project requires a series of carefully executed steps. Start by halting all containers, excluding the postgres container. Following this, create a backup and proceed to remove the outdated data volume. ::\n\n    $ docker compose -f docker-compose.local.yml down\n    $ docker compose -f docker-compose.local.yml up -d postgres\n    $ docker compose -f docker-compose.local.yml run --rm postgres backup\n    $ docker compose -f docker-compose.local.yml down\n    $ docker volume rm my_project_postgres_data\n\n.. note:: Neglecting to remove the old data volume may lead to issues, such as the new postgres container failing to start with errors like ``FATAL:  database files are incompatible with server``, and ``could not translate host name \"postgres\" to address: Name or service not known``.\n\nTo complete the upgrade, update the PostgreSQL version in the corresponding Dockerfile (e.g. ``compose/production/postgres/Dockerfile``) and build a new version of PostgreSQL. ::\n\n    $ docker compose -f docker-compose.local.yml build postgres\n    $ docker compose -f docker-compose.local.yml up -d postgres\n    $ docker compose -f docker-compose.local.yml run --rm postgres restore backup_2018_03_13T09_05_07.sql.gz\n    $ docker compose -f docker-compose.local.yml up -d\n"
  },
  {
    "path": "docs/4-guides/document.rst",
    "content": ".. _document:\n\nDocument\n=========\n\nThis project uses Sphinx_ documentation generator.\n\nAfter you have set up to `develop locally`_, run the following command from the project directory to build and serve HTML documentation: ::\n\n    $ make -C docs livehtml\n\nIf you set up your project to `develop locally with docker`_, run the following command: ::\n\n    $ docker compose -f docker-compose.docs.yml up\n\nNavigate to port 9000 on your host to see the documentation. This will be opened automatically at `localhost`_ for local, non-docker development.\n\nNote: using Docker for documentation sets up a temporary SQLite file by setting the environment variable ``DATABASE_URL=sqlite:///readthedocs.db`` in ``docs/conf.py`` to avoid a dependency on PostgreSQL.\n\nGenerate API documentation\n----------------------------\n\nEdit the ``docs`` files and project application docstrings to create your documentation.\n\nSphinx can automatically include class and function signatures and docstrings in generated documentation.\nSee the generated project documentation for more examples.\n\nSetting up ReadTheDocs\n----------------------\n\nTo setup your documentation on `ReadTheDocs`_, you must\n\n1. Go to `ReadTheDocs`_ and login/create an account\n2. Add your GitHub repository\n3. Trigger a build\n\nAdditionally, you can auto-build Pull Request previews, but `you must enable it`_.\n\n.. _localhost: http://localhost:9000/\n.. _Sphinx: https://www.sphinx-doc.org/en/master/index.html\n.. _develop locally: ../2-local-development/developing-locally.html\n.. _develop locally with docker: ../2-local-development/developing-locally-docker.html\n.. _ReadTheDocs: https://readthedocs.org/\n.. _you must enable it: https://docs.readthedocs.com/platform/latest/pull-requests.html#features\n"
  },
  {
    "path": "docs/4-guides/linters.rst",
    "content": "Linters\n=======\n\n.. index:: linters\n\n\nruff\n------\n\nRuff is a Python linter and code formatter, written in Rust.\nIt is a aggregation of flake8, pylint, pyupgrade and many more.\n\nRuff comes with a linter (``ruff check``) and a formatter (``ruff format``).\nThe linter is a wrapper around flake8, pylint, and other linters,\nand the formatter is a wrapper around black, isort, and other formatters.\n\nTo run ruff without modifying your files: ::\n\n    $ ruff format --diff .\n    $ ruff check .\n\nRuff is capable of fixing most of the problems it encounters.\nBe sure you commit first before running `ruff` so you can restore to a savepoint (and amend afterwards to prevent a double commit. : ::\n\n    $ ruff format  .\n    $ ruff check --fix .\n    # be careful with the --unsafe-fixes option, it can break your code\n    $ ruff check --fix --unsafe-fixes  .\n\nThe config for ruff is located in pyproject.toml.\nOn of the most important option is `tool.ruff.lint.select`.\n`select` determines which linters are run. In example, `DJ <https://docs.astral.sh/ruff/rules/#flake8-django-dj>`_ refers to flake8-django.\nFor a full list of available linters, see `https://docs.astral.sh/ruff/rules/ <https://docs.astral.sh/ruff/rules/>`_\n"
  },
  {
    "path": "docs/4-guides/testing.rst",
    "content": ".. _testing:\n\nTesting\n========\n\nWe encourage users to build application tests. As best practice, this should be done immediately after documentation of the application being built, before starting on any coding.\n\nPytest\n------\n\nThis project uses the Pytest_, a framework for easily building simple and scalable tests.\nAfter you have set up to `develop locally`_, run the following commands to make sure the testing environment is ready: ::\n\n    $ pytest\n\nYou will get a readout of the `users` app that has already been set up with tests. If you do not want to run the `pytest` on the entire project, you can target a particular app by typing in its location: ::\n\n   $ pytest <path-to-app-in-project/app>\n\nIf you set up your project to `develop locally with docker`_, run the following command: ::\n\n   $ docker compose -f docker-compose.local.yml run --rm django pytest\n\nTargeting particular apps for testing in ``docker`` follows a similar pattern as previously shown above.\n\nCoverage\n--------\n\nYou should build your tests to provide the highest level of **code coverage**. You can run the ``pytest`` with code ``coverage`` by typing in the following command: ::\n\n   $ coverage run -m pytest\n\nOnce the tests are complete, in order to see the code coverage, run the following command: ::\n\n   $ coverage report\n\nIf you're running the project locally with Docker, use these commands instead: ::\n\n   $ docker compose -f docker-compose.local.yml run --rm django coverage run -m pytest\n   $ docker compose -f docker-compose.local.yml run --rm django coverage report\n\n.. note::\n\n   At the root of the project folder, you will find the `pytest.ini` file. You can use this to customize_ the ``pytest`` to your liking.\n\n   The configuration for ``coverage`` can be found in ``pyproject.toml``. You can find out more about `configuring`_ ``coverage``.\n\n.. seealso::\n\n   For unit tests, run: ::\n\n      $ python manage.py test\n\n   Since this is a fresh install, and there are no tests built using the Python `unittest`_ library yet, you should get feedback that says there were no tests carried out.\n\n.. _Pytest: https://docs.pytest.org/en/latest/example/simple.html\n.. _develop locally: ./developing-locally.html\n.. _develop locally with docker: ./developing-locally-docker.html\n.. _customize: https://docs.pytest.org/en/latest/customize.html\n.. _unittest: https://docs.python.org/3/library/unittest.html#module-unittest\n.. _configuring: https://coverage.readthedocs.io/en/latest/config.html\n"
  },
  {
    "path": "docs/4-guides/websocket.rst",
    "content": ".. _websocket:\n\n=========\nWebsocket\n=========\n\nYou can enable web sockets if you select ``use_async`` option when creating a project. That indicates whether the project can use web sockets with Uvicorn + Gunicorn.\n\nUsage\n-----\n\nJavaScript example: ::\n\n    > ws = new WebSocket('ws://localhost:8000/') // or 'wss://<mydomain.com>/' in prod\n    WebSocket {url: \"ws://localhost:8000/\", readyState: 0, bufferedAmount: 0, onopen: null, onerror: null, …}\n    > ws.onmessage = event => console.log(event.data)\n    event => console.log(event.data)\n    > ws.send(\"ping\")\n    undefined\n    pong!\n\n\nIf you don't use Traefik, you might have to configure your reverse proxy accordingly (example with Nginx_).\n\n.. _Nginx: https://www.nginx.com/blog/websocket-nginx/\n"
  },
  {
    "path": "docs/5-help/faq.rst",
    "content": "FAQ\n===\n\n.. index:: FAQ, 12-Factor App\n\nWhy is there a django.contrib.sites directory in Cookiecutter Django?\n---------------------------------------------------------------------\n\nIt is there to add a migration so you don't have to manually change the ``sites.Site`` record from ``example.com`` to whatever your domain is. Instead, your ``{{cookiecutter.domain_name}}`` and ``{{cookiecutter.project_name}}`` value is placed by **Cookiecutter** in the domain and name fields respectively.\n\nSee `0003_set_site_domain_and_name.py`_.\n\n.. _`0003_set_site_domain_and_name.py`: https://github.com/cookiecutter/cookiecutter-django/blob/main/%7B%7Bcookiecutter.project_slug%7D%7D/%7B%7Bcookiecutter.project_slug%7D%7D/contrib/sites/migrations/0003_set_site_domain_and_name.py\n\n\nWhy aren't you using just one configuration file (12-Factor App)\n----------------------------------------------------------------------\n\nTODO\n.. TODO\n\nWhy doesn't this follow the layout from Two Scoops of Django?\n-------------------------------------------------------------\n\nYou may notice that some elements of this project do not exactly match what we describe in chapter 3 of `Two Scoops of Django 3.x`_. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.\n\n.. _Two Scoops of Django 3.x: https://www.feldroy.com/two-scoops-of-django\n"
  },
  {
    "path": "docs/5-help/troubleshooting.rst",
    "content": "Troubleshooting\n===============\n\nThis page contains some advice about errors and problems commonly encountered during the development of Cookiecutter Django applications.\n\nServer Error on sign-up/log-in\n------------------------------\n\nMake sure you have configured the mail backend (e.g. Mailgun) by adding the API key and sender domain\n\n.. include:: ../includes/mailgun.rst\n\n.. _docker-postgres-auth-failed:\n\nDocker: Postgres authentication failed\n--------------------------------------\n\nExamples of logs::\n\n    postgres_1      | 2018-06-07 19:11:23.963 UTC [81] FATAL:  password authentication failed for user \"pydanny\"\n    postgres_1      | 2018-06-07 19:11:23.963 UTC [81] DETAIL:  Password does not match for user \"pydanny\".\n    postgres_1      | \tConnection matched pg_hba.conf line 95: \"host all all all md5\"\n\nIf you recreate the project multiple times with the same name, Docker would preserve the volumes for the postgres container between projects. Here is what happens:\n\n#. You generate the project the first time. The .env postgres file is populated with the random password\n#. You run the docker compose and the containers are created. The postgres container creates the database based on the .env file credentials\n#. You \"regenerate\" the project with the same name, so the postgres .env file is populated with a new random password\n#. You run docker compose. Since the names of the containers are the same, docker will try to start them (not create them from scratch i.e. it won't execute the Dockerfile to recreate the database). When this happens, it tries to start the database based on the new credentials which do not match the ones that the database was created with, and you get the error message above.\n\nTo fix this, you can either:\n\n- Clear your project-related Docker cache with ``docker compose -f docker-compose.local.yml down --volumes --rmi all``.\n- Use the Docker volume sub-commands to find volumes (`ls`_) and remove them (`rm`_).\n- Use the `prune`_ command to clear system-wide (use with care!).\n\n.. _ls: https://docs.docker.com/engine/reference/commandline/volume_ls/\n.. _rm: https://docs.docker.com/engine/reference/commandline/volume_rm/\n.. _prune: https://docs.docker.com/v17.09/engine/reference/commandline/system_prune/\n\nVariable is not set. Defaulting to a blank string\n-------------------------------------------------\n\nExample::\n\n    WARN[0000] The \"DJANGO_AWS_STORAGE_BUCKET_NAME\" variable is not set. Defaulting to a blank string.\n    WARN[0000] The \"DJANGO_AWS_S3_CUSTOM_DOMAIN\" variable is not set. Defaulting to a blank string.\n\nYou have probably opted for Docker + Webpack without Whitenoise. This is a know limitation of the combination, which needs a little bit of manual intervention. See the :ref:`dedicated section about it <webpack-whitenoise-limitation>`.\n\nOthers\n------\n\n#. ``project_slug`` must be a valid Python module name or you will have issues on imports.\n\n#. ``jinja2.exceptions.TemplateSyntaxError: Encountered unknown tag 'now'.``: please upgrade your cookiecutter version to >= 1.4 (see `#528`_)\n\n#. New apps not getting created in project root: This is the expected behavior, because cookiecutter-django does not change the way that django startapp works, you'll have to fix this manually (see `#1725`_)\n\n.. _#528: https://github.com/cookiecutter/cookiecutter-django/issues/528#issuecomment-212650373\n.. _#1725: https://github.com/cookiecutter/cookiecutter-django/issues/1725#issuecomment-407493176\n"
  },
  {
    "path": "docs/6-about/contributing.md",
    "content": "```{include} ../../CONTRIBUTING.md\n\n```\n"
  },
  {
    "path": "docs/6-about/generative-ai.md",
    "content": "# Generative AI\n\nYou are encouraged to use all the tools you want to do your work and contribute as efficiently as possible, this includes AI (LLM) tools, etc. Nevertheless, contributions should have meaningful human intervention, judgement, context, etc.\n\nGenerative AI tools have evolved rapidly, and their suggested results can be helpful. As with using any tool, the resulting contribution is the responsibility of the contributor. We value good code, concise accurate documentation, and avoiding unneeded code churn. Discretion, good judgment, and critical thinking are the foundation of all good contributions, regardless of the tools used in their creation.\n\n## Acceptable uses\n\nSome of the acceptable uses of generative AI include:\n\n- Assistance with writing comments, especially in a non-native language.\n- Gaining understanding of existing code.\n- Supplementing contributor knowledge for code, tests, and documentation.\n\n## Unacceptable uses\n\nMaintainers may close issues and PRs that are not useful or productive, including those that are fully generated by AI. If a contributor repeatedly opens unproductive issues or PRs, they may be blocked.\n\nThe same applies to comments and descriptions, please don't copy paste the content generated by an LLM. A good rule of thumb is that if you can't make yourself carefully read some LLM output that you generated, nobody else wants to read it either.\n\n## Human Effort Denial of Service\n\nUsing automated tools and AI to submit PRs or comments that we have to carefully review and handle would be the equivalent of a [Denial-of-service attack](https://en.wikipedia.org/wiki/Denial-of-service_attack) on our human effort.\n\nIt would be very little effort from the person submitting the PR (an LLM prompt) that generates a large amount of effort on our side (carefully reviewing code).\n\nPlease don't do that.\n\nWe'll need to block accounts that spam us with repeated automated PRs or comments.\n"
  },
  {
    "path": "docs/6-about/maintainer-guide.md",
    "content": "# Maintainer guide\n\nThis document is intended for maintainers of the template.\n\n## Automated updates\n\nWe use 2 separate services to keep our dependencies up-to-date:\n\n- Dependabot, which manages updates of Python deps of the template, GitHub actions, npm packages and Docker images.\n- PyUp, which manages the Python deps for the generated project.\n\nWe don't use Dependabot for the generated project deps because our requirements files are templated, and Dependabot fails to parse them. PyUp is -AFAIK- the only service out there that supports having Jinja tags in the requirements file.\n\nUpdates for the template should be labelled as `project infrastructure` while the ones about the generated project should be labelled as `update`. This is use to work in conjunction with our changelog script (see later).\n\n## Automation scripts\n\nWe have a few workflows which have been automated over time. They usually run using GitHub actions and might need a few small manual actions to work nicely. Some have a few limitations which we should document here.\n\n### CI\n\n`ci.yml`\n\nThe CI workflow tries to cover 2 main aspects of the template:\n\n- Check all combinations to make sure that valid files are generated with no major linting issues. Issues which are fixed by an auto-formatter after generation aren't considered major, and only aim for best effort. This is under the `test` job.\n- Run more in-depth tests on a few combinations, by installing dependencies, running type checker and the test suite of the generated project. We try to cover docker (`docker` job) and non-docker (`bare` job) setups.\n\nWe also run the deployment checks, but we don't do much more beyond that for testing the production setup.\n\n### Django issue checker\n\n`django-issue-checker.yml`\n\nThis workflow runs daily, on schedule, and checks if there is a new major version of Django (not in the pure SemVer sense) released that we are not running, and list our dependencies compatibility.\n\nFor example, at time of writing, we use Django 4.2, but the latest version of Django is 5.0, so the workflow created a [\"Django 5.0\" issue](https://github.com/cookiecutter/cookiecutter-django/issues/4724) in GitHub, with a compatibility table and keeps it up to date every day.\n\n#### Limitations\n\nHere are a few current and past limitations of the script\n\n- ~~When a new dependency is added to the template, the script fails to update an existing issue~~\n- Not sure what happens when a deps is removed\n- ~~Unable to parse classifiers without minor version~~\n- ~~Creates an issue even if we are on the latest version~~\n\n### Issue manager\n\n`issue-manager.yml`\n\nA workflow that uses [Sebastian Ramirez' issue-manager](https://github.com/tiangolo/issue-manager) to help us automate issue management. The tag line from the repo explains it well:\n\n> Automatically close issues or Pull Requests that have a label, after a custom delay, if no one replies back.\n\nIt runs on a schedule as well as when some actions are taken on issues and pull requests.\n\nWe wait 10 days before closing issues, and we have a few customised reasons, which are configured in the workflow itself. The config should be fairly self-explanatory.\n\n### Pre-commit auto-update\n\n`pre-commit-autoupdate.yml`\n\nRun daily, to do `pre-commit autoupdate` on the template as well as the generated project, and opens a pull request with the changes.\n\n#### Limitations\n\n- The PR is open as GitHub action which means that CI does NOT run. The documentation for create-pull-request action [explains why](https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs).\n- Some hooks are also installed as local dependencies (via `requirements/local.txt`), but these are updated separately via PyUP.\n\n### Update changelog\n\n`update-changelog.yml`\n\nRun daily at 2AM to update our changelog and create a GitHub release. This runs a custom script which:\n\n- List all pull requests merged the day before\n- The release name is calendar based, so `YYYY.MM.DD`\n- For each PR:\n  - Get the PR title to summarize the change\n  - Look at the PR labels to classify it in a section of the release notes:\n    - anything labelled `project infrastructure` is excluded\n    - label `update` goes in section \"Updated\"\n    - label `bug` goes in section \"Fixed\"\n    - label `docs` goes in section \"Documentation\"\n    - Default to section \"Changed\"\n\nWith that in mind, when merging changes, it's a good idea to set the labels and rename the PR title to give a good summary of the change, in the context of the changelog.\n\n#### Limitations\n\n- Dependabot updates for npm & Docker have a verbose title, try to rename them to be more readable: `Bump webpack-dev-server from 4.15.1 to 5.0.2 in /{{cookiecutter.project_slug}}` -> `Bump webpack-dev-server to 5.0.2`\n- ~~Dependencies updates for the template repo (tox, cookiecutter, etc...) don't need to appear in changelog, and need to be labelled as `project infrastructure` manually. By default, they come from PyUp labelled as `update`.~~\n\n### Update contributors\n\n`update-contributors.yml`\n\nRuns on each push to main branch. List the 5 most recently merged pull requests and extract their author. If any of the authors is a new one, updates the `.github/contributors.json`, regenerate the `CONTRIBUTORS.md` from it, and push back the changes to master.\n\n#### Limitations\n\n- If you merge a pull request from a new contributor, and merge another one right after, the push to main will fail as the remote will be out of date.\n- If you merge more than 5 pull requests in a row like this, the new contributor might fail to be added.\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = uv run --group docs sphinx-build\nSOURCEDIR     = .\nBUILDDIR      = _build\n\n.PHONY: help clean livehtml linkcheck\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"html        Build the docs as HTML\"\n\t@awk '/^#/{c=substr($$0,3);next}c&&/^[[:alpha:]][[:alnum:]_-]+:/{print substr($$1,1,index($$1,\":\")),c}1{c=0}' $(MAKEFILE_LIST) | column -s: -t\n\n# Clean the build output\nclean:\n\t-rm -rf $(BUILDDIR)/*\n\n# Build and serve docs with live reload\nlivehtml:\n\tsphinx-autobuild -b html --port 9000 --watch . -c . $(SOURCEDIR) $(BUILDDIR)/html\n\n# Check all external links for integrity\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(SPHINXOPTS) $(SOURCEDIR) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\n# Catch-all target: route all unknown targets to Sphinx using the new\n# \"make mode\" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).\n%:\n\t@$(SPHINXBUILD) -M $@ \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O) -c .\n"
  },
  {
    "path": "docs/__init__.py",
    "content": "# Included so that Django's startproject comment runs against the docs directory\n"
  },
  {
    "path": "docs/_static/.gitkeep",
    "content": ""
  },
  {
    "path": "docs/conf.py",
    "content": "# cookiecutter-django documentation build configuration file.\n#\n# This file is execfile()d with the current directory set to its containing dir.\n#\n# Note that not all possible configuration values are present in this\n# autogenerated file.\n#\n# All configuration values have a default; values that are commented out\n# serve to show the default.\nfrom datetime import datetime\n\nnow = datetime.now()\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n# sys.path.insert(0, os.path.abspath('.'))\n\n# -- General configuration -----------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n# needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be extensions\n# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.\nextensions = [\"myst_parser\"]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = [\"_templates\"]\n\n# The suffix of source filenames.\nsource_suffix = {\n    \".rst\": \"restructuredtext\",\n    \".md\": \"markdown\",\n}\n\n# The encoding of source files.\n# source_encoding = 'utf-8-sig'\n\n# The master toctree document.\nmaster_doc = \"index\"\n\n# General information about the project.\nproject = \"Cookiecutter Django\"\ncopyright = f\"2013-{now.year}, Daniel Roy Greenfeld\"\n\n# The version info for the project you're documenting, acts as replacement for\n# |version| and |release|, also used in various other places throughout the\n# built documents.\n#\n# The short X.Y version.\nversion = \"{}.{}.{}\".format(*now.isocalendar())\n# The full version, including alpha/beta/rc tags.\nrelease = \"{}.{}.{}\".format(*now.isocalendar())\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n# language = None\n\n# There are two options for replacing |today|: either, you set today to some\n# non-false value, then it is used:\n# today = ''\n# Else, today_fmt is used as the format for a strftime call.\n# today_fmt = '%B %d, %Y'\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\nexclude_patterns = [\"_build\"]\n\n# The reST default role (used for this markup: `text`) to use for all documents.\n# default_role = None\n\n# If true, '()' will be appended to :func: etc. cross-reference text.\n# add_function_parentheses = True\n\n# If true, the current module name will be prepended to all description\n# unit titles (such as .. function::).\n# add_module_names = True\n\n# If true, sectionauthor and moduleauthor directives will be shown in the\n# output. They are ignored by default.\n# show_authors = False\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = \"sphinx\"\n\n# A list of ignored prefixes for module index sorting.\n# modindex_common_prefix = []\n\n\n# -- Options for HTML output ---------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\nhtml_theme = \"sphinx_rtd_theme\"\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n# html_theme_options = {}\n\n# Add any paths that contain custom themes here, relative to this directory.\n# html_theme_path = []\n\n# The name for this set of Sphinx documents.  If None, it defaults to\n# \"<project> v<release> documentation\".\n# html_title = None\n\n# A shorter title for the navigation bar.  Default is the same as html_title.\n# html_short_title = None\n\n# The name of an image file (relative to this directory) to place at the top\n# of the sidebar.\n# html_logo = None\n\n# The name of an image file (within the static path) to use as favicon of the\n# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32\n# pixels large.\n# html_favicon = None\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = [\"_static\"]\n\n# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,\n# using the given strftime format.\n# html_last_updated_fmt = '%b %d, %Y'\n\n# If true, SmartyPants will be used to convert quotes and dashes to\n# typographically correct entities.\n# html_use_smartypants = True\n\n# Custom sidebar templates, maps document names to template names.\n# html_sidebars = {}\n\n# Additional templates that should be rendered to pages, maps page names to\n# template names.\n# html_additional_pages = {}\n\n# If false, no module index is generated.\n# html_domain_indices = True\n\n# If false, no index is generated.\n# html_use_index = True\n\n# If true, the index is split into individual pages for each letter.\n# html_split_index = False\n\n# If true, links to the reST sources are added to the pages.\n# html_show_sourcelink = True\n\n# If true, \"Created using Sphinx\" is shown in the HTML footer. Default is True.\n# html_show_sphinx = True\n\n# If true, \"(C) Copyright ...\" is shown in the HTML footer. Default is True.\n# html_show_copyright = True\n\n# If true, an OpenSearch description file will be output, and all pages will\n# contain a <link> tag referring to it.  The value of this option must be the\n# base URL from which the finished HTML is served.\n# html_use_opensearch = ''\n\n# This is the file name suffix for HTML files (e.g. \".xhtml\").\n# html_file_suffix = None\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = \"cookiecutter-djangodoc\"\n\n\n# -- Options for LaTeX output --------------------------------------------------\n\nlatex_elements = {\n    # The paper size ('letterpaper' or 'a4paper').\n    # 'papersize': 'letterpaper',\n    # The font size ('10pt', '11pt' or '12pt').\n    # 'pointsize': '10pt',\n    # Additional stuff for the LaTeX preamble.\n    # 'preamble': '',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title, author, documentclass [howto/manual]).\nlatex_documents = [\n    (\n        \"index\",\n        \"cookiecutter-django.tex\",\n        \"cookiecutter-django Documentation\",\n        \"cookiecutter-django\",\n        \"manual\",\n    ),\n]\n\n# The name of an image file (relative to this directory) to place at the top of\n# the title page.\n# latex_logo = None\n\n# For \"manual\" documents, if this is true, then toplevel headings are parts,\n# not chapters.\n# latex_use_parts = False\n\n# If true, show page references after internal links.\n# latex_show_pagerefs = False\n\n# If true, show URL addresses after external links.\n# latex_show_urls = False\n\n# Documents to append as an appendix to all manuals.\n# latex_appendices = []\n\n# If false, no module index is generated.\n# latex_domain_indices = True\n\n\n# -- Options for manual page output --------------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (\n        \"index\",\n        \"Cookiecutter Django\",\n        \"Cookiecutter Django documentation\",\n        [\"Daniel Roy Greenfeld\"],\n        1,\n    ),\n]\n\n# If true, show URL addresses after external links.\n# man_show_urls = False\n\n\n# -- Options for Texinfo output ------------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n    (\n        \"index\",\n        \"Cookiecutter Django\",\n        \"Cookiecutter Django documentation\",\n        \"Daniel Roy Greenfeld\",\n        \"Cookiecutter Django\",\n        \"A Cookiecutter template for creating production-ready Django projects quickly.\",\n        \"Miscellaneous\",\n    )\n]\n\n# Documents to append as an appendix to all manuals.\n# texinfo_appendices = []\n\n# If false, no module index is generated.\n# texinfo_domain_indices = True\n\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\n# texinfo_show_urls = 'footnote'\n"
  },
  {
    "path": "docs/includes/mailgun.rst",
    "content": "If your email server used to send email isn't configured properly (Mailgun by default),\nattempting to send an email will cause an Internal Server Error.\n\nBy default, ``django-allauth`` is setup to `have emails verifications mandatory`_,\nwhich means it'll send a verification email when an unverified user tries to\nlog-in or when someone tries to sign-up.\n\nThis may happen just after you've setup your Mailgun account, which is running in a\nsandbox subdomain by default. Either add your email to the list of authorized recipients\nor verify your domain.\n\n\n.. _have emails verifications mandatory: https://docs.allauth.org/en/latest/account/configuration.html#email-verification\n"
  },
  {
    "path": "docs/index.rst",
    "content": ".. cookiecutter-django documentation master file.\n\nWelcome to Cookiecutter Django's documentation!\n===============================================\n\nPowered by Cookiecutter_, Cookiecutter Django is a project template for jumpstarting production-ready Django projects. The template offers a number of generation options, we invite you to check the :ref:`dedicated page <template-options>` to learn more about each of them.\n\n.. _cookiecutter: https://github.com/cookiecutter/cookiecutter\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Getting Started\n\n   1-getting-started/project-generation-options\n   1-getting-started/settings\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Local Development\n\n   2-local-development/developing-locally\n   2-local-development/developing-locally-docker\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Deployment\n\n   3-deployment/deployment-on-pythonanywhere\n   3-deployment/deployment-on-heroku\n   3-deployment/deployment-with-docker\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Guides\n\n   4-guides/docker-postgres-backups\n   4-guides/linters\n   4-guides/testing\n   4-guides/document\n   4-guides/websocket\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Help\n\n   5-help/faq\n   5-help/troubleshooting\n\n.. toctree::\n   :maxdepth: 2\n   :caption: About\n\n   6-about/contributing\n   6-about/generative-ai\n   6-about/maintainer-guide\n\nIndices and tables\n------------------\n\n* :ref:`genindex`\n* :ref:`search`\n\n.. At some point it would be good to have a module index of the high level things we are doing. Then we can * :ref:`modindex` back in.\n"
  },
  {
    "path": "docs/make.bat",
    "content": "@ECHO OFF\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-build\n)\nset SOURCEDIR=.\nset BUILDDIR=_build\nset ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS%\nset I18NSPHINXOPTS=%SPHINXOPTS% .\n\nif \"%1\" == \"\" goto help\n\nif \"%1\" == \"help\" (\n\t:help\n\techo.Please use `make ^<target^>` where ^<target^> is one of\n\techo.  clean      to clean the build directory\n\techo.  html       to make standalone HTML files\n\techo.  livehtml   to build and serve docs with live reload\n\techo.  linkcheck  to check all external links for integrity\n\tgoto end\n)\n\nif \"%1\" == \"clean\" (\n\tfor /d %%i in (%BUILDDIR%\\*) do rmdir /q /s %%i\n\tdel /q /s %BUILDDIR%\\*\n\tgoto end\n)\n\nif \"%1\" == \"html\" (\n\t%SPHINXBUILD% -b html %ALLSPHINXOPTS% %SOURCEDIR% %BUILDDIR%/html\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The HTML pages are in %BUILDDIR%/html.\n\tgoto end\n)\n\nif \"%1\" == \"livehtml\" (\n    sphinx-autobuild -b html --port 9000 --watch . -c . %SOURCEDIR% %BUILDDIR%/html\n\t%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html\n\tif errorlevel 1 exit /b 1\n\tgoto end\n)\n\nif \"%1\" == \"linkcheck\" (\n\t%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %SOURCEDIR% %BUILDDIR%/linkcheck\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Link check complete; look for any errors in the above output ^\nor in %BUILDDIR%/linkcheck/output.txt.\n\tgoto end\n)\n\n:end\n"
  },
  {
    "path": "hooks/__init__.py",
    "content": ""
  },
  {
    "path": "hooks/post_gen_project.py",
    "content": "# ruff: noqa: PLR0133\nimport json\nimport os\nimport random\nimport shutil\nimport string\nimport subprocess\nimport sys\nfrom pathlib import Path\n\ntry:\n    # Inspired by\n    # https://github.com/django/django/blob/main/django/utils/crypto.py\n    random = random.SystemRandom()\n    using_sysrandom = True\nexcept NotImplementedError:\n    using_sysrandom = False\n\nTERMINATOR = \"\\x1b[0m\"\nWARNING = \"\\x1b[1;33m [WARNING]: \"\nINFO = \"\\x1b[1;33m [INFO]: \"\nHINT = \"\\x1b[3;33m\"\nSUCCESS = \"\\x1b[1;32m [SUCCESS]: \"\n\nDEBUG_VALUE = \"debug\"\n\n\ndef remove_open_source_files():\n    file_names = [\"CONTRIBUTORS.txt\", \"LICENSE\"]\n    for file_name in file_names:\n        Path(file_name).unlink()\n\n\ndef remove_gplv3_files():\n    file_names = [\"COPYING\"]\n    for file_name in file_names:\n        Path(file_name).unlink()\n\n\ndef remove_custom_user_manager_files():\n    users_path = Path(\"{{cookiecutter.project_slug}}\", \"users\")\n    (users_path / \"managers.py\").unlink()\n    (users_path / \"tests\" / \"test_managers.py\").unlink()\n\n\ndef remove_pycharm_files():\n    idea_dir_path = Path(\".idea\")\n    if idea_dir_path.exists():\n        shutil.rmtree(idea_dir_path)\n\n    docs_dir_path = Path(\"docs\", \"pycharm\")\n    if docs_dir_path.exists():\n        shutil.rmtree(docs_dir_path)\n\n\ndef remove_docker_files():\n    shutil.rmtree(\".devcontainer\")\n    shutil.rmtree(\"compose\")\n\n    file_names = [\n        \"docker-compose.local.yml\",\n        \"docker-compose.production.yml\",\n        \".dockerignore\",\n        \"justfile\",\n    ]\n    for file_name in file_names:\n        Path(file_name).unlink()\n    if \"{{ cookiecutter.editor }}\" == \"PyCharm\":\n        file_names = [\"docker_compose_up_django.xml\", \"docker_compose_up_docs.xml\"]\n        for file_name in file_names:\n            Path(\".idea\", \"runConfigurations\", file_name).unlink()\n\n\ndef remove_nginx_docker_files():\n    shutil.rmtree(Path(\"compose\", \"production\", \"nginx\"))\n\n\ndef remove_utility_files():\n    shutil.rmtree(\"utility\")\n\n\ndef remove_heroku_files():\n    file_names = [\"Procfile\"]\n    for file_name in file_names:\n        if file_name == \"requirements.txt\" and \"{{ cookiecutter.ci_tool }}\".lower() == \"travis\":\n            # Don't remove the file if we are using Travis CI but not using Heroku\n            continue\n        Path(file_name).unlink()\n    shutil.rmtree(\"bin\")\n\n\ndef remove_sass_files():\n    shutil.rmtree(Path(\"{{cookiecutter.project_slug}}\", \"static\", \"sass\"))\n\n\ndef remove_gulp_files():\n    file_names = [\"gulpfile.mjs\"]\n    for file_name in file_names:\n        Path(file_name).unlink()\n\n\ndef remove_webpack_files():\n    shutil.rmtree(\"webpack\")\n    remove_vendors_js()\n\n\ndef remove_vendors_js():\n    vendors_js_path = Path(\"{{ cookiecutter.project_slug }}\", \"static\", \"js\", \"vendors.js\")\n    if vendors_js_path.exists():\n        vendors_js_path.unlink()\n\n\ndef remove_project_css():\n    project_css_path = Path(\"{{ cookiecutter.project_slug }}\", \"static\", \"css\", \"project.css\")\n    if project_css_path.exists():\n        project_css_path.unlink()\n\n\ndef remove_packagejson_file():\n    file_names = [\"package.json\"]\n    for file_name in file_names:\n        Path(file_name).unlink()\n\n\ndef update_package_json(remove_dev_deps=None, remove_keys=None, scripts=None):\n    remove_dev_deps = remove_dev_deps or []\n    remove_keys = remove_keys or []\n    scripts = scripts or {}\n    package_json = Path(\"package.json\")\n    content = json.loads(package_json.read_text())\n    for package_name in remove_dev_deps:\n        content[\"devDependencies\"].pop(package_name)\n    for key in remove_keys:\n        content.pop(key)\n    content[\"scripts\"].update(scripts)\n    updated_content = json.dumps(content, ensure_ascii=False, indent=2) + \"\\n\"\n    package_json.write_text(updated_content)\n\n\ndef handle_js_runner(choice, use_docker, use_async):\n    if choice == \"Gulp\":\n        update_package_json(\n            remove_dev_deps=[\n                \"@babel/core\",\n                \"@babel/preset-env\",\n                \"babel-loader\",\n                \"concurrently\",\n                \"css-loader\",\n                \"mini-css-extract-plugin\",\n                \"postcss-loader\",\n                \"postcss-preset-env\",\n                \"sass-loader\",\n                \"webpack\",\n                \"webpack-bundle-tracker\",\n                \"webpack-cli\",\n                \"webpack-dev-server\",\n                \"webpack-merge\",\n            ],\n            remove_keys=[\"babel\"],\n            scripts={\n                \"dev\": \"gulp\",\n                \"build\": \"gulp build\",\n            },\n        )\n        remove_webpack_files()\n    elif choice == \"Webpack\":\n        scripts = {\n            \"dev\": \"webpack serve --config webpack/dev.config.js\",\n            \"build\": \"webpack --config webpack/prod.config.js\",\n        }\n        remove_dev_deps = [\n            \"browser-sync\",\n            \"cssnano\",\n            \"gulp\",\n            \"gulp-concat\",\n            \"gulp-imagemin\",\n            \"gulp-plumber\",\n            \"gulp-postcss\",\n            \"gulp-rename\",\n            \"gulp-sass\",\n            \"gulp-uglify-es\",\n        ]\n        if not use_docker:\n            dev_django_cmd = (\n                \"uvicorn config.asgi:application --reload\" if use_async else \"python manage.py runserver_plus\"\n            )\n            scripts.update(\n                {\n                    \"dev\": \"concurrently npm:dev:*\",\n                    \"dev:webpack\": \"webpack serve --config webpack/dev.config.js\",\n                    \"dev:django\": dev_django_cmd,\n                },\n            )\n        else:\n            remove_dev_deps.append(\"concurrently\")\n        update_package_json(remove_dev_deps=remove_dev_deps, scripts=scripts)\n        remove_gulp_files()\n\n\ndef remove_prettier_pre_commit():\n    remove_repo_from_pre_commit_config(\"mirrors-prettier\")\n\n\ndef remove_repo_from_pre_commit_config(repo_to_remove: str):\n    pre_commit_config = Path(\".pre-commit-config.yaml\")\n    content = pre_commit_config.read_text().splitlines(keepends=True)\n\n    removing = False\n    new_lines = []\n    for line in content:\n        if removing and \"- repo:\" in line:\n            removing = False\n        if repo_to_remove in line:\n            removing = True\n        if not removing:\n            new_lines.append(line)\n\n    pre_commit_config.write_text(\"\".join(new_lines))\n\n\ndef remove_celery_files():\n    file_paths = [\n        Path(\"config\", \"celery_app.py\"),\n        Path(\"{{ cookiecutter.project_slug }}\", \"users\", \"tasks.py\"),\n        Path(\"{{ cookiecutter.project_slug }}\", \"users\", \"tests\", \"test_tasks.py\"),\n    ]\n    for file_path in file_paths:\n        file_path.unlink()\n\n\ndef remove_async_files():\n    file_paths = [\n        Path(\"config\", \"asgi.py\"),\n        Path(\"config\", \"websocket.py\"),\n    ]\n    for file_path in file_paths:\n        file_path.unlink()\n\n\ndef remove_dottravisyml_file():\n    Path(\".travis.yml\").unlink()\n\n\ndef remove_dotgitlabciyml_file():\n    Path(\".gitlab-ci.yml\").unlink()\n\n\ndef remove_dotgithub_folder():\n    shutil.rmtree(\".github\")\n\n\ndef remove_dotdrone_file():\n    Path(\".drone.yml\").unlink()\n\n\ndef generate_random_string(length, using_digits=False, using_ascii_letters=False, using_punctuation=False):  # noqa: FBT002\n    \"\"\"\n    Example:\n        opting out for 50 symbol-long, [a-z][A-Z][0-9] string\n        would yield log_2((26+26+50)^50) ~= 334 bit strength.\n    \"\"\"\n    if not using_sysrandom:\n        return None\n\n    symbols = []\n    if using_digits:\n        symbols += string.digits\n    if using_ascii_letters:\n        symbols += string.ascii_letters\n    if using_punctuation:\n        all_punctuation = set(string.punctuation)\n        # These symbols can cause issues in environment variables\n        unsuitable = {\"'\", '\"', \"\\\\\", \"$\"}\n        suitable = all_punctuation.difference(unsuitable)\n        symbols += \"\".join(suitable)\n    return \"\".join([random.choice(symbols) for _ in range(length)])\n\n\ndef set_flag(file_path: Path, flag, value=None, formatted=None, *args, **kwargs):\n    if value is None:\n        random_string = generate_random_string(*args, **kwargs)\n        if random_string is None:\n            print(\n                \"We couldn't find a secure pseudo-random number generator on your \"\n                f\"system. Please, make sure to manually {flag} later.\",\n            )\n            random_string = flag\n        if formatted is not None:\n            random_string = formatted.format(random_string)\n        value = random_string\n\n    with file_path.open(\"r+\") as f:\n        file_contents = f.read().replace(flag, value)\n        f.seek(0)\n        f.write(file_contents)\n        f.truncate()\n\n    return value\n\n\ndef set_django_secret_key(file_path: Path):\n    return set_flag(\n        file_path,\n        \"!!!SET DJANGO_SECRET_KEY!!!\",\n        length=64,\n        using_digits=True,\n        using_ascii_letters=True,\n    )\n\n\ndef set_django_admin_url(file_path: Path):\n    return set_flag(\n        file_path,\n        \"!!!SET DJANGO_ADMIN_URL!!!\",\n        formatted=\"{}/\",\n        length=32,\n        using_digits=True,\n        using_ascii_letters=True,\n    )\n\n\ndef generate_random_user():\n    return generate_random_string(length=32, using_ascii_letters=True)\n\n\ndef generate_postgres_user(debug=False):  # noqa: FBT002\n    return DEBUG_VALUE if debug else generate_random_user()\n\n\ndef set_postgres_user(file_path, value):\n    return set_flag(file_path, \"!!!SET POSTGRES_USER!!!\", value=value)\n\n\ndef set_postgres_password(file_path, value=None):\n    return set_flag(\n        file_path,\n        \"!!!SET POSTGRES_PASSWORD!!!\",\n        value=value,\n        length=64,\n        using_digits=True,\n        using_ascii_letters=True,\n    )\n\n\ndef set_celery_flower_user(file_path, value):\n    return set_flag(file_path, \"!!!SET CELERY_FLOWER_USER!!!\", value=value)\n\n\ndef set_celery_flower_password(file_path, value=None):\n    return set_flag(\n        file_path,\n        \"!!!SET CELERY_FLOWER_PASSWORD!!!\",\n        value=value,\n        length=64,\n        using_digits=True,\n        using_ascii_letters=True,\n    )\n\n\ndef append_to_gitignore_file(ignored_line):\n    with Path(\".gitignore\").open(\"a\") as gitignore_file:\n        gitignore_file.write(ignored_line)\n        gitignore_file.write(\"\\n\")\n\n\ndef set_flags_in_envs(postgres_user, celery_flower_user, debug=False):  # noqa: FBT002\n    local_django_envs_path = Path(\".envs\", \".local\", \".django\")\n    production_django_envs_path = Path(\".envs\", \".production\", \".django\")\n    local_postgres_envs_path = Path(\".envs\", \".local\", \".postgres\")\n    production_postgres_envs_path = Path(\".envs\", \".production\", \".postgres\")\n\n    set_django_secret_key(production_django_envs_path)\n    set_django_admin_url(production_django_envs_path)\n\n    set_postgres_user(local_postgres_envs_path, value=postgres_user)\n    set_postgres_password(local_postgres_envs_path, value=DEBUG_VALUE if debug else None)\n    set_postgres_user(production_postgres_envs_path, value=postgres_user)\n    set_postgres_password(production_postgres_envs_path, value=DEBUG_VALUE if debug else None)\n\n    set_celery_flower_user(local_django_envs_path, value=celery_flower_user)\n    set_celery_flower_password(local_django_envs_path, value=DEBUG_VALUE if debug else None)\n    set_celery_flower_user(production_django_envs_path, value=celery_flower_user)\n    set_celery_flower_password(production_django_envs_path, value=DEBUG_VALUE if debug else None)\n\n\ndef set_flags_in_settings_files():\n    set_django_secret_key(Path(\"config\", \"settings\", \"local.py\"))\n    set_django_secret_key(Path(\"config\", \"settings\", \"test.py\"))\n\n\ndef remove_envs_and_associated_files():\n    shutil.rmtree(\".envs\")\n    Path(\"merge_production_dotenvs_in_dotenv.py\").unlink()\n    shutil.rmtree(\"tests\")\n\n\ndef remove_celery_compose_dirs():\n    shutil.rmtree(Path(\"compose\", \"local\", \"django\", \"celery\"))\n    shutil.rmtree(Path(\"compose\", \"production\", \"django\", \"celery\"))\n\n\ndef remove_node_dockerfile():\n    shutil.rmtree(Path(\"compose\", \"local\", \"node\"))\n\n\ndef remove_aws_dockerfile():\n    shutil.rmtree(Path(\"compose\", \"production\", \"aws\"))\n\n\ndef remove_drf_starter_files():\n    Path(\"config\", \"api_router.py\").unlink()\n    Path(\"{{cookiecutter.project_slug}}\", \"users\", \"api\", \"serializers.py\").unlink()\n\n\ndef remove_ninja_starter_files():\n    Path(\"config\", \"api.py\").unlink()\n    Path(\"{{cookiecutter.project_slug}}\", \"users\", \"api\", \"schema.py\").unlink()\n\n\ndef remove_rest_api_files():\n    remove_drf_starter_files()\n    remove_ninja_starter_files()\n    shutil.rmtree(Path(\"{{cookiecutter.project_slug}}\", \"users\", \"api\"))\n    shutil.rmtree(Path(\"{{cookiecutter.project_slug}}\", \"users\", \"tests\", \"api\"))\n\n\ndef main():  # noqa: C901, PLR0912, PLR0915\n    debug = \"{{ cookiecutter.debug }}\".lower() == \"y\"\n\n    set_flags_in_envs(\n        DEBUG_VALUE if debug else generate_random_user(),\n        DEBUG_VALUE if debug else generate_random_user(),\n        debug=debug,\n    )\n    set_flags_in_settings_files()\n\n    if \"{{ cookiecutter.open_source_license }}\" == \"Not open source\":\n        remove_open_source_files()\n    if \"{{ cookiecutter.open_source_license}}\" != \"GPLv3\":\n        remove_gplv3_files()\n\n    if \"{{ cookiecutter.username_type }}\" == \"username\":\n        remove_custom_user_manager_files()\n\n    if \"{{ cookiecutter.editor }}\" != \"PyCharm\":\n        remove_pycharm_files()\n\n    if \"{{ cookiecutter.use_docker }}\".lower() == \"y\":\n        remove_utility_files()\n        if \"{{ cookiecutter.cloud_provider }}\".lower() != \"none\":\n            remove_nginx_docker_files()\n    else:\n        remove_docker_files()\n\n    if \"{{ cookiecutter.use_docker }}\".lower() == \"y\" and \"{{ cookiecutter.cloud_provider}}\" != \"AWS\":\n        remove_aws_dockerfile()\n\n    if \"{{ cookiecutter.use_heroku }}\".lower() == \"n\":\n        remove_heroku_files()\n\n    if \"{{ cookiecutter.use_docker }}\".lower() == \"n\" and \"{{ cookiecutter.use_heroku }}\".lower() == \"n\":\n        if \"{{ cookiecutter.keep_local_envs_in_vcs }}\".lower() == \"y\":\n            print(\n                INFO + \".env(s) are only utilized when Docker Compose and/or \"\n                \"Heroku support is enabled. Keeping them as requested, but they may not be useful \"\n                \"in your current setup.\" + TERMINATOR,\n            )\n        else:\n            remove_envs_and_associated_files()\n    else:\n        append_to_gitignore_file(\".env\")\n        append_to_gitignore_file(\".envs/*\")\n        if \"{{ cookiecutter.keep_local_envs_in_vcs }}\".lower() == \"y\":\n            append_to_gitignore_file(\"!.envs/.local/\")\n\n    if \"{{ cookiecutter.frontend_pipeline }}\" in [\"None\", \"Django Compressor\"]:\n        remove_gulp_files()\n        remove_webpack_files()\n        remove_sass_files()\n        remove_packagejson_file()\n        remove_prettier_pre_commit()\n        if \"{{ cookiecutter.use_docker }}\".lower() == \"y\":\n            remove_node_dockerfile()\n    else:\n        remove_project_css()\n        handle_js_runner(\n            \"{{ cookiecutter.frontend_pipeline }}\",\n            use_docker=(\"{{ cookiecutter.use_docker }}\".lower() == \"y\"),\n            use_async=(\"{{ cookiecutter.use_async }}\".lower() == \"y\"),\n        )\n\n    if \"{{ cookiecutter.cloud_provider }}\" == \"None\" and \"{{ cookiecutter.use_docker }}\".lower() == \"n\":\n        print(\n            WARNING + \"You chose to not use any cloud providers nor Docker, \"\n            \"media files won't be served in production.\" + TERMINATOR,\n        )\n\n    if \"{{ cookiecutter.use_celery }}\".lower() == \"n\":\n        remove_celery_files()\n        if \"{{ cookiecutter.use_docker }}\".lower() == \"y\":\n            remove_celery_compose_dirs()\n\n    if \"{{ cookiecutter.ci_tool }}\" != \"Travis\":\n        remove_dottravisyml_file()\n\n    if \"{{ cookiecutter.ci_tool }}\" != \"Gitlab\":\n        remove_dotgitlabciyml_file()\n\n    if \"{{ cookiecutter.ci_tool }}\" != \"Github\":\n        remove_dotgithub_folder()\n\n    if \"{{ cookiecutter.ci_tool }}\" != \"Drone\":\n        remove_dotdrone_file()\n\n    if \"{{ cookiecutter.rest_api }}\" == \"DRF\":\n        remove_ninja_starter_files()\n    elif \"{{ cookiecutter.rest_api }}\" == \"Django Ninja\":\n        remove_drf_starter_files()\n    else:\n        remove_rest_api_files()\n\n    if \"{{ cookiecutter.use_async }}\".lower() == \"n\":\n        remove_async_files()\n\n    setup_dependencies()\n\n    print(SUCCESS + \"Project initialized, keep up the good work!\" + TERMINATOR)\n\n\ndef setup_dependencies():\n    print(\"Installing python dependencies using uv...\")\n\n    if \"{{ cookiecutter.use_docker }}\".lower() == \"y\":\n        # Build a trimmed down Docker image add dependencies with uv\n        uv_docker_image_path = Path(\"compose/local/uv/Dockerfile\")\n        uv_image_tag = \"cookiecutter-django-uv-runner:latest\"\n        try:\n            subprocess.run(  # noqa: S603\n                [  # noqa: S607\n                    \"docker\",\n                    \"build\",\n                    \"--load\",\n                    \"-t\",\n                    uv_image_tag,\n                    \"-f\",\n                    str(uv_docker_image_path),\n                    \"-q\",\n                    \".\",\n                ],\n                check=True,\n                env={\n                    **os.environ,\n                    \"DOCKER_BUILDKIT\": \"1\",\n                },\n            )\n        except subprocess.CalledProcessError as e:\n            print(f\"Error building Docker image: {e}\", file=sys.stderr)\n            sys.exit(1)\n\n        current_path = Path.cwd().absolute()\n        # Use Docker to run the uv command\n        uv_cmd = [\"docker\", \"run\", \"--rm\", \"-v\", f\"{current_path}:/app\", uv_image_tag, \"uv\"]\n    else:\n        # Use uv command directly\n        uv_cmd = [\"uv\"]\n\n    # Install production dependencies\n    try:\n        subprocess.run([*uv_cmd, \"add\", \"--no-sync\", \"-r\", \"requirements/production.txt\"], check=True)  # noqa: S603\n    except subprocess.CalledProcessError as e:\n        print(f\"Error installing production dependencies: {e}\", file=sys.stderr)\n        sys.exit(1)\n\n    # Install local (development) dependencies\n    try:\n        subprocess.run([*uv_cmd, \"add\", \"--no-sync\", \"--dev\", \"-r\", \"requirements/local.txt\"], check=True)  # noqa: S603\n    except subprocess.CalledProcessError as e:\n        print(f\"Error installing local dependencies: {e}\", file=sys.stderr)\n        sys.exit(1)\n\n    # Remove the requirements directory\n    requirements_dir = Path(\"requirements\")\n    if requirements_dir.exists():\n        try:\n            shutil.rmtree(requirements_dir)\n        except Exception as e:  # noqa: BLE001\n            print(f\"Error removing 'requirements' folder: {e}\", file=sys.stderr)\n            sys.exit(1)\n\n    uv_image_parent_dir_path = Path(\"compose/local/uv\")\n    if uv_image_parent_dir_path.exists():\n        shutil.rmtree(str(uv_image_parent_dir_path))\n\n    print(\"Setup complete!\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "hooks/pre_gen_project.py",
    "content": "# ruff: noqa: PLR0133\nimport sys\n\nTERMINATOR = \"\\x1b[0m\"\nWARNING = \"\\x1b[1;33m [WARNING]: \"\nINFO = \"\\x1b[1;33m [INFO]: \"\nHINT = \"\\x1b[3;33m\"\nSUCCESS = \"\\x1b[1;32m [SUCCESS]: \"\n\n# The content of this string is evaluated by Jinja, and plays an important role.\n# It updates the cookiecutter context to trim leading and trailing spaces\n# from domain/email values\n\"\"\"\n{{ cookiecutter.update({ \"domain_name\": cookiecutter.domain_name | trim }) }}\n{{ cookiecutter.update({ \"email\": cookiecutter.email | trim }) }}\n\"\"\"\n\nproject_slug = \"{{ cookiecutter.project_slug }}\"\nif hasattr(project_slug, \"isidentifier\"):\n    assert project_slug.isidentifier(), f\"'{project_slug}' project slug is not a valid Python identifier.\"\n\nassert project_slug == project_slug.lower(), f\"'{project_slug}' project slug should be all lowercase\"\n\nassert \"\\\\\" not in \"{{ cookiecutter.author_name }}\", \"Don't include backslashes in author name.\"\n\nif \"{{ cookiecutter.use_whitenoise }}\".lower() == \"n\" and \"{{ cookiecutter.cloud_provider }}\" == \"None\":\n    print(\"You should either use Whitenoise or select a Cloud Provider to serve static files\")\n    sys.exit(1)\n\nif \"{{ cookiecutter.mail_service }}\" == \"Amazon SES\" and \"{{ cookiecutter.cloud_provider }}\" != \"AWS\":\n    print(\"You should either use AWS or select a different Mail Service for sending emails.\")\n    sys.exit(1)\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[project]\nname = \"cookiecutter-django\"\nversion = \"2026.03.19\"\ndescription = \"A Cookiecutter template for creating production-ready Django projects quickly.\"\nreadme = \"README.md\"\nkeywords = [\n  \"cookiecutter\",\n  \"django\",\n  \"project template\",\n  \"scaffolding\",\n  \"skeleton\",\n]\nlicense = { text = \"BSD\" }\nauthors = [\n  { name = \"Daniel Roy Greenfeld\", email = \"pydanny@gmail.com\" },\n]\nrequires-python = \"==3.13.*\"\nclassifiers = [\n  \"Development Status :: 4 - Beta\",\n  \"Environment :: Console\",\n  \"Framework :: Django :: 6.0\",\n  \"Intended Audience :: Developers\",\n  \"License :: OSI Approved :: BSD License\",\n  \"Natural Language :: English\",\n  \"Programming Language :: Python\",\n  \"Programming Language :: Python :: 3 :: Only\",\n  \"Programming Language :: Python :: 3.13\",\n  \"Programming Language :: Python :: Implementation :: CPython\",\n  \"Topic :: Software Development\",\n]\ndependencies = [\n  \"binaryornot==0.6.0\",\n  \"cookiecutter==2.7.1\",\n  \"django-upgrade==1.30.0\",\n  \"djlint==1.36.4\",\n  \"gitpython==3.1.46\",\n  \"jinja2==3.1.6\",\n  \"pre-commit==4.5.1\",\n  \"pygithub==2.8.1\",\n  \"pytest==9.0.2\",\n  \"pytest-cookies==0.7\",\n  \"pytest-instafail==0.5\",\n  \"pytest-xdist==3.8.0\",\n  \"pyyaml==6.0.3\",\n  \"requests==2.32.5\",\n  \"ruff==0.15.7\",\n  \"sh==2.2.2; sys_platform!='win23'\",\n  \"tox==4.50.3\",\n  \"tox-uv>=1.17\",\n]\nurls = { Repository = \"https://github.com/cookiecutter/cookiecutter-django\" }\n\n[dependency-groups]\ndocs = [\n  \"myst-parser>=4\",\n  \"sphinx>=8.0.2\",\n  \"sphinx-autobuild>=2024.10.3\",\n  \"sphinx-rtd-theme>=3\",\n]\n\n[tool.ruff]\ntarget-version = \"py39\"\nline-length = 119\n# Exclude the template content as most files aren't parseable\nextend-exclude = [\n  \"[{]{2}cookiecutter.project_slug[}]{2}/*\",\n  \"docs/*\",\n]\nlint.select = [\n  \"A\",\n  # \"ANN\", # flake8-annotations: we should support this in the future but many errors atm\n  \"ASYNC\",\n  \"B\",\n  \"BLE\",\n  \"C4\",\n  \"C90\",\n  \"COM\",\n  \"DTZ\",\n  \"E\",\n  \"EM\",\n  \"ERA\",\n  \"EXE\",\n  \"F\",\n  \"FA\",\n  \"FBT\",\n  \"FLY\",\n  \"G\",\n  \"I\",\n  \"ICN\",\n  \"INP\",\n  \"INT\",\n  \"ISC\",\n  \"N\",\n  \"PD\",\n  \"PERF\",\n  \"PGH\",\n  \"PIE\",\n  \"PL\",\n  \"PT\",\n  # \"ARG\", # Unused function argument\n  \"PTH\",\n  \"PYI\",\n  \"Q\",\n  \"RET\",\n  \"RSE\",\n  # \"FURB\",\n  # \"LOG\",\n  \"RUF\",\n  \"S\",\n  \"SIM\",\n  \"SLF\",\n  \"SLOT\",\n  \"T10\",\n  \"TC\",\n  \"TID\",\n  \"TRY\",\n  \"UP\",\n  \"W\",\n  \"YTT\",\n]\nlint.ignore = [\n  \"EM101\",\n  \"RUF012\", # Mutable class attributes should be annotated with `typing.ClassVar`\n  \"S101\",   # Use of assert detected https://docs.astral.sh/ruff/rules/assert/\n  \"SIM102\", # sometimes it's better to nest\n  \"TRY003\", # Avoid specifying long messages outside the exception class\n]\nlint.isort.force-single-line = true\n\n[tool.pyproject-fmt]\nkeep_full_version = true\n\n# ==== pytest ====\n[tool.pytest]\nminversion = \"9.0\"\naddopts = [ \"-v\", \"--tb=short\" ]\nnorecursedirs = [\n  \".tox\",\n  \".git\",\n  \"*/migrations/*\",\n  \"*/static/*\",\n  \"docs\",\n  \"venv\",\n  \"*/{{cookiecutter.project_slug}}/*\",\n]\n\n# ==== djLint ====\n[tool.djlint]\nblank_line_after_tag = \"load,extends\"\nclose_void_tags = true\nformat_css = true\nformat_js = true\n# TODO: remove T002 when fixed https://github.com/Riverside-Healthcare/djLint/issues/687\nignore = \"H006,H030,H031,T002,T028\"\nignore_blocks = \"raw\"\ninclude = \"H017,H035\"\nindent = 2\nmax_line_length = 119\nprofile = \"jinja\"\ncss.indent_size = 2\njs.indent_size = 2\n"
  },
  {
    "path": "scripts/__init__.py",
    "content": ""
  },
  {
    "path": "scripts/create_django_issue.py",
    "content": "\"\"\"\nCreates an issue that generates a table for dependency checking whether\nall packages support the latest Django version. \"Latest\" does not include\npatches, only comparing major and minor version numbers.\n\nThis script handles when there are multiple Django versions that need\nto keep up to date.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nimport re\nimport sys\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING\nfrom typing import Any\nfrom typing import NamedTuple\n\nimport requests\nfrom github import Github\n\nif TYPE_CHECKING:\n    from collections.abc import Iterable\n\n    from github.Issue import Issue\n\nCURRENT_FILE = Path(__file__)\nROOT = CURRENT_FILE.parents[1]\nREQUIREMENTS_DIR = ROOT / \"{{cookiecutter.project_slug}}\" / \"requirements\"\nGITHUB_TOKEN = os.getenv(\"GITHUB_TOKEN\", None)\nGITHUB_REPO = os.getenv(\"GITHUB_REPOSITORY\", None)\n\n\nclass DjVersion(NamedTuple):\n    \"\"\"\n    Wrapper to parse, compare and render Django versions.\n\n    Only keeps track on (major, minor) versions, excluding patches and pre-releases.\n    \"\"\"\n\n    major: int\n    minor: int\n\n    def __str__(self) -> str:\n        \"\"\"To render as string.\"\"\"\n        return f\"{self.major}.{self.minor}\"\n\n    @classmethod\n    def parse(cls, version_str: str) -> DjVersion:\n        \"\"\"Parse interesting values from the version string.\"\"\"\n        major, minor, *_ = version_str.split(\".\")\n        return cls(major=int(major), minor=int(minor))\n\n    @classmethod\n    def parse_to_tuple(cls, version_str: str):\n        version = cls.parse(version_str=version_str)\n        return version.major, version.minor\n\n\ndef get_package_info(package: str) -> dict:\n    \"\"\"Get package metadata using PyPI API.\"\"\"\n    # \"django\" converts to \"Django\" on redirect\n    r = requests.get(f\"https://pypi.org/pypi/{package}/json\", allow_redirects=True)  # noqa: S113\n    if not r.ok:\n        print(f\"Couldn't find package: {package}\")\n        sys.exit(1)\n    return r.json()\n\n\ndef get_django_versions() -> Iterable[DjVersion]:\n    \"\"\"List all django versions.\"\"\"\n    django_package_info: dict[str, Any] = get_package_info(\"django\")\n    releases = django_package_info[\"releases\"].keys()\n    for release_str in releases:\n        if release_str.replace(\".\", \"\").isdigit():\n            # Exclude pre-releases with non-numeric characters in version\n            yield DjVersion.parse(release_str)\n\n\ndef get_name_and_version(requirements_line: str) -> tuple[str, ...]:\n    \"\"\"Get the name a version of a package from a line in the requirement file.\"\"\"\n    full_name, version = requirements_line.split(\" \", 1)[0].split(\"==\")\n    name_without_extras = full_name.split(\"[\", 1)[0]\n    return name_without_extras, version\n\n\ndef get_all_latest_django_versions(\n    django_max_version: tuple[DjVersion] | None = None,\n) -> tuple[DjVersion, list[DjVersion]]:\n    \"\"\"\n    Grabs all Django versions that are worthy of a GitHub issue.\n    Depends on Django versions having higher major version or minor version.\n    \"\"\"\n    _django_max_version = (99, 99)\n    if django_max_version:\n        _django_max_version = django_max_version\n\n    print(\"Fetching all Django versions from PyPI\")\n    base_txt = REQUIREMENTS_DIR / \"base.txt\"\n    with base_txt.open() as f:\n        for line in f.readlines():\n            if \"django==\" in line.lower():\n                break\n        else:\n            print(f\"django not found in {base_txt}\")  # Huh...?\n            sys.exit(1)\n\n    # Begin parsing and verification\n    _, current_version_str = get_name_and_version(line)\n    # Get a tuple of (major, minor) - ignoring patch version\n    current_minor_version = DjVersion.parse(current_version_str)\n    newer_versions: set[DjVersion] = set()\n    for django_version in get_django_versions():\n        if current_minor_version < django_version <= _django_max_version:\n            newer_versions.add(django_version)\n\n    return current_minor_version, sorted(newer_versions, reverse=True)\n\n\n_TABLE_HEADER = \"\"\"\n\n## {file}.txt\n\n| Name | Version in Master | {dj_version} Compatible Version | OK |\n| ---- | :---------------: | :-----------------------------: | :-: |\n\"\"\"\nVITAL_BUT_UNKNOWN = [\n    \"django-environ\",  # not updated often\n]\n\n\nclass GitHubManager:\n    def __init__(self, base_dj_version: DjVersion, needed_dj_versions: list[DjVersion]):\n        self.github = Github(GITHUB_TOKEN)\n        self.repo = self.github.get_repo(GITHUB_REPO)\n\n        self.base_dj_version = base_dj_version\n        self.needed_dj_versions = needed_dj_versions\n        # (major+minor) Version and description\n        self.existing_issues: dict[DjVersion, Issue] = {}\n\n        # Load all requirements from our requirements files and preload their\n        # package information like a cache:\n        self.requirements_files = [\"base\", \"local\", \"production\"]\n        # Format:\n        # requirement file name: {package name: (master_version, package_info)}\n        self.requirements: dict[str, dict[str, tuple[str, dict]]] = {x: {} for x in self.requirements_files}\n\n    def setup(self) -> None:\n        self.load_requirements()\n        self.load_existing_issues()\n\n    def load_requirements(self):\n        print(\"Reading requirements\")\n        for requirements_file in self.requirements_files:\n            with (REQUIREMENTS_DIR / f\"{requirements_file}.txt\").open() as f:\n                for line in f.readlines():\n                    if (\n                        \"==\" in line\n                        and not line.startswith(\"{%\")\n                        and not line.startswith(\"    #\")\n                        and not line.startswith(\"#\")\n                        and not line.startswith(\" \")\n                    ):\n                        name, version = get_name_and_version(line)\n                        self.requirements[requirements_file][name] = (\n                            version,\n                            get_package_info(name),\n                        )\n\n    def load_existing_issues(self):\n        \"\"\"Closes the issue if the base Django version is greater than needed\"\"\"\n        print(\"Load existing issues from GitHub\")\n        qualifiers = {\n            \"repo\": GITHUB_REPO,\n            \"author\": \"app/github-actions\",\n            \"state\": \"open\",\n            \"is\": \"issue\",\n            \"in\": \"title\",\n        }\n        issues = list(self.github.search_issues(\"[Django Update]\", \"created\", \"desc\", **qualifiers))\n        print(f\"Found {len(issues)} issues matching search\")\n        for issue in issues:\n            matches = re.match(r\"\\[Update Django] Django (\\d+.\\d+)$\", issue.title)\n            if not matches:\n                continue\n            issue_version = DjVersion.parse(matches.group(1))\n            if self.base_dj_version >= issue_version:\n                self.close_issue(issue)\n            else:\n                self.existing_issues[issue_version] = issue\n\n    def get_compatibility(self, package_name: str, package_info: dict, needed_dj_version: DjVersion):\n        \"\"\"\n        Verify compatibility via setup.py classifiers. If Django is not in the\n        classifiers, then default compatibility is n/a and OK is ✅.\n\n        If it's a package that's vital but known to not be updated often, we give it\n        a ❓. If a package has ❓ or 🕒, then we allow manual update. Automatic updates\n         only include ❌ and ✅.\n        \"\"\"\n        # If issue previously existed, find package and skip any gtg, manually\n        # updated packages, or known releases that will happen but haven't yet\n        if issue := self.existing_issues.get(needed_dj_version):\n            if (index := issue.body.find(package_name)) > 0:\n                print(f\"Found {package_name} at {index=}\")\n                _name, _current, prev_compat, ok = (s.strip() for s in issue.body[index:].split(\"|\", 4)[:4])\n                if ok in (\"✅\", \"❓\", \"🕒\"):\n                    return prev_compat, ok\n\n        if package_name in VITAL_BUT_UNKNOWN:\n            return \"\", \"❓\"\n\n        # Check classifiers if it includes Django\n        supported_dj_versions: list[DjVersion] = []\n        for classifier in package_info[\"info\"][\"classifiers\"]:\n            # Usually in the form of \"Framework :: Django :: 3.2\"\n            tokens = classifier.split(\" \")\n            if len(tokens) >= 5 and tokens[2].lower() == \"django\" and \".\" in tokens[4]:  # noqa: PLR2004\n                version = DjVersion.parse(tokens[4])\n                if len(version) == 2:  # noqa: PLR2004\n                    supported_dj_versions.append(version)\n\n        if supported_dj_versions:\n            if any(v >= needed_dj_version for v in supported_dj_versions):\n                return package_info[\"info\"][\"version\"], \"✅\"\n            return \"\", \"❌\"\n\n        # Django classifier DNE; assume it isn't a Django lib\n        # Great exceptions include pylint-django, where we need to do this manually...\n        return \"n/a\", \"✅\"\n\n    HOME_PAGE_URL_KEYS = [\n        \"home_page\",\n        \"project_url\",\n        \"docs_url\",\n        \"package_url\",\n        \"release_url\",\n        \"bugtrack_url\",\n    ]\n\n    def _get_md_home_page_url(self, package_info: dict):\n        urls = [package_info[\"info\"].get(url_key) for url_key in self.HOME_PAGE_URL_KEYS]\n        try:\n            return f\"[{{}}]({next(item for item in urls if item)})\"\n        except StopIteration:\n            return \"{}\"\n\n    def generate_markdown(self, needed_dj_version: DjVersion):\n        requirements = f\"{needed_dj_version} requirements tables\\n\\n\"\n        for _file in self.requirements_files:\n            requirements += _TABLE_HEADER.format_map({\"file\": _file, \"dj_version\": needed_dj_version})\n            for package_name, (version, info) in self.requirements[_file].items():\n                compat_version, icon = self.get_compatibility(package_name, info, needed_dj_version)\n                requirements += (\n                    f\"| {self._get_md_home_page_url(info).format(package_name)} \"\n                    f\"| {version.strip()} \"\n                    f\"| {compat_version.strip()} \"\n                    f\"| {icon} \"\n                    f\"|\\n\"\n                )\n\n        return requirements\n\n    def create_or_edit_issue(self, needed_dj_version: DjVersion, description: str):\n        if issue := self.existing_issues.get(needed_dj_version):\n            print(f\"Editing issue #{issue.number} for Django {needed_dj_version}\")\n            issue.edit(body=description)\n        else:\n            print(f\"Creating new issue for Django {needed_dj_version}\")\n            issue = self.repo.create_issue(f\"[Update Django] Django {needed_dj_version}\", description)\n            issue.add_to_labels(f\"django{needed_dj_version}\")\n\n    @staticmethod\n    def close_issue(issue: Issue):\n        issue.edit(state=\"closed\")\n        print(f\"Closed issue {issue.title} (ID: [{issue.id}]({issue.url}))\")\n\n    def generate(self):\n        for version in self.needed_dj_versions:\n            print(f\"Handling GitHub issue for Django {version}\")\n            md_content = self.generate_markdown(version)\n            print(f\"Generated markdown:\\n\\n{md_content}\")\n            self.create_or_edit_issue(version, md_content)\n\n\ndef main(django_max_version=None) -> None:\n    # Check if there are any djs\n    current_dj, latest_djs = get_all_latest_django_versions(django_max_version=django_max_version)\n\n    # Run the setup, which might close old issues\n    manager = GitHubManager(current_dj, latest_djs)\n    manager.setup()\n\n    if not latest_djs:\n        print(\"No new Django versions to update. Exiting...\")\n        sys.exit(0)\n\n    manager.generate()\n\n\nif __name__ == \"__main__\":\n    if GITHUB_REPO is None:\n        raise RuntimeError(\"No github repo, please set the environment variable GITHUB_REPOSITORY\")\n    max_version = None\n    last_arg = sys.argv[-1]\n    if CURRENT_FILE.name not in last_arg:\n        max_version = DjVersion.parse_to_tuple(version_str=last_arg)\n\n    main(django_max_version=max_version)\n"
  },
  {
    "path": "scripts/node_version.py",
    "content": "from __future__ import annotations\n\nimport json\nfrom pathlib import Path\n\nROOT = Path(__file__).parent.parent\nTEMPLATED_ROOT = ROOT / \"{{cookiecutter.project_slug}}\"\nDOCKERFILE = TEMPLATED_ROOT / \"compose\" / \"local\" / \"node\" / \"Dockerfile\"\nPROD_DOCKERFILE = TEMPLATED_ROOT / \"compose\" / \"production\" / \"django\" / \"Dockerfile\"\nPACKAGE_JSON = TEMPLATED_ROOT / \"package.json\"\n\n\ndef main() -> None:\n    new_version = get_version_from_dockerfile()\n    old_version = get_version_from_package_json()\n    if old_version != new_version:\n        update_package_json_version(old_version, new_version)\n        update_production_node_version(old_version, new_version)\n\n\ndef get_version_from_dockerfile() -> str:\n    # Extract version out of base image name:\n    # FROM docker.io/node:22.13-bookworm-slim\n    # -> 22.13\n    with DOCKERFILE.open(\"r\") as f:\n        for line in f:\n            if \"FROM docker.io/node:\" in line:\n                _, _, docker_tag = line.partition(\":\")\n                version_str, _, _ = docker_tag.partition(\"-\")\n                return version_str\n    raise RuntimeError(\"Could not find version in Dockerfile\")\n\n\ndef get_version_from_package_json() -> str:\n    package_json = json.loads(PACKAGE_JSON.read_text())\n    return package_json[\"engines\"][\"node\"]\n\n\ndef update_package_json_version(old_version: str, new_version: str) -> None:\n    package_json_text = PACKAGE_JSON.read_text()\n    package_json_text = package_json_text.replace(\n        f'\"node\": \"{old_version}\"',\n        f'\"node\": \"{new_version}\"',\n    )\n    PACKAGE_JSON.write_text(package_json_text)\n\n\ndef update_production_node_version(old_version: str, new_version: str) -> None:\n    dockerfile_content = PROD_DOCKERFILE.read_text()\n    dockerfile_content = dockerfile_content.replace(\n        f\"FROM docker.io/node:{old_version}\",\n        f\"FROM docker.io/node:{new_version}\",\n    )\n    PROD_DOCKERFILE.write_text(dockerfile_content)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/ruff_version.py",
    "content": "from __future__ import annotations\n\nimport subprocess\nfrom pathlib import Path\n\nimport tomllib\n\nROOT = Path(__file__).parent.parent\nTEMPLATED_ROOT = ROOT / \"{{cookiecutter.project_slug}}\"\nREQUIREMENTS_LOCAL_TXT = TEMPLATED_ROOT / \"requirements\" / \"local.txt\"\nTEMPLATE_PRE_COMMIT_CONFIG = ROOT / \".pre-commit-config.yaml\"\nPRE_COMMIT_CONFIG = TEMPLATED_ROOT / \".pre-commit-config.yaml\"\nPYPROJECT_TOML = ROOT / \"pyproject.toml\"\n\n\ndef main() -> None:\n    new_version = get_requirements_txt_version()\n    old_version = get_pyproject_toml_version()\n    if old_version == new_version:\n        return\n\n    update_ruff_version(old_version, new_version)\n    subprocess.run([\"uv\", \"lock\", \"--no-upgrade\"], cwd=ROOT, check=False)  # noqa: S607\n\n\ndef get_requirements_txt_version() -> str:\n    content = REQUIREMENTS_LOCAL_TXT.read_text()\n    for line in content.split(\"\\n\"):\n        if line.startswith(\"ruff\"):\n            return line.split(\" \")[0].split(\"==\")[1]\n    raise RuntimeError(\"Could not find ruff version in requirements/local.txt\")\n\n\ndef get_pyproject_toml_version() -> str:\n    data = tomllib.loads(PYPROJECT_TOML.read_text())\n    for dependency in data[\"project\"][\"dependencies\"]:\n        if dependency.startswith(\"ruff==\"):\n            return dependency.split(\"==\")[1]\n    raise RuntimeError(\"Could not find ruff version in pyproject.toml\")\n\n\ndef update_ruff_version(old_version: str, new_version: str) -> None:\n    # Update pyproject.toml\n    new_content = PYPROJECT_TOML.read_text().replace(\n        f\"ruff=={old_version}\",\n        f\"ruff=={new_version}\",\n    )\n    PYPROJECT_TOML.write_text(new_content)\n    # Update pre-commit configs\n    for config_file in [PRE_COMMIT_CONFIG, TEMPLATE_PRE_COMMIT_CONFIG]:\n        new_content = config_file.read_text().replace(\n            f\"repo: https://github.com/astral-sh/ruff-pre-commit\\n    rev: v{old_version}\",\n            f\"repo: https://github.com/astral-sh/ruff-pre-commit\\n    rev: v{new_version}\",\n        )\n        config_file.write_text(new_content)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/update_changelog.py",
    "content": "import datetime as dt\nimport os\nimport re\nimport subprocess\nfrom collections.abc import Iterable\nfrom pathlib import Path\n\nimport git\nimport github.PullRequest\nimport github.Repository\nfrom github import Github\nfrom jinja2 import Template\n\nCURRENT_FILE = Path(__file__)\nROOT = CURRENT_FILE.parents[1]\nGITHUB_TOKEN = os.getenv(\"GITHUB_TOKEN\")\nGITHUB_REPO = os.getenv(\"GITHUB_REPOSITORY\")\nGIT_BRANCH = os.getenv(\"GITHUB_REF_NAME\")\n\n\ndef main() -> None:\n    \"\"\"\n    Script entry point.\n    \"\"\"\n    # Generate changelog for PRs merged yesterday\n    merged_date = dt.date.today() - dt.timedelta(days=1)  # noqa: DTZ011\n    repo = Github(login_or_token=GITHUB_TOKEN).get_repo(GITHUB_REPO)\n    merged_pulls = list(iter_pulls(repo, merged_date))\n    print(f\"Merged pull requests: {merged_pulls}\")\n    if not merged_pulls:\n        print(\"Nothing was merged, existing.\")\n        return\n\n    # Group pull requests by type of change\n    grouped_pulls = group_pulls_by_change_type(merged_pulls)\n    if not any(grouped_pulls.values()):\n        print(\"Pull requests merged aren't worth a changelog mention.\")\n        return\n\n    # Generate portion of markdown\n    release_changes_summary = generate_md(grouped_pulls)\n    print(f\"Summary of changes: {release_changes_summary}\")\n\n    # Update CHANGELOG.md file\n    release = f\"{merged_date:%Y.%m.%d}\"\n    changelog_path = ROOT / \"CHANGELOG.md\"\n    write_changelog(changelog_path, release, release_changes_summary)\n    print(f\"Wrote {changelog_path}\")\n\n    # Update version\n    setup_py_path = ROOT / \"pyproject.toml\"\n    update_version(setup_py_path, release)\n    print(f\"Updated version in {setup_py_path}\")\n\n    # Run uv lock\n    uv_lock_path = ROOT / \"uv.lock\"\n    subprocess.run([\"uv\", \"lock\", \"--no-upgrade\"], cwd=ROOT, check=False)  # noqa: S607\n\n    # Commit changes, create tag and push\n    update_git_repo([changelog_path, setup_py_path, uv_lock_path], release)\n\n    # Create GitHub release\n    github_release = repo.create_git_release(\n        tag=release,\n        name=release,\n        message=release_changes_summary,\n    )\n    print(f\"Created release on GitHub {github_release}\")\n\n\ndef iter_pulls(\n    repo: github.Repository.Repository,\n    merged_date: dt.date,\n) -> Iterable[github.PullRequest.PullRequest]:\n    \"\"\"Fetch merged pull requests at the date we're interested in.\"\"\"\n    recent_pulls = repo.get_pulls(\n        state=\"closed\",\n        sort=\"updated\",\n        direction=\"desc\",\n    ).get_page(0)\n    for pull in recent_pulls:\n        if pull.merged and pull.merged_at.date() == merged_date:\n            yield pull\n\n\ndef group_pulls_by_change_type(\n    pull_requests_list: list[github.PullRequest.PullRequest],\n) -> dict[str, list[github.PullRequest.PullRequest]]:\n    \"\"\"Group pull request by change type.\"\"\"\n    grouped_pulls = {\n        \"Changed\": [],\n        \"Fixed\": [],\n        \"Documentation\": [],\n        \"Updated\": [],\n    }\n    for pull in pull_requests_list:\n        label_names = {label.name for label in pull.labels}\n        if \"project infrastructure\" in label_names:\n            # Don't mention it in the changelog\n            continue\n        if \"update\" in label_names:\n            group_name = \"Updated\"\n        elif \"bug\" in label_names:\n            group_name = \"Fixed\"\n        elif \"docs\" in label_names:\n            group_name = \"Documentation\"\n        else:\n            group_name = \"Changed\"\n        grouped_pulls[group_name].append(pull)\n    return grouped_pulls\n\n\ndef generate_md(grouped_pulls: dict[str, list[github.PullRequest.PullRequest]]) -> str:\n    \"\"\"Generate markdown file from Jinja template.\"\"\"\n    changelog_template = ROOT / \".github\" / \"changelog-template.md\"\n    template = Template(changelog_template.read_text(), autoescape=True)\n    return template.render(grouped_pulls=grouped_pulls)\n\n\ndef write_changelog(file_path: Path, release: str, content: str) -> None:\n    \"\"\"Write Release details to the changelog file.\"\"\"\n    content = f\"## {release}\\n{content}\"\n    old_content = file_path.read_text()\n    updated_content = old_content.replace(\n        \"<!-- GENERATOR_PLACEHOLDER -->\",\n        f\"<!-- GENERATOR_PLACEHOLDER -->\\n\\n{content}\",\n    )\n    file_path.write_text(updated_content)\n\n\ndef update_version(file_path: Path, release: str) -> None:\n    \"\"\"Update template version in pyproject.toml.\"\"\"\n    old_content = file_path.read_text()\n    updated_content = re.sub(\n        r'\\nversion = \"\\d+\\.\\d+\\.\\d+\"\\n',\n        f'\\nversion = \"{release}\"\\n',\n        old_content,\n    )\n    file_path.write_text(updated_content)\n\n\ndef update_git_repo(paths: list[Path], release: str) -> None:\n    \"\"\"Commit, tag changes in git repo and push to origin.\"\"\"\n    repo = git.Repo(ROOT)\n    for path in paths:\n        repo.git.add(path)\n    message = f\"Release {release}\"\n\n    user = repo.git.config(\"--get\", \"user.name\")\n    email = repo.git.config(\"--get\", \"user.email\")\n\n    repo.git.commit(\n        m=message,\n        author=f\"{user} <{email}>\",\n    )\n    repo.git.tag(\"-a\", release, m=message)\n    server = f\"https://{GITHUB_TOKEN}@github.com/{GITHUB_REPO}.git\"\n    print(f\"Pushing changes to {GIT_BRANCH} branch of {GITHUB_REPO}\")\n    repo.git.push(server, GIT_BRANCH)\n    repo.git.push(\"--tags\", server, GIT_BRANCH)\n\n\nif __name__ == \"__main__\":\n    if GITHUB_REPO is None:\n        raise RuntimeError(\"No github repo, please set the environment variable GITHUB_REPOSITORY\")\n    if GIT_BRANCH is None:\n        raise RuntimeError(\"No git branch set, please set the GITHUB_REF_NAME environment variable\")\n    main()\n"
  },
  {
    "path": "scripts/update_contributors.py",
    "content": "import json\nimport os\nfrom pathlib import Path\n\nfrom github import Github\nfrom github.NamedUser import NamedUser\nfrom jinja2 import Template\n\nCURRENT_FILE = Path(__file__)\nROOT = CURRENT_FILE.parents[1]\nBOT_LOGINS = [\"pyup-bot\"]\nGITHUB_TOKEN = os.getenv(\"GITHUB_TOKEN\", None)\nGITHUB_REPO = os.getenv(\"GITHUB_REPOSITORY\", None)\n\n\ndef main() -> None:\n    \"\"\"\n    Script entry point.\n\n    1. Fetch recent contributors from the Github API\n    2. Add missing ones to the JSON file\n    3. Generate Markdown from JSON file\n    \"\"\"\n    recent_authors = set(iter_recent_authors())\n\n    # Add missing users to the JSON file\n    contrib_file = ContributorsJSONFile()\n    for author in recent_authors:\n        print(f\"Checking if {author.login} should be added\")\n        if author.login not in contrib_file:\n            contrib_file.add_contributor(author)\n            print(f\"Added {author.login} to contributors\")\n    contrib_file.save()\n\n    # Generate MD file from JSON file\n    write_md_file(contrib_file.content)\n\n\ndef iter_recent_authors():\n    \"\"\"\n    Fetch users who opened recently merged pull requests.\n\n    Use GitHub API to fetch recent authors rather than\n    git CLI to work with GitHub usernames.\n    \"\"\"\n    repo = Github(login_or_token=GITHUB_TOKEN, per_page=5).get_repo(GITHUB_REPO)\n    recent_pulls = repo.get_pulls(state=\"closed\", sort=\"updated\", direction=\"desc\").get_page(0)\n    for pull in recent_pulls:\n        if pull.merged and pull.user.type == \"User\" and pull.user.login not in BOT_LOGINS:\n            yield pull.user\n\n\nclass ContributorsJSONFile:\n    \"\"\"Helper to interact with the JSON file.\"\"\"\n\n    file_path = ROOT / \".github\" / \"contributors.json\"\n    content = None\n\n    def __init__(self) -> None:\n        \"\"\"Read initial content.\"\"\"\n        self.content = json.loads(self.file_path.read_text())\n\n    def __contains__(self, github_login: str):\n        \"\"\"Provide a nice API to do: `username in file`.\"\"\"\n        return any(\n            # Github usernames are case insensitive\n            github_login.lower() == contrib[\"github_login\"].lower()\n            for contrib in self.content\n        )\n\n    def add_contributor(self, user: NamedUser):\n        \"\"\"Append the contributor data we care about at the end.\"\"\"\n        contributor_data = {\n            \"name\": user.name or user.login,\n            \"github_login\": user.login,\n            \"twitter_username\": user.twitter_username or \"\",\n        }\n        self.content.append(contributor_data)\n\n    def save(self):\n        \"\"\"Write the file to disk with indentation.\"\"\"\n        text_content = json.dumps(self.content, indent=2, ensure_ascii=False)\n        self.file_path.write_text(text_content)\n\n\ndef write_md_file(contributors):\n    \"\"\"Generate markdown file from Jinja template.\"\"\"\n    contributors_template = ROOT / \".github\" / \"CONTRIBUTORS-template.md\"\n    template = Template(contributors_template.read_text(), autoescape=True)\n    core_contributors = [c for c in contributors if c.get(\"is_core\", False)]\n    other_contributors = (c for c in contributors if not c.get(\"is_core\", False))\n    other_contributors = sorted(other_contributors, key=lambda c: c[\"name\"].lower())\n    content = template.render(core_contributors=core_contributors, other_contributors=other_contributors)\n\n    file_path = ROOT / \"CONTRIBUTORS.md\"\n    file_path.write_text(content)\n\n\nif __name__ == \"__main__\":\n    if GITHUB_REPO is None:\n        raise RuntimeError(\"No github repo, please set the environment variable GITHUB_REPOSITORY\")\n    main()\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/test_bare.sh",
    "content": "#!/bin/sh\n# this is a very simple script that tests the docker configuration for cookiecutter-django\n# it is meant to be run from the root directory of the repository, eg:\n# sh tests/test_bare.sh\n\nset -o errexit\nset -x\n\n# create a cache directory\nmkdir -p .cache/bare\ncd .cache/bare\n\n# create the project using the default settings in cookiecutter.json\nuv run cookiecutter ../../ --no-input --overwrite-if-exists use_docker=n \"$@\"\ncd my_awesome_project\n\n# Install OS deps\nsudo utility/install_os_dependencies.sh install\n\n# Install Python deps\nuv sync\n\n# run the project's tests\nuv run pytest\n\n# Make sure the check doesn't raise any warnings\nuv run python manage.py check --fail-level WARNING\n\n# Run npm build script if package.json is present\nif [ -f \"package.json\" ]\nthen\n    npm install\n    npm run build\nfi\n\n# Generate the HTML for the documentation\ncd docs && uv run make html\n"
  },
  {
    "path": "tests/test_cookiecutter_generation.py",
    "content": "import glob  # noqa: EXE002\nimport os\nimport re\nimport sys\nfrom collections.abc import Iterable\nfrom pathlib import Path\n\nimport pytest\nimport tomllib\n\ntry:\n    import sh\nexcept (ImportError, ModuleNotFoundError):\n    sh = None  # sh doesn't support Windows\nimport yaml\nfrom binaryornot.check import is_binary\nfrom cookiecutter.exceptions import FailedHookException\n\nPATTERN = r\"{{(\\s?cookiecutter)[.](.*?)}}\"\nRE_OBJ = re.compile(PATTERN)\n\nif sys.platform.startswith(\"win\"):\n    pytest.skip(\"sh doesn't support windows\", allow_module_level=True)\nelif sys.platform.startswith(\"darwin\") and os.getenv(\"CI\"):\n    pytest.skip(\"skipping slow macOS tests on CI\", allow_module_level=True)\n\n# Run auto-fixable styles checks - skipped on CI by default. These can be fixed\n# automatically by running pre-commit after generation. However, they are tedious\n# to fix in the template, so we don't insist too much on fixing them.\nAUTOFIXABLE_STYLES = os.getenv(\"AUTOFIXABLE_STYLES\") == \"1\"\nauto_fixable = pytest.mark.skipif(not AUTOFIXABLE_STYLES, reason=\"auto-fixable\")\n\n\n@pytest.fixture\ndef context():\n    return {\n        \"project_name\": \"My Test Project\",\n        \"project_slug\": \"my_test_project\",\n        \"author_name\": \"Test Author\",\n        \"email\": \"test@example.com\",\n        \"description\": \"A short description of the project.\",\n        \"domain_name\": \"example.com\",\n        \"version\": \"0.1.0\",\n        \"timezone\": \"UTC\",\n    }\n\n\nSUPPORTED_COMBINATIONS = [\n    {\"username_type\": \"username\"},\n    {\"username_type\": \"email\"},\n    {\"open_source_license\": \"MIT\"},\n    {\"open_source_license\": \"BSD\"},\n    {\"open_source_license\": \"GPLv3\"},\n    {\"open_source_license\": \"Apache Software License 2.0\"},\n    {\"open_source_license\": \"Not open source\"},\n    {\"windows\": \"y\"},\n    {\"windows\": \"n\"},\n    {\"editor\": \"None\"},\n    {\"editor\": \"PyCharm\"},\n    {\"editor\": \"VS Code\"},\n    {\"use_docker\": \"y\"},\n    {\"use_docker\": \"n\"},\n    {\"postgresql_version\": \"18\"},\n    {\"postgresql_version\": \"17\"},\n    {\"postgresql_version\": \"16\"},\n    {\"postgresql_version\": \"15\"},\n    {\"postgresql_version\": \"14\"},\n    {\"cloud_provider\": \"AWS\", \"use_whitenoise\": \"y\"},\n    {\"cloud_provider\": \"AWS\", \"use_whitenoise\": \"n\"},\n    {\"cloud_provider\": \"GCP\", \"use_whitenoise\": \"y\"},\n    {\"cloud_provider\": \"GCP\", \"use_whitenoise\": \"n\"},\n    {\"cloud_provider\": \"Azure\", \"use_whitenoise\": \"y\"},\n    {\"cloud_provider\": \"Azure\", \"use_whitenoise\": \"n\"},\n    {\"cloud_provider\": \"None\", \"use_whitenoise\": \"y\", \"mail_service\": \"Mailgun\"},\n    {\"cloud_provider\": \"None\", \"use_whitenoise\": \"y\", \"mail_service\": \"Mailjet\"},\n    {\"cloud_provider\": \"None\", \"use_whitenoise\": \"y\", \"mail_service\": \"Mandrill\"},\n    {\"cloud_provider\": \"None\", \"use_whitenoise\": \"y\", \"mail_service\": \"Postmark\"},\n    {\"cloud_provider\": \"None\", \"use_whitenoise\": \"y\", \"mail_service\": \"Sendgrid\"},\n    {\"cloud_provider\": \"None\", \"use_whitenoise\": \"y\", \"mail_service\": \"Brevo\"},\n    {\"cloud_provider\": \"None\", \"use_whitenoise\": \"y\", \"mail_service\": \"SparkPost\"},\n    {\"cloud_provider\": \"None\", \"use_whitenoise\": \"y\", \"mail_service\": \"Other SMTP\"},\n    # Note: cloud_provider=None AND use_whitenoise=n is not supported\n    {\"cloud_provider\": \"AWS\", \"mail_service\": \"Mailgun\"},\n    {\"cloud_provider\": \"AWS\", \"mail_service\": \"Amazon SES\"},\n    {\"cloud_provider\": \"AWS\", \"mail_service\": \"Mailjet\"},\n    {\"cloud_provider\": \"AWS\", \"mail_service\": \"Mandrill\"},\n    {\"cloud_provider\": \"AWS\", \"mail_service\": \"Postmark\"},\n    {\"cloud_provider\": \"AWS\", \"mail_service\": \"Sendgrid\"},\n    {\"cloud_provider\": \"AWS\", \"mail_service\": \"Brevo\"},\n    {\"cloud_provider\": \"AWS\", \"mail_service\": \"SparkPost\"},\n    {\"cloud_provider\": \"AWS\", \"mail_service\": \"Other SMTP\"},\n    {\"cloud_provider\": \"GCP\", \"mail_service\": \"Mailgun\"},\n    {\"cloud_provider\": \"GCP\", \"mail_service\": \"Mailjet\"},\n    {\"cloud_provider\": \"GCP\", \"mail_service\": \"Mandrill\"},\n    {\"cloud_provider\": \"GCP\", \"mail_service\": \"Postmark\"},\n    {\"cloud_provider\": \"GCP\", \"mail_service\": \"Sendgrid\"},\n    {\"cloud_provider\": \"GCP\", \"mail_service\": \"Brevo\"},\n    {\"cloud_provider\": \"GCP\", \"mail_service\": \"SparkPost\"},\n    {\"cloud_provider\": \"GCP\", \"mail_service\": \"Other SMTP\"},\n    {\"cloud_provider\": \"Azure\", \"mail_service\": \"Mailgun\"},\n    {\"cloud_provider\": \"Azure\", \"mail_service\": \"Mailjet\"},\n    {\"cloud_provider\": \"Azure\", \"mail_service\": \"Mandrill\"},\n    {\"cloud_provider\": \"Azure\", \"mail_service\": \"Postmark\"},\n    {\"cloud_provider\": \"Azure\", \"mail_service\": \"Sendgrid\"},\n    {\"cloud_provider\": \"Azure\", \"mail_service\": \"Brevo\"},\n    {\"cloud_provider\": \"Azure\", \"mail_service\": \"SparkPost\"},\n    {\"cloud_provider\": \"Azure\", \"mail_service\": \"Other SMTP\"},\n    # Note: cloud_providers GCP, Azure, and None\n    # with mail_service Amazon SES is not supported\n    {\"rest_api\": \"None\"},\n    {\"rest_api\": \"DRF\"},\n    {\"rest_api\": \"Django Ninja\"},\n    {\"use_async\": \"y\"},\n    {\"use_async\": \"n\"},\n    {\"frontend_pipeline\": \"None\"},\n    {\"frontend_pipeline\": \"Django Compressor\"},\n    {\"frontend_pipeline\": \"Gulp\"},\n    {\"frontend_pipeline\": \"Webpack\"},\n    {\"use_celery\": \"y\"},\n    {\"use_celery\": \"n\"},\n    {\"use_mailpit\": \"y\"},\n    {\"use_mailpit\": \"n\"},\n    {\"use_sentry\": \"y\"},\n    {\"use_sentry\": \"n\"},\n    {\"use_whitenoise\": \"y\"},\n    {\"use_whitenoise\": \"n\"},\n    {\"use_heroku\": \"y\"},\n    {\"use_heroku\": \"n\"},\n    {\"ci_tool\": \"None\"},\n    {\"ci_tool\": \"Travis\"},\n    {\"ci_tool\": \"Gitlab\"},\n    {\"ci_tool\": \"Github\"},\n    {\"ci_tool\": \"Drone\"},\n    {\"keep_local_envs_in_vcs\": \"y\"},\n    {\"keep_local_envs_in_vcs\": \"n\"},\n    {\"debug\": \"y\"},\n    {\"debug\": \"n\"},\n]\n\nUNSUPPORTED_COMBINATIONS = [\n    {\"cloud_provider\": \"None\", \"use_whitenoise\": \"n\"},\n    {\"cloud_provider\": \"GCP\", \"mail_service\": \"Amazon SES\"},\n    {\"cloud_provider\": \"Azure\", \"mail_service\": \"Amazon SES\"},\n    {\"cloud_provider\": \"None\", \"mail_service\": \"Amazon SES\"},\n]\n\n\ndef _fixture_id(ctx):\n    \"\"\"Helper to get a user-friendly test name from the parametrized context.\"\"\"\n    return \"-\".join(f\"{key}:{value}\" for key, value in ctx.items())\n\n\ndef build_files_list(base_path: Path):\n    \"\"\"Build a list containing absolute paths to the generated files.\"\"\"\n    excluded_dirs = {\".venv\", \"__pycache__\"}\n\n    f = []\n    for dirpath, subdirs, files in base_path.walk():\n        subdirs[:] = [d for d in subdirs if d not in excluded_dirs]\n\n        f.extend(dirpath / file_path for file_path in files)\n    return f\n\n\ndef check_paths(paths: Iterable[Path]):\n    \"\"\"Method to check all paths have correct substitutions.\"\"\"\n    # Assert that no match is found in any of the files\n    for path in paths:\n        if is_binary(str(path)):\n            continue\n\n        content = path.read_text()\n        match = RE_OBJ.search(content)\n        assert match is None, f\"cookiecutter variable not replaced in {path}\"\n\n\n@pytest.mark.parametrize(\"context_override\", SUPPORTED_COMBINATIONS, ids=_fixture_id)\ndef test_project_generation(cookies, context, context_override):\n    \"\"\"Test that project is generated and fully rendered.\"\"\"\n\n    result = cookies.bake(extra_context={**context, **context_override})\n    assert result.exit_code == 0\n    assert result.exception is None\n    assert result.project_path.name == context[\"project_slug\"]\n    assert result.project_path.is_dir()\n\n    paths = build_files_list(result.project_path)\n    assert paths\n    check_paths(paths)\n\n\n@pytest.mark.parametrize(\"context_override\", SUPPORTED_COMBINATIONS, ids=_fixture_id)\ndef test_ruff_check_passes(cookies, context_override):\n    \"\"\"Generated project should pass ruff check.\"\"\"\n    result = cookies.bake(extra_context=context_override)\n\n    try:\n        sh.ruff(\"check\", \".\", _cwd=str(result.project_path))\n    except sh.ErrorReturnCode as e:\n        pytest.fail(e.stdout.decode())\n\n\n@auto_fixable\n@pytest.mark.parametrize(\"context_override\", SUPPORTED_COMBINATIONS, ids=_fixture_id)\ndef test_ruff_format_passes(cookies, context_override):\n    \"\"\"Check whether generated project passes ruff format.\"\"\"\n    result = cookies.bake(extra_context=context_override)\n\n    try:\n        sh.ruff(\n            \"format\",\n            \".\",\n            _cwd=str(result.project_path),\n        )\n    except sh.ErrorReturnCode as e:\n        pytest.fail(e.stdout.decode())\n\n\n@auto_fixable\n@pytest.mark.parametrize(\"context_override\", SUPPORTED_COMBINATIONS, ids=_fixture_id)\ndef test_django_upgrade_passes(cookies, context_override):\n    \"\"\"Check whether generated project passes django-upgrade.\"\"\"\n    result = cookies.bake(extra_context=context_override)\n\n    python_files = [\n        file_path.removeprefix(f\"{result.project_path}/\")\n        for file_path in glob.glob(str(result.project_path / \"**\" / \"*.py\"), recursive=True)  # noqa: PTH207\n    ]\n    try:\n        sh.django_upgrade(\n            \"--target-version\",\n            \"5.0\",\n            *python_files,\n            _cwd=str(result.project_path),\n        )\n    except sh.ErrorReturnCode as e:\n        pytest.fail(e.stdout.decode())\n\n\n@pytest.mark.parametrize(\"context_override\", SUPPORTED_COMBINATIONS, ids=_fixture_id)\ndef test_djlint_lint_passes(cookies, context_override):\n    \"\"\"Check whether generated project passes djLint --lint.\"\"\"\n    result = cookies.bake(extra_context=context_override)\n\n    autofixable_rules = \"H014,T001\"\n    # TODO: remove T002 when fixed https://github.com/Riverside-Healthcare/djLint/issues/687\n    ignored_rules = \"H006,H030,H031,T002\"\n    try:\n        sh.djlint(\n            \"--lint\",\n            \"--ignore\",\n            f\"{autofixable_rules},{ignored_rules}\",\n            \".\",\n            _cwd=str(result.project_path),\n        )\n    except sh.ErrorReturnCode as e:\n        pytest.fail(e.stdout.decode())\n\n\n@auto_fixable\n@pytest.mark.parametrize(\"context_override\", SUPPORTED_COMBINATIONS, ids=_fixture_id)\ndef test_djlint_check_passes(cookies, context_override):\n    \"\"\"Check whether generated project passes djLint --check.\"\"\"\n    result = cookies.bake(extra_context=context_override)\n\n    try:\n        sh.djlint(\"--check\", \".\", _cwd=str(result.project_path))\n    except sh.ErrorReturnCode as e:\n        pytest.fail(e.stdout.decode())\n\n\n@pytest.mark.parametrize(\n    (\"use_docker\", \"expected_test_script\"),\n    [\n        (\"n\", \"uv run pytest\"),\n        (\"y\", \"docker compose -f docker-compose.local.yml run django pytest\"),\n    ],\n)\ndef test_travis_invokes_pytest(cookies, context, use_docker, expected_test_script):\n    context.update({\"ci_tool\": \"Travis\", \"use_docker\": use_docker})\n    result = cookies.bake(extra_context=context)\n\n    assert result.exit_code == 0\n    assert result.exception is None\n    assert result.project_path.name == context[\"project_slug\"]\n    assert result.project_path.is_dir()\n\n    with (result.project_path / \".travis.yml\").open() as travis_yml:\n        try:\n            yml = yaml.safe_load(travis_yml)[\"jobs\"][\"include\"]\n            assert yml[0][\"script\"] == [\"ruff check .\"]\n            assert yml[1][\"script\"] == [expected_test_script]\n        except yaml.YAMLError as e:\n            pytest.fail(str(e))\n\n\n@pytest.mark.parametrize(\n    (\"use_docker\", \"expected_test_script\"),\n    [\n        (\"n\", \"uv run pytest\"),\n        (\"y\", \"docker compose -f docker-compose.local.yml run django pytest\"),\n    ],\n)\ndef test_gitlab_invokes_precommit_and_pytest(cookies, context, use_docker, expected_test_script):\n    context.update({\"ci_tool\": \"Gitlab\", \"use_docker\": use_docker})\n    result = cookies.bake(extra_context=context)\n\n    assert result.exit_code == 0\n    assert result.exception is None\n    assert result.project_path.name == context[\"project_slug\"]\n    assert result.project_path.is_dir()\n\n    with (result.project_path / \".gitlab-ci.yml\").open() as gitlab_yml:\n        try:\n            gitlab_config = yaml.safe_load(gitlab_yml)\n            assert gitlab_config[\"precommit\"][\"script\"] == [\n                \"uv run pre-commit run --show-diff-on-failure --color=always --all-files\",\n            ]\n            assert gitlab_config[\"pytest\"][\"script\"] == [expected_test_script]\n        except yaml.YAMLError as e:\n            pytest.fail(e)\n\n\n@pytest.mark.parametrize(\n    (\"use_docker\", \"expected_test_script\"),\n    [\n        (\"n\", \"uv run pytest\"),\n        (\"y\", \"docker compose -f docker-compose.local.yml run django pytest\"),\n    ],\n)\ndef test_github_invokes_linter_and_pytest(cookies, context, use_docker, expected_test_script):\n    context.update({\"ci_tool\": \"Github\", \"use_docker\": use_docker})\n    result = cookies.bake(extra_context=context)\n\n    assert result.exit_code == 0\n    assert result.exception is None\n    assert result.project_path.name == context[\"project_slug\"]\n    assert result.project_path.is_dir()\n\n    with (result.project_path / \".github\" / \"workflows\" / \"ci.yml\").open() as github_yml:\n        try:\n            github_config = yaml.safe_load(github_yml)\n            linter_present = False\n            for action_step in github_config[\"jobs\"][\"linter\"][\"steps\"]:\n                if action_step.get(\"uses\", \"NA\").startswith(\"pre-commit\"):\n                    linter_present = True\n            assert linter_present\n\n            expected_test_script_present = False\n            for action_step in github_config[\"jobs\"][\"pytest\"][\"steps\"]:\n                if action_step.get(\"run\") == expected_test_script:\n                    expected_test_script_present = True\n            assert expected_test_script_present\n        except yaml.YAMLError as e:\n            pytest.fail(e)\n\n\n@pytest.mark.parametrize(\"slug\", [\"project slug\", \"Project_Slug\"])\ndef test_invalid_slug(cookies, context, slug):\n    \"\"\"Invalid slug should fail pre-generation hook.\"\"\"\n    context.update({\"project_slug\": slug})\n\n    result = cookies.bake(extra_context=context)\n\n    assert result.exit_code != 0\n    assert isinstance(result.exception, FailedHookException)\n\n\n@pytest.mark.parametrize(\"invalid_context\", UNSUPPORTED_COMBINATIONS)\ndef test_error_if_incompatible(cookies, context, invalid_context):\n    \"\"\"It should not generate project an incompatible combination is selected.\"\"\"\n    context.update(invalid_context)\n    result = cookies.bake(extra_context=context)\n\n    assert result.exit_code != 0\n    assert isinstance(result.exception, FailedHookException)\n\n\n@pytest.mark.parametrize(\n    (\"editor\", \"pycharm_docs_exist\"),\n    [\n        (\"None\", False),\n        (\"PyCharm\", True),\n        (\"VS Code\", False),\n    ],\n)\ndef test_pycharm_docs_removed(cookies, context, editor, pycharm_docs_exist):\n    context.update({\"editor\": editor})\n    result = cookies.bake(extra_context=context)\n\n    index_rst = result.project_path / \"docs\" / \"index.rst\"\n    has_pycharm_docs = \"pycharm/configuration\" in index_rst.read_text()\n    assert has_pycharm_docs is pycharm_docs_exist\n\n\ndef test_trim_domain_email(cookies, context):\n    \"\"\"Check that leading and trailing spaces are trimmed in domain and email.\"\"\"\n    context.update(\n        {\n            \"use_docker\": \"y\",\n            \"domain_name\": \"   example.com   \",\n            \"email\": \"  me@example.com  \",\n        },\n    )\n    result = cookies.bake(extra_context=context)\n\n    assert result.exit_code == 0\n\n    prod_django_env = result.project_path / \".envs\" / \".production\" / \".django\"\n    assert \"DJANGO_ALLOWED_HOSTS=.example.com\" in prod_django_env.read_text()\n\n    base_settings = result.project_path / \"config\" / \"settings\" / \"base.py\"\n    assert \"<me@example.com>\" in base_settings.read_text()\n\n\ndef test_pyproject_toml(cookies, context):\n    author_name = \"Project Author\"\n    author_email = \"me@example.com\"\n    context.update(\n        {\n            \"description\": \"DESCRIPTION\",\n            \"domain_name\": \"example.com\",\n            \"email\": author_email,\n            \"author_name\": author_name,\n        },\n    )\n    result = cookies.bake(extra_context=context)\n    assert result.exit_code == 0\n\n    pyproject_toml = result.project_path / \"pyproject.toml\"\n\n    data = tomllib.loads(pyproject_toml.read_text())\n\n    assert data\n    assert data[\"project\"][\"authors\"][0][\"email\"] == author_email\n    assert data[\"project\"][\"authors\"][0][\"name\"] == author_name\n    assert data[\"project\"][\"name\"] == context[\"project_slug\"]\n\n\ndef test_pre_commit_without_heroku(cookies, context):\n    context.update({\"use_heroku\": \"n\"})\n    result = cookies.bake(extra_context=context)\n    assert result.exit_code == 0\n\n    pre_commit_config = result.project_path / \".pre-commit-config.yaml\"\n\n    data = pre_commit_config.read_text()\n\n    assert \"uv-pre-commit\" not in data\n"
  },
  {
    "path": "tests/test_docker.sh",
    "content": "#!/bin/sh\n# this is a very simple script that tests the docker configuration for cookiecutter-django\n# it is meant to be run from the root directory of the repository, eg:\n# sh tests/test_docker.sh\n\nset -o errexit\nset -x\nset -e\n\nfinish() {\n  # Your cleanup code here\n  docker compose -f docker-compose.local.yml down --remove-orphans\n  docker volume rm my_awesome_project_my_awesome_project_local_postgres_data\n\n}\n# the cleanup doesn't work in the github actions\nif [ -z \"$GITHUB_ACTIONS\" ]; then\n  trap finish EXIT\nfi\n\n\n# create a cache directory\nmkdir -p .cache/docker\ncd .cache/docker\n\nsudo rm -rf my_awesome_project\n\n# create the project using the default settings in cookiecutter.json\nuv run cookiecutter ../../ --no-input --overwrite-if-exists use_docker=y \"$@\"\ncd my_awesome_project\n\n# make sure all images build\ndocker compose -f docker-compose.local.yml build\n\ndocker compose -f docker-compose.local.yml run django uv lock\n\ndocker compose -f docker-compose.local.yml build\n\n# run the project's type checks\ndocker compose -f docker-compose.local.yml run --rm django mypy my_awesome_project\n\n# run the project's tests\ndocker compose -f docker-compose.local.yml run --rm django pytest\n\n# return non-zero status code if there are migrations that have not been created\ndocker compose -f docker-compose.local.yml run --rm django python manage.py makemigrations --check || { echo \"ERROR: there were changes in the models, but migration listed above have not been created and are not saved in version control\"; exit 1; }\n\n# Test support for translations\ndocker compose -f docker-compose.local.yml run --rm django python manage.py makemessages --all\n\n# Make sure the check doesn't raise any warnings\ndocker compose -f docker-compose.local.yml run --rm \\\n  -e DJANGO_SECRET_KEY=\"$(openssl rand -base64 64)\" \\\n  -e REDIS_URL=redis://redis:6379/0 \\\n  -e DJANGO_AWS_ACCESS_KEY_ID=x \\\n  -e DJANGO_AWS_SECRET_ACCESS_KEY=x \\\n  -e DJANGO_AWS_STORAGE_BUCKET_NAME=x \\\n  -e DJANGO_ADMIN_URL=x \\\n  -e MAILGUN_API_KEY=x \\\n  -e MAILGUN_DOMAIN=x \\\n  django python manage.py check --settings=config.settings.production --deploy --database default --fail-level WARNING\n\n# Generate the HTML for the documentation\ndocker compose -f docker-compose.docs.yml run --rm docs make html\n\ndocker build -f ./compose/production/django/Dockerfile -t django-prod .\n\ndocker run --rm \\\n--env-file .envs/.local/.django \\\n--env-file .envs/.local/.postgres \\\n--network my_awesome_project_default \\\n-e DJANGO_SECRET_KEY=\"$(openssl rand -base64 64)\" \\\n-e REDIS_URL=redis://redis:6379/0 \\\n-e DJANGO_AWS_ACCESS_KEY_ID=x \\\n-e DJANGO_AWS_SECRET_ACCESS_KEY=x \\\n-e DJANGO_AWS_STORAGE_BUCKET_NAME=x \\\n-e DJANGO_ADMIN_URL=x \\\n-e MAILGUN_API_KEY=x \\\n-e MAILGUN_DOMAIN=x \\\ndjango-prod python manage.py check --settings=config.settings.production --deploy --database default --fail-level WARNING\n\n# Run npm build script if package.json is present\nif [ -f \"package.json\" ]\nthen\n    docker compose -f docker-compose.local.yml run --rm node npm run build\nfi\n"
  },
  {
    "path": "tests/test_hooks.py",
    "content": "\"\"\"Unit tests for the hooks\"\"\"\n\nimport os\nfrom pathlib import Path\n\nimport pytest\n\nfrom hooks.post_gen_project import append_to_gitignore_file\n\n\n@pytest.fixture\ndef working_directory(tmp_path):\n    prev_cwd = Path.cwd()\n    os.chdir(tmp_path)\n    try:\n        yield tmp_path\n    finally:\n        os.chdir(prev_cwd)\n\n\ndef test_append_to_gitignore_file(working_directory):\n    gitignore_file = working_directory / \".gitignore\"\n    gitignore_file.write_text(\"node_modules/\\n\")\n    append_to_gitignore_file(\".envs/*\")\n    linesep = os.linesep.encode()\n    assert gitignore_file.read_bytes() == b\"node_modules/\" + linesep + b\".envs/*\" + linesep\n    assert gitignore_file.read_text() == \"node_modules/\\n.envs/*\\n\"\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nskipsdist = true\nenvlist = py313\n\n[testenv]\npassenv = AUTOFIXABLE_STYLES\ncommands = pytest --instafail -n auto {posargs:./tests}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.devcontainer/bash_history",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/.devcontainer/bashrc.override.sh",
    "content": "\n#\n# .bashrc.override.sh\n#\n\n# persistent bash history\nHISTFILE=~/.bash_history\nPROMPT_COMMAND=\"history -a; $PROMPT_COMMAND\"\n\n# set some django env vars\nsource /entrypoint\n\n# restore default shell options\nset +o errexit\nset +o pipefail\nset +o nounset\n\n# start ssh-agent\n# https://code.visualstudio.com/docs/remote/troubleshooting\neval \"$(ssh-agent -s)\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.devcontainer/devcontainer.json",
    "content": "// For format details, see https://containers.dev/implementors/json_reference/\n{\n    \"name\": \"{{cookiecutter.project_slug}}_dev\",\n    \"dockerComposeFile\": [\n        \"../docker-compose.local.yml\"\n    ],\n    \"init\": true,\n    \"mounts\": [\n        {\n            \"source\": \"./.devcontainer/bash_history\",\n            \"target\": \"/home/dev-user/.bash_history\",\n            \"type\": \"bind\"\n        },\n        {\n            \"source\": \"~/.ssh\",\n            \"target\": \"/home/dev-user/.ssh\",\n            \"type\": \"bind\"\n        }\n    ],\n    // Tells devcontainer.json supporting services / tools whether they should run\n    // /bin/sh -c \"while sleep 1000; do :; done\" when starting the container instead of the container’s default command\n    \"overrideCommand\": false,\n    \"service\": \"django\",\n    // \"remoteEnv\": {\"PATH\": \"/home/dev-user/.local/bin:${containerEnv:PATH}\"},\n    \"remoteUser\": \"dev-user\",\n    \"workspaceFolder\": \"/app\",\n    // Set *default* container specific settings.json values on container create.\n    \"customizations\": {\n        {%- if cookiecutter.editor == \"VS Code\" %}\n        \"vscode\": {\n            \"settings\": {\n                \"editor.formatOnSave\": true,\n                \"[python]\": {\n                    \"analysis.autoImportCompletions\": true,\n                    \"analysis.typeCheckingMode\": \"basic\",\n                    \"defaultInterpreterPath\": \"/usr/local/bin/python\",\n                    \"editor.codeActionsOnSave\": {\n                        \"source.organizeImports\": \"always\"\n                    },\n                    \"editor.defaultFormatter\": \"charliermarsh.ruff\",\n                    \"languageServer\": \"Pylance\",\n                    \"linting.enabled\": true,\n                    \"linting.mypyEnabled\": true,\n                    \"linting.mypyPath\": \"/usr/local/bin/mypy\",\n                }\n            },\n            // https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_vs-code-specific-properties\n            // Add the IDs of extensions you want installed when the container is created.\n            \"extensions\": [\n                \"davidanson.vscode-markdownlint\",\n                \"mrmlnc.vscode-duplicate\",\n                \"visualstudioexptteam.vscodeintellicode\",\n                \"visualstudioexptteam.intellicode-api-usage-examples\",\n                // python\n                \"ms-python.python\",\n                \"ms-python.vscode-pylance\",\n                \"charliermarsh.ruff\",\n                // django\n                \"batisteo.vscode-django\"\n            ]\n        }\n        {%- endif %}\n    },\n    // Uncomment the next line if you want start specific services in your Docker Compose config.\n    // \"runServices\": [],\n    // Uncomment the next line if you want to keep your containers running after VS Code shuts down.\n    // \"shutdownAction\": \"none\",\n    // Uncomment the next line to run commands after the container is created.\n    \"postCreateCommand\": \"cat .devcontainer/bashrc.override.sh >> ~/.bashrc\"\n}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.dockerignore",
    "content": ".editorconfig\n.gitattributes\n.github\n.gitignore\n.gitlab-ci.yml\n.idea\n.pre-commit-config.yaml\n.readthedocs.yml\n.travis.yml\nvenv\n.git\n.envs/\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.drone.yml",
    "content": "kind: pipeline\nname: default\n\nenvironment:\n  POSTGRES_USER: '{{ cookiecutter.project_slug }}'\n  POSTGRES_PASSWORD: ''\n  POSTGRES_DB: 'test_{{ cookiecutter.project_slug }}'\n  POSTGRES_HOST_AUTH_METHOD: trust\n  {%- if cookiecutter.use_celery == 'y' %}\n  REDIS_URL: 'redis://redis:6379/0'\n  {%- endif %}\n\nsteps:\n- name: lint\n  pull: if-not-exists\n  image: ghcr.io/astral-sh/uv:python3.13\n  environment:\n    PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit\n  volumes:\n  - name: pre-commit cache\n    path: ${PRE_COMMIT_HOME}\n  commands:\n  - export PRE_COMMIT_HOME=$CI_PROJECT_DIR/.cache/pre-commit\n  - uv pip install -q pre-commit pre-commit-uv\n  - uv run pre-commit run --show-diff-on-failure --color=always --all-files\n\n- name: test\n  pull: if-not-exists\n  {%- if cookiecutter.use_docker == 'y' %}\n  image: docker:25.0\n  environment:\n    DATABASE_URL: pgsql://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres/$POSTGRES_DB\n  commands:\n  - docker-compose -f docker-compose.local.yml build\n  - docker-compose -f docker-compose.docs.yml build\n  - docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate\n  - docker-compose -f docker-compose.local.yml up -d\n  - docker-compose -f docker-compose.local.yml run django pytest\n  {%- else %}\n  image: ghcr.io/astral-sh/uv:python3.13\n  commands:\n  - uv sync --locked\n  - uv run pytest\n  {%- endif%}\n\nvolumes:\n- name: pre-commit cache\n  host:\n    path: /tmp/drone/cache/pre-commit\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.editorconfig",
    "content": "# http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.{py,rst,ini}]\nindent_style = space\nindent_size = 4\n\n[*.{html,css,scss,json,yml,xml,toml}]\nindent_style = space\nindent_size = 2\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[Makefile]\nindent_style = tab\n\n[default.conf]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.envs/.local/.django",
    "content": "# General\n# ------------------------------------------------------------------------------\nUSE_DOCKER=yes\nIPYTHONDIR=/app/.ipython\n\n{%- if cookiecutter.use_celery == 'y' %}\n# Redis\n# ------------------------------------------------------------------------------\nREDIS_URL=redis://redis:6379/0\n\n# Celery\n# ------------------------------------------------------------------------------\n\n# Flower\nCELERY_FLOWER_USER=!!!SET CELERY_FLOWER_USER!!!\nCELERY_FLOWER_PASSWORD=!!!SET CELERY_FLOWER_PASSWORD!!!\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.envs/.local/.postgres",
    "content": "# PostgreSQL\n# ------------------------------------------------------------------------------\nPOSTGRES_HOST=postgres\nPOSTGRES_PORT=5432\nPOSTGRES_DB={{ cookiecutter.project_slug }}\nPOSTGRES_USER=!!!SET POSTGRES_USER!!!\nPOSTGRES_PASSWORD=!!!SET POSTGRES_PASSWORD!!!\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.envs/.production/.django",
    "content": "# General\n# ------------------------------------------------------------------------------\n# DJANGO_READ_DOT_ENV_FILE=True\nDJANGO_SETTINGS_MODULE=config.settings.production\nDJANGO_SECRET_KEY=!!!SET DJANGO_SECRET_KEY!!!\nDJANGO_ADMIN_URL=!!!SET DJANGO_ADMIN_URL!!!\nDJANGO_ALLOWED_HOSTS=.{{ cookiecutter.domain_name }}\n\n# Security\n# ------------------------------------------------------------------------------\n# TIP: better off using DNS, however, redirect is OK too\nDJANGO_SECURE_SSL_REDIRECT=False\n\n# Email\n# ------------------------------------------------------------------------------\nDJANGO_SERVER_EMAIL=\n{% if cookiecutter.mail_service == 'Mailgun' %}\nMAILGUN_API_KEY=\nMAILGUN_DOMAIN=\n{% elif cookiecutter.mail_service == 'Mailjet' %}\nMAILJET_API_KEY=\nMAILJET_SECRET_KEY=\n{% elif cookiecutter.mail_service == 'Mandrill' %}\nMANDRILL_API_KEY=\n{% elif cookiecutter.mail_service == 'Postmark' %}\nPOSTMARK_SERVER_TOKEN=\n{% elif cookiecutter.mail_service == 'Sendgrid' %}\nSENDGRID_API_KEY=\nSENDGRID_GENERATE_MESSAGE_ID=True\nSENDGRID_MERGE_FIELD_FORMAT=None\n{% elif cookiecutter.mail_service == 'Brevo' %}\nBREVO_API_KEY=\n{% elif cookiecutter.mail_service == 'SparkPost' %}\nSPARKPOST_API_KEY=\n{% endif %}\n{% if cookiecutter.cloud_provider == 'AWS' %}\n# AWS\n# ------------------------------------------------------------------------------\nDJANGO_AWS_ACCESS_KEY_ID=\nDJANGO_AWS_SECRET_ACCESS_KEY=\nDJANGO_AWS_STORAGE_BUCKET_NAME=\n{% elif cookiecutter.cloud_provider == 'GCP' %}\n# GCP\n# ------------------------------------------------------------------------------\nGOOGLE_APPLICATION_CREDENTIALS=\nDJANGO_GCP_STORAGE_BUCKET_NAME=\n{% elif cookiecutter.cloud_provider == 'Azure' %}\n# Azure\n# ------------------------------------------------------------------------------\nDJANGO_AZURE_ACCOUNT_KEY=\nDJANGO_AZURE_ACCOUNT_NAME=\nDJANGO_AZURE_CONTAINER_NAME=\n{% endif %}\n# django-allauth\n# ------------------------------------------------------------------------------\nDJANGO_ACCOUNT_ALLOW_REGISTRATION=True\n\n# Gunicorn\n# ------------------------------------------------------------------------------\nWEB_CONCURRENCY=4\n{% if cookiecutter.use_sentry == 'y' %}\n# Sentry\n# ------------------------------------------------------------------------------\nSENTRY_DSN=\n{% endif %}\n\n# Redis\n# ------------------------------------------------------------------------------\nREDIS_URL=redis://redis:6379/0\n{% if cookiecutter.use_celery == 'y' %}\n# Celery\n# ------------------------------------------------------------------------------\n\n# Flower\nCELERY_FLOWER_USER=!!!SET CELERY_FLOWER_USER!!!\nCELERY_FLOWER_PASSWORD=!!!SET CELERY_FLOWER_PASSWORD!!!\n{% endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.envs/.production/.postgres",
    "content": "# PostgreSQL\n# ------------------------------------------------------------------------------\nPOSTGRES_HOST=postgres\nPOSTGRES_PORT=5432\nPOSTGRES_DB={{ cookiecutter.project_slug }}\nPOSTGRES_USER=!!!SET POSTGRES_USER!!!\nPOSTGRES_PASSWORD=!!!SET POSTGRES_PASSWORD!!!\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.gitattributes",
    "content": "* text=auto\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.github/dependabot.yml",
    "content": "# Config for Dependabot updates. See Documentation here:\n# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file\n\nversion: 2\nupdates:\n  # Update GitHub actions in workflows\n  - package-ecosystem: 'github-actions'\n    directory: '/'\n    # Every weekday\n    schedule:\n      interval: 'daily'\n    groups:\n      github-actions:\n        patterns:\n          - '*'\n\n{%- if cookiecutter.use_docker == 'y' %}\n\n  # Enable version updates for Docker\n  - package-ecosystem: 'docker'\n    # Look for a `Dockerfile` in the `compose/local/django` directory\n    directories:\n      - 'compose/local/django/'\n      - 'compose/local/docs/'\n      - 'compose/production/django/'\n    # Every weekday\n    schedule:\n      interval: 'daily'\n    # Ignore minor version updates (3.10 -> 3.11) but update patch versions\n    ignore:\n      - dependency-name: '*'\n        update-types:\n          - 'version-update:semver-major'\n          - 'version-update:semver-minor'\n    groups:\n      docker-python:\n        patterns:\n          - '*'\n\n\n  - package-ecosystem: 'docker'\n    # Look for a `Dockerfile` in the listed directories\n    directories:\n      - 'compose/local/node/'\n      - 'compose/production/aws/'\n      - 'compose/production/postgres/'\n      - 'compose/production/traefik/'\n{%- if cookiecutter.cloud_provider == 'None' %}\n      - 'compose/production/nginx/'\n{%- endif %}\n    # Every weekday\n    schedule:\n      interval: 'daily'\n\n  # Enable version updates for Docker Compose files\n  - package-ecosystem: 'docker-compose'\n    directories:\n      - '/'\n    # Every weekday\n    schedule:\n      interval: 'daily'\n\n{%- endif %}\n\n  # Enable version updates for Python/uv\n  - package-ecosystem: 'uv'\n    # Look for a `pyproject.toml` in the `root` directory\n    directory: '/'\n    # Every weekday\n    schedule:\n      interval: 'daily'\n    groups:\n      python:\n        update-types:\n          - 'minor'\n          - 'patch'\n\n{%- if cookiecutter.frontend_pipeline == 'Gulp' %}\n\n  # Enable version updates for javascript/npm\n  - package-ecosystem: 'npm'\n    # Look for a `packages.json` in the `root` directory\n    directory: '/'\n    # Every weekday\n    schedule:\n      interval: 'daily'\n    groups:\n      javascript:\n        update-types:\n          - 'minor'\n          - 'patch'\n\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.github/workflows/ci.yml",
    "content": "name: CI\n\n# Enable Buildkit and let compose use it to speed up image building\nenv:\n  DOCKER_BUILDKIT: 1\n  COMPOSE_DOCKER_CLI_BUILD: 1\n\non:\n  pull_request:\n    branches: ['main']\n    paths-ignore: ['docs/**']\n\n  push:\n    branches: ['main']\n    paths-ignore: ['docs/**']\n\nconcurrency:\n  group: {% raw %}${{ github.head_ref || github.run_id }}{% endraw %}\n  cancel-in-progress: true\n\njobs:\n  linter:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Code Repository\n        uses: actions/checkout@v6\n\n      - name: Set up Python\n        uses: actions/setup-python@v6\n        with:\n          python-version-file: '.python-version'\n\n      {%- if cookiecutter.open_source_license != 'Not open source' %}\n      # Consider using pre-commit.ci for open source project\n      {%- endif %}\n      - name: Run pre-commit\n        uses: pre-commit/action@v3.0.1\n\n  # With no caching at all the entire ci process takes 3m to complete!\n  pytest:\n    runs-on: ubuntu-latest\n    {%- if cookiecutter.use_docker == 'n' %}\n\n    services:\n      {%- if cookiecutter.use_celery == 'y' %}\n      redis:\n        image: redis:7.2\n        ports:\n          - 6379:6379\n      {%- endif %}\n      postgres:\n        image: postgres:{{ cookiecutter.postgresql_version }}\n        ports:\n          - 5432:5432\n        env:\n          POSTGRES_PASSWORD: postgres\n\n    env:\n      {%- if cookiecutter.use_celery == 'y' %}\n      REDIS_URL: 'redis://localhost:6379/0'\n      {%- endif %}\n      # postgres://user:password@host:port/database\n      DATABASE_URL: 'postgres://postgres:postgres@localhost:5432/postgres'\n    {%- endif %}\n\n    steps:\n      - name: Checkout Code Repository\n        uses: actions/checkout@v6\n      {%- if cookiecutter.use_docker == 'y' %}\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n\n      - name: Build and cache local backend\n        uses: docker/bake-action@v6\n        with:\n          push: false\n          load: true\n          files: docker-compose.local.yml\n          targets: django\n          set: |\n            django.cache-from=type=gha,scope=django-cached-tests\n            django.cache-to=type=gha,scope=django-cached-tests,mode=max\n            postgres.cache-from=type=gha,scope=postgres-cached-tests\n            postgres.cache-to=type=gha,scope=postgres-cached-tests,mode=max\n\n      - name: Build and cache docs\n        uses: docker/bake-action@v6\n        with:\n          push: false\n          load: true\n          files: docker-compose.docs.yml\n          set: |\n            docs.cache-from=type=gha,scope=cached-docs\n            docs.cache-to=type=gha,scope=cached-docs,mode=max\n\n      - name: Check DB Migrations\n        run: docker compose -f docker-compose.local.yml run --rm django python manage.py makemigrations --check\n\n      - name: Run DB Migrations\n        run: docker compose -f docker-compose.local.yml run --rm django python manage.py migrate\n\n      - name: Run Django Tests\n        run: docker compose -f docker-compose.local.yml run django pytest\n\n      - name: Tear down the Stack\n        run: docker compose -f docker-compose.local.yml down\n      {%- else %}\n\n      - name: Install uv\n        uses: astral-sh/setup-uv@v5\n        with:\n          enable-cache: \"true\"\n\n      - name: Set up Python\n        uses: actions/setup-python@v6\n        with:\n          python-version-file: \".python-version\"\n\n      - name: Install dependencies\n        run: uv sync --locked\n\n      - name: Check DB Migrations\n        run: uv run python manage.py makemigrations --check\n\n      - name: Run DB Migrations\n        run: uv run python manage.py migrate\n\n      - name: Test with pytest\n        run: uv run pytest\n      {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.gitignore",
    "content": "### Python template\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\n*.egg-info/\n.installed.cfg\n*.egg\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*.cover\n.hypothesis/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\nstaticfiles/\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n\n{% if cookiecutter.use_celery == 'y' -%}\n# celery beat schedule file\ncelerybeat-schedule\n{%- endif %}\n\n# Environments\n.venv\nvenv/\nENV/\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n\n\n### Node template\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n\n### Linux template\n*~\n\n# temporary files which can be created if a process still has a handle open of a deleted file\n.fuse_hidden*\n\n# KDE directory preferences\n.directory\n\n# Linux trash folder which might appear on any partition or disk\n.Trash-*\n\n# .nfs files are created when an open file is removed but is still being accessed\n.nfs*\n\n\n### VisualStudioCode template\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n*.code-workspace\n\n# Local History for devcontainer\n.devcontainer/bash_history\n\n{% if cookiecutter.editor == 'PyCharm' -%}\n# Provided default Pycharm Run/Debug Configurations should be tracked by git\n# In case of local modifications made by Pycharm, use update-index command\n# for each changed file, like this:\n# git update-index --assume-unchanged .idea/{{cookiecutter.project_slug}}.iml\n### JetBrains template\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n# User-specific stuff:\n.idea/**/workspace.xml\n.idea/**/tasks.xml\n.idea/dictionaries\n\n# Sensitive or high-churn files:\n.idea/**/dataSources/\n.idea/**/dataSources.ids\n.idea/**/dataSources.xml\n.idea/**/dataSources.local.xml\n.idea/**/sqlDataSources.xml\n.idea/**/dynamic.xml\n.idea/**/uiDesigner.xml\n\n# Gradle:\n.idea/**/gradle.xml\n.idea/**/libraries\n\n# CMake\ncmake-build-debug/\n\n# Mongo Explorer plugin:\n.idea/**/mongoSettings.xml\n\n## File-based project format:\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\nout/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Cursive Clojure plugin\n.idea/replstate.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n{% endif %}\n\n\n### Windows template\n# Windows thumbnail cache files\nThumbs.db\nehthumbs.db\nehthumbs_vista.db\n\n# Dump file\n*.stackdump\n\n# Folder config file\nDesktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n\n### macOS template\n# General\n*.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n\n### SublimeText template\n# Cache files for Sublime Text\n*.tmlanguage.cache\n*.tmPreferences.cache\n*.stTheme.cache\n\n# Workspace files are user-specific\n*.sublime-workspace\n\n# Project files should be checked into the repository, unless a significant\n# proportion of contributors will probably not be using Sublime Text\n# *.sublime-project\n\n# SFTP configuration file\nsftp-config.json\n\n# Package control specific files\nPackage Control.last-run\nPackage Control.ca-list\nPackage Control.ca-bundle\nPackage Control.system-ca-bundle\nPackage Control.cache/\nPackage Control.ca-certs/\nPackage Control.merged-ca-bundle\nPackage Control.user-ca-bundle\noscrypto-ca-bundle.crt\nbh_unicode_properties.cache\n\n# Sublime-github package stores a github token in this file\n# https://packagecontrol.io/packages/sublime-github\nGitHub.sublime-settings\n\n\n### Vim template\n# Swap\n[._]*.s[a-v][a-z]\n[._]*.sw[a-p]\n[._]s[a-v][a-z]\n[._]sw[a-p]\n\n# Session\nSession.vim\n\n# Temporary\n.netrwhist\n\n# Auto-generated tag files\ntags\n\n# Redis dump file\ndump.rdb\n\n### Project template\n{%- if cookiecutter.use_mailpit == 'y' and cookiecutter.use_docker == 'n' %}\nmailpit\n{%- endif %}\n{{ cookiecutter.project_slug }}/media/\n\n.pytest_cache/\n\n{%- if cookiecutter.use_docker == 'y' %}\n.ipython/\n{%- endif %}\n\n{%- if cookiecutter.frontend_pipeline == 'Gulp' %}\nproject.css\nproject.min.css\nvendors.js\n*.min.js\n*.min.js.map\n{%- endif %}\n{%- if cookiecutter.frontend_pipeline == 'Webpack' %}\n{{ cookiecutter.project_slug }}/static/webpack_bundles/\nwebpack-stats.json\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.gitlab-ci.yml",
    "content": "stages:\n  - lint\n  - test\n\nvariables:\n  POSTGRES_USER: '{{ cookiecutter.project_slug }}'\n  POSTGRES_PASSWORD: ''\n  POSTGRES_DB: 'test_{{ cookiecutter.project_slug }}'\n  POSTGRES_HOST_AUTH_METHOD: trust\n  {%- if cookiecutter.use_celery == 'y' %}\n  REDIS_URL: 'redis://redis:6379/0'\n  {%- endif %}\n\nprecommit:\n  stage: lint\n  image: ghcr.io/astral-sh/uv:python3.13-bookworm\n  variables:\n    PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit\n  cache:\n    paths:\n      - ${PRE_COMMIT_HOME}\n  before_script:\n    - uv venv\n    - uv pip install -q pre-commit pre-commit-uv\n  script:\n    - uv run pre-commit run --show-diff-on-failure --color=always --all-files\n\npytest:\n  stage: test\n  {%- if cookiecutter.use_docker == 'y' %}\n  image: docker:25.0\n  services:\n    - docker:dind\n  before_script:\n    - docker compose -f docker-compose.local.yml build\n    - docker compose -f docker-compose.docs.yml build\n    # Ensure celerybeat does not crash due to non-existent tables\n    - docker compose -f docker-compose.local.yml run --rm django python manage.py migrate\n    - docker compose -f docker-compose.local.yml up -d\n  script:\n    - docker compose -f docker-compose.local.yml run django pytest\n  {%- else %}\n  image: ghcr.io/astral-sh/uv:python3.13\n  services:\n    - postgres:{{ cookiecutter.postgresql_version }}\n  variables:\n    DATABASE_URL: pgsql://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres/$POSTGRES_DB\n  before_script:\n    - uv sync --locked\n  script:\n    - uv run pytest\n  {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.pre-commit-config.yaml",
    "content": "exclude: '^docs/|/migrations/|devcontainer.json'\ndefault_stages: [pre-commit]\nminimum_pre_commit_version: \"3.2.0\"\n\ndefault_language_version:\n  python: python3.13\n\nrepos:\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v6.0.0\n    hooks:\n      - id: trailing-whitespace\n      - id: end-of-file-fixer\n      - id: check-json\n      - id: check-toml\n      - id: check-xml\n      - id: check-yaml\n      - id: debug-statements\n      - id: check-builtin-literals\n      - id: check-case-conflict\n      - id: check-docstring-first\n      - id: detect-private-key\n\n  - repo: https://github.com/pre-commit/mirrors-prettier\n    rev: v4.0.0-alpha.8\n    hooks:\n      - id: prettier\n        args: ['--tab-width', '2', '--single-quote']\n        exclude: '{{cookiecutter.project_slug}}/templates/'\n\n  - repo: https://github.com/adamchainz/django-upgrade\n    rev: '1.30.0'\n    hooks:\n      - id: django-upgrade\n        args: ['--target-version', '6.0']\n\n  # Run the Ruff linter.\n  - repo: https://github.com/astral-sh/ruff-pre-commit\n    rev: v0.15.7\n    hooks:\n      # Linter\n      - id: ruff-check\n        args: [--fix, --exit-non-zero-on-fix]\n      # Formatter\n      - id: ruff-format\n\n  - repo: https://github.com/tox-dev/pyproject-fmt\n    rev: v2.20.0\n    hooks:\n      - id: pyproject-fmt\n\n  - repo: https://github.com/Riverside-Healthcare/djLint\n    rev: v1.36.4\n    hooks:\n      - id: djlint-reformat-django\n      - id: djlint-django\n\n# sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date\nci:\n  autoupdate_schedule: weekly\n  skip: []\n  submodules: false\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.readthedocs.yml",
    "content": "# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\nversion: 2\n\nbuild:\n  os: ubuntu-24.04\n  tools:\n    python: \"3.13\"\n  jobs:\n    pre_create_environment:\n      - asdf plugin add uv\n      - asdf install uv latest\n      - asdf global uv latest\n    create_environment:\n      - uv venv \"${READTHEDOCS_VIRTUALENV_PATH}\"\n    install:\n      - UV_PROJECT_ENVIRONMENT=\"${READTHEDOCS_VIRTUALENV_PATH}\" uv sync --frozen --no-dev --only-group docs\n\nsphinx:\n  configuration: docs/conf.py\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/.travis.yml",
    "content": "dist: focal\n\nlanguage: python\npython:\n  - \"3.13\"\n\nservices:\n  - {% if cookiecutter.use_docker == 'y' %}docker{% else %}postgresql{% endif %}\njobs:\n  include:\n    - name: \"Linter\"\n      before_script:\n        - pip install -q ruff\n      script:\n        - ruff check .\n\n    - name: \"Django Test\"\n    {%- if cookiecutter.use_docker == 'y' %}\n      before_script:\n        - docker compose -v\n        - docker -v\n        - docker compose -f docker-compose.local.yml build\n        - docker compose -f docker-compose.docs.yml build\n        # Ensure celerybeat does not crash due to non-existent tables\n        - docker compose -f docker-compose.local.yml run --rm django python manage.py migrate\n        - docker compose -f docker-compose.local.yml up -d\n      script:\n        - docker compose -f docker-compose.local.yml run django pytest\n      after_failure:\n        - docker compose -f docker-compose.local.yml logs\n    {%- else %}\n      before_install:\n        - sudo apt-get update -qq\n        - sudo apt-get install -qq build-essential gettext python-dev zlib1g-dev libpq-dev xvfb\n        - sudo apt-get install -qq libjpeg8-dev libfreetype6-dev libwebp-dev\n        - sudo apt-get install -qq graphviz-dev python-setuptools python3-dev python-virtualenv python-pip\n        - sudo apt-get install -qq firefox automake libtool libreadline6 libreadline6-dev libreadline-dev\n        - sudo apt-get install -qq libsqlite3-dev libxml2 libxml2-dev libssl-dev libbz2-dev wget curl llvm\n      language: python\n      python:\n        - \"3.13\"\n      install:\n        - pip install uv\n        - uv sync\n      script:\n        - uv run pytest\n    {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/CONTRIBUTORS.txt",
    "content": "{{ cookiecutter.author_name }}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/LICENSE",
    "content": "{% if cookiecutter.open_source_license == 'MIT' %}\nThe MIT License (MIT)\nCopyright (c) {% now 'utc', '%Y' %}, {{ cookiecutter.author_name }}\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n{%- elif cookiecutter.open_source_license == 'BSD' %}\nCopyright (c) {% now 'utc', '%Y' %}, {{ cookiecutter.author_name }}\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice, this\n  list of conditions and the following disclaimer in the documentation and/or\n  other materials provided with the distribution.\n\n* Neither the name of {{ cookiecutter.project_name }} nor the names of its\n  contributors may be used to endorse or promote products derived from this\n  software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\nOF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\nOF THE POSSIBILITY OF SUCH DAMAGE.\n{%- elif cookiecutter.open_source_license == 'GPLv3' %}\nCopyright (c) {% now 'utc', '%Y' %}, {{ cookiecutter.author_name }}\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see <http://www.gnu.org/licenses/>.\n{%- elif cookiecutter.open_source_license == 'Apache Software License 2.0' %}\n\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   Copyright {% now 'utc', '%Y' %} {{ cookiecutter.author_name }}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/Procfile",
    "content": "release: python manage.py migrate\n{%- if cookiecutter.use_async == \"y\" %}\nweb: gunicorn config.asgi:application -k uvicorn_worker.UvicornWorker\n{%- else %}\nweb: gunicorn config.wsgi:application\n{%- endif %}\n{%- if cookiecutter.use_celery == \"y\" %}\nworker: REMAP_SIGTERM=SIGQUIT celery -A config.celery_app worker --loglevel=info\nbeat: REMAP_SIGTERM=SIGQUIT celery -A config.celery_app beat --loglevel=info\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/README.md",
    "content": "# {{cookiecutter.project_name}}\n\n{{ cookiecutter.description }}\n\n[![Built with Cookiecutter Django](https://img.shields.io/badge/built%20with-Cookiecutter%20Django-ff69b4.svg?logo=cookiecutter)](https://github.com/cookiecutter/cookiecutter-django/)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n\n{%- if cookiecutter.open_source_license != \"Not open source\" %}\n\nLicense: {{cookiecutter.open_source_license}}\n{%- endif %}\n\n## Settings\n\nMoved to [settings](https://cookiecutter-django.readthedocs.io/en/latest/1-getting-started/settings.html).\n\n## Basic Commands\n\n### Setting Up Your Users\n\n- To create a **normal user account**, just go to Sign Up and fill out the form. Once you submit it, you'll see a \"Verify Your E-mail Address\" page. Go to your console to see a simulated email verification message. Copy the link into your browser. Now the user's email should be verified and ready to go.\n\n- To create a **superuser account**, use this command:\n\n      uv run python manage.py createsuperuser\n\nFor convenience, you can keep your normal user logged in on Chrome and your superuser logged in on Firefox (or similar), so that you can see how the site behaves for both kinds of users.\n\n### Type checks\n\nRunning type checks with mypy:\n\n    uv run mypy {{cookiecutter.project_slug}}\n\n### Test coverage\n\nTo run the tests, check your test coverage, and generate an HTML coverage report:\n\n    uv run coverage run -m pytest\n    uv run coverage html\n    uv run open htmlcov/index.html\n\n#### Running tests with pytest\n\n    uv run pytest\n\n### Live reloading and Sass CSS compilation\n\nMoved to [Live reloading and SASS compilation](https://cookiecutter-django.readthedocs.io/en/latest/2-local-development/developing-locally.html#using-webpack-or-gulp).\n\n{%- if cookiecutter.use_celery == \"y\" %}\n\n### Celery\n\nThis app comes with Celery.\n\nTo run a celery worker:\n\n```bash\ncd {{cookiecutter.project_slug}}\nuv run celery -A config.celery_app worker -l info\n```\n\nPlease note: For Celery's import magic to work, it is important _where_ the celery commands are run. If you are in the same folder with _manage.py_, you should be right.\n\nTo run [periodic tasks](https://docs.celeryq.dev/en/stable/userguide/periodic-tasks.html), you'll need to start the celery beat scheduler service. You can start it as a standalone process:\n\n```bash\ncd {{cookiecutter.project_slug}}\nuv run celery -A config.celery_app beat\n```\n\nor you can embed the beat service inside a worker with the `-B` option (not recommended for production use):\n\n```bash\ncd {{cookiecutter.project_slug}}\nuv run celery -A config.celery_app worker -B -l info\n```\n\n{%- endif %}\n{%- if cookiecutter.use_mailpit == \"y\" %}\n\n### Email Server\n\n{%- if cookiecutter.use_docker == \"y\" %}\n\nIn development, it is often nice to be able to see emails that are being sent from your application. For that reason local SMTP server [Mailpit](https://github.com/axllent/mailpit) with a web interface is available as docker container.\n\nContainer mailpit will start automatically when you will run all docker containers.\nPlease check [cookiecutter-django Docker documentation](https://cookiecutter-django.readthedocs.io/en/latest/2-local-development/developing-locally-docker.html) for more details how to start all containers.\n\nWith Mailpit running, to view messages that are sent by your application, open your browser and go to `http://127.0.0.1:8025`\n{%- else %}\n\nIn development, it is often nice to be able to see emails that are being sent from your application. If you choose to use [Mailpit](https://github.com/axllent/mailpit) when generating the project a local SMTP server with a web interface will be available.\n\n1.  [Download the latest Mailpit release](https://github.com/axllent/mailpit/releases) for your OS.\n\n2.  Copy the binary file to the project root.\n\n3.  Make it executable:\n\n        chmod +x mailpit\n\n4.  Spin up another terminal window and start it there:\n\n        ./mailpit\n\n5.  Check out <http://127.0.0.1:8025/> to see how it goes.\n\nNow you have your own mail server running locally, ready to receive whatever you send it.\n\n{%- endif %}\n\n{%- endif %}\n{%- if cookiecutter.use_sentry == \"y\" %}\n\n### Sentry\n\nSentry is an error logging aggregator service. You can sign up for a free account at <https://sentry.io/signup/?code=cookiecutter> or download and host it yourself.\nThe system is set up with reasonable defaults, including 404 logging and integration with the WSGI application.\n\nYou must set the DSN url in production.\n{%- endif %}\n\n## Deployment\n\nThe following details how to deploy this application.\n{%- if cookiecutter.use_heroku.lower() == \"y\" %}\n\n### Heroku\n\nSee detailed [cookiecutter-django Heroku documentation](https://cookiecutter-django.readthedocs.io/en/latest/3-deployment/deployment-on-heroku.html).\n\n{%- endif %}\n{%- if cookiecutter.use_docker.lower() == \"y\" %}\n\n### Docker\n\nSee detailed [cookiecutter-django Docker documentation](https://cookiecutter-django.readthedocs.io/en/latest/3-deployment/deployment-with-docker.html).\n\n{%- endif %}\n{%- if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] %}\n\n### Custom Bootstrap Compilation\n\nThe generated CSS is set up with automatic Bootstrap recompilation with variables of your choice.\nBootstrap v5 is installed using npm and customised by tweaking your variables in `static/sass/custom_bootstrap_vars`.\n\nYou can find a list of available variables [in the bootstrap source](https://github.com/twbs/bootstrap/blob/v5.1.3/scss/_variables.scss), or get explanations on them in the [Bootstrap docs](https://getbootstrap.com/docs/5.1/customize/sass/).\n\nBootstrap's javascript as well as its dependencies are concatenated into a single file: `static/js/vendors.js`.\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/bin/post_compile",
    "content": "#!/usr/bin/env bash\n{%- if cookiecutter.frontend_pipeline == \"Django Compressor\" %}\n\ncompress_enabled() {\npython << END\nimport sys\n\nfrom environ import Env\n\nenv = Env(COMPRESS_ENABLED=(bool, True))\nif env('COMPRESS_ENABLED'):\n    sys.exit(0)\nelse:\n    sys.exit(1)\n\nEND\n}\n\nif compress_enabled\nthen\n  python manage.py compress\nfi\n{%- endif %}\n\npython manage.py collectstatic --noinput\npython manage.py compilemessages -i site-packages\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/local/django/Dockerfile",
    "content": "# define an alias for the specific python version used in this file.\nFROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS python\n\n# Python build stage\nFROM python AS python-build-stage\n\nARG APP_HOME=/app\n\nWORKDIR ${APP_HOME}\n\n# we need to move the virtualenv outside of the $APP_HOME directory because it will be overriden by the docker compose mount\nENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=0\n\n# Install apt packages\nRUN apt-get update && apt-get install --no-install-recommends -y \\\n  # dependencies for building Python packages\n  build-essential \\\n  # psycopg dependencies\n  libpq-dev \\\n  gettext \\\n  wait-for-it\n\n# Requirements are installed here to ensure they will be cached.\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \\\n    --mount=type=bind,source=uv.lock,target=uv.lock:rw \\\n    uv sync --no-install-project\n\nCOPY . ${APP_HOME}\n\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \\\n    --mount=type=bind,source=uv.lock,target=uv.lock:rw \\\n    uv sync\n\n# devcontainer dependencies and utils\nRUN apt-get update && apt-get install --no-install-recommends -y \\\n  sudo git bash-completion nano ssh\n\n# Create devcontainer user and add it to sudoers\nRUN groupadd --gid 1000 dev-user \\\n  && useradd --uid 1000 --gid dev-user --shell /bin/bash --create-home dev-user \\\n  && echo dev-user ALL=\\(root\\) NOPASSWD:ALL > /etc/sudoers.d/dev-user \\\n  && chmod 0440 /etc/sudoers.d/dev-user\n\nENV PATH=\"/${APP_HOME}/.venv/bin:$PATH\"\nENV PYTHONPATH=\"${APP_HOME}/.venv/lib/python3.13/site-packages:$PYTHONPATH\"\n\nCOPY ./compose/production/django/entrypoint /entrypoint\nRUN sed -i 's/\\r$//g' /entrypoint\nRUN chmod +x /entrypoint\n\nCOPY ./compose/local/django/start /start\nRUN sed -i 's/\\r$//g' /start\nRUN chmod +x /start\n\n{% if cookiecutter.use_celery == \"y\" %}\nCOPY ./compose/local/django/celery/worker/start /start-celeryworker\nRUN sed -i 's/\\r$//g' /start-celeryworker\nRUN chmod +x /start-celeryworker\n\nCOPY ./compose/local/django/celery/beat/start /start-celerybeat\nRUN sed -i 's/\\r$//g' /start-celerybeat\nRUN chmod +x /start-celerybeat\n\nCOPY ./compose/local/django/celery/flower/start /start-flower\nRUN sed -i 's/\\r$//g' /start-flower\nRUN chmod +x /start-flower\n{% endif %}\n\nENTRYPOINT [\"/entrypoint\"]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/local/django/celery/beat/start",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o nounset\n\n\nrm -f './celerybeat.pid'\nexec watchfiles --filter python celery.__main__.main --args '-A config.celery_app beat -l INFO'\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/local/django/celery/flower/start",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o nounset\n\n\nuntil timeout 10 celery -A config.celery_app inspect ping; do\n    >&2 echo \"Celery workers not available\"\ndone\n\necho 'Starting flower'\n\n\nexec watchfiles --filter python celery.__main__.main \\\n    --args \\\n    \"-A config.celery_app -b \\\"${REDIS_URL}\\\" flower --basic_auth=\\\"${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}\\\"\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/local/django/celery/worker/start",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o nounset\n\n\nexec watchfiles --filter python celery.__main__.main --args '-A config.celery_app worker -l INFO'\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/local/django/start",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\n\npython manage.py migrate\n{%- if cookiecutter.use_async == 'y' %}\nexec uvicorn config.asgi:application --host 0.0.0.0 --reload --reload-include '*.html'\n{%- else %}\nexec python manage.py runserver_plus 0.0.0.0:8000\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile",
    "content": "# define an alias for the specific python version used in this file.\nFROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS python\n\n\n# Python build stage\nFROM python AS python-build-stage\n\nARG APP_HOME=/app\n\nWORKDIR ${APP_HOME}\n\nRUN apt-get update && apt-get install --no-install-recommends -y \\\n  # dependencies for building Python packages\n  build-essential \\\n  # psycopg dependencies\n  libpq-dev \\\n  # cleaning up unused files\n  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \\\n  && rm -rf /var/lib/apt/lists/*\n\n# Requirements are installed here to ensure they will be cached.\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    --mount=type=bind,source=uv.lock,target=uv.lock \\\n    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \\\n    uv sync --no-install-project\n\nCOPY . ${APP_HOME}\n\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    uv sync\n\n\n# Python 'run' stage\nFROM python AS python-run-stage\n\nARG BUILD_ENVIRONMENT\nENV PYTHONUNBUFFERED=1\nENV PYTHONDONTWRITEBYTECODE=1\n\nRUN apt-get update && apt-get install --no-install-recommends -y \\\n  # To run the Makefile\n  make \\\n  # psycopg dependencies\n  libpq-dev \\\n  # Translations dependencies\n  gettext \\\n  # Uncomment below lines to enable Sphinx output to latex and pdf\n  # texlive-latex-recommended \\\n  # texlive-fonts-recommended \\\n  # texlive-latex-extra \\\n  # latexmk \\\n  # cleaning up unused files\n  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \\\n  && rm -rf /var/lib/apt/lists/*\n\n# copy python dependency wheels from python-build-stage\nCOPY --from=python-build-stage --chown=app:app /app /app\n\nCOPY ./compose/local/docs/start /start-docs\nRUN sed -i 's/\\r$//g' /start-docs\nRUN chmod +x /start-docs\n\nENV PATH=\"/app/.venv/bin:$PATH\"\n\nWORKDIR /docs\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/local/docs/start",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\nexec make livehtml\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/local/node/Dockerfile",
    "content": "FROM docker.io/node:24.14-bookworm-slim\n\nWORKDIR /app\n\nCOPY ./package.json /app\n\nRUN npm install && npm cache clean --force\n\nENV PATH=./node_modules/.bin/:$PATH\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/local/uv/Dockerfile",
    "content": "FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS python\n\nARG APP_HOME=/app\n\nWORKDIR ${APP_HOME}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/aws/Dockerfile",
    "content": "FROM docker.io/amazon/aws-cli:2.34.0\n\n# Clear entrypoint from the base image, otherwise it's always calling the aws CLI\nENTRYPOINT []\nCMD [\"/bin/bash\"]\n\nCOPY ./compose/production/aws/maintenance /usr/local/bin/maintenance\nCOPY ./compose/production/postgres/maintenance/_sourced /usr/local/bin/maintenance/_sourced\n\nRUN chmod +x /usr/local/bin/maintenance/*\n\nRUN mv /usr/local/bin/maintenance/* /usr/local/bin \\\n    && rmdir /usr/local/bin/maintenance\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/aws/maintenance/download",
    "content": "#!/bin/sh\n\n### Download a file from your Amazon S3 bucket to the postgres /backups folder\n###\n### Usage:\n###     $ docker compose -f docker-compose.production.yml run --rm awscli <1>\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\nworking_dir=\"$(dirname ${0})\"\nsource \"${working_dir}/_sourced/constants.sh\"\nsource \"${working_dir}/_sourced/messages.sh\"\n\nexport AWS_ACCESS_KEY_ID=\"${DJANGO_AWS_ACCESS_KEY_ID}\"\nexport AWS_SECRET_ACCESS_KEY=\"${DJANGO_AWS_SECRET_ACCESS_KEY}\"\nexport AWS_STORAGE_BUCKET_NAME=\"${DJANGO_AWS_STORAGE_BUCKET_NAME}\"\n\n\naws s3 cp s3://${AWS_STORAGE_BUCKET_NAME}${BACKUP_DIR_PATH}/${1} ${BACKUP_DIR_PATH}/${1}\n\nmessage_success \"Finished downloading ${1}.\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/aws/maintenance/upload",
    "content": "#!/bin/sh\n\n### Upload the /backups folder to Amazon S3\n###\n### Usage:\n###     $ docker compose -f docker-compose.production.yml run --rm awscli upload\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\nworking_dir=\"$(dirname ${0})\"\nsource \"${working_dir}/_sourced/constants.sh\"\nsource \"${working_dir}/_sourced/messages.sh\"\n\nexport AWS_ACCESS_KEY_ID=\"${DJANGO_AWS_ACCESS_KEY_ID}\"\nexport AWS_SECRET_ACCESS_KEY=\"${DJANGO_AWS_SECRET_ACCESS_KEY}\"\nexport AWS_STORAGE_BUCKET_NAME=\"${DJANGO_AWS_STORAGE_BUCKET_NAME}\"\n\n\nmessage_info \"Upload the backups directory to S3 bucket {$AWS_STORAGE_BUCKET_NAME}\"\n\naws s3 cp ${BACKUP_DIR_PATH} s3://${AWS_STORAGE_BUCKET_NAME}${BACKUP_DIR_PATH} --recursive\n\nmessage_info \"Cleaning the directory ${BACKUP_DIR_PATH}\"\n\nrm -rf ${BACKUP_DIR_PATH}/*\n\nmessage_success \"Finished uploading and cleaning.\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/django/Dockerfile",
    "content": "{% if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] -%}\nFROM docker.io/node:24.14-bookworm-slim AS client-builder\n\nARG APP_HOME=/app\nWORKDIR ${APP_HOME}\n\nCOPY ./package.json ${APP_HOME}\nRUN npm install && npm cache clean --force\nCOPY . ${APP_HOME}\n{%- if cookiecutter.frontend_pipeline == 'Webpack' and cookiecutter.use_whitenoise == 'n' %}\n{%- if cookiecutter.cloud_provider == 'AWS' %}\nARG DJANGO_AWS_STORAGE_BUCKET_NAME\nENV DJANGO_AWS_STORAGE_BUCKET_NAME=${DJANGO_AWS_STORAGE_BUCKET_NAME}\nARG DJANGO_AWS_S3_CUSTOM_DOMAIN\nENV DJANGO_AWS_S3_CUSTOM_DOMAIN=${DJANGO_AWS_S3_CUSTOM_DOMAIN}\n{%- elif cookiecutter.cloud_provider == 'GCP' %}\nARG DJANGO_GCP_STORAGE_BUCKET_NAME\nENV DJANGO_GCP_STORAGE_BUCKET_NAME=${DJANGO_GCP_STORAGE_BUCKET_NAME}\n{%- elif cookiecutter.cloud_provider == 'Azure' %}\nARG DJANGO_AZURE_ACCOUNT_NAME\nENV DJANGO_AZURE_ACCOUNT_NAME=${DJANGO_AZURE_ACCOUNT_NAME}\n{%- endif %}\n{%- endif %}\nRUN npm run build\n{%- endif %}\n# define an alias for the specific python version used in this file.\nFROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS python-build-stage\n\nENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=0\n\nARG APP_HOME=/app\n\nWORKDIR ${APP_HOME}\n\n# Install apt packages\nRUN apt-get update && apt-get install --no-install-recommends -y \\\n  # dependencies for building Python packages\n  build-essential \\\n  # psycopg dependencies\n  libpq-dev\n\n\n# Requirements are installed here to ensure they will be cached.\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    --mount=type=bind,source=uv.lock,target=uv.lock \\\n    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \\\n    uv sync --locked --no-install-project --no-dev\n{%- if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] %}\nCOPY --from=client-builder ${APP_HOME} ${APP_HOME}\n{% else %}\nCOPY . ${APP_HOME}\n{%- endif %}\n\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    --mount=type=bind,source=uv.lock,target=uv.lock \\\n    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \\\n    uv sync --locked --no-dev\n\n# Python 'run' stage\nFROM python:3.13-slim-bookworm AS python-run-stage\n\nARG APP_HOME=/app\n\nWORKDIR ${APP_HOME}\n\nRUN addgroup --system django \\\n  && adduser --system --ingroup django django\n\n\n# Install required system dependencies\nRUN apt-get update && apt-get install --no-install-recommends -y \\\n  # psycopg dependencies\n  libpq-dev \\\n  # Translations dependencies\n  gettext \\\n  # entrypoint\n  wait-for-it \\\n  # cleaning up unused files\n  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \\\n  && rm -rf /var/lib/apt/lists/*\n\n\nCOPY --chown=django:django ./compose/production/django/entrypoint /entrypoint\nRUN sed -i 's/\\r$//g' /entrypoint\nRUN chmod +x /entrypoint\n\n\nCOPY --chown=django:django ./compose/production/django/start /start\nRUN sed -i 's/\\r$//g' /start\nRUN chmod +x /start\n\n\n{%- if cookiecutter.use_celery == \"y\" %}\nCOPY --chown=django:django ./compose/production/django/celery/worker/start /start-celeryworker\nRUN sed -i 's/\\r$//g' /start-celeryworker\nRUN chmod +x /start-celeryworker\n\n\nCOPY --chown=django:django ./compose/production/django/celery/beat/start /start-celerybeat\nRUN sed -i 's/\\r$//g' /start-celerybeat\nRUN chmod +x /start-celerybeat\n\n\nCOPY --chown=django:django ./compose/production/django/celery/flower/start /start-flower\nRUN sed -i 's/\\r$//g' /start-flower\nRUN chmod +x /start-flower\n{%- endif %}\n\n# Copy the application from the builder\nCOPY --from=python-build-stage --chown=django:django ${APP_HOME} ${APP_HOME}\n\n{%- if cookiecutter.cloud_provider == 'None' %}\n# explicitly create the media folder before changing ownership below\nRUN mkdir -p ${APP_HOME}/{{ cookiecutter.project_slug }}/media\n{%- endif %}\n\n# make django owner of the WORKDIR directory as well.\nRUN chown django:django ${APP_HOME}\n\n# Place executables in the environment at the front of the path\nENV PATH=\"/app/.venv/bin:$PATH\"\n\nUSER django\n\nRUN DATABASE_URL=\"\" \\\n  DJANGO_SETTINGS_MODULE=\"config.settings.test\" \\\n  python manage.py compilemessages\n\nENTRYPOINT [\"/entrypoint\"]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/django/celery/beat/start",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\n\nexec celery -A config.celery_app beat -l INFO\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/django/celery/flower/start",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o nounset\n\n\n\nuntil timeout 10 celery -A config.celery_app inspect ping; do\n    >&2 echo \"Celery workers not available\"\ndone\n\necho 'Starting flower'\n\n\nexec celery \\\n    -A config.celery_app \\\n    -b \"${REDIS_URL}\" \\\n    flower \\\n    --basic_auth=\"${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/django/celery/worker/start",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\n\nexec celery -A config.celery_app worker -l INFO\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/django/entrypoint",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\nif [ -z \"${POSTGRES_USER}\" ]; then\n    base_postgres_image_default_user='postgres'\n    export POSTGRES_USER=\"${base_postgres_image_default_user}\"\nfi\nexport DATABASE_URL=\"postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}\"\n\nwait-for-it \"${POSTGRES_HOST}:${POSTGRES_PORT}\" -t 30\n\n>&2 echo 'PostgreSQL is available'\n\nexec \"$@\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/django/start",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\n\npython /app/manage.py collectstatic --noinput\n{% if cookiecutter.use_whitenoise == 'y' and cookiecutter.frontend_pipeline == 'Django Compressor' %}\ncompress_enabled() {\npython << END\nimport sys\n\nfrom environ import Env\n\nenv = Env(COMPRESS_ENABLED=(bool, True))\nif env('COMPRESS_ENABLED'):\n    sys.exit(0)\nelse:\n    sys.exit(1)\n\nEND\n}\n\nif compress_enabled; then\n  # NOTE this command will fail if django-compressor is disabled\n  python /app/manage.py compress\nfi\n{%- endif %}\n{%- if cookiecutter.use_async == 'y' %}\nexec gunicorn config.asgi --bind 0.0.0.0:5000 --chdir=/app -k uvicorn_worker.UvicornWorker\n{%- else %}\nexec gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/nginx/Dockerfile",
    "content": "FROM docker.io/nginx:1.29.6-alpine\nCOPY ./compose/production/nginx/default.conf /etc/nginx/conf.d/default.conf\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/nginx/default.conf",
    "content": "server {\n  listen       80;\n  server_name  localhost;\n  location /media/ {\n    alias /usr/share/nginx/media/;\n  }\n}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/postgres/Dockerfile",
    "content": "FROM docker.io/postgres:{{ cookiecutter.postgresql_version }}\n\nCOPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance\nRUN chmod +x /usr/local/bin/maintenance/*\nRUN mv /usr/local/bin/maintenance/* /usr/local/bin \\\n    && rmdir /usr/local/bin/maintenance\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/postgres/maintenance/_sourced/constants.sh",
    "content": "#!/usr/bin/env bash\n\n\nBACKUP_DIR_PATH='/backups'\nBACKUP_FILE_PREFIX='backup'\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/postgres/maintenance/_sourced/countdown.sh",
    "content": "#!/usr/bin/env bash\n\n\ncountdown() {\n    declare desc=\"A simple countdown. Source: https://superuser.com/a/611582\"\n    local seconds=\"${1}\"\n    local d=$(($(date +%s) + \"${seconds}\"))\n    while [ \"$d\" -ge `date +%s` ]; do\n        echo -ne \"$(date -u --date @$(($d - `date +%s`)) +%H:%M:%S)\\r\";\n        sleep 0.1\n    done\n}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/postgres/maintenance/_sourced/messages.sh",
    "content": "#!/usr/bin/env bash\n\n\nmessage_newline() {\n    echo\n}\n\nmessage_debug()\n{\n    echo -e \"DEBUG: ${@}\"\n}\n\nmessage_welcome()\n{\n    echo -e \"\\e[1m${@}\\e[0m\"\n}\n\nmessage_warning()\n{\n    echo -e \"\\e[33mWARNING\\e[0m: ${@}\"\n}\n\nmessage_error()\n{\n    echo -e \"\\e[31mERROR\\e[0m: ${@}\"\n}\n\nmessage_info()\n{\n    echo -e \"\\e[37mINFO\\e[0m: ${@}\"\n}\n\nmessage_suggestion()\n{\n    echo -e \"\\e[33mSUGGESTION\\e[0m: ${@}\"\n}\n\nmessage_success()\n{\n    echo -e \"\\e[32mSUCCESS\\e[0m: ${@}\"\n}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/postgres/maintenance/_sourced/yes_no.sh",
    "content": "#!/usr/bin/env bash\n\n\nyes_no() {\n    declare desc=\"Prompt for confirmation. \\$\\\"\\{1\\}\\\": confirmation message.\"\n    local arg1=\"${1}\"\n\n    local response=\n    read -r -p \"${arg1} (y/[n])? \" response\n    if [[ \"${response}\" =~ ^[Yy]$ ]]\n    then\n        exit 0\n    else\n        exit 1\n    fi\n}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/postgres/maintenance/backup",
    "content": "#!/usr/bin/env bash\n\n\n### Create a database backup.\n###\n### Usage:\n###     $ docker compose -f <environment>.yml (exec |run --rm) postgres backup\n\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\n\nworking_dir=\"$(dirname ${0})\"\nsource \"${working_dir}/_sourced/constants.sh\"\nsource \"${working_dir}/_sourced/messages.sh\"\n\n\nmessage_welcome \"Backing up the '${POSTGRES_DB}' database...\"\n\n\nif [[ \"${POSTGRES_USER}\" == \"postgres\" ]]; then\n    message_error \"Backing up as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again.\"\n    exit 1\nfi\n\nexport PGHOST=\"${POSTGRES_HOST}\"\nexport PGPORT=\"${POSTGRES_PORT}\"\nexport PGUSER=\"${POSTGRES_USER}\"\nexport PGPASSWORD=\"${POSTGRES_PASSWORD}\"\nexport PGDATABASE=\"${POSTGRES_DB}\"\n\nbackup_filename=\"${BACKUP_FILE_PREFIX}_$(date +'%Y_%m_%dT%H_%M_%S').sql.gz\"\npg_dump | gzip > \"${BACKUP_DIR_PATH}/${backup_filename}\"\n\n\nmessage_success \"'${POSTGRES_DB}' database backup '${backup_filename}' has been created and placed in '${BACKUP_DIR_PATH}'.\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/postgres/maintenance/backups",
    "content": "#!/usr/bin/env bash\n\n\n### View backups.\n###\n### Usage:\n###     $ docker compose -f <environment>.yml (exec |run --rm) postgres backups\n\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\n\nworking_dir=\"$(dirname ${0})\"\nsource \"${working_dir}/_sourced/constants.sh\"\nsource \"${working_dir}/_sourced/messages.sh\"\n\n\nmessage_welcome \"These are the backups you have got:\"\n\nls -lht \"${BACKUP_DIR_PATH}\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/postgres/maintenance/restore",
    "content": "#!/usr/bin/env bash\n\n\n### Restore database from a backup.\n###\n### Parameters:\n###     <1> filename of an existing backup.\n###\n### Usage:\n###     $ docker compose -f <environment>.yml (exec |run --rm) postgres restore <1>\n\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\n\nworking_dir=\"$(dirname ${0})\"\nsource \"${working_dir}/_sourced/constants.sh\"\nsource \"${working_dir}/_sourced/messages.sh\"\n\n\nif [[ -z ${1+x} ]]; then\n    message_error \"Backup filename is not specified yet it is a required parameter. Make sure you provide one and try again.\"\n    exit 1\nfi\nbackup_filename=\"${BACKUP_DIR_PATH}/${1}\"\nif [[ ! -f \"${backup_filename}\" ]]; then\n    message_error \"No backup with the specified filename found. Check out the 'backups' maintenance script output to see if there is one and try again.\"\n    exit 1\nfi\n\nmessage_welcome \"Restoring the '${POSTGRES_DB}' database from the '${backup_filename}' backup...\"\n\nif [[ \"${POSTGRES_USER}\" == \"postgres\" ]]; then\n    message_error \"Restoring as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again.\"\n    exit 1\nfi\n\nexport PGHOST=\"${POSTGRES_HOST}\"\nexport PGPORT=\"${POSTGRES_PORT}\"\nexport PGUSER=\"${POSTGRES_USER}\"\nexport PGPASSWORD=\"${POSTGRES_PASSWORD}\"\nexport PGDATABASE=\"${POSTGRES_DB}\"\n\nmessage_info \"Dropping the database...\"\ndropdb \"${PGDATABASE}\"\n\nmessage_info \"Creating a new database...\"\ncreatedb --owner=\"${POSTGRES_USER}\"\n\nmessage_info \"Applying the backup to the new database...\"\ngunzip -c \"${backup_filename}\" | psql \"${POSTGRES_DB}\"\n\nmessage_success \"The '${POSTGRES_DB}' database has been restored from the '${backup_filename}' backup.\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/postgres/maintenance/rmbackup",
    "content": "#!/usr/bin/env bash\n\n### Remove a database backup.\n###\n### Parameters:\n###     <1> filename of a backup to remove.\n###\n### Usage:\n###     $ docker-compose -f <environment>.yml (exec |run --rm) postgres rmbackup <1>\n\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\n\nworking_dir=\"$(dirname ${0})\"\nsource \"${working_dir}/_sourced/constants.sh\"\nsource \"${working_dir}/_sourced/messages.sh\"\n\n\nif [[ -z ${1+x} ]]; then\n    message_error \"Backup filename is not specified yet it is a required parameter. Make sure you provide one and try again.\"\n    exit 1\nfi\nbackup_filename=\"${BACKUP_DIR_PATH}/${1}\"\nif [[ ! -f \"${backup_filename}\" ]]; then\n    message_error \"No backup with the specified filename found. Check out the 'backups' maintenance script output to see if there is one and try again.\"\n    exit 1\nfi\n\nmessage_welcome \"Removing the '${backup_filename}' backup file...\"\n\nrm -r \"${backup_filename}\"\n\nmessage_success \"The '${backup_filename}' database backup has been removed.\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/traefik/Dockerfile",
    "content": "FROM docker.io/traefik:v3.6.11\nRUN mkdir -p /etc/traefik/acme \\\n  && touch /etc/traefik/acme/acme.json \\\n  && chmod 600 /etc/traefik/acme/acme.json\nCOPY ./compose/production/traefik/traefik.yml /etc/traefik\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/compose/production/traefik/traefik.yml",
    "content": "log:\n  level: INFO\n\nentryPoints:\n  web:\n    # http\n    address: ':80'\n    http:\n      # https://doc.traefik.io/traefik/routing/entrypoints/#entrypoint\n      redirections:\n        entryPoint:\n          to: web-secure\n\n  web-secure:\n    # https\n    address: ':443'\n  {%- if cookiecutter.use_celery == 'y' %}\n\n  flower:\n    address: ':5555'\n  {%- endif %}\n\ncertificatesResolvers:\n  letsencrypt:\n    # https://doc.traefik.io/traefik/https/acme/#lets-encrypt\n    acme:\n      email: '{{ cookiecutter.email }}'\n      storage: /etc/traefik/acme/acme.json\n      # https://doc.traefik.io/traefik/https/acme/#httpchallenge\n      httpChallenge:\n        entryPoint: web\n\nhttp:\n  routers:\n    web-secure-router:\n      {%- if cookiecutter.domain_name.count('.') == 1 %}\n      rule: 'Host(`{{ cookiecutter.domain_name }}`) || Host(`www.{{ cookiecutter.domain_name }}`)'\n      {%- else %}\n      rule: 'Host(`{{ cookiecutter.domain_name }}`)'\n      {%- endif %}\n      entryPoints:\n        - web-secure\n      middlewares:\n        - csrf\n      service: django\n      tls:\n        # https://doc.traefik.io/traefik/routing/routers/#certresolver\n        certResolver: letsencrypt\n    {%- if cookiecutter.use_celery == 'y' %}\n\n    flower-secure-router:\n      rule: 'Host(`{{ cookiecutter.domain_name }}`)'\n      entryPoints:\n        - flower\n      service: flower\n      tls:\n        # https://doc.traefik.io/traefik/master/routing/routers/#certresolver\n        certResolver: letsencrypt\n    {%- endif %}\n    {%- if cookiecutter.cloud_provider == 'None' %}\n\n    web-media-router:\n      {%- if cookiecutter.domain_name.count('.') == 1 %}\n      rule: '(Host(`{{ cookiecutter.domain_name }}`) || Host(`www.{{ cookiecutter.domain_name }}`)) && PathPrefix(`/media/`)'\n      {%- else %}\n      rule: 'Host(`{{ cookiecutter.domain_name }}`) && PathPrefix(`/media/`)'\n      {%- endif %}\n      entryPoints:\n        - web-secure\n      middlewares:\n        - csrf\n      service: django-media\n      tls:\n        certResolver: letsencrypt\n    {%- endif %}\n\n  middlewares:\n    csrf:\n      # https://doc.traefik.io/traefik/master/middlewares/http/headers/#hostsproxyheaders\n      # https://docs.djangoproject.com/en/dev/ref/csrf/#ajax\n      headers:\n        hostsProxyHeaders: ['X-CSRFToken']\n\n  services:\n    django:\n      loadBalancer:\n        servers:\n          - url: http://django:5000\n    {%- if cookiecutter.use_celery == 'y' %}\n\n    flower:\n      loadBalancer:\n        servers:\n          - url: http://flower:5555\n    {%- endif %}\n    {%- if cookiecutter.cloud_provider == 'None' %}\n\n    django-media:\n      loadBalancer:\n        servers:\n          - url: http://nginx:80\n    {%- endif %}\n\nproviders:\n  # https://doc.traefik.io/traefik/master/providers/file/\n  file:\n    filename: /etc/traefik/traefik.yml\n    watch: true\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/__init__.py",
    "content": "{% if cookiecutter.use_celery == 'y' -%}\n# This will make sure the app is always imported when\n# Django starts so that shared_task will use this app.\nfrom .celery_app import app as celery_app\n\n__all__ = (\"celery_app\",)\n{% endif -%}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/api.py",
    "content": "from django.contrib.admin.views.decorators import staff_member_required\nfrom ninja import NinjaAPI\nfrom ninja.security import SessionAuth\n\napi = NinjaAPI(\n    urls_namespace=\"api\",\n    auth=SessionAuth(),\n    docs_decorator=staff_member_required,\n)\n\napi.add_router(\"/users/\", \"{{ cookiecutter.project_slug }}.users.api.views.router\")\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/api_router.py",
    "content": "from django.conf import settings\nfrom rest_framework.routers import DefaultRouter\nfrom rest_framework.routers import SimpleRouter\n\nfrom {{ cookiecutter.project_slug }}.users.api.views import UserViewSet\n\nrouter = DefaultRouter() if settings.DEBUG else SimpleRouter()\n\nrouter.register(\"users\", UserViewSet)\n\n\napp_name = \"api\"\nurlpatterns = router.urls\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/asgi.py",
    "content": "\"\"\"\nASGI config for {{ cookiecutter.project_name }} project.\n\nIt exposes the ASGI callable as a module-level variable named ``application``.\n\nFor more information on this file, see\nhttps://docs.djangoproject.com/en/dev/howto/deployment/asgi/\n\n\"\"\"\n\nimport os\nimport sys\nfrom pathlib import Path\n\nfrom django.core.asgi import get_asgi_application\n\n# This allows easy placement of apps within the interior\n# {{ cookiecutter.project_slug }} directory.\nBASE_DIR = Path(__file__).resolve(strict=True).parent.parent\nsys.path.append(str(BASE_DIR / \"{{ cookiecutter.project_slug }}\"))\n\n# If DJANGO_SETTINGS_MODULE is unset, default to the local settings\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"config.settings.local\")\n\n# This application object is used by any ASGI server configured to use this file.\ndjango_application = get_asgi_application()\n\n# Import websocket application here, so apps from django_application are loaded first\nfrom config.websocket import websocket_application  # noqa: E402\n\n\nasync def application(scope, receive, send):\n    if scope[\"type\"] == \"http\":\n        await django_application(scope, receive, send)\n    elif scope[\"type\"] == \"websocket\":\n        await websocket_application(scope, receive, send)\n    else:\n        msg = f\"Unknown scope type {scope['type']}\"\n        raise NotImplementedError(msg)\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/celery_app.py",
    "content": "import os\n\nfrom celery import Celery\nfrom celery.signals import setup_logging\n\n# set the default Django settings module for the 'celery' program.\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"config.settings.local\")\n\napp = Celery(\"{{cookiecutter.project_slug}}\")\n\n# Using a string here means the worker doesn't have to serialize\n# the configuration object to child processes.\n# - namespace='CELERY' means all celery-related configuration keys\n#   should have a `CELERY_` prefix.\napp.config_from_object(\"django.conf:settings\", namespace=\"CELERY\")\n\n\n@setup_logging.connect\ndef config_loggers(*args, **kwargs):\n    from logging.config import dictConfig  # noqa: PLC0415\n\n    from django.conf import settings  # noqa: PLC0415\n\n    dictConfig(settings.LOGGING)\n\n\n# Load task modules from all registered Django app configs.\napp.autodiscover_tasks()\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/settings/__init__.py",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/settings/base.py",
    "content": "# ruff: noqa: ERA001, E501\n\"\"\"Base settings to build other settings files upon.\"\"\"\n{% if cookiecutter.use_celery == 'y' %}\nimport ssl\n{%- endif %}\nfrom pathlib import Path\n\nimport environ\n\nBASE_DIR = Path(__file__).resolve(strict=True).parent.parent.parent\n# {{ cookiecutter.project_slug }}/\nAPPS_DIR = BASE_DIR / \"{{ cookiecutter.project_slug }}\"\nenv = environ.Env()\n\nREAD_DOT_ENV_FILE = env.bool(\"DJANGO_READ_DOT_ENV_FILE\", default=False)\nif READ_DOT_ENV_FILE:\n    # OS environment variables take precedence over variables from .env\n    env.read_env(str(BASE_DIR / \".env\"))\n\n# GENERAL\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#debug\nDEBUG = env.bool(\"DJANGO_DEBUG\", False)\n# Local time zone. Choices are\n# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name\n# though not all of them may be available with every OS.\n# In Windows, this must be set to your system time zone.\nTIME_ZONE = \"{{ cookiecutter.timezone }}\"\n# https://docs.djangoproject.com/en/dev/ref/settings/#language-code\nLANGUAGE_CODE = \"en-us\"\n# https://docs.djangoproject.com/en/dev/ref/settings/#languages\n# from django.utils.translation import gettext_lazy as _\n# LANGUAGES = [\n#     ('en', _('English')),\n#     ('fr-fr', _('French')),\n#     ('pt-br', _('Portuguese')),\n# ]\n# https://docs.djangoproject.com/en/dev/ref/settings/#site-id\nSITE_ID = 1\n# https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n\nUSE_I18N = True\n# https://docs.djangoproject.com/en/dev/ref/settings/#use-tz\nUSE_TZ = True\n# https://docs.djangoproject.com/en/dev/ref/settings/#locale-paths\nLOCALE_PATHS = [str(BASE_DIR / \"locale\")]\n\n# DATABASES\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#databases\n{% if cookiecutter.use_docker == \"y\" -%}\nDATABASES = {\"default\": env.db(\"DATABASE_URL\")}\n{%- else %}\nDATABASES = {\n    \"default\": env.db(\n        \"DATABASE_URL\",\n        default=\"postgres://{% if cookiecutter.windows == 'y' %}localhost{% endif %}/{{cookiecutter.project_slug}}\",\n    ),\n}\n{%- endif %}\nDATABASES[\"default\"][\"ATOMIC_REQUESTS\"] = True\n# https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-DEFAULT_AUTO_FIELD\nDEFAULT_AUTO_FIELD = \"django.db.models.BigAutoField\"\n\n# URLS\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf\nROOT_URLCONF = \"config.urls\"\n# https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application\nWSGI_APPLICATION = \"config.wsgi.application\"\n\n# APPS\n# ------------------------------------------------------------------------------\nDJANGO_APPS = [\n    \"django.contrib.auth\",\n    \"django.contrib.contenttypes\",\n    \"django.contrib.sessions\",\n    \"django.contrib.sites\",\n    \"django.contrib.messages\",\n    \"django.contrib.staticfiles\",\n    # \"django.contrib.humanize\", # Handy template tags\n    \"django.contrib.admin\",\n    \"django.forms\",\n]\nTHIRD_PARTY_APPS = [\n    \"crispy_forms\",\n    \"crispy_bootstrap5\",\n    \"allauth\",\n    \"allauth.account\",\n    \"allauth.mfa\",\n    \"allauth.socialaccount\",\n{%- if cookiecutter.use_celery == 'y' %}\n    \"django_celery_beat\",\n{%- endif %}\n{%- if cookiecutter.rest_api == 'DRF' %}\n    \"rest_framework\",\n    \"rest_framework.authtoken\",\n    \"corsheaders\",\n    \"drf_spectacular\",\n{%- elif cookiecutter.rest_api == 'Django Ninja' %}\n    \"corsheaders\",\n{%- endif %}\n{%- if cookiecutter.frontend_pipeline == 'Webpack' %}\n    \"webpack_loader\",\n{%- endif %}\n]\n\nLOCAL_APPS = [\n    \"{{ cookiecutter.project_slug }}.users\",\n    # Your stuff: custom apps go here\n]\n# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps\nINSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS\n\n# MIGRATIONS\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules\nMIGRATION_MODULES = {\"sites\": \"{{ cookiecutter.project_slug }}.contrib.sites.migrations\"}\n\n# AUTHENTICATION\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends\nAUTHENTICATION_BACKENDS = [\n    \"django.contrib.auth.backends.ModelBackend\",\n    \"allauth.account.auth_backends.AuthenticationBackend\",\n]\n# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model\nAUTH_USER_MODEL = \"users.User\"\n# https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url\nLOGIN_REDIRECT_URL = \"users:redirect\"\n# https://docs.djangoproject.com/en/dev/ref/settings/#login-url\nLOGIN_URL = \"account_login\"\n\n# PASSWORDS\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers\nPASSWORD_HASHERS = [\n    # https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django\n    \"django.contrib.auth.hashers.Argon2PasswordHasher\",\n    \"django.contrib.auth.hashers.PBKDF2PasswordHasher\",\n    \"django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher\",\n    \"django.contrib.auth.hashers.BCryptSHA256PasswordHasher\",\n]\n# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.UserAttributeSimilarityValidator\",\n    },\n    {\"NAME\": \"django.contrib.auth.password_validation.MinimumLengthValidator\"},\n    {\"NAME\": \"django.contrib.auth.password_validation.CommonPasswordValidator\"},\n    {\"NAME\": \"django.contrib.auth.password_validation.NumericPasswordValidator\"},\n]\n\n# MIDDLEWARE\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#middleware\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n{%- if cookiecutter.rest_api != 'None' %}\n    \"corsheaders.middleware.CorsMiddleware\",\n{%- endif %}\n{%- if cookiecutter.use_whitenoise == 'y' %}\n    \"whitenoise.middleware.WhiteNoiseMiddleware\",\n{%- endif %}\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\n    \"django.middleware.locale.LocaleMiddleware\",\n    \"django.middleware.common.CommonMiddleware\",\n    \"django.middleware.csrf.CsrfViewMiddleware\",\n    \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n    \"django.contrib.messages.middleware.MessageMiddleware\",\n    \"django.middleware.clickjacking.XFrameOptionsMiddleware\",\n    \"allauth.account.middleware.AccountMiddleware\",\n]\n\n# STATIC\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#static-root\nSTATIC_ROOT = str(BASE_DIR / \"staticfiles\")\n# https://docs.djangoproject.com/en/dev/ref/settings/#static-url\nSTATIC_URL = \"/static/\"\n# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS\nSTATICFILES_DIRS = [str(APPS_DIR / \"static\")]\n# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders\nSTATICFILES_FINDERS = [\n    \"django.contrib.staticfiles.finders.FileSystemFinder\",\n    \"django.contrib.staticfiles.finders.AppDirectoriesFinder\",\n]\n\n# MEDIA\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#media-root\nMEDIA_ROOT = str(APPS_DIR / \"media\")\n# https://docs.djangoproject.com/en/dev/ref/settings/#media-url\nMEDIA_URL = \"/media/\"\n\n# TEMPLATES\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#templates\nTEMPLATES = [\n    {\n        # https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND\n        \"BACKEND\": \"django.template.backends.django.DjangoTemplates\",\n        # https://docs.djangoproject.com/en/dev/ref/settings/#dirs\n        \"DIRS\": [str(APPS_DIR / \"templates\")],\n        # https://docs.djangoproject.com/en/dev/ref/settings/#app-dirs\n        \"APP_DIRS\": True,\n        \"OPTIONS\": {\n            # https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors\n            \"context_processors\": [\n                \"django.template.context_processors.debug\",\n                \"django.template.context_processors.request\",\n                \"django.contrib.auth.context_processors.auth\",\n                \"django.template.context_processors.i18n\",\n                \"django.template.context_processors.media\",\n                \"django.template.context_processors.static\",\n                \"django.template.context_processors.tz\",\n                \"django.contrib.messages.context_processors.messages\",\n                \"{{cookiecutter.project_slug}}.users.context_processors.allauth_settings\",\n            ],\n        },\n    },\n]\n\n# https://docs.djangoproject.com/en/dev/ref/settings/#form-renderer\nFORM_RENDERER = \"django.forms.renderers.TemplatesSetting\"\n\n# http://django-crispy-forms.readthedocs.io/en/latest/install.html#template-packs\nCRISPY_TEMPLATE_PACK = \"bootstrap5\"\nCRISPY_ALLOWED_TEMPLATE_PACKS = \"bootstrap5\"\n\n# FIXTURES\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs\nFIXTURE_DIRS = (str(APPS_DIR / \"fixtures\"),)\n\n# SECURITY\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-httponly\nSESSION_COOKIE_HTTPONLY = True\n# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-httponly\nCSRF_COOKIE_HTTPONLY = True\n# https://docs.djangoproject.com/en/dev/ref/settings/#x-frame-options\nX_FRAME_OPTIONS = \"DENY\"\n\n# EMAIL\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend\nEMAIL_BACKEND = env(\n    \"DJANGO_EMAIL_BACKEND\",\n    default=\"django.core.mail.backends.smtp.EmailBackend\",\n)\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-timeout\nEMAIL_TIMEOUT = 5\n\n# ADMIN\n# ------------------------------------------------------------------------------\n# Django Admin URL.\nADMIN_URL = \"admin/\"\n# https://docs.djangoproject.com/en/dev/ref/settings/#admins\nADMINS = ['\"{{cookiecutter.author_name}}\" <{{cookiecutter.email}}>']\n# https://docs.djangoproject.com/en/dev/ref/settings/#managers\nMANAGERS = ADMINS\n# https://cookiecutter-django.readthedocs.io/en/latest/settings.html#other-environment-settings\n# Force the `admin` sign in process to go through the `django-allauth` workflow\nDJANGO_ADMIN_FORCE_ALLAUTH = env.bool(\"DJANGO_ADMIN_FORCE_ALLAUTH\", default=False)\n\n# LOGGING\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#logging\n# See https://docs.djangoproject.com/en/dev/topics/logging for\n# more details on how to customize your logging configuration.\nLOGGING = {\n    \"version\": 1,\n    \"disable_existing_loggers\": False,\n    \"formatters\": {\n        \"verbose\": {\n            \"format\": \"%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s\",\n        },\n    },\n    \"handlers\": {\n        \"console\": {\n            \"level\": \"DEBUG\",\n            \"class\": \"logging.StreamHandler\",\n            \"formatter\": \"verbose\",\n        },\n    },\n    \"root\": {\"level\": \"INFO\", \"handlers\": [\"console\"]},\n}\n\nREDIS_URL = env(\"REDIS_URL\", default=\"redis://{% if cookiecutter.use_docker == 'y' %}redis{%else%}localhost{% endif %}:6379/0\")\nREDIS_SSL = REDIS_URL.startswith(\"rediss://\")\n\n{% if cookiecutter.use_celery == 'y' -%}\n# Celery\n# ------------------------------------------------------------------------------\nif USE_TZ:\n    # https://docs.celeryq.dev/en/stable/userguide/configuration.html#std:setting-timezone\n    CELERY_TIMEZONE = TIME_ZONE\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#std:setting-broker_url\nCELERY_BROKER_URL = REDIS_URL\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#redis-backend-use-ssl\nCELERY_BROKER_USE_SSL = {\"ssl_cert_reqs\": ssl.CERT_NONE} if REDIS_SSL else None\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#std:setting-result_backend\nCELERY_RESULT_BACKEND = REDIS_URL\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#redis-backend-use-ssl\nCELERY_REDIS_BACKEND_USE_SSL = CELERY_BROKER_USE_SSL\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#result-extended\nCELERY_RESULT_EXTENDED = True\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#result-backend-always-retry\n# https://github.com/celery/celery/pull/6122\nCELERY_RESULT_BACKEND_ALWAYS_RETRY = True\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#result-backend-max-retries\nCELERY_RESULT_BACKEND_MAX_RETRIES = 10\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#std:setting-accept_content\nCELERY_ACCEPT_CONTENT = [\"json\"]\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#std:setting-task_serializer\nCELERY_TASK_SERIALIZER = \"json\"\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#std:setting-result_serializer\nCELERY_RESULT_SERIALIZER = \"json\"\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#task-time-limit\n# TODO: set to whatever value is adequate in your circumstances\nCELERY_TASK_TIME_LIMIT = 5 * 60\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#task-soft-time-limit\n# TODO: set to whatever value is adequate in your circumstances\nCELERY_TASK_SOFT_TIME_LIMIT = 60\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#beat-scheduler\nCELERY_BEAT_SCHEDULER = \"django_celery_beat.schedulers:DatabaseScheduler\"\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#worker-send-task-events\nCELERY_WORKER_SEND_TASK_EVENTS = True\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#std-setting-task_send_sent_event\nCELERY_TASK_SEND_SENT_EVENT = True\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#worker-hijack-root-logger\nCELERY_WORKER_HIJACK_ROOT_LOGGER = False\n\n{%- endif %}\n# django-allauth\n# ------------------------------------------------------------------------------\nACCOUNT_ALLOW_REGISTRATION = env.bool(\"DJANGO_ACCOUNT_ALLOW_REGISTRATION\", True)\n# https://docs.allauth.org/en/latest/account/configuration.html\nACCOUNT_LOGIN_METHODS = {\"{{cookiecutter.username_type}}\"}\n# https://docs.allauth.org/en/latest/account/configuration.html\n{%- if cookiecutter.username_type == \"username\" %}\nACCOUNT_SIGNUP_FIELDS = [\"email*\", \"username*\", \"password1*\", \"password2*\"]\n{%- else %}\nACCOUNT_SIGNUP_FIELDS = [\"email*\", \"password1*\", \"password2*\"]\n# https://docs.allauth.org/en/latest/account/configuration.html\nACCOUNT_USER_MODEL_USERNAME_FIELD = None\n{%- endif %}\n# https://docs.allauth.org/en/latest/account/configuration.html\nACCOUNT_EMAIL_VERIFICATION = \"mandatory\"\n# https://docs.allauth.org/en/latest/account/configuration.html\nACCOUNT_ADAPTER = \"{{cookiecutter.project_slug}}.users.adapters.AccountAdapter\"\n# https://docs.allauth.org/en/latest/account/forms.html\nACCOUNT_FORMS = {\"signup\": \"{{cookiecutter.project_slug}}.users.forms.UserSignupForm\"}\n# https://docs.allauth.org/en/latest/socialaccount/configuration.html\nSOCIALACCOUNT_ADAPTER = \"{{cookiecutter.project_slug}}.users.adapters.SocialAccountAdapter\"\n# https://docs.allauth.org/en/latest/socialaccount/configuration.html\nSOCIALACCOUNT_FORMS = {\"signup\": \"{{cookiecutter.project_slug}}.users.forms.UserSocialSignupForm\"}\n{% if cookiecutter.frontend_pipeline == 'Django Compressor' -%}\n# django-compressor\n# ------------------------------------------------------------------------------\n# https://django-compressor.readthedocs.io/en/latest/quickstart/#installation\nINSTALLED_APPS += [\"compressor\"]\nSTATICFILES_FINDERS += [\"compressor.finders.CompressorFinder\"]\n{%- endif %}\n{% if cookiecutter.rest_api == 'DRF' -%}\n# django-rest-framework\n# -------------------------------------------------------------------------------\n# django-rest-framework - https://www.django-rest-framework.org/api-guide/settings/\nREST_FRAMEWORK = {\n    \"DEFAULT_AUTHENTICATION_CLASSES\": (\n        \"rest_framework.authentication.SessionAuthentication\",\n        \"rest_framework.authentication.TokenAuthentication\",\n    ),\n    \"DEFAULT_PERMISSION_CLASSES\": (\"rest_framework.permissions.IsAuthenticated\",),\n    \"DEFAULT_SCHEMA_CLASS\": \"drf_spectacular.openapi.AutoSchema\",\n}\n\n# django-cors-headers - https://github.com/adamchainz/django-cors-headers#setup\nCORS_URLS_REGEX = r\"^/api/.*$\"\n\n# By Default swagger ui is available only to admin user(s). You can change permission classes to change that\n# See more configuration options at https://drf-spectacular.readthedocs.io/en/latest/settings.html#settings\nSPECTACULAR_SETTINGS = {\n    \"TITLE\": \"{{ cookiecutter.project_name }} API\",\n    \"DESCRIPTION\": \"Documentation of API endpoints of {{ cookiecutter.project_name }}\",\n    \"VERSION\": \"1.0.0\",\n    \"SERVE_PERMISSIONS\": [\"rest_framework.permissions.IsAdminUser\"],\n    \"SCHEMA_PATH_PREFIX\": \"/api/\",\n}\n{%- endif %}\n{%- if cookiecutter.frontend_pipeline == 'Webpack' %}\n# django-webpack-loader\n# ------------------------------------------------------------------------------\nWEBPACK_LOADER = {\n    \"DEFAULT\": {\n        \"CACHE\": not DEBUG,\n        \"STATS_FILE\": BASE_DIR / \"webpack-stats.json\",\n        \"POLL_INTERVAL\": 0.1,\n        \"IGNORE\": [r\".+\\.hot-update.js\", r\".+\\.map\"],\n    },\n}\n\n{%- endif %}\n# Your stuff...\n# ------------------------------------------------------------------------------\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/settings/local.py",
    "content": "from .base import *  # noqa: F403\nfrom .base import INSTALLED_APPS\nfrom .base import MIDDLEWARE\n{%- if cookiecutter.frontend_pipeline == 'Webpack' %}\nfrom .base import WEBPACK_LOADER\n{%- endif %}\nfrom .base import env\n\n# GENERAL\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#debug\nDEBUG = True\n# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key\nSECRET_KEY = env(\n    \"DJANGO_SECRET_KEY\",\n    default=\"!!!SET DJANGO_SECRET_KEY!!!\",\n)\n# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts\nALLOWED_HOSTS = [\"localhost\", \"0.0.0.0\", \"127.0.0.1\"]  # noqa: S104\n\n# CACHES\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#caches\nCACHES = {\n    \"default\": {\n        \"BACKEND\": \"django.core.cache.backends.locmem.LocMemCache\",\n        \"LOCATION\": \"\",\n    },\n}\n\n# EMAIL\n# ------------------------------------------------------------------------------\n{% if cookiecutter.use_mailpit == 'y' and cookiecutter.use_docker == 'y' -%}\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-host\nEMAIL_HOST = env(\"EMAIL_HOST\", default=\"mailpit\")\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-port\nEMAIL_PORT = 1025\n{%- elif cookiecutter.use_mailpit == 'y' and cookiecutter.use_docker == 'n' -%}\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-host\nEMAIL_HOST = \"localhost\"\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-port\nEMAIL_PORT = 1025\n{%- else -%}\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend\nEMAIL_BACKEND = env(\n    \"DJANGO_EMAIL_BACKEND\",\n    default=\"django.core.mail.backends.console.EmailBackend\",\n)\n{%- endif %}\n\n{%- if cookiecutter.use_whitenoise == 'y' %}\n\n# WhiteNoise\n# ------------------------------------------------------------------------------\n# http://whitenoise.evans.io/en/latest/django.html#using-whitenoise-in-development\nINSTALLED_APPS = [\"whitenoise.runserver_nostatic\", *INSTALLED_APPS]\n{% endif %}\n\n# django-debug-toolbar\n# ------------------------------------------------------------------------------\n# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites\nINSTALLED_APPS += [\"debug_toolbar\"]\n# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#middleware\nMIDDLEWARE += [\"debug_toolbar.middleware.DebugToolbarMiddleware\"]\n# https://django-debug-toolbar.readthedocs.io/en/latest/configuration.html#debug-toolbar-config\nDEBUG_TOOLBAR_CONFIG = {\n    \"DISABLE_PANELS\": [\n        \"debug_toolbar.panels.redirects.RedirectsPanel\",\n        # Disable profiling panel due to an issue with Python 3.12+:\n        # https://github.com/jazzband/django-debug-toolbar/issues/1875\n        \"debug_toolbar.panels.profiling.ProfilingPanel\",\n    ],\n    \"SHOW_TEMPLATE_CONTEXT\": True,\n}\n# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips\nINTERNAL_IPS = [\"127.0.0.1\", \"10.0.2.2\"]\n{% if cookiecutter.use_docker == 'y' -%}\nif env(\"USE_DOCKER\") == \"yes\":\n    import socket\n\n    hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())\n    INTERNAL_IPS += [\".\".join([*ip.split(\".\")[:-1], \"1\"]) for ip in ips]\n    {%- if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] %}\n    try:\n        _, _, ips = socket.gethostbyname_ex(\"node\")\n        INTERNAL_IPS.extend(ips)\n    except socket.gaierror:\n        # The node container isn't started (yet?)\n        pass\n    {%- endif %}\n    {%- if cookiecutter.windows == 'y' %}\n    # RunServerPlus\n    # ------------------------------------------------------------------------------\n    # This is a custom setting for RunServerPlus to fix reloader issue in Windows docker environment\n    # Werkzeug reloader type [auto, watchdog, or stat]\n    RUNSERVERPLUS_POLLER_RELOADER_TYPE = 'stat'\n    # If you have CPU and IO load issues, you can increase this poller interval e.g) 5\n    RUNSERVERPLUS_POLLER_RELOADER_INTERVAL = 1\n    {%- endif %}\n{%- endif %}\n\n# django-extensions\n# ------------------------------------------------------------------------------\n# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration\nINSTALLED_APPS += [\"django_extensions\"]\n{% if cookiecutter.use_celery == 'y' -%}\n\n# Celery\n# ------------------------------------------------------------------------------\n{% if cookiecutter.use_docker == 'n' -%}\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#task-always-eager\nCELERY_TASK_ALWAYS_EAGER = True\n{%- endif %}\n# https://docs.celeryq.dev/en/stable/userguide/configuration.html#task-eager-propagates\nCELERY_TASK_EAGER_PROPAGATES = True\n\n{%- endif %}\n{%- if cookiecutter.frontend_pipeline == 'Webpack' %}\n# django-webpack-loader\n# ------------------------------------------------------------------------------\nWEBPACK_LOADER[\"DEFAULT\"][\"CACHE\"] = not DEBUG\n\n{%- endif %}\n# Your stuff...\n# ------------------------------------------------------------------------------\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/settings/production.py",
    "content": "# ruff: noqa: E501\n{% if cookiecutter.use_sentry == 'y' -%}\nimport logging\n\nimport sentry_sdk\n\n{%- if cookiecutter.use_celery == 'y' %}\nfrom sentry_sdk.integrations.celery import CeleryIntegration\n\n{%- endif %}\nfrom sentry_sdk.integrations.django import DjangoIntegration\nfrom sentry_sdk.integrations.logging import LoggingIntegration\nfrom sentry_sdk.integrations.redis import RedisIntegration\n\n{% endif -%}\nfrom .base import *  # noqa: F403\nfrom .base import DATABASES\nfrom .base import INSTALLED_APPS\nfrom .base import REDIS_URL\n{%- if cookiecutter.rest_api == 'DRF' %}\nfrom .base import SPECTACULAR_SETTINGS\n{%- endif %}\nfrom .base import env\n\n# GENERAL\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key\nSECRET_KEY = env(\"DJANGO_SECRET_KEY\")\n# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts\nALLOWED_HOSTS = env.list(\"DJANGO_ALLOWED_HOSTS\", default=[\"{{ cookiecutter.domain_name }}\"])\n\n# DATABASES\n# ------------------------------------------------------------------------------\nDATABASES[\"default\"][\"CONN_MAX_AGE\"] = env.int(\"CONN_MAX_AGE\", default=60)\n\n# CACHES\n# ------------------------------------------------------------------------------\nCACHES = {\n    \"default\": {\n        \"BACKEND\": \"django_redis.cache.RedisCache\",\n        \"LOCATION\": REDIS_URL,\n        \"OPTIONS\": {\n            \"CLIENT_CLASS\": \"django_redis.client.DefaultClient\",\n            # Mimicking memcache behavior.\n            # https://github.com/jazzband/django-redis#memcached-exceptions-behavior\n            \"IGNORE_EXCEPTIONS\": True,\n        },\n    },\n}\n\n# SECURITY\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header\nSECURE_PROXY_SSL_HEADER = (\"HTTP_X_FORWARDED_PROTO\", \"https\")\n# https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect\nSECURE_SSL_REDIRECT = env.bool(\"DJANGO_SECURE_SSL_REDIRECT\", default=True)\n# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure\nSESSION_COOKIE_SECURE = True\n# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-name\nSESSION_COOKIE_NAME = \"__Secure-sessionid\"\n# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure\nCSRF_COOKIE_SECURE = True\n# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-name\nCSRF_COOKIE_NAME = \"__Secure-csrftoken\"\n# https://docs.djangoproject.com/en/dev/topics/security/#ssl-https\n# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds\n# TODO: set this to 60 seconds first and then to 518400 once you prove the former works\nSECURE_HSTS_SECONDS = 60\n# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains\nSECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(\n    \"DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS\",\n    default=True,\n)\n# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload\nSECURE_HSTS_PRELOAD = env.bool(\"DJANGO_SECURE_HSTS_PRELOAD\", default=True)\n# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff\nSECURE_CONTENT_TYPE_NOSNIFF = env.bool(\n    \"DJANGO_SECURE_CONTENT_TYPE_NOSNIFF\",\n    default=True,\n)\n\n{% if cookiecutter.cloud_provider == 'AWS' %}\n# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings\nAWS_ACCESS_KEY_ID = env(\"DJANGO_AWS_ACCESS_KEY_ID\")\n# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings\nAWS_SECRET_ACCESS_KEY = env(\"DJANGO_AWS_SECRET_ACCESS_KEY\")\n# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings\nAWS_STORAGE_BUCKET_NAME = env(\"DJANGO_AWS_STORAGE_BUCKET_NAME\")\n# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings\nAWS_QUERYSTRING_AUTH = False\n# DO NOT change these unless you know what you're doing.\n_AWS_EXPIRY = 60 * 60 * 24 * 7\n# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings\nAWS_S3_OBJECT_PARAMETERS = {\n    \"CacheControl\": f\"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate\",\n}\n# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings\nAWS_S3_MAX_MEMORY_SIZE = env.int(\n    \"DJANGO_AWS_S3_MAX_MEMORY_SIZE\",\n    default=100_000_000,  # 100MB\n)\n# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings\nAWS_S3_REGION_NAME = env(\"DJANGO_AWS_S3_REGION_NAME\", default=None)\n# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#cloudfront\nAWS_S3_CUSTOM_DOMAIN = env(\"DJANGO_AWS_S3_CUSTOM_DOMAIN\", default=None)\naws_s3_domain = AWS_S3_CUSTOM_DOMAIN or f\"{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com\"\n{% elif cookiecutter.cloud_provider == 'GCP' %}\nGS_BUCKET_NAME = env(\"DJANGO_GCP_STORAGE_BUCKET_NAME\")\nGS_DEFAULT_ACL = \"publicRead\"\n{% elif cookiecutter.cloud_provider == 'Azure' %}\nAZURE_ACCOUNT_KEY = env(\"DJANGO_AZURE_ACCOUNT_KEY\")\nAZURE_ACCOUNT_NAME = env(\"DJANGO_AZURE_ACCOUNT_NAME\")\nAZURE_CONTAINER = env(\"DJANGO_AZURE_CONTAINER_NAME\")\n{% endif -%}\n\n{% if cookiecutter.cloud_provider != 'None' or cookiecutter.use_whitenoise == 'y' -%}\n# STATIC & MEDIA\n# ------------------------\nSTORAGES = {\n{%- if cookiecutter.use_whitenoise == 'y' and cookiecutter.cloud_provider == 'None' %}\n    \"default\": {\n        \"BACKEND\": \"django.core.files.storage.FileSystemStorage\",\n    },\n    \"staticfiles\": {\n        \"BACKEND\": \"whitenoise.storage.CompressedManifestStaticFilesStorage\",\n    },\n{%- elif cookiecutter.cloud_provider == 'AWS' %}\n    \"default\": {\n        \"BACKEND\": \"storages.backends.s3.S3Storage\",\n        \"OPTIONS\": {\n            \"location\": \"media\",\n            \"file_overwrite\": False,\n        },\n    },\n    {%- if cookiecutter.use_whitenoise == 'y' %}\n    \"staticfiles\": {\n        \"BACKEND\": \"whitenoise.storage.CompressedManifestStaticFilesStorage\",\n    },\n    {%- else %}\n    \"staticfiles\": {\n        \"BACKEND\": \"storages.backends.s3.S3Storage\",\n        \"OPTIONS\": {\n            \"location\": \"static\",\n            \"default_acl\": \"public-read\",\n        },\n    },\n    {%- endif %}\n{%- elif cookiecutter.cloud_provider == 'GCP' %}\n    \"default\": {\n        \"BACKEND\": \"storages.backends.gcloud.GoogleCloudStorage\",\n        \"OPTIONS\": {\n            \"location\": \"media\",\n            \"file_overwrite\": False,\n        },\n    },\n    {%- if cookiecutter.use_whitenoise == 'y' %}\n    \"staticfiles\": {\n        \"BACKEND\": \"whitenoise.storage.CompressedManifestStaticFilesStorage\",\n    },\n    {%- else %}\n    \"staticfiles\": {\n        \"BACKEND\": \"storages.backends.gcloud.GoogleCloudStorage\",\n        \"OPTIONS\": {\n            \"location\": \"static\",\n            \"default_acl\": \"publicRead\",\n        },\n    },\n    {%- endif %}\n{%- elif cookiecutter.cloud_provider == 'Azure' %}\n    \"default\": {\n        \"BACKEND\": \"storages.backends.azure_storage.AzureStorage\",\n        \"OPTIONS\": {\n            \"location\": \"media\",\n            \"overwrite_files\": False,\n        },\n    },\n    {%- if cookiecutter.use_whitenoise == 'y' %}\n    \"staticfiles\": {\n        \"BACKEND\": \"whitenoise.storage.CompressedManifestStaticFilesStorage\",\n    },\n    {%- else %}\n    \"staticfiles\": {\n        \"BACKEND\": \"storages.backends.azure_storage.AzureStorage\",\n        \"OPTIONS\": {\n            \"location\": \"static\",\n        },\n    },\n    {%- endif %}\n{%- endif %}\n}\n{%- endif %}\n\n{%- if cookiecutter.cloud_provider == 'AWS' %}\nMEDIA_URL = f\"https://{aws_s3_domain}/media/\"\n{%- if cookiecutter.use_whitenoise == 'n' %}\nCOLLECTFASTA_STRATEGY = \"collectfasta.strategies.boto3.Boto3Strategy\"\nSTATIC_URL = f\"https://{aws_s3_domain}/static/\"\n{%- endif %}\n{%- elif cookiecutter.cloud_provider == 'GCP' %}\nMEDIA_URL = f\"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/\"\n{%- if cookiecutter.use_whitenoise == 'n' %}\nCOLLECTFASTA_STRATEGY = \"collectfasta.strategies.gcloud.GoogleCloudStrategy\"\nSTATIC_URL = f\"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/\"\n{%- endif %}\n{%- elif cookiecutter.cloud_provider == 'Azure' %}\nMEDIA_URL = f\"https://{AZURE_ACCOUNT_NAME}.blob.core.windows.net/media/\"\n{%- if cookiecutter.use_whitenoise == 'n' %}\nCOLLECTFASTA_STRATEGY = \"collectfasta.strategies.azure.AzureBlobStrategy\"\nSTATIC_URL = f\"https://{AZURE_ACCOUNT_NAME}.blob.core.windows.net/static/\"\n{%- endif %}\n{%- endif %}\n\n# EMAIL\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email\nDEFAULT_FROM_EMAIL = env(\n    \"DJANGO_DEFAULT_FROM_EMAIL\",\n    default=\"{{cookiecutter.project_name}} <noreply@{{cookiecutter.domain_name}}>\",\n)\n# https://docs.djangoproject.com/en/dev/ref/settings/#server-email\nSERVER_EMAIL = env(\"DJANGO_SERVER_EMAIL\", default=DEFAULT_FROM_EMAIL)\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix\nEMAIL_SUBJECT_PREFIX = env(\n    \"DJANGO_EMAIL_SUBJECT_PREFIX\",\n    default=\"[{{cookiecutter.project_name}}] \",\n)\nACCOUNT_EMAIL_SUBJECT_PREFIX = EMAIL_SUBJECT_PREFIX\n\n# ADMIN\n# ------------------------------------------------------------------------------\n# Django Admin URL regex.\nADMIN_URL = env(\"DJANGO_ADMIN_URL\")\n\n# Anymail\n# ------------------------------------------------------------------------------\n# https://anymail.readthedocs.io/en/stable/installation/#installing-anymail\nINSTALLED_APPS += [\"anymail\"]\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend\n# https://anymail.readthedocs.io/en/stable/installation/#anymail-settings-reference\n{%- if cookiecutter.mail_service == 'Mailgun' %}\n# https://anymail.readthedocs.io/en/stable/esps/mailgun/\nEMAIL_BACKEND = \"anymail.backends.mailgun.EmailBackend\"\nANYMAIL = {\n    \"MAILGUN_API_KEY\": env(\"MAILGUN_API_KEY\"),\n    \"MAILGUN_SENDER_DOMAIN\": env(\"MAILGUN_DOMAIN\"),\n    \"MAILGUN_API_URL\": env(\"MAILGUN_API_URL\", default=\"https://api.mailgun.net/v3\"),\n}\n{%- elif cookiecutter.mail_service == 'Amazon SES' %}\n# https://anymail.readthedocs.io/en/stable/esps/amazon_ses/\nEMAIL_BACKEND = \"anymail.backends.amazon_ses.EmailBackend\"\nANYMAIL = {}\n{%- elif cookiecutter.mail_service == 'Mailjet' %}\n# https://anymail.readthedocs.io/en/stable/esps/mailjet/\nEMAIL_BACKEND = \"anymail.backends.mailjet.EmailBackend\"\nANYMAIL = {\n    \"MAILJET_API_KEY\": env(\"MAILJET_API_KEY\"),\n    \"MAILJET_SECRET_KEY\": env(\"MAILJET_SECRET_KEY\"),\n}\n{%- elif cookiecutter.mail_service == 'Mandrill' %}\n# https://anymail.readthedocs.io/en/stable/esps/mandrill/\nEMAIL_BACKEND = \"anymail.backends.mandrill.EmailBackend\"\nANYMAIL = {\n    \"MANDRILL_API_KEY\": env(\"MANDRILL_API_KEY\"),\n    \"MANDRILL_API_URL\": env(\"MANDRILL_API_URL\", default=\"https://mandrillapp.com/api/1.0\"),\n}\n{%- elif cookiecutter.mail_service == 'Postmark' %}\n# https://anymail.readthedocs.io/en/stable/esps/postmark/\nEMAIL_BACKEND = \"anymail.backends.postmark.EmailBackend\"\nANYMAIL = {\n    \"POSTMARK_SERVER_TOKEN\": env(\"POSTMARK_SERVER_TOKEN\"),\n    \"POSTMARK_API_URL\": env(\"POSTMARK_API_URL\", default=\"https://api.postmarkapp.com/\"),\n}\n{%- elif cookiecutter.mail_service == 'Sendgrid' %}\n# https://anymail.readthedocs.io/en/stable/esps/sendgrid/\nEMAIL_BACKEND = \"anymail.backends.sendgrid.EmailBackend\"\nANYMAIL = {\n    \"SENDGRID_API_KEY\": env(\"SENDGRID_API_KEY\"),\n    \"SENDGRID_API_URL\": env(\"SENDGRID_API_URL\", default=\"https://api.sendgrid.com/v3/\"),\n}\n{%- elif cookiecutter.mail_service == 'Brevo' %}\n# https://anymail.readthedocs.io/en/stable/esps/brevo/\nEMAIL_BACKEND = \"anymail.backends.brevo.EmailBackend\"\nANYMAIL = {\n    \"BREVO_API_KEY\": env(\"BREVO_API_KEY\"),\n    \"BREVO_API_URL\": env(\"BREVO_API_URL\", default=\"https://api.brevo.com/v3/\"),\n}\n{%- elif cookiecutter.mail_service == 'SparkPost' %}\n# https://anymail.readthedocs.io/en/stable/esps/sparkpost/\nEMAIL_BACKEND = \"anymail.backends.sparkpost.EmailBackend\"\nANYMAIL = {\n    \"SPARKPOST_API_KEY\": env(\"SPARKPOST_API_KEY\"),\n    \"SPARKPOST_API_URL\": env(\"SPARKPOST_API_URL\", default=\"https://api.sparkpost.com/api/v1\"),\n}\n{%- elif cookiecutter.mail_service == 'Other SMTP' %}\n# https://anymail.readthedocs.io/en/stable/esps\nEMAIL_BACKEND = \"django.core.mail.backends.smtp.EmailBackend\"\nANYMAIL = {}\n{%- endif %}\n\n{% if cookiecutter.frontend_pipeline == 'Django Compressor' -%}\n# django-compressor\n# ------------------------------------------------------------------------------\n# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_ENABLED\nCOMPRESS_ENABLED = env.bool(\"COMPRESS_ENABLED\", default=True)\n{%- if cookiecutter.cloud_provider == 'None' %}\n# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE\nCOMPRESS_STORAGE = \"compressor.storage.GzipCompressorFileStorage\"\n{%- elif cookiecutter.cloud_provider in ('AWS', 'GCP', 'Azure') and cookiecutter.use_whitenoise == 'n' %}\n# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE\nCOMPRESS_STORAGE = STORAGES[\"staticfiles\"][\"BACKEND\"]\n{%- endif %}\n# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_URL\nCOMPRESS_URL = STATIC_URL{% if cookiecutter.use_whitenoise == 'y' or cookiecutter.cloud_provider == 'None' %}  # noqa: F405\n{%- endif -%}\n{%- if cookiecutter.use_whitenoise == 'y' %}\n# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_OFFLINE\nCOMPRESS_OFFLINE = True  # Offline compression is required when using Whitenoise\n{%- endif %}\n# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_FILTERS\nCOMPRESS_FILTERS = {\n    \"css\": [\n        \"compressor.filters.css_default.CssAbsoluteFilter\",\n        \"compressor.filters.cssmin.rCSSMinFilter\",\n    ],\n    \"js\": [\"compressor.filters.jsmin.JSMinFilter\"],\n}\n{% endif %}\n{%- if cookiecutter.use_whitenoise == 'n' and cookiecutter.cloud_provider in ('AWS', 'GCP', 'Azure') -%}\n# Collectfasta\n# ------------------------------------------------------------------------------\n# https://github.com/jasongi/collectfasta#installation\nINSTALLED_APPS = [\"collectfasta\", *INSTALLED_APPS]\n{% endif %}\n# LOGGING\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#logging\n# See https://docs.djangoproject.com/en/dev/topics/logging for\n# more details on how to customize your logging configuration.\n{% if cookiecutter.use_sentry == 'n' -%}\n# A sample logging configuration. The only tangible logging\n# performed by this configuration is to send an email to\n# the site admins on every HTTP 500 error when DEBUG=False.\nLOGGING = {\n    \"version\": 1,\n    \"disable_existing_loggers\": False,\n    \"filters\": {\"require_debug_false\": {\"()\": \"django.utils.log.RequireDebugFalse\"}},\n    \"formatters\": {\n        \"verbose\": {\n            \"format\": \"%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s\",\n        },\n    },\n    \"handlers\": {\n        \"mail_admins\": {\n            \"level\": \"ERROR\",\n            \"filters\": [\"require_debug_false\"],\n            \"class\": \"django.utils.log.AdminEmailHandler\",\n        },\n        \"console\": {\n            \"level\": \"DEBUG\",\n            \"class\": \"logging.StreamHandler\",\n            \"formatter\": \"verbose\",\n        },\n    },\n    \"root\": {\"level\": \"INFO\", \"handlers\": [\"console\"]},\n    \"loggers\": {\n        \"django.request\": {\n            \"handlers\": [\"mail_admins\"],\n            \"level\": \"ERROR\",\n            \"propagate\": True,\n        },\n        \"django.security.DisallowedHost\": {\n            \"level\": \"ERROR\",\n            \"handlers\": [\"console\", \"mail_admins\"],\n            \"propagate\": True,\n        },\n    },\n}\n{% else %}\nLOGGING = {\n    \"version\": 1,\n    \"disable_existing_loggers\": True,\n    \"formatters\": {\n        \"verbose\": {\n            \"format\": \"%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s\",\n        },\n    },\n    \"handlers\": {\n        \"console\": {\n            \"level\": \"DEBUG\",\n            \"class\": \"logging.StreamHandler\",\n            \"formatter\": \"verbose\",\n        },\n    },\n    \"root\": {\"level\": \"INFO\", \"handlers\": [\"console\"]},\n    \"loggers\": {\n        \"django.db.backends\": {\n            \"level\": \"ERROR\",\n            \"handlers\": [\"console\"],\n            \"propagate\": False,\n        },\n        # Errors logged by the SDK itself\n        \"sentry_sdk\": {\"level\": \"ERROR\", \"handlers\": [\"console\"], \"propagate\": False},\n        \"django.security.DisallowedHost\": {\n            \"level\": \"ERROR\",\n            \"handlers\": [\"console\"],\n            \"propagate\": False,\n        },\n    },\n}\n\n# Sentry\n# ------------------------------------------------------------------------------\nSENTRY_DSN = env(\"SENTRY_DSN\")\nSENTRY_LOG_LEVEL = env.int(\"DJANGO_SENTRY_LOG_LEVEL\", logging.INFO)\n\nsentry_logging = LoggingIntegration(\n    level=SENTRY_LOG_LEVEL,  # Capture info and above as breadcrumbs\n    event_level=logging.ERROR,  # Send errors as events\n)\n\n{%- if cookiecutter.use_celery == 'y' %}\nintegrations = [\n    sentry_logging,\n    DjangoIntegration(),\n    CeleryIntegration(),\n    RedisIntegration(),\n]\n{% else %}\nintegrations = [sentry_logging, DjangoIntegration(), RedisIntegration()]\n{% endif -%}\n\nsentry_sdk.init(\n    dsn=SENTRY_DSN,\n    integrations=integrations,\n    environment=env(\"SENTRY_ENVIRONMENT\", default=\"production\"),\n    traces_sample_rate=env.float(\"SENTRY_TRACES_SAMPLE_RATE\", default=0.0),\n)\n{% endif %}\n{% if cookiecutter.rest_api == 'DRF' -%}\n\n# django-rest-framework\n# -------------------------------------------------------------------------------\n# Tools that generate code samples can use SERVERS to point to the correct domain\nSPECTACULAR_SETTINGS[\"SERVERS\"] = [\n    {\"url\": \"https://{{ cookiecutter.domain_name }}\", \"description\": \"Production server\"},\n]\n\n{%- endif %}\n# Your stuff...\n# ------------------------------------------------------------------------------\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/settings/test.py",
    "content": "\"\"\"\nWith these settings, tests run faster.\n\"\"\"\n\nfrom .base import *  # noqa: F403\nfrom .base import TEMPLATES\nfrom .base import env\n\n# GENERAL\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key\nSECRET_KEY = env(\n    \"DJANGO_SECRET_KEY\",\n    default=\"!!!SET DJANGO_SECRET_KEY!!!\",\n)\n# https://docs.djangoproject.com/en/dev/ref/settings/#test-runner\nTEST_RUNNER = \"django.test.runner.DiscoverRunner\"\n\n# PASSWORDS\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers\nPASSWORD_HASHERS = [\"django.contrib.auth.hashers.MD5PasswordHasher\"]\n\n# EMAIL\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend\nEMAIL_BACKEND = \"django.core.mail.backends.locmem.EmailBackend\"\n\n# DEBUGGING FOR TEMPLATES\n# ------------------------------------------------------------------------------\nTEMPLATES[0][\"OPTIONS\"][\"debug\"] = True  # type: ignore[index]\n\n# MEDIA\n# ------------------------------------------------------------------------------\n# https://docs.djangoproject.com/en/dev/ref/settings/#media-url\nMEDIA_URL = \"http://media.testserver/\"\n\n{%- if cookiecutter.frontend_pipeline == 'Webpack' %}\n# django-webpack-loader\n# ------------------------------------------------------------------------------\nWEBPACK_LOADER[\"DEFAULT\"][\"LOADER_CLASS\"] = \"webpack_loader.loaders.FakeWebpackLoader\"  # noqa: F405\n\n{%- endif %}\n# Your stuff...\n# ------------------------------------------------------------------------------\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/urls.py",
    "content": "from django.conf import settings\nfrom django.conf.urls.static import static\nfrom django.contrib import admin\n{%- if cookiecutter.use_async == 'y' %}\nfrom django.contrib.staticfiles.urls import staticfiles_urlpatterns\n{%- endif %}\nfrom django.urls import include\nfrom django.urls import path\nfrom django.views import defaults as default_views\nfrom django.views.generic import TemplateView\n{%- if cookiecutter.rest_api == 'DRF' %}\nfrom drf_spectacular.views import SpectacularAPIView\nfrom drf_spectacular.views import SpectacularSwaggerView\nfrom rest_framework.authtoken.views import obtain_auth_token\n{%- elif cookiecutter.rest_api == 'Django Ninja' %}\n\nfrom .api import api\n{%- endif %}\n\nurlpatterns = [\n    path(\"\", TemplateView.as_view(template_name=\"pages/home.html\"), name=\"home\"),\n    path(\n        \"about/\",\n        TemplateView.as_view(template_name=\"pages/about.html\"),\n        name=\"about\",\n    ),\n    # Django Admin, use {% raw %}{% url 'admin:index' %}{% endraw %}\n    path(settings.ADMIN_URL, admin.site.urls),\n    # User management\n    path(\"users/\", include(\"{{ cookiecutter.project_slug }}.users.urls\", namespace=\"users\")),\n    path(\"accounts/\", include(\"allauth.urls\")),\n    # Your stuff: custom urls includes go here\n    # ...\n    # Media files\n    *static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT),\n]\n{%- if cookiecutter.use_async == 'y' %}\nif settings.DEBUG:\n    # Static file serving when using Gunicorn + Uvicorn for local web socket development\n    urlpatterns += staticfiles_urlpatterns()\n{%- endif %}\n{% if cookiecutter.rest_api == 'DRF' %}\n# API URLS\nurlpatterns += [\n    # API base url\n    path(\"api/\", include(\"config.api_router\")),\n    # DRF auth token\n    path(\"api/auth-token/\", obtain_auth_token, name=\"obtain_auth_token\"),\n    path(\"api/schema/\", SpectacularAPIView.as_view(), name=\"api-schema\"),\n    path(\n        \"api/docs/\",\n        SpectacularSwaggerView.as_view(url_name=\"api-schema\"),\n        name=\"api-docs\",\n    ),\n]\n{%- elif cookiecutter.rest_api == 'Django Ninja' %}\n\n# API URLS\nurlpatterns += [\n    # API base url\n    path(\"api/\", api.urls),\n]\n{%- endif %}\n\nif settings.DEBUG:\n    # This allows the error pages to be debugged during development, just visit\n    # these url in browser to see how these error pages look like.\n    urlpatterns += [\n        path(\n            \"400/\",\n            default_views.bad_request,\n            kwargs={\"exception\": Exception(\"Bad Request!\")},\n        ),\n        path(\n            \"403/\",\n            default_views.permission_denied,\n            kwargs={\"exception\": Exception(\"Permission Denied\")},\n        ),\n        path(\n            \"404/\",\n            default_views.page_not_found,\n            kwargs={\"exception\": Exception(\"Page not Found\")},\n        ),\n        path(\"500/\", default_views.server_error),\n    ]\n    if \"debug_toolbar\" in settings.INSTALLED_APPS:\n        import debug_toolbar\n\n        urlpatterns = [\n            path(\"__debug__/\", include(debug_toolbar.urls)),\n            *urlpatterns,\n        ]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/websocket.py",
    "content": "async def websocket_application(scope, receive, send):\n    while True:\n        event = await receive()\n\n        if event[\"type\"] == \"websocket.connect\":\n            await send({\"type\": \"websocket.accept\"})\n\n        if event[\"type\"] == \"websocket.disconnect\":\n            break\n\n        if event[\"type\"] == \"websocket.receive\":\n            if event[\"text\"] == \"ping\":\n                await send({\"type\": \"websocket.send\", \"text\": \"pong!\"})\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/config/wsgi.py",
    "content": "\"\"\"\nWSGI config for {{ cookiecutter.project_name }} project.\n\nThis module contains the WSGI application used by Django's development server\nand any production WSGI deployments. It should expose a module-level variable\nnamed ``application``. Django's ``runserver`` and ``runfcgi`` commands discover\nthis application via the ``WSGI_APPLICATION`` setting.\n\nUsually you will have the standard Django WSGI application here, but it also\nmight make sense to replace the whole Django WSGI application with a custom one\nthat later delegates to the Django one. For example, you could introduce WSGI\nmiddleware here, or combine a Django application with an application of another\nframework.\n\n\"\"\"\n\nimport os\nimport sys\nfrom pathlib import Path\n\nfrom django.core.wsgi import get_wsgi_application\n\n# This allows easy placement of apps within the interior\n# {{ cookiecutter.project_slug }} directory.\nBASE_DIR = Path(__file__).resolve(strict=True).parent.parent\nsys.path.append(str(BASE_DIR / \"{{ cookiecutter.project_slug }}\"))\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"config.settings.production\")\n\n# This application object is used by any WSGI server configured to use this\n# file. This includes Django's development server, if the WSGI_APPLICATION\n# setting points here.\napplication = get_wsgi_application()\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docker-compose.docs.yml",
    "content": "services:\n  docs:\n    image: {{ cookiecutter.project_slug }}_local_docs\n    container_name: {{ cookiecutter.project_slug }}_local_docs\n    build:\n      context: .\n      dockerfile: ./compose/local/docs/Dockerfile\n    env_file:\n      - ./.envs/.local/.django\n    volumes:\n      - /app/.venv\n      - ./docs:/docs:z\n      - ./config:/app/config:z\n      - ./{{ cookiecutter.project_slug }}:/app/{{ cookiecutter.project_slug }}:z\n    ports:\n      - '9000:9000'\n    command: /start-docs\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docker-compose.local.yml",
    "content": "volumes:\n  {{ cookiecutter.project_slug }}_local_postgres_data: {}\n  {{ cookiecutter.project_slug }}_local_postgres_data_backups: {}\n  {% if cookiecutter.use_celery == 'y' %}{{ cookiecutter.project_slug }}_local_redis_data: {}{% endif %}\n\nservices:\n  django:{% if cookiecutter.use_celery == 'y' %} &django{% endif %}\n    build:\n      context: .\n      dockerfile: ./compose/local/django/Dockerfile\n    image: {{ cookiecutter.project_slug }}_local_django\n    container_name: {{ cookiecutter.project_slug }}_local_django\n    depends_on:\n      - postgres\n      {%- if cookiecutter.use_celery == 'y' %}\n      - redis\n      {%- endif %}\n      {%- if cookiecutter.use_mailpit == 'y' %}\n      - mailpit\n      {%- endif %}\n    volumes:\n      - /app/.venv\n      - .:/app:z\n    env_file:\n      - ./.envs/.local/.django\n      - ./.envs/.local/.postgres\n    ports:\n      - '8000:8000'\n    command: /start\n\n  postgres:\n    build:\n      context: .\n      dockerfile: ./compose/production/postgres/Dockerfile\n    image: {{ cookiecutter.project_slug }}_production_postgres\n    container_name: {{ cookiecutter.project_slug }}_local_postgres\n    volumes:\n      {%- if cookiecutter.postgresql_version|int >= 18 %}\n      - {{ cookiecutter.project_slug }}_local_postgres_data:/var/lib/postgresql/{{ cookiecutter.postgresql_version }}/docker\n      {%- else %}\n      - {{ cookiecutter.project_slug }}_local_postgres_data:/var/lib/postgresql/data\n      {%- endif %}\n      - {{ cookiecutter.project_slug }}_local_postgres_data_backups:/backups\n    env_file:\n      - ./.envs/.local/.postgres\n\n  {%- if cookiecutter.use_mailpit == 'y' %}\n\n  mailpit:\n    image: docker.io/axllent/mailpit:latest\n    container_name: {{ cookiecutter.project_slug }}_local_mailpit\n    ports:\n      - \"8025:8025\"\n\n  {%- endif %}\n  {%- if cookiecutter.use_celery == 'y' %}\n\n  redis:\n    image: docker.io/redis:7.2\n    container_name: {{ cookiecutter.project_slug }}_local_redis\n    volumes:\n      - {{ cookiecutter.project_slug }}_local_redis_data:/data\n\n  celeryworker:\n    <<: *django\n    image: {{ cookiecutter.project_slug }}_local_celeryworker\n    container_name: {{ cookiecutter.project_slug }}_local_celeryworker\n    depends_on:\n      - redis\n      - postgres\n      {%- if cookiecutter.use_mailpit == 'y' %}\n      - mailpit\n      {%- endif %}\n    ports: []\n    command: /start-celeryworker\n\n  celerybeat:\n    <<: *django\n    image: {{ cookiecutter.project_slug }}_local_celerybeat\n    container_name: {{ cookiecutter.project_slug }}_local_celerybeat\n    depends_on:\n      - redis\n      - postgres\n      {%- if cookiecutter.use_mailpit == 'y' %}\n      - mailpit\n      {%- endif %}\n    ports: []\n    command: /start-celerybeat\n\n  flower:\n    <<: *django\n    image: {{ cookiecutter.project_slug }}_local_flower\n    container_name: {{ cookiecutter.project_slug }}_local_flower\n    ports:\n      - '5555:5555'\n    command: /start-flower\n\n  {%- endif %}\n  {%- if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] %}\n\n  node:\n    build:\n      context: .\n      dockerfile: ./compose/local/node/Dockerfile\n    image: {{ cookiecutter.project_slug }}_local_node\n    container_name: {{ cookiecutter.project_slug }}_local_node\n    depends_on:\n      - django\n    volumes:\n      - .:/app:z\n      # http://jdlm.info/articles/2016/03/06/lessons-building-node-app-docker.html\n      - /app/node_modules\n    command: npm run dev\n    ports:\n      - '3000:3000'\n      {%- if cookiecutter.frontend_pipeline == 'Gulp' %}\n      # Expose browsersync UI: https://www.browsersync.io/docs/options/#option-ui\n      - '3001:3001'\n      {%- endif %}\n\n  {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docker-compose.production.yml",
    "content": "volumes:\n  production_postgres_data: {}\n  production_postgres_data_backups: {}\n  production_traefik: {}\n  {%- if cookiecutter.cloud_provider == 'None' %}\n  production_django_media: {}\n  {%- endif %}\n  {% if cookiecutter.use_celery == 'y' %}\n  production_redis_data: {}\n  {% endif %}\n\n\nservices:\n  django:{% if cookiecutter.use_celery == 'y' %} &django{% endif %}\n    build:\n      context: .\n      dockerfile: ./compose/production/django/Dockerfile\n      {%- if cookiecutter.frontend_pipeline == 'Webpack' and cookiecutter.use_whitenoise == 'n' %}\n      args:\n        # These variable can be defined in an .env file in the root of the repo\n        {%- if cookiecutter.cloud_provider == 'AWS' %}\n        DJANGO_AWS_STORAGE_BUCKET_NAME: ${DJANGO_AWS_STORAGE_BUCKET_NAME}\n        DJANGO_AWS_S3_CUSTOM_DOMAIN: ${DJANGO_AWS_S3_CUSTOM_DOMAIN}\n        {%- elif cookiecutter.cloud_provider == 'GCP' %}\n        DJANGO_GCP_STORAGE_BUCKET_NAME: ${DJANGO_GCP_STORAGE_BUCKET_NAME}\n        {%- elif cookiecutter.cloud_provider == 'Azure' %}\n        DJANGO_AZURE_ACCOUNT_NAME: ${DJANGO_AZURE_ACCOUNT_NAME}\n        {%- endif %}\n      {%- endif %}\n\n    image: {{ cookiecutter.project_slug }}_production_django\n    {%- if cookiecutter.cloud_provider == 'None' %}\n    volumes:\n      - production_django_media:/app/{{ cookiecutter.project_slug }}/media\n    {%- endif %}\n    depends_on:\n      - postgres\n      - redis\n    env_file:\n      - ./.envs/.production/.django\n      - ./.envs/.production/.postgres\n    command: /start\n\n  postgres:\n    build:\n      context: .\n      dockerfile: ./compose/production/postgres/Dockerfile\n    image: {{ cookiecutter.project_slug }}_production_postgres\n    volumes:\n      {%- if cookiecutter.postgresql_version|int >= 18 %}\n      - production_postgres_data:/var/lib/postgresql/{{ cookiecutter.postgresql_version }}/docker\n      {%- else %}\n      - production_postgres_data:/var/lib/postgresql/data\n      {%- endif %}\n      - production_postgres_data_backups:/backups\n    env_file:\n      - ./.envs/.production/.postgres\n\n  traefik:\n    build:\n      context: .\n      dockerfile: ./compose/production/traefik/Dockerfile\n    image: {{ cookiecutter.project_slug }}_production_traefik\n    depends_on:\n      - django\n    volumes:\n      - production_traefik:/etc/traefik/acme\n    ports:\n      - '0.0.0.0:80:80'\n      - '0.0.0.0:443:443'\n      {%- if cookiecutter.use_celery == 'y' %}\n      - '0.0.0.0:5555:5555'\n      {%- endif %}\n\n  redis:\n    image: docker.io/redis:7.2\n    {% if cookiecutter.use_celery == 'y' %}\n    volumes:\n      - production_redis_data:/data\n    {% endif %}\n\n\n  {%- if cookiecutter.use_celery == 'y' %}\n\n  celeryworker:\n    <<: *django\n    image: {{ cookiecutter.project_slug }}_production_celeryworker\n    command: /start-celeryworker\n\n  celerybeat:\n    <<: *django\n    image: {{ cookiecutter.project_slug }}_production_celerybeat\n    command: /start-celerybeat\n\n  flower:\n    <<: *django\n    image: {{ cookiecutter.project_slug }}_production_flower\n    command: /start-flower\n  {%- endif %}\n  {%- if cookiecutter.cloud_provider == 'AWS' %}\n\n  awscli:\n    build:\n      context: .\n      dockerfile: ./compose/production/aws/Dockerfile\n    env_file:\n      - ./.envs/.production/.django\n    volumes:\n      - production_postgres_data_backups:/backups:z\n  {%- endif %}\n  {%- if cookiecutter.cloud_provider == 'None' %}\n\n  nginx:\n    build:\n      context: .\n      dockerfile: ./compose/production/nginx/Dockerfile\n    image: {{ cookiecutter.project_slug }}_production_nginx\n    depends_on:\n      - django\n    volumes:\n      - production_django_media:/usr/share/nginx/media:ro\n  {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docs/Makefile",
    "content": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line, and also\n# from the environment for the first two.\nSPHINXOPTS    ?=\nSPHINXBUILD   ?= sphinx-build\nSOURCEDIR     = .\nBUILDDIR      = ./_build\n{%- if cookiecutter.use_docker == 'y' %}\nAPP = /app\n{%- else %}\nAPP = ../{{cookiecutter.project_slug}}\n{% endif %}\n\n.PHONY: help livehtml apidocs Makefile\n\n# Put it first so that \"make\" without argument is like \"make help\".\nhelp:\n\t@$(SPHINXBUILD) -M help \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O) -c .\n\n# Build, watch and serve docs with live reload\nlivehtml:\n\tsphinx-autobuild -b html\n\t{%- if cookiecutter.use_docker == 'y' %} --host 0.0.0.0\n\t{%- else %} --open-browser\n\t{%- endif %} --port 9000 --watch $(APP) -c . $(SOURCEDIR) $(BUILDDIR)/html\n\n# Outputs rst files from django application code\napidocs:\n\tsphinx-apidoc -o $(SOURCEDIR)/api $(APP)\n\n# Catch-all target: route all unknown targets to Sphinx using the new\n# \"make mode\" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).\n%: Makefile\n\t@$(SPHINXBUILD) -M $@ \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O) -c .\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docs/__init__.py",
    "content": "# Included so that Django's startproject comment runs against the docs directory\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docs/conf.py",
    "content": "# ruff: noqa: ERA001, PTH100\n# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common options. For a full\n# list see the documentation:\n# https://www.sphinx-doc.org/en/master/usage/configuration.html\n\n# -- Path setup --------------------------------------------------------------\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n\nimport os\nimport sys\n\nimport django\n\nif os.getenv(\"READTHEDOCS\", default=\"False\") == \"True\":\n    sys.path.insert(0, os.path.abspath(\"..\"))\n    os.environ[\"DJANGO_READ_DOT_ENV_FILE\"] = \"True\"\n    os.environ[\"USE_DOCKER\"] = \"no\"\nelse:\n{%- if cookiecutter.use_docker == 'y' %}\n    sys.path.insert(0, os.path.abspath(\"/app\"))\n{%- else %}\n    sys.path.insert(0, os.path.abspath(\"..\"))\n{%- endif %}\nos.environ[\"DATABASE_URL\"] = \"sqlite:///readthedocs.db\"\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"config.settings.local\")\ndjango.setup()\n\n# -- Project information -----------------------------------------------------\n\nproject = \"{{ cookiecutter.project_name }}\"\ncopyright = \"\"\"{% now 'utc', '%Y' %}, {{ cookiecutter.author_name }}\"\"\"  # noqa: A001\nauthor = \"{{ cookiecutter.author_name }}\"\n\n\n# -- General configuration ---------------------------------------------------\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    \"sphinx.ext.autodoc\",\n    \"sphinx.ext.napoleon\",\n]\n\n# Add any paths that contain templates here, relative to this directory.\n# templates_path = [\"_templates\"]\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path.\nexclude_patterns = [\"_build\", \"Thumbs.db\", \".DS_Store\"]\n\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\nhtml_theme = \"alabaster\"\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\n# html_static_path = [\"_static\"]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docs/howto.rst",
    "content": "How To - Project Documentation\n======================================================================\n\nGet Started\n----------------------------------------------------------------------\n\nDocumentation can be written as rst files in `{{cookiecutter.project_slug}}/docs`.\n\n{% if cookiecutter.use_docker == 'n' %}\nTo build and serve docs, use the command::\n\n    uv run make livehtml\n\nfrom inside the `{{cookiecutter.project_slug}}/docs` directory.\n{% else %}\nTo build and serve docs, use the commands::\n\n    docker compose -f docker-compose.docs.yml up\n\n{% endif %}\n\nChanges to files in `docs/_source` will be picked up and reloaded automatically.\n\n`Sphinx <https://www.sphinx-doc.org/>`_ is the tool used to build documentation.\n\nDocstrings to Documentation\n----------------------------------------------------------------------\n\nThe sphinx extension `apidoc <https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html>`_ is used to automatically document code using signatures and docstrings.\n\nNumpy or Google style docstrings will be picked up from project files and available for documentation. See the `Napoleon <https://sphinxcontrib-napoleon.readthedocs.io/en/latest/>`_ extension for details.\n\nFor an in-use example, see the `page source <_sources/users.rst.txt>`_ for :ref:`users`.\n\nTo compile all docstrings automatically into documentation source files, use the command:\n    ::\n\n        uv run make apidocs\n\n{% if cookiecutter.use_docker == 'y' %}\nThis can be done in the docker container:\n    ::\n\n        docker run --rm docs make apidocs\n{% endif -%}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docs/index.rst",
    "content": ".. {{ cookiecutter.project_name }} documentation master file, created by\n   sphinx-quickstart.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nWelcome to {{ cookiecutter.project_name }}'s documentation!\n======================================================================\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Contents:\n\n   howto{% if cookiecutter.editor == 'PyCharm' %}\n   pycharm/configuration{% endif %}\n   users\n\n\n\nIndices and tables\n==================\n\n* :ref:`genindex`\n* :ref:`modindex`\n* :ref:`search`\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docs/make.bat",
    "content": "@ECHO OFF\n\npushd %~dp0\n\nREM Command file for Sphinx documentation\n\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-build -c .\n)\nset SOURCEDIR=_source\nset BUILDDIR=_build\nset APP=..\\{{cookiecutter.project_slug}}\n\nif \"%1\" == \"\" goto help\n\n%SPHINXBUILD% >NUL 2>NUL\nif errorlevel 9009 (\n\techo.\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\n\techo.installed, then set the SPHINXBUILD environment variable to point\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\n\techo.may add the Sphinx directory to PATH.\n\techo.\n\techo.Install sphinx-autobuild for live serving.\n\techo.If you don't have Sphinx installed, grab it from\n\techo.http://sphinx-doc.org/\n\texit /b 1\n)\n\n%SPHINXBUILD% -b %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%\ngoto end\n\n:livehtml\nsphinx-autobuild -b html --open-browser -p 9000 --watch %APP% -c . %SOURCEDIR% %BUILDDIR%/html\nGOTO :EOF\n\n:apidocs\nsphinx-apidoc -o %SOURCEDIR%/api %APP%\nGOTO :EOF\n\n:help\n%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%\n\n:end\npopd\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docs/pycharm/configuration.rst",
    "content": "Docker Remote Debugging\n=======================\n\nTo connect to python remote interpreter inside docker, you have to make sure first, that Pycharm is aware of your docker.\n\nGo to *Settings > Build, Execution, Deployment > Docker*. If you are on linux, you can use docker directly using its socket  `unix:///var/run/docker.sock`, if you are on Windows or Mac, make sure that you have docker-machine installed, then you can simply *Import credentials from Docker Machine*.\n\n.. image:: images/1.png\n\nConfigure Remote Python Interpreter\n-----------------------------------\n\nThis repository comes with already prepared \"Run/Debug Configurations\" for docker.\n\n.. image:: images/2.png\n\nBut as you can see, at the beginning there is something wrong with them. They have red X on django icon, and they cannot be used, without configuring remote python interpreter. To do that, you have to go to *Settings > Build, Execution, Deployment* first.\n\n\nNext, you have to add new remote python interpreter, based on already tested deployment settings. Go to *Settings > Project > Project Interpreter*. Click on the cog icon, and click *Add Remote*.\n\n.. image:: images/3.png\n\nSwitch to *Docker Compose* and select `docker-compose.local.yml` file from directory of your project, next set *Service name* to `django`\n\n.. image:: images/4.png\n\nHaving that, click *OK*. Close *Settings* panel, and wait few seconds...\n\n.. image:: images/7.png\n\nAfter few seconds, all *Run/Debug Configurations* should be ready to use.\n\n.. image:: images/8.png\n\n**Things you can do with provided configuration**:\n\n* run and debug python code\n\n.. image:: images/f1.png\n\n* run and debug tests\n\n.. image:: images/f2.png\n.. image:: images/f3.png\n\n* run and debug migrations or different django management commands\n\n.. image:: images/f4.png\n\n* and many others..\n\nKnown issues\n------------\n\n* Pycharm hangs on \"Connecting to Debugger\"\n\n.. image:: images/issue1.png\n\nThis might be fault of your firewall. Take a look on this ticket - https://youtrack.jetbrains.com/issue/PY-18913\n\n* Modified files in `.idea` directory\n\nMost of the files from `.idea/` were added to `.gitignore` with a few exceptions, which were made, to provide \"ready to go\" configuration. After adding remote interpreter some of these files are altered by PyCharm:\n\n.. image:: images/issue2.png\n\nIn theory you can remove them from repository, but then, other people will lose a ability to initialize a project from provided configurations as you did. To get rid of this annoying state, you can run command::\n\n    $ git update-index --assume-unchanged {{cookiecutter.project_slug}}.iml\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/docs/users.rst",
    "content": " .. _users:\n\nUsers\n======================================================================\n\nStarting a new project, it’s highly recommended to set up a custom user model, \neven if the default User model is sufficient for you. \n\nThis model behaves identically to the default user model, \nbut you’ll be able to customize it in the future if the need arises.\n\n.. automodule:: {{cookiecutter.project_slug}}.users.models\n   :members:\n   :noindex:\n\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/gulpfile.mjs",
    "content": "////////////////////////////////\n// Setup\n////////////////////////////////\n\n// Gulp and package\nimport { src, dest, parallel, series, task, watch } from 'gulp';\nimport pjson from './package.json' with {type: 'json'};\n\n// Plugins\nimport autoprefixer from 'autoprefixer';\nimport browserSyncLib from 'browser-sync';\nimport concat from 'gulp-concat';\nimport tildeImporter from 'node-sass-tilde-importer';\nimport cssnano from 'cssnano';\nimport pixrem from 'pixrem';\nimport plumber from 'gulp-plumber';\nimport postcss from 'gulp-postcss';\nimport rename from 'gulp-rename';\nimport gulpSass from 'gulp-sass';\nimport * as dartSass from 'sass';\nimport gulUglifyES from 'gulp-uglify-es';\nimport { spawn } from 'node:child_process';\n\nconst browserSync = browserSyncLib.create();\nconst reload = browserSync.reload;\nconst sass = gulpSass(dartSass);\nconst uglify = gulUglifyES.default;\n\n// Relative paths function\nfunction pathsConfig() {\n  const appName = `./${pjson.name}`;\n  const vendorsRoot = 'node_modules';\n\n  return {\n    vendorsJs: [\n      `${vendorsRoot}/@popperjs/core/dist/umd/popper.js`,\n      `${vendorsRoot}/bootstrap/dist/js/bootstrap.js`,\n    ],\n    app: appName,\n    templates: `${appName}/templates`,\n    css: `${appName}/static/css`,\n    sass: `${appName}/static/sass`,\n    fonts: `${appName}/static/fonts`,\n    images: `${appName}/static/images`,\n    js: `${appName}/static/js`,\n  };\n}\n\nconst paths = pathsConfig();\n\n////////////////////////////////\n// Tasks\n////////////////////////////////\n\n// Styles autoprefixing and minification\nfunction styles() {\n  const processCss = [\n    autoprefixer(), // adds vendor prefixes\n    pixrem(), // add fallbacks for rem units\n  ];\n\n  const minifyCss = [\n    cssnano({ preset: 'default' }), // minify result\n  ];\n\n  return src(`${paths.sass}/project.scss`)\n    .pipe(\n      sass({\n        importer: tildeImporter,\n        includePaths: [paths.sass],\n      }).on('error', sass.logError),\n    )\n    .pipe(plumber()) // Checks for errors\n    .pipe(postcss(processCss))\n    .pipe(dest(paths.css))\n    .pipe(rename({ suffix: '.min' }))\n    .pipe(postcss(minifyCss)) // Minifies the result\n    .pipe(dest(paths.css));\n}\n\n// Javascript minification\nfunction scripts() {\n  return src(`${paths.js}/project.js`)\n    .pipe(plumber()) // Checks for errors\n    .pipe(uglify()) // Minifies the js\n    .pipe(rename({ suffix: '.min' }))\n    .pipe(dest(paths.js));\n}\n\n// Vendor Javascript minification\nfunction vendorScripts() {\n  return src(paths.vendorsJs, { sourcemaps: true })\n    .pipe(concat('vendors.js'))\n    .pipe(dest(paths.js))\n    .pipe(plumber()) // Checks for errors\n    .pipe(uglify()) // Minifies the js\n    .pipe(rename({ suffix: '.min' }))\n    .pipe(dest(paths.js, { sourcemaps: '.' }));\n}\n\n// Image compression\nasync function imgCompression() {\n  const imagemin = (await import(\"gulp-imagemin\")).default;\n  return src(`${paths.images}/*`, { encoding: false })\n    .pipe(imagemin()) // Compresses PNG, JPEG, GIF and SVG images\n    .pipe(dest(paths.images));\n}\n\n{%- if cookiecutter.use_async == 'y' -%}\n// Run django server\nfunction asyncRunServer() {\n  const cmd = spawn(\n    'gunicorn',\n    ['config.asgi', '-k', 'uvicorn_worker.UvicornWorker', '--reload'],\n    {stdio: 'inherit'},\n  );\n  cmd.on('close', function (code) {\n    console.log('gunicorn exited with code ' + code);\n  })\n}\n{%- else %}\n// Run django server\nfunction runServer(cb) {\n  const cmd = spawn('python', ['manage.py', 'runserver'], { stdio: 'inherit' });\n  cmd.on('close', function (code) {\n    console.log('runServer exited with code ' + code);\n    cb(code);\n  });\n}\n{%- endif %}\n\n// Browser sync server for live reload\nfunction initBrowserSync() {\n  browserSync.init(\n    [`${paths.css}/*.css`, `${paths.js}/*.js`, `${paths.templates}/*.html`],\n    {\n      {%- if cookiecutter.use_docker == 'y' %}\n      // https://www.browsersync.io/docs/options/#option-open\n      // Disable as it doesn't work from inside a container\n      open: false,\n      {%- endif %}\n      // https://www.browsersync.io/docs/options/#option-proxy\n      proxy: {\n        {%- if cookiecutter.use_docker == 'n' %}\n        target: '127.0.0.1:8000',\n        {%- else %}\n        target: 'django:8000',\n        {%- endif %}\n        proxyReq: [\n          function (proxyReq, req) {\n            // Assign proxy 'host' header same as current request at Browsersync server\n            proxyReq.setHeader('Host', req.headers.host);\n          },\n        ],\n      },\n    },\n  );\n}\n\n// Watch\nfunction watchPaths() {\n  watch(`${paths.sass}/*.scss`{% if cookiecutter.windows == 'y' %}, { usePolling: true }{% endif %}, styles);\n  watch(`${paths.templates}/**/*.html`{% if cookiecutter.windows == 'y' %}, { usePolling: true }{% endif %}).on('change', reload);\n  watch([`${paths.js}/*.js`, `!${paths.js}/*.min.js`]{% if cookiecutter.windows == 'y' %}, { usePolling: true }{% endif %}, scripts).on(\n    'change',\n    reload,\n  );\n}\n\n// Generate all assets\nconst build = parallel(styles, scripts, vendorScripts, imgCompression);\n\n// Set up dev environment\n{%- if cookiecutter.use_docker == 'n' %}\n{%- if cookiecutter.use_async == 'y' %}\nconst dev = parallel(asyncRunServer, initBrowserSync, watchPaths);\n{%- else %}\nconst dev = parallel(runServer, initBrowserSync, watchPaths);\n{%- endif %}\n{%- else %}\nconst dev = parallel(initBrowserSync, watchPaths);\n{%- endif %}\n\ntask('default', series(build, dev));\ntask('build', build);\ntask('dev', dev);\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/justfile",
    "content": "export COMPOSE_FILE := \"docker-compose.local.yml\"\n\n## Just does not yet manage signals for subprocesses reliably, which can lead to unexpected behavior.\n## Exercise caution before expanding its usage in production environments.\n## For more information, see https://github.com/casey/just/issues/2473 .\n\n\n# Default command to list all available commands.\ndefault:\n    @just --list\n\n# build: Build python image.\nbuild *args:\n    @echo \"Building python image...\"\n    @docker compose build {{ \"{{args}}\" }}\n\n# up: Start up containers.\nup:\n    @echo \"Starting up containers...\"\n    @docker compose up -d --remove-orphans\n\n# down: Stop containers.\ndown:\n    @echo \"Stopping containers...\"\n    @docker compose down\n\n# prune: Remove containers and their volumes.\nprune *args:\n    @echo \"Killing containers and removing volumes...\"\n    @docker compose down -v {{ \"{{args}}\" }}\n\n# logs: View container logs\nlogs *args:\n    @docker compose logs -f {{ \"{{args}}\" }}\n\n# manage: Executes `manage.py` command.\nmanage +args:\n    @docker compose run --rm django python ./manage.py {{ \"{{args}}\" }}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/locale/README.md",
    "content": "# Translations\n\nStart by configuring the `LANGUAGES` settings in `base.py`, by uncommenting languages you are willing to support. Then, translation strings will be placed in this folder when running:\n\n```bash\n{% if cookiecutter.use_docker == 'y' %}docker compose -f docker-compose.local.yml run --rm django {% endif %}python manage.py makemessages --all --no-location\n```\n\nThis should generate `django.po` (stands for Portable Object) files under each locale `<locale name>/LC_MESSAGES/django.po`. Each translatable string in the codebase is collected with its `msgid` and need to be translated as `msgstr`, for example:\n\n```po\nmsgid \"users\"\nmsgstr \"utilisateurs\"\n```\n\nOnce all translations are done, they need to be compiled into `.mo` files (stands for Machine Object), which are the actual binary files used by the application:\n\n```bash\n{% if cookiecutter.use_docker == 'y' %}docker compose -f docker-compose.local.yml run --rm django {% endif %}python manage.py compilemessages\n```\n\nNote that the `.po` files are NOT used by the application directly, so if the `.mo` files are out of date, the content won't appear as translated even if the `.po` files are up-to-date.\n\n## Production\n\nThe production image runs `compilemessages` automatically at build time, so as long as your translated source files (PO) are up-to-date, you're good to go.\n\n## Add a new language\n\n1. Update the [`LANGUAGES` setting](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-LANGUAGES) to your project's base settings.\n2. Create the locale folder for the language next to this file, e.g. `fr_FR` for French. Make sure the case is correct.\n3. Run `makemessages` (as instructed above) to generate the PO files for the new language.\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/locale/en_US/LC_MESSAGES/django.po",
    "content": "# Translations for the {{ cookiecutter.project_name }} project\n# Copyright (C) {% now 'utc', '%Y' %} {{ cookiecutter.author_name }}\n# {{ cookiecutter.author_name }} <{{ cookiecutter.email }}>, {% now 'utc', '%Y' %}.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: {{ cookiecutter.version }}\\n\"\n\"Language: en-US\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/locale/fr_FR/LC_MESSAGES/django.po",
    "content": "# Translations for the {{ cookiecutter.project_name }} project\n# Copyright (C) {% now 'utc', '%Y' %} {{ cookiecutter.author_name }}\n# {{ cookiecutter.author_name }} <{{ cookiecutter.email }}>, {% now 'utc', '%Y' %}.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: {{ cookiecutter.version }}\\n\"\n\"Language: fr-FR\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n#: {{cookiecutter.project_slug}}/templates/account/account_inactive.html:5\n#: {{cookiecutter.project_slug}}/templates/account/account_inactive.html:8\nmsgid \"Account Inactive\"\nmsgstr \"Compte inactif\"\n\n#: {{cookiecutter.project_slug}}/templates/account/account_inactive.html:10\nmsgid \"This account is inactive.\"\nmsgstr \"Ce compte est inactif.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:7\nmsgid \"Account\"\nmsgstr \"Compte\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:10\nmsgid \"E-mail Addresses\"\nmsgstr \"Adresses e-mail\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:13\nmsgid \"The following e-mail addresses are associated with your account:\"\nmsgstr \"Les adresses e-mail suivantes sont associées à votre compte :\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:27\nmsgid \"Verified\"\nmsgstr \"Vérifié\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:29\nmsgid \"Unverified\"\nmsgstr \"Non vérifié\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:31\nmsgid \"Primary\"\nmsgstr \"Primaire\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:37\nmsgid \"Make Primary\"\nmsgstr \"Changer Primaire\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:38\nmsgid \"Re-send Verification\"\nmsgstr \"Renvoyer vérification\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:39\nmsgid \"Remove\"\nmsgstr \"Supprimer\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:46\nmsgid \"Warning:\"\nmsgstr \"Avertissement:\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:46\nmsgid \"\"\n\"You currently do not have any e-mail address set up. You should really add \"\n\"an e-mail address so you can receive notifications, reset your password, etc.\"\nmsgstr \"\"\n\"Vous n'avez actuellement aucune adresse e-mail configurée. Vous devriez ajouter \"\n\"une adresse e-mail pour reçevoir des notifications, réinitialiser votre mot \"\n\"de passe, etc.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:51\nmsgid \"Add E-mail Address\"\nmsgstr \"Ajouter une adresse e-mail\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:56\nmsgid \"Add E-mail\"\nmsgstr \"Ajouter e-mail\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:66\nmsgid \"Do you really want to remove the selected e-mail address?\"\nmsgstr \"Voulez-vous vraiment supprimer l'adresse e-mail sélectionnée ?\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:6\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:10\nmsgid \"Confirm E-mail Address\"\nmsgstr \"Confirmez votre adresse email\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:16\n#, python-format\nmsgid \"\"\n\"Please confirm that <a href=\\\"mailto:%(email)s\\\">%(email)s</a> is an e-mail \"\n\"address for user %(user_display)s.\"\nmsgstr \"\"\n\"Veuillez confirmer que <a href=\\\"mailto:%(email)s\\\">%(email)s</a> est un e-mail \"\n\"adresse de l'utilisateur %(user_display)s.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:20\nmsgid \"Confirm\"\nmsgstr \"Confirm\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:27\n#, python-format\nmsgid \"\"\n\"This e-mail confirmation link expired or is invalid. Please <a href=\"\n\"\\\"%(email_url)s\\\">issue a new e-mail confirmation request</a>.\"\nmsgstr \"\"\n\"Ce lien de confirmation par e-mail a expiré ou n'est pas valide. Veuillez\"\n \"<a href=\\\"%(email_url)s\\\">émettre une nouvelle demande de confirmation \"\n\"par e-mail</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:7\n#: {{cookiecutter.project_slug}}/templates/account/login.html:11\n#: {{cookiecutter.project_slug}}/templates/account/login.html:56\n#: {{cookiecutter.project_slug}}/templates/base.html:72\nmsgid \"Sign In\"\nmsgstr \"S'identifier\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:17\nmsgid \"Please sign in with one of your existing third party accounts:\"\nmsgstr \"Veuillez vous connecter avec l'un de vos comptes tiers existants :\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:19\n#, python-format\nmsgid \"\"\n\"Or, <a href=\\\"%(signup_url)s\\\">sign up</a> for a %(site_name)s account and \"\n\"sign in below:\"\nmsgstr \"\"\n\"Ou, <a href=\\\"%(signup_url)s\\\">créez</a> un compte %(site_name)s et \"\n\"connectez-vous ci-dessous :\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:32\nmsgid \"or\"\nmsgstr \"ou\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:41\n#, python-format\nmsgid \"\"\n\"If you have not created an account yet, then please <a href=\\\"%(signup_url)s\"\n\"\\\">sign up</a> first.\"\nmsgstr \"\"\n\"Si vous n'avez pas encore créé de compte, veuillez d'abord <a href=\\\"%(signup_url)s\"\n\"\\\">vous inscrire</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:55\nmsgid \"Forgot Password?\"\nmsgstr \"Mot de passe oublié?\"\n\n#: {{cookiecutter.project_slug}}/templates/account/logout.html:5\n#: {{cookiecutter.project_slug}}/templates/account/logout.html:8\n#: {{cookiecutter.project_slug}}/templates/account/logout.html:17\n#: {{cookiecutter.project_slug}}/templates/base.html:61\nmsgid \"Sign Out\"\nmsgstr \"Se déconnecter\"\n\n#: {{cookiecutter.project_slug}}/templates/account/logout.html:10\nmsgid \"Are you sure you want to sign out?\"\nmsgstr \"Êtes-vous certain de vouloir vous déconnecter?\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_change.html:6\n#: {{cookiecutter.project_slug}}/templates/account/password_change.html:9\n#: {{cookiecutter.project_slug}}/templates/account/password_change.html:14\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:5\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:8\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html:4\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html:7\nmsgid \"Change Password\"\nmsgstr \"Changer le mot de passe\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:7\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:11\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_done.html:6\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_done.html:9\nmsgid \"Password Reset\"\nmsgstr \"Réinitialisation du mot de passe\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:16\nmsgid \"\"\n\"Forgotten your password? Enter your e-mail address below, and we'll send you \"\n\"an e-mail allowing you to reset it.\"\nmsgstr \"\"\n\"Mot de passe oublié? Entrez votre adresse e-mail ci-dessous, et nous vous \"\n\"enverrons un e-mail vous permettant de le réinitialiser.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:21\nmsgid \"Reset My Password\"\nmsgstr \"Réinitialiser mon mot de passe\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:24\nmsgid \"Please contact us if you have any trouble resetting your password.\"\nmsgstr \"\"\n\"Veuillez nous contacter si vous rencontrez des difficultés pour réinitialiser\"\n\"votre mot de passe.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_done.html:15\nmsgid \"\"\n\"We have sent you an e-mail. Please contact us if you do not receive it \"\n\"within a few minutes.\"\nmsgstr \"\"\n\"Nous vous avons envoyé un e-mail. Veuillez nous contacter si vous ne le \"\n\"recevez pas d'ici quelques minutes.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:8\nmsgid \"Bad Token\"\nmsgstr \"Token Invalide\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:12\n#, python-format\nmsgid \"\"\n\"The password reset link was invalid, possibly because it has already been \"\n\"used.  Please request a <a href=\\\"%(passwd_reset_url)s\\\">new password reset</\"\n\"a>.\"\nmsgstr \"\"\n\"Le lien de réinitialisation du mot de passe n'était pas valide, peut-être parce \"\n\"qu'il a déjà été utilisé. Veuillez faire une <a href=\\\"%(passwd_reset_url)s\\\"> \"\n\"nouvelle demande de réinitialisation de mot de passe</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:18\nmsgid \"change password\"\nmsgstr \"changer le mot de passe\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:21\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html:8\nmsgid \"Your password is now changed.\"\nmsgstr \"Votre mot de passe est maintenant modifié.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_set.html:6\n#: {{cookiecutter.project_slug}}/templates/account/password_set.html:9\n#: {{cookiecutter.project_slug}}/templates/account/password_set.html:14\nmsgid \"Set Password\"\nmsgstr \"Définir le mot de passe\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup.html:6\nmsgid \"Signup\"\nmsgstr \"S'inscrire\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup.html:9\n#: {{cookiecutter.project_slug}}/templates/account/signup.html:19\n#: {{cookiecutter.project_slug}}/templates/base.html:67\nmsgid \"Sign Up\"\nmsgstr \"S'inscrire\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup.html:11\n#, python-format\nmsgid \"\"\n\"Already have an account? Then please <a href=\\\"%(login_url)s\\\">sign in</a>.\"\nmsgstr \"\"\n\"Vous avez déjà un compte? Alors veuillez <a href=\\\"%(login_url)s\\\">vous connecter</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup_closed.html:5\n#: {{cookiecutter.project_slug}}/templates/account/signup_closed.html:8\nmsgid \"Sign Up Closed\"\nmsgstr \"Inscriptions closes\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup_closed.html:10\nmsgid \"We are sorry, but the sign up is currently closed.\"\nmsgstr \"Désolé, mais l'inscription est actuellement fermée.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verification_sent.html:5\n#: {{cookiecutter.project_slug}}/templates/account/verification_sent.html:8\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:5\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:8\nmsgid \"Verify Your E-mail Address\"\nmsgstr \"Vérifiez votre adresse e-mail\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verification_sent.html:10\nmsgid \"\"\n\"We have sent an e-mail to you for verification. Follow the link provided to \"\n\"finalize the signup process. Please contact us if you do not receive it \"\n\"within a few minutes.\"\nmsgstr \"Nous vous avons envoyé un e-mail pour vérification. Suivez le lien fourni \"\n\"pour finalisez le processus d'inscription. Veuillez nous contacter si vous ne le \"\n\"recevez pas d'ici quelques minutes.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:12\nmsgid \"\"\n\"This part of the site requires us to verify that\\n\"\n\"you are who you claim to be. For this purpose, we require that you\\n\"\n\"verify ownership of your e-mail address. \"\nmsgstr \"\"\n\"Cette partie du site nous oblige à vérifier que\\n\"\n\"vous êtes qui vous prétendez être. Nous vous demandons donc de\\n\"\n\"vérifier la propriété de votre adresse e-mail.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:16\nmsgid \"\"\n\"We have sent an e-mail to you for\\n\"\n\"verification. Please click on the link inside this e-mail. Please\\n\"\n\"contact us if you do not receive it within a few minutes.\"\nmsgstr \"\"\n\"Nous vous avons envoyé un e-mail pour\\n\"\n\"vérification. Veuillez cliquer sur le lien contenu dans cet e-mail. Veuillez nous\\n\"\n\"contacter si vous ne le recevez pas d'ici quelques minutes.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:20\n#, python-format\nmsgid \"\"\n\"<strong>Note:</strong> you can still <a href=\\\"%(email_url)s\\\">change your e-\"\n\"mail address</a>.\"\nmsgstr \"\"\n\"<strong>Remarque :</strong> vous pouvez toujours <a href=\\\"%(email_url)s\\\">changer votre e-\"\n\"adresse e-mail</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/base.html:57\nmsgid \"My Profile\"\nmsgstr \"Mon Profil\"\n\n#: {{cookiecutter.project_slug}}/users/admin.py:17\nmsgid \"Personal info\"\nmsgstr \"Personal info\"\n\n#: {{cookiecutter.project_slug}}/users/admin.py:19\nmsgid \"Permissions\"\nmsgstr \"Permissions\"\n\n#: {{cookiecutter.project_slug}}/users/admin.py:30\nmsgid \"Important dates\"\nmsgstr \"Dates importantes\"\n\n#: {{cookiecutter.project_slug}}/users/apps.py:7\nmsgid \"Users\"\nmsgstr \"Utilisateurs\"\n\n#: {{cookiecutter.project_slug}}/users/forms.py:24\n#: {{cookiecutter.project_slug}}/users/tests/test_forms.py:36\nmsgid \"This username has already been taken.\"\nmsgstr \"Ce nom d'utilisateur est déjà pris.\"\n\n#: {{cookiecutter.project_slug}}/users/models.py:15\nmsgid \"Name of User\"\nmsgstr \"Nom de l'utilisateur\"\n\n#: {{cookiecutter.project_slug}}/users/views.py:23\nmsgid \"Information successfully updated\"\nmsgstr \"Informations mises à jour avec succès\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/locale/pt_BR/LC_MESSAGES/django.po",
    "content": "# Translations for the {{ cookiecutter.project_name }} project\n# Copyright (C) {% now 'utc', '%Y' %} {{ cookiecutter.author_name }}\n# {{ cookiecutter.author_name }} <{{ cookiecutter.email }}>, {% now 'utc', '%Y' %}.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: {{ cookiecutter.version }}\\n\"\n\"Language: pt-BR\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n#: {{cookiecutter.project_slug}}/templates/account/account_inactive.html:5\n#: {{cookiecutter.project_slug}}/templates/account/account_inactive.html:8\nmsgid \"Account Inactive\"\nmsgstr \"Conta Inativa\"\n\n#: {{cookiecutter.project_slug}}/templates/account/account_inactive.html:10\nmsgid \"This account is inactive.\"\nmsgstr \"Esta conta está inativa.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:7\nmsgid \"Account\"\nmsgstr \"Conta\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:10\nmsgid \"E-mail Addresses\"\nmsgstr \"Endereços de E-mail\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:13\nmsgid \"The following e-mail addresses are associated with your account:\"\nmsgstr \"Os seguintes endereços de e-mail estão associados à sua conta:\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:27\nmsgid \"Verified\"\nmsgstr \"Verificado\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:29\nmsgid \"Unverified\"\nmsgstr \"Não verificado\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:31\nmsgid \"Primary\"\nmsgstr \"Primário\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:37\nmsgid \"Make Primary\"\nmsgstr \"Tornar Primário\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:38\nmsgid \"Re-send Verification\"\nmsgstr \"Reenviar verificação\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:39\nmsgid \"Remove\"\nmsgstr \"Remover\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:46\nmsgid \"Warning:\"\nmsgstr \"Aviso:\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:46\nmsgid \"\"\n\"You currently do not have any e-mail address set up. You should really add \"\n\"an e-mail address so you can receive notifications, reset your password, etc.\"\nmsgstr \"\"\n\"No momento, você não tem nenhum endereço de e-mail configurado. Você \"\n\"realmente deve adicionar um endereço de e-mail para receber notificações, \"\n\"redefinir sua senha etc.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:51\nmsgid \"Add E-mail Address\"\nmsgstr \"Adicionar Endereço de E-mail\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:56\nmsgid \"Add E-mail\"\nmsgstr \"Adicionar E-mail\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email.html:66\nmsgid \"Do you really want to remove the selected e-mail address?\"\nmsgstr \"Você realmente deseja remover o endereço de e-mail selecionado?\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:6\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:10\nmsgid \"Confirm E-mail Address\"\nmsgstr \"Confirme o endereço de e-mail\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:16\n#, python-format\nmsgid \"\"\n\"Please confirm that <a href=\\\"mailto:%(email)s\\\">%(email)s</a> is an e-mail \"\n\"address for user %(user_display)s.\"\nmsgstr \"\"\n\"Confirme se <a href=\\\"mailto:%(email)s\\\">%(email)s</a> é um endereço de \"\n\"e-mail do usuário %(user_display)s.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:20\nmsgid \"Confirm\"\nmsgstr \"Confirmar\"\n\n#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:27\n#, python-format\nmsgid \"\"\n\"This e-mail confirmation link expired or is invalid. Please <a href=\"\n\"\\\"%(email_url)s\\\">issue a new e-mail confirmation request</a>.\"\nmsgstr \"Este link de confirmação de e-mail expirou ou é inválido. \"\n\"Por favor, <a href=\\\"%(email_url)s\\\">emita um novo pedido de confirmação por e-mail</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:7\n#: {{cookiecutter.project_slug}}/templates/account/login.html:11\n#: {{cookiecutter.project_slug}}/templates/account/login.html:56\n#: {{cookiecutter.project_slug}}/templates/base.html:72\nmsgid \"Sign In\"\nmsgstr \"Entrar\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:17\nmsgid \"Please sign in with one of your existing third party accounts:\"\nmsgstr \"Faça login com uma de suas contas de terceiros existentes:\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:19\n#, python-format\nmsgid \"\"\n\"Or, <a href=\\\"%(signup_url)s\\\">sign up</a> for a %(site_name)s account and \"\n\"sign in below:\"\nmsgstr \"Ou, <a href=\\\"%(signup_url)s\\\">cadastre-se</a> para uma conta em %(site_name)s e entre abaixo:\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:32\nmsgid \"or\"\nmsgstr \"ou\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:41\n#, python-format\nmsgid \"\"\n\"If you have not created an account yet, then please <a href=\\\"%(signup_url)s\"\n\"\\\">sign up</a> first.\"\nmsgstr \"Se você ainda não criou uma conta, <a href=\\\"%(signup_url)s\"\n\"\\\">registre-se primeiro</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/login.html:55\nmsgid \"Forgot Password?\"\nmsgstr \"Esqueceu sua senha?\"\n\n#: {{cookiecutter.project_slug}}/templates/account/logout.html:5\n#: {{cookiecutter.project_slug}}/templates/account/logout.html:8\n#: {{cookiecutter.project_slug}}/templates/account/logout.html:17\n#: {{cookiecutter.project_slug}}/templates/base.html:61\nmsgid \"Sign Out\"\nmsgstr \"Sair\"\n\n#: {{cookiecutter.project_slug}}/templates/account/logout.html:10\nmsgid \"Are you sure you want to sign out?\"\nmsgstr \"Você tem certeza que deseja sair?\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_change.html:6\n#: {{cookiecutter.project_slug}}/templates/account/password_change.html:9\n#: {{cookiecutter.project_slug}}/templates/account/password_change.html:14\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:5\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:8\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html:4\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html:7\nmsgid \"Change Password\"\nmsgstr \"Alterar Senha\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:7\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:11\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_done.html:6\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_done.html:9\nmsgid \"Password Reset\"\nmsgstr \"Redefinição de senha\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:16\nmsgid \"\"\n\"Forgotten your password? Enter your e-mail address below, and we'll send you \"\n\"an e-mail allowing you to reset it.\"\nmsgstr \"Esqueceu sua senha? Digite seu endereço de e-mail abaixo e enviaremos um e-mail permitindo que você o redefina.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:21\nmsgid \"Reset My Password\"\nmsgstr \"Redefinir minha senha\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:24\nmsgid \"Please contact us if you have any trouble resetting your password.\"\nmsgstr \"Entre em contato conosco se tiver algum problema para redefinir sua senha.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_done.html:15\nmsgid \"\"\n\"We have sent you an e-mail. Please contact us if you do not receive it \"\n\"within a few minutes.\"\nmsgstr \"Enviamos um e-mail para você. Entre em contato conosco se você não recebê-lo dentro de alguns minutos.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:8\nmsgid \"Bad Token\"\nmsgstr \"Token Inválido\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:12\n#, python-format\nmsgid \"\"\n\"The password reset link was invalid, possibly because it has already been \"\n\"used.  Please request a <a href=\\\"%(passwd_reset_url)s\\\">new password reset</\"\n\"a>.\"\nmsgstr \"O link de redefinição de senha era inválido, possivelmente porque já foi usado. \"\n\"<a href=\\\"%(passwd_reset_url)s\\\">Solicite uma nova redefinição de senha</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:18\nmsgid \"change password\"\nmsgstr \"alterar senha\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:21\n#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html:8\nmsgid \"Your password is now changed.\"\nmsgstr \"Sua senha agora foi alterada.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/password_set.html:6\n#: {{cookiecutter.project_slug}}/templates/account/password_set.html:9\n#: {{cookiecutter.project_slug}}/templates/account/password_set.html:14\nmsgid \"Set Password\"\nmsgstr \"Definir Senha\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup.html:6\nmsgid \"Signup\"\nmsgstr \"Cadastro\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup.html:9\n#: {{cookiecutter.project_slug}}/templates/account/signup.html:19\n#: {{cookiecutter.project_slug}}/templates/base.html:67\nmsgid \"Sign Up\"\nmsgstr \"Cadastro\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup.html:11\n#, python-format\nmsgid \"\"\n\"Already have an account? Then please <a href=\\\"%(login_url)s\\\">sign in</a>.\"\nmsgstr \"já tem uma conta? Então, por favor, faça <a href=\\\"%(login_url)s\\\">login</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup_closed.html:5\n#: {{cookiecutter.project_slug}}/templates/account/signup_closed.html:8\nmsgid \"Sign Up Closed\"\nmsgstr \"Inscrições encerradas\"\n\n#: {{cookiecutter.project_slug}}/templates/account/signup_closed.html:10\nmsgid \"We are sorry, but the sign up is currently closed.\"\nmsgstr \"Lamentamos, mas as inscrições estão encerradas no momento.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verification_sent.html:5\n#: {{cookiecutter.project_slug}}/templates/account/verification_sent.html:8\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:5\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:8\nmsgid \"Verify Your E-mail Address\"\nmsgstr \"Verifique seu endereço de e-mail\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verification_sent.html:10\nmsgid \"\"\n\"We have sent an e-mail to you for verification. Follow the link provided to \"\n\"finalize the signup process. Please contact us if you do not receive it \"\n\"within a few minutes.\"\nmsgstr \"Enviamos um e-mail para você para verificação. Siga o link fornecido para finalizar o processo de inscrição. Entre em contato conosco se você não recebê-lo dentro de alguns minutos.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:12\nmsgid \"\"\n\"This part of the site requires us to verify that\\n\"\n\"you are who you claim to be. For this purpose, we require that you\\n\"\n\"verify ownership of your e-mail address. \"\nmsgstr \"Esta parte do site exige que verifiquemos se você é quem afirma ser.\\n\"\n\"Para esse fim, exigimos que você verifique a propriedade\\n\"\n\"do seu endereço de e-mail.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:16\nmsgid \"\"\n\"We have sent an e-mail to you for\\n\"\n\"verification. Please click on the link inside this e-mail. Please\\n\"\n\"contact us if you do not receive it within a few minutes.\"\nmsgstr \"Enviamos um e-mail para você para verificação.\\n\"\n\"Por favor, clique no link dentro deste e-mail.\\n\"\n\"Entre em contato conosco se você não recebê-lo dentro de alguns minutos.\"\n\n#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:20\n#, python-format\nmsgid \"\"\n\"<strong>Note:</strong> you can still <a href=\\\"%(email_url)s\\\">change your e-\"\n\"mail address</a>.\"\nmsgstr \"<strong>Nota</strong>: você ainda pode <a href=\\\"%(email_url)s\\\">alterar seu endereço de e-mail</a>.\"\n\n#: {{cookiecutter.project_slug}}/templates/base.html:57\nmsgid \"My Profile\"\nmsgstr \"Meu perfil\"\n\n#: {{cookiecutter.project_slug}}/users/admin.py:17\nmsgid \"Personal info\"\nmsgstr \"Informação pessoal\"\n\n#: {{cookiecutter.project_slug}}/users/admin.py:19\nmsgid \"Permissions\"\nmsgstr \"Permissões\"\n\n#: {{cookiecutter.project_slug}}/users/admin.py:30\nmsgid \"Important dates\"\nmsgstr \"Datas importantes\"\n\n#: {{cookiecutter.project_slug}}/users/apps.py:7\nmsgid \"Users\"\nmsgstr \"Usuários\"\n\n#: {{cookiecutter.project_slug}}/users/forms.py:24\n#: {{cookiecutter.project_slug}}/users/tests/test_forms.py:36\nmsgid \"This username has already been taken.\"\nmsgstr \"Este nome de usuário já foi usado.\"\n\n#: {{cookiecutter.project_slug}}/users/models.py:15\nmsgid \"Name of User\"\nmsgstr \"Nome do Usuário\"\n\n#: {{cookiecutter.project_slug}}/users/views.py:23\nmsgid \"Information successfully updated\"\nmsgstr \"Informação atualizada com sucesso\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/manage.py",
    "content": "#!/usr/bin/env python\n\"\"\"Django's command-line utility for administrative tasks.\"\"\"\n\nimport os\nimport sys\nfrom pathlib import Path\n\n\ndef main():\n    \"\"\"Run administrative tasks.\"\"\"\n    os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"config.settings.local\")\n\n    try:\n        from django.core.management import execute_from_command_line  # noqa: PLC0415\n    except ImportError as exc:\n        raise ImportError(  # noqa: TRY003\n            \"Couldn't import Django. Are you sure it's installed and \"  # noqa: EM101\n            \"available on your PYTHONPATH environment variable? Did you \"\n            \"forget to activate a virtual environment?\",\n        ) from exc\n\n    # This allows easy placement of apps within the interior\n    # {{ cookiecutter.project_slug }} directory.\n    current_path = Path(__file__).parent.resolve()\n    sys.path.append(str(current_path / \"{{ cookiecutter.project_slug }}\"))\n\n    execute_from_command_line(sys.argv)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/merge_production_dotenvs_in_dotenv.py",
    "content": "from collections.abc import Sequence\nfrom pathlib import Path\n\nBASE_DIR = Path(__file__).parent.resolve()\nPRODUCTION_DOTENVS_DIR = BASE_DIR / \".envs\" / \".production\"\nPRODUCTION_DOTENV_FILES = [\n    PRODUCTION_DOTENVS_DIR / \".django\",\n    PRODUCTION_DOTENVS_DIR / \".postgres\",\n]\nDOTENV_FILE = BASE_DIR / \".env\"\n\n\ndef merge(\n    output_file: Path,\n    files_to_merge: Sequence[Path],\n) -> None:\n    merged_content = \"\"\n    for merge_file in files_to_merge:\n        merged_content += merge_file.read_text()\n        merged_content += \"\\n\"\n    output_file.write_text(merged_content)\n\n\nif __name__ == \"__main__\":\n    merge(DOTENV_FILE, PRODUCTION_DOTENV_FILES)\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/package.json",
    "content": "{\n  \"name\": \"{{cookiecutter.project_slug}}\",\n  \"version\": \"{{ cookiecutter.version }}\",\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.16.5\",\n    \"@babel/preset-env\": \"^7.16.5\",\n    \"@popperjs/core\": \"^2.10.2\",\n    \"autoprefixer\": \"^10.4.0\",\n    \"babel-loader\": \"^10.0.0\",\n    \"bootstrap\": \"^5.2.3\",\n    \"browser-sync\": \"^3.0.2\",\n    \"css-loader\": \"^7.1.2\",\n    \"gulp-concat\": \"^2.6.1\",\n    \"concurrently\": \"^9.0.0\",\n    \"cssnano\": \"^7.0.0\",\n    \"gulp\": \"^5.0.0\",\n    \"gulp-imagemin\": \"^9.1.0\",\n    \"gulp-plumber\": \"^1.2.1\",\n    \"gulp-postcss\": \"^10.0.0\",\n    \"gulp-rename\": \"^2.0.0\",\n    \"gulp-sass\": \"^5.0.0\",\n    \"gulp-uglify-es\": \"^3.0.0\",\n    \"mini-css-extract-plugin\": \"^2.4.5\",\n    \"node-sass-tilde-importer\": \"^1.0.2\",\n    \"pixrem\": \"^5.0.0\",\n    \"postcss\": \"^8.3.11\",\n    \"postcss-loader\": \"^8.0.0\",\n    \"postcss-preset-env\": \"^10.0.3\",\n    \"sass\": \"^1.93.1\",\n    \"sass-loader\": \"^16.0.1\",\n    \"webpack\": \"^5.82.0\",\n    \"webpack-bundle-tracker\": \"^3.0.1\",\n    \"webpack-cli\": \"^6.0.1\",\n    \"webpack-dev-server\": \"^5.0.2\",\n    \"webpack-merge\": \"^6.0.1\"\n  },\n  \"engines\": {\n    \"node\": \"24.14\"\n  },\n  \"browserslist\": [\n    \"last 2 versions\"\n  ],\n  \"babel\": {\n    \"presets\": [\"@babel/preset-env\"]\n  },\n  \"scripts\": {\n    \"dev\": \"\",\n    \"build\": \"\"\n  }\n}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/pyproject.toml",
    "content": "[project]\nname = \"{{ cookiecutter.project_slug }}\"\nversion = \"{{ cookiecutter.version }}\"\ndescription = \"{{ cookiecutter.description }}\"\nreadme = \"README.md\"\nlicense = { text = \"{{ cookiecutter.open_source_license }}\" }\nauthors = [\n  { name = \"{{ cookiecutter.author_name }}\", email = \"{{ cookiecutter.email }}\" },\n]\nrequires-python = \"==3.13.*\"\nclassifiers = [\n  \"Programming Language :: Python :: 3 :: Only\",\n  \"Programming Language :: Python :: 3.13\",\n]\ndependencies = [\n  {# set the an initial indentation for uv to follow #}\n  \"django\",\n]\n\n[dependency-groups]\ndev = [\n  {# set the an initial indentation for uv to follow #}\n  \"pytest\",\n]\n\n[tool.ruff]\n# Exclude a variety of commonly ignored directories.\nextend-exclude = [\n  \"*/migrations/*.py\",\n  \"staticfiles/*\",\n]\n\nlint.select = [\n  \"A\",\n  \"ASYNC\",\n  \"B\",\n  \"BLE\",\n  \"C4\",\n  \"C90\",\n  \"COM\",\n  \"DJ\",\n  \"DTZ\",\n  \"E\",\n  \"EM\",\n  \"ERA\",\n  \"EXE\",\n  \"F\",\n  \"FA\",\n  \"FBT\",\n  \"FLY\",\n  \"G\",\n  \"I\",\n  \"ICN\",\n  \"INP\",\n  \"INT\",\n  \"ISC\",\n  \"N\",\n  \"PD\",\n  \"PERF\",\n  \"PGH\",\n  \"PIE\",\n  \"PL\",\n  \"PT\",\n  \"PTH\",\n  \"PYI\",\n  \"Q\",\n  \"RET\",\n  \"RSE\",\n  \"RUF\",\n  \"S\",\n  \"SIM\",\n  \"SLF\",\n  \"SLOT\",\n  \"T10\",\n  \"T20\",\n  \"TC\",\n  \"TID\",\n  \"TRY\",\n  \"UP\",\n  \"W\",\n  \"YTT\",\n]\nlint.ignore = [\n  \"RUF012\", # Mutable class attributes should be annotated with `typing.ClassVar`\n  \"S101\",   # Use of assert detected https://docs.astral.sh/ruff/rules/assert/\n  \"SIM102\", # sometimes it's better to nest\n  # of types for comparison.\n  # Deactivated because it can make the code slow:\n  # https://github.com/astral-sh/ruff/issues/7871\n]\nlint.isort.force-single-line = true\n\n[tool.pyproject-fmt]\nkeep_full_version = true\n\n# ==== pytest ====\n\n[tool.pytest.ini_options]\nminversion = \"6.0\"\naddopts = \"--ds=config.settings.test --reuse-db --import-mode=importlib\"\npython_files = [\n  \"tests.py\",\n  \"test_*.py\",\n]\n{%- if cookiecutter.frontend_pipeline == 'Gulp' %}\nnorecursedirs = [ \"node_modules\" ]\n{%- endif %}\n\n# ==== Coverage ====\n\n[tool.coverage.run]\ninclude = [ \"{{cookiecutter.project_slug}}/**\" ]\nomit = [ \"*/migrations/*\", \"*/tests/*\" ]\nplugins = [ \"django_coverage_plugin\" ]\n\n# ==== mypy ====\n\n[tool.mypy]\npython_version = \"3.13\"\ncheck_untyped_defs = true\nignore_missing_imports = true\nwarn_unused_ignores = true\nwarn_redundant_casts = true\nwarn_unused_configs = true\nplugins = [\n  \"mypy_django_plugin.main\",\n  {%- if cookiecutter.rest_api == 'DRF' %}\n  \"mypy_drf_plugin.main\",\n  {%- endif %}\n]\n\n[[tool.mypy.overrides]]\n# Django migrations should not produce any errors:\nmodule = \"*.migrations.*\"\nignore_errors = true\n\n[tool.django-stubs]\ndjango_settings_module = \"config.settings.test\"\n\n# ==== djLint ====\n\n[tool.djlint]\nblank_line_after_tag = \"load,extends\"\nclose_void_tags = true\nformat_css = true\nformat_js = true\n# TODO: remove T002 when fixed https://github.com/djlint/djLint/issues/687\nignore = \"H006,H030,H031,T002\"\ninclude = \"H017,H035\"\nindent = 2\nmax_line_length = 119\nprofile = \"django\"\n\n[tool.djlint.css]\nindent_size = 2\n\n[tool.djlint.js]\nindent_size = 2\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/requirements/base.txt",
    "content": "python-slugify==8.0.4  # https://github.com/un33k/python-slugify\nPillow==12.1.1  # https://github.com/python-pillow/Pillow\n{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}\n{%- if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %}\nrcssmin==1.2.2 --install-option=\"--without-c-extensions\"  # https://github.com/ndparker/rcssmin\n{%- else %}\nrcssmin==1.2.2  # https://github.com/ndparker/rcssmin\n{%- endif %}\n{%- endif %}\nargon2-cffi==25.1.0  # https://github.com/hynek/argon2_cffi\n{%- if cookiecutter.use_whitenoise == 'y' %}\nwhitenoise==6.12.0  # https://github.com/evansd/whitenoise\n{%- endif %}\nredis==7.3.0  # https://github.com/redis/redis-py\n{%- if cookiecutter.use_docker == \"y\" or cookiecutter.windows == \"n\" %}\nhiredis==3.3.1  # https://github.com/redis/hiredis-py\n{%- endif %}\n{%- if cookiecutter.use_celery == \"y\" %}\ncelery==5.6.2  # pyup: < 6.0  # https://github.com/celery/celery\ndjango-celery-beat==2.9.0  # https://github.com/celery/django-celery-beat\n{%- if cookiecutter.use_docker == 'y' %}\nflower==2.0.1  # https://github.com/mher/flower\n{%- endif %}\n{%- endif %}\n{%- if cookiecutter.use_async == 'y' %}\nuvicorn[standard]==0.42.0  # https://github.com/Kludex/uvicorn\nuvicorn-worker==0.4.0  # https://github.com/Kludex/uvicorn-worker\n{%- endif %}\n\n# Django\n# ------------------------------------------------------------------------------\ndjango==6.0.3  # pyup: < 6.1 # https://www.djangoproject.com/\ndjango-environ==0.13.0  # https://github.com/joke2k/django-environ\ndjango-model-utils==5.0.0  # https://github.com/jazzband/django-model-utils\ndjango-allauth[mfa]==65.15.0  # https://github.com/pennersr/django-allauth\ndjango-crispy-forms==2.6  # https://github.com/django-crispy-forms/django-crispy-forms\ncrispy-bootstrap5==2026.3  # https://github.com/django-crispy-forms/crispy-bootstrap5\n{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}\ndjango-compressor==4.6.0  # https://github.com/django-compressor/django-compressor\n{%- endif %}\ndjango-redis==6.0.0  # https://github.com/jazzband/django-redis\n{%- if cookiecutter.rest_api == 'DRF' %}\n# Django REST Framework\ndjangorestframework==3.17.0  # https://github.com/encode/django-rest-framework\ndjango-cors-headers==4.9.0  # https://github.com/adamchainz/django-cors-headers\n# DRF-spectacular for api documentation\ndrf-spectacular==0.29.0  # https://github.com/tfranzel/drf-spectacular\n{%- elif cookiecutter.rest_api == 'Django Ninja' %}\n# Django Ninja\ndjango-ninja==1.6.2  # https://github.com/vitalik/django-ninja\ndjango-cors-headers==4.9.0  # https://github.com/adamchainz/django-cors-headers\n{%- endif %}\n{%- if cookiecutter.frontend_pipeline == 'Webpack' %}\ndjango-webpack-loader==3.2.3  # https://github.com/django-webpack/django-webpack-loader\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/requirements/local.txt",
    "content": "Werkzeug[watchdog]==3.1.6 # https://github.com/pallets/werkzeug\nipdb==0.13.13  # https://github.com/gotcha/ipdb\n{%- if cookiecutter.use_docker == 'y' %}\npsycopg[c]==3.3.3  # https://github.com/psycopg/psycopg\n{%- else %}\npsycopg[binary]==3.3.3  # https://github.com/psycopg/psycopg\n{%- endif %}\n{%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %}\nwatchfiles==1.1.1  # https://github.com/samuelcolvin/watchfiles\n{%- endif %}\n\n# Testing\n# ------------------------------------------------------------------------------\nmypy==1.19.1  # https://github.com/python/mypy\ndjango-stubs[compatible-mypy]==6.0.1  # https://github.com/typeddjango/django-stubs\npytest==9.0.2  # https://github.com/pytest-dev/pytest\npytest-sugar==1.1.1  # https://github.com/Teemu/pytest-sugar\n{%- if cookiecutter.rest_api == 'DRF' %}\ndjangorestframework-stubs==3.16.8  # https://github.com/typeddjango/djangorestframework-stubs\n{%- endif %}\n\n# Documentation\n# ------------------------------------------------------------------------------\nsphinx==9.1.0  # https://github.com/sphinx-doc/sphinx\nsphinx-autobuild==2025.8.25 # https://github.com/GaretJax/sphinx-autobuild\n\n# Code quality\n# ------------------------------------------------------------------------------\nruff==0.15.7  # https://github.com/astral-sh/ruff\ncoverage==7.13.5  # https://github.com/nedbat/coveragepy\ndjlint==1.36.4  # https://github.com/Riverside-Healthcare/djLint\npre-commit==4.5.1  # https://github.com/pre-commit/pre-commit\n\n# Django\n# ------------------------------------------------------------------------------\nfactory-boy==3.3.3  # https://github.com/FactoryBoy/factory_boy\n\ndjango-debug-toolbar==6.2.0  # https://github.com/jazzband/django-debug-toolbar\ndjango-extensions==4.1  # https://github.com/django-extensions/django-extensions\ndjango-coverage-plugin==3.2.0  # https://github.com/nedbat/django_coverage_plugin\npytest-django==4.12.0  # https://github.com/pytest-dev/pytest-django\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/requirements/production.txt",
    "content": "# PRECAUTION: avoid production dependencies that aren't in development\n\n-r base.txt\n\ngunicorn==25.1.0  # https://github.com/benoitc/gunicorn\npsycopg[c]==3.3.3  # https://github.com/psycopg/psycopg\n{%- if cookiecutter.use_whitenoise == 'n'and cookiecutter.cloud_provider in ('AWS', 'GCP', 'Azure') %}\nCollectfasta==3.3.3  # https://github.com/jasongi/collectfasta\n{%- endif %}\n{%- if cookiecutter.use_sentry == \"y\" %}\nsentry-sdk==2.55.0  # https://github.com/getsentry/sentry-python\n{%- endif %}\n{%- if cookiecutter.use_docker == \"n\" and cookiecutter.windows == \"y\" %}\nhiredis==3.3.1  # https://github.com/redis/hiredis-py\n{%- endif %}\n\n# Django\n# ------------------------------------------------------------------------------\n{%- if cookiecutter.cloud_provider == 'AWS' %}\ndjango-storages[s3]==1.14.6  # https://github.com/jschneier/django-storages\n{%- elif cookiecutter.cloud_provider == 'GCP' %}\ndjango-storages[google]==1.14.6  # https://github.com/jschneier/django-storages\n{%- elif cookiecutter.cloud_provider == 'Azure' %}\ndjango-storages[azure]==1.14.6  # https://github.com/jschneier/django-storages\n{%- endif %}\n{%- if cookiecutter.mail_service == 'Mailgun' %}\ndjango-anymail[mailgun]==14.0  # https://github.com/anymail/django-anymail\n{%- elif cookiecutter.mail_service == 'Amazon SES' %}\ndjango-anymail[amazon-ses]==14.0  # https://github.com/anymail/django-anymail\n{%- elif cookiecutter.mail_service == 'Mailjet' %}\ndjango-anymail[mailjet]==14.0  # https://github.com/anymail/django-anymail\n{%- elif cookiecutter.mail_service == 'Mandrill' %}\ndjango-anymail[mandrill]==14.0  # https://github.com/anymail/django-anymail\n{%- elif cookiecutter.mail_service == 'Postmark' %}\ndjango-anymail[postmark]==14.0  # https://github.com/anymail/django-anymail\n{%- elif cookiecutter.mail_service == 'Sendgrid' %}\ndjango-anymail[sendgrid]==14.0  # https://github.com/anymail/django-anymail\n{%- elif cookiecutter.mail_service == 'Brevo' %}\ndjango-anymail[brevo]==14.0  # https://github.com/anymail/django-anymail\n{%- elif cookiecutter.mail_service == 'SparkPost' %}\ndjango-anymail[sparkpost]==14.0  # https://github.com/anymail/django-anymail\n{%- elif cookiecutter.mail_service == 'Other SMTP' %}\ndjango-anymail==14.0  # https://github.com/anymail/django-anymail\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/tests/__init__.py",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/tests/test_merge_production_dotenvs_in_dotenv.py",
    "content": "from pathlib import Path\n\nimport pytest\n\nfrom merge_production_dotenvs_in_dotenv import merge\n\n\n@pytest.mark.parametrize(\n    (\"input_contents\", \"expected_output\"),\n    [\n        ([], \"\"),\n        ([\"\"], \"\\n\"),\n        ([\"JANE=doe\"], \"JANE=doe\\n\"),\n        ([\"SEP=true\", \"AR=ator\"], \"SEP=true\\nAR=ator\\n\"),\n        ([\"A=0\", \"B=1\", \"C=2\"], \"A=0\\nB=1\\nC=2\\n\"),\n        ([\"X=x\\n\", \"Y=y\", \"Z=z\\n\"], \"X=x\\n\\nY=y\\nZ=z\\n\\n\"),\n    ],\n)\ndef test_merge(\n    tmp_path: Path,\n    input_contents: list[str],\n    expected_output: str,\n):\n    output_file = tmp_path / \".env\"\n\n    files_to_merge = []\n    for num, input_content in enumerate(input_contents, start=1):\n        merge_file = tmp_path / f\".service{num}\"\n        merge_file.write_text(input_content)\n        files_to_merge.append(merge_file)\n\n    merge(output_file, files_to_merge)\n\n    assert output_file.read_text() == expected_output\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/install_os_dependencies.sh",
    "content": "#!/bin/bash\n\nWORK_DIR=\"$(dirname \"$0\")\"\nDISTRO_NAME=$(lsb_release -sc)\nOS_REQUIREMENTS_FILENAME=\"requirements-$DISTRO_NAME.apt\"\n\ncd $WORK_DIR\n\n# Check if a requirements file exist for the current distribution.\nif [ ! -r \"$OS_REQUIREMENTS_FILENAME\" ]; then\n    cat <<-EOF >&2\n\t\tThere is no requirements file for your distribution.\n\t\tYou can see one of the files listed below to help search the equivalent package in your system:\n\t\t$(find ./ -name \"requirements-*.apt\" -printf \"  - %f\\n\")\n\tEOF\n    exit 1;\nfi\n\n# Handle call with wrong command\nfunction wrong_command()\n{\n    echo \"${0##*/} - unknown command: '${1}'\" >&2\n    usage_message\n}\n\n# Print help / script usage\nfunction usage_message()\n{\n    cat <<-EOF\n\t\tUsage: $WORK_DIR/${0##*/} <command>\n\t\tAvailable commands are:\n\t\t    list        Print a list of all packages defined on ${OS_REQUIREMENTS_FILENAME} file\n\t\t    help        Print this help\n\n\t\tCommands that require superuser permission:\n\t\t    install     Install packages defined on ${OS_REQUIREMENTS_FILENAME} file. Note: This\n\t\t                does not upgrade the packages already installed for new versions, even if\n\t\t                new version is available in the repository.\n\t\t    upgrade     Same that install, but upgrade the already installed packages, if new\n\t\t                version is available.\n\tEOF\n}\n\n# Read the requirements.apt file, and remove comments and blank lines\nfunction list_packages(){\n    grep -v \"#\" \"${OS_REQUIREMENTS_FILENAME}\" | grep -v \"^$\";\n}\n\nfunction install_packages()\n{\n    list_packages | xargs apt-get --no-upgrade install -y;\n}\n\nfunction upgrade_packages()\n{\n    list_packages | xargs apt-get install -y;\n}\n\nfunction install_or_upgrade()\n{\n    P=${1}\n    PARAN=${P:-\"install\"}\n\n    if [[ $EUID -ne 0 ]]; then\n        cat <<-EOF >&2\n\t\t\tYou must run this script with root privilege\n\t\t\tPlease do:\n\t\t\tsudo $WORK_DIR/${0##*/} $PARAN\n\t\tEOF\n        exit 1\n    else\n\n        apt-get update\n\n        # Install the basic compilation dependencies and other required libraries of this project\n        if [ \"$PARAN\" == \"install\" ]; then\n            install_packages;\n        else\n            upgrade_packages;\n        fi\n\n        # cleaning downloaded packages from apt-get cache\n        apt-get clean\n\n        exit 0\n    fi\n}\n\n# Handle command argument\ncase \"$1\" in\n    install) install_or_upgrade;;\n    upgrade) install_or_upgrade \"upgrade\";;\n    list) list_packages;;\n    help|\"\") usage_message;;\n    *) wrong_command \"$1\";;\nesac\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/install_python_dependencies.sh",
    "content": "#!/bin/bash\n\nWORK_DIR=\"$(dirname \"$0\")\"\nPROJECT_DIR=\"$(dirname \"$WORK_DIR\")\"\n\nuv --version >/dev/null 2>&1 || {\n    echo >&2 -e \"\\nuv is required but it's not installed.\"\n    echo >&2 -e \"You can install it by following the instructions at https://github.com/astral-sh/uv#installation\"\n    exit 1;\n}\n\nuv sync --locked\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-bionic.apt",
    "content": "##basic build dependencies of various Django apps for Ubuntu Bionic 18.04\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg8-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\nlibgraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-bookworm.apt",
    "content": "##basic build dependencies of various Django apps for Debian Bookworm 12.x\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg62-turbo-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\nlibgraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-bullseye.apt",
    "content": "##basic build dependencies of various Django apps for Debian Bullseye 11.x\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg62-turbo-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\nlibgraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-buster.apt",
    "content": "##basic build dependencies of various Django apps for Debian Jessie 10.x\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg62-turbo-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\nlibgraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-focal.apt",
    "content": "##basic build dependencies of various Django apps for Ubuntu Focal 20.04\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg8-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\ngraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-jammy.apt",
    "content": "##basic build dependencies of various Django apps for Ubuntu Jammy 22.04\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg8-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\ngraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-jessie.apt",
    "content": "##basic build dependencies of various Django apps for Debian Jessie 8.x\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg62-turbo-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\ngraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-noble.apt",
    "content": "##basic build dependencies of various Django apps for Debian Bookworm 12.x\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg62-turbo-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\nlibgraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-stretch.apt",
    "content": "##basic build dependencies of various Django apps for Debian Jessie 9.x\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg62-turbo-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\ngraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-trusty.apt",
    "content": "##basic build dependencies of various Django apps for Ubuntu Trusty 14.04\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff4-dev\nlibjpeg8-dev\nlibfreetype6-dev\nliblcms1-dev\nlibwebp-dev\n\n##django-extensions\ngraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/utility/requirements-xenial.apt",
    "content": "##basic build dependencies of various Django apps for Ubuntu Xenial 16.04\n#build-essential metapackage install: make, gcc, g++,\nbuild-essential\n#required to translate\ngettext\npython3-dev\n\n##shared dependencies of:\n##Pillow, pylibmc\nzlib1g-dev\n\n##Postgresql and psycopg dependencies\nlibpq-dev\n\n##Pillow dependencies\nlibtiff5-dev\nlibjpeg8-dev\nlibfreetype6-dev\nliblcms2-dev\nlibwebp-dev\n\n##django-extensions\ngraphviz-dev\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/webpack/common.config.js",
    "content": "const path = require('path');\nconst BundleTracker = require('webpack-bundle-tracker');\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\n\nmodule.exports = {\n  target: 'web',\n  context: path.join(__dirname, '../'),\n  entry: {\n    project: path.resolve(__dirname, '../{{cookiecutter.project_slug}}/static/js/project'),\n    vendors: path.resolve(__dirname, '../{{cookiecutter.project_slug}}/static/js/vendors'),\n  },\n  output: {\n    path: path.resolve(\n      __dirname,\n      '../{{cookiecutter.project_slug}}/static/webpack_bundles/',\n    ),\n    publicPath: '/static/webpack_bundles/',\n    filename: 'js/[name]-[fullhash].js',\n    chunkFilename: 'js/[name]-[hash].js',\n  },\n  plugins: [\n    new BundleTracker({\n      path: path.resolve(path.join(__dirname, '../')),\n      filename: 'webpack-stats.json',\n    }),\n    new MiniCssExtractPlugin({ filename: 'css/[name].[contenthash].css' }),\n  ],\n  module: {\n    rules: [\n      // we pass the output from babel loader to react-hot loader\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n      },\n      {\n        test: /\\.s?css$/i,\n        use: [\n          MiniCssExtractPlugin.loader,\n          'css-loader',\n          {\n            loader: 'postcss-loader',\n            options: {\n              postcssOptions: {\n                plugins: ['postcss-preset-env', 'autoprefixer', 'pixrem'],\n              },\n            },\n          },\n          'sass-loader',\n        ],\n      },\n    ],\n  },\n  resolve: {\n    modules: ['node_modules'],\n    extensions: ['.js', '.jsx'],\n  },\n};\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/webpack/dev.config.js",
    "content": "const { merge } = require('webpack-merge');\nconst commonConfig = require('./common.config');\n\nmodule.exports = merge(commonConfig, {\n  mode: 'development',\n  devtool: 'inline-source-map',\n  devServer: {\n    port: 3000,\n    proxy: [\n      {\n        context: ['/'],\n        {%- if cookiecutter.use_docker == 'n' %}\n        target: 'http://0.0.0.0:8000',\n        {%- else %}\n        target: 'http://django:8000',\n        {%- endif %}\n      },\n    ],\n    client: {\n      overlay: {\n        errors: true,\n        warnings: false,\n        runtimeErrors: true,\n      },\n    },\n    // We need hot=false (Disable HMR) to set liveReload=true\n    hot: false,\n    liveReload: true,\n  },\n});\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/webpack/prod.config.js",
    "content": "const { merge } = require('webpack-merge');\nconst commonConfig = require('./common.config');\n\n// This variable should mirror the one from config/settings/production.py\n{%- if cookiecutter.use_whitenoise == 'n' %}\n{%- if cookiecutter.cloud_provider == 'AWS' %}\nconst s3BucketName = process.env.DJANGO_AWS_STORAGE_BUCKET_NAME;\nconst awsS3Domain = process.env.DJANGO_AWS_S3_CUSTOM_DOMAIN\n  ? process.env.DJANGO_AWS_S3_CUSTOM_DOMAIN\n  : `${s3BucketName}.s3.amazonaws.com`;\nconst staticUrl = `https://${awsS3Domain}/static/`;\n{%- elif cookiecutter.cloud_provider == 'GCP' %}\nconst staticUrl = `https://storage.googleapis.com/${process.env.DJANGO_GCP_STORAGE_BUCKET_NAME}/static/`;\n{%- elif cookiecutter.cloud_provider == 'Azure' %}\nconst staticUrl = `https://${process.env.DJANGO_AZURE_ACCOUNT_NAME}.blob.core.windows.net/static/`;\n{%- endif %}\n{%- else %}\nconst staticUrl = '/static/';\n{%- endif %}\n\nmodule.exports = merge(commonConfig, {\n  mode: 'production',\n  devtool: 'source-map',\n  bail: true,\n  output: {\n    publicPath: `${staticUrl}webpack_bundles/`,\n  },\n});\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/__init__.py",
    "content": "__version__ = \"{{ cookiecutter.version }}\"\n__version_info__ = tuple(\n    int(num) if num.isdigit() else num\n    for num in __version__.replace(\"-\", \".\", 1).split(\".\")\n)\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/conftest.py",
    "content": "import pytest\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\nfrom {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory\n\n\n@pytest.fixture(autouse=True)\ndef _media_storage(settings, tmpdir) -> None:\n    settings.MEDIA_ROOT = tmpdir.strpath\n\n\n@pytest.fixture\ndef user(db) -> User:\n    return UserFactory.create()\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/contrib/__init__.py",
    "content": "\"\"\"\nTo understand why this file is here, please read:\n\nhttps://cookiecutter-django.readthedocs.io/en/latest/5-help/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django\n\"\"\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/contrib/sites/__init__.py",
    "content": "\"\"\"\nTo understand why this file is here, please read:\n\nhttps://cookiecutter-django.readthedocs.io/en/latest/5-help/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django\n\"\"\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/contrib/sites/migrations/0001_initial.py",
    "content": "import django.contrib.sites.models\nfrom django.contrib.sites.models import _simple_domain_name_validator\nfrom django.db import migrations\nfrom django.db import models\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = []\n\n    operations = [\n        migrations.CreateModel(\n            name=\"Site\",\n            fields=[\n                (\n                    \"id\",\n                    models.AutoField(\n                        verbose_name=\"ID\",\n                        serialize=False,\n                        auto_created=True,\n                        primary_key=True,\n                    ),\n                ),\n                (\n                    \"domain\",\n                    models.CharField(\n                        max_length=100,\n                        verbose_name=\"domain name\",\n                        validators=[_simple_domain_name_validator],\n                    ),\n                ),\n                (\"name\", models.CharField(max_length=50, verbose_name=\"display name\")),\n            ],\n            options={\n                \"ordering\": (\"domain\",),\n                \"db_table\": \"django_site\",\n                \"verbose_name\": \"site\",\n                \"verbose_name_plural\": \"sites\",\n            },\n            bases=(models.Model,),\n            managers=[(\"objects\", django.contrib.sites.models.SiteManager())],\n        ),\n    ]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/contrib/sites/migrations/0002_alter_domain_unique.py",
    "content": "import django.contrib.sites.models\nfrom django.db import migrations\nfrom django.db import models\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = [(\"sites\", \"0001_initial\")]\n\n    operations = [\n        migrations.AlterField(\n            model_name=\"site\",\n            name=\"domain\",\n            field=models.CharField(\n                max_length=100,\n                unique=True,\n                validators=[django.contrib.sites.models._simple_domain_name_validator],\n                verbose_name=\"domain name\",\n            ),\n        )\n    ]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/contrib/sites/migrations/0003_set_site_domain_and_name.py",
    "content": "\"\"\"\nTo understand why this file is here, please read:\n\nhttps://cookiecutter-django.readthedocs.io/en/latest/5-help/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django\n\"\"\"\nfrom django.conf import settings\nfrom django.db import migrations\n\n\ndef _update_or_create_site_with_sequence(site_model, connection, domain, name):\n    \"\"\"Update or create the site with default ID and keep the DB sequence in sync.\"\"\"\n    site, created = site_model.objects.update_or_create(\n        id=settings.SITE_ID,\n        defaults={\n            \"domain\": domain,\n            \"name\": name,\n        },\n    )\n    if created:\n        # We provided the ID explicitly when creating the Site entry, therefore the DB\n        # sequence to auto-generate them wasn't used and is now out of sync. If we\n        # don't do anything, we'll get a unique constraint violation the next time a\n        # site is created.\n        # To avoid this, we need to manually update DB sequence and make sure it's\n        # greater than the maximum value.\n        max_id = site_model.objects.order_by(\"-id\").first().id\n        with connection.cursor() as cursor:\n            cursor.execute(\"SELECT last_value from django_site_id_seq\")\n            (current_id,) = cursor.fetchone()\n            if current_id <= max_id:\n                cursor.execute(\n                    \"alter sequence django_site_id_seq restart with %s\",\n                    [max_id + 1],\n                )\n\n\ndef update_site_forward(apps, schema_editor):\n    \"\"\"Set site domain and name.\"\"\"\n    Site = apps.get_model(\"sites\", \"Site\")\n    _update_or_create_site_with_sequence(\n        Site,\n        schema_editor.connection,\n        \"{{ cookiecutter.domain_name }}\",\n        \"{{ cookiecutter.project_name[:50] }}\",\n    )\n\n\ndef update_site_backward(apps, schema_editor):\n    \"\"\"Revert site domain and name to default.\"\"\"\n    Site = apps.get_model(\"sites\", \"Site\")\n    _update_or_create_site_with_sequence(\n        Site,\n        schema_editor.connection,\n        \"example.com\",\n        \"example.com\",\n    )\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = [(\"sites\", \"0002_alter_domain_unique\")]\n\n    operations = [migrations.RunPython(update_site_forward, update_site_backward)]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/contrib/sites/migrations/0004_alter_options_ordering_domain.py",
    "content": "# Generated by Django 3.1.7 on 2021-02-04 14:49\n\nfrom django.db import migrations\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = [\n        (\"sites\", \"0003_set_site_domain_and_name\"),\n    ]\n\n    operations = [\n        migrations.AlterModelOptions(\n            name=\"site\",\n            options={\n                \"ordering\": [\"domain\"],\n                \"verbose_name\": \"site\",\n                \"verbose_name_plural\": \"sites\",\n            },\n        ),\n    ]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/contrib/sites/migrations/__init__.py",
    "content": "\"\"\"\nTo understand why this file is here, please read:\n\nhttps://cookiecutter-django.readthedocs.io/en/latest/5-help/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django\n\"\"\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/fonts/.gitkeep",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/js/project.js",
    "content": "{%- if cookiecutter.frontend_pipeline == 'Webpack' -%}\nimport '../sass/project.scss';\n\n{% endif -%}\n/* Project specific Javascript goes here. */\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/custom_bootstrap_vars.scss",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/project.scss",
    "content": "@import 'custom_bootstrap_vars';\n@import '~bootstrap/scss/bootstrap';\n\n// project specific CSS goes here\n\n///////////////\n// Variables //\n///////////////\n\n// Alert colors\n\n$white: #fff;\n$mint-green: #d6e9c6;\n$black: #000;\n$pink: #f2dede;\n$dark-pink: #eed3d7;\n$red: #b94a48;\n\n////////////\n// Alerts //\n////////////\n\n// bootstrap alert CSS, translated to the django-standard levels of\n// debug, info, success, warning, error\n\n.alert-debug {\n  background-color: $white;\n  border-color: $mint-green;\n  color: $black;\n}\n\n.alert-error {\n  background-color: $pink;\n  border-color: $dark-pink;\n  color: $red;\n}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/403.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n\n{% block title %}Forbidden (403){% endblock title %}\n{% block content %}\n  <h1>Forbidden (403)</h1>\n  <p>\n    {% if exception %}\n      {{ exception }}\n    {% else %}\n      You're not allowed to access this page.\n    {% endif %}\n  </p>\n{% endblock content %}\n{%- endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/403_csrf.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n\n{% block title %}Forbidden (403){% endblock title %}\n{% block content %}\n  <h1>Forbidden (403)</h1>\n  <p>\n    {% if exception %}\n      {{ exception }}\n    {% else %}\n      You're not allowed to access this page.\n    {% endif %}\n  </p>\n{% endblock content %}\n{%- endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/404.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n\n{% block title %}Page not found{% endblock title %}\n{% block content %}\n  <h1>Page not found</h1>\n  <p>\n    {% if exception %}\n      {{ exception }}\n    {% else %}\n      This is not the page you were looking for.\n    {% endif %}\n  </p>\n{% endblock content %}\n{%- endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/500.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n\n{% block title %}Server Error{% endblock title %}\n{% block content %}\n  <h1>Ooops!!! 500</h1>\n  <h3>Looks like something went wrong!</h3>\n  <p>\n    We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.\n  </p>\n{% endblock content %}\n{%- endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/base_manage_password.html",
    "content": "{% raw %}{% extends \"account/base_manage.html\" %}\n\n{% block main %}\n  <div class=\"card\">\n    <div class=\"card-body\">\n      {% block content %}\n      {% endblock content %}\n    </div>\n  </div>\n{% endblock main %}{% endraw %}\n\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/allauth/elements/alert.html",
    "content": "{% raw %}{% load i18n %}\n{% load allauth %}\n\n<div class=\"alert alert-error\">\n  {% slot message %}\n{% endslot %}\n</div>{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/allauth/elements/badge.html",
    "content": "{% raw %}{% load allauth %}\n\n<span class=\"badge {% if 'success' in attrs.tags %}bg-success{% endif %} {% if 'warning' in attrs.tags %}bg-warning{% endif %} {% if 'secondary' in attrs.tags %}bg-secondary{% endif %} {% if 'danger' in attrs.tags %}bg-danger{% endif %} {% if 'primary' in attrs.tags %}bg-primary{% endif %}\">\n  {% slot %}\n{% endslot %}\n</span>{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/allauth/elements/button.html",
    "content": "{% raw %}{% load allauth %}\n\n{% comment %} djlint:off {% endcomment %}\n<{% if attrs.href %}a href=\"{{ attrs.href }}\"{% else %}button{% endif %}\n                      {% if attrs.form %}form=\"{{ attrs.form }}\"{% endif %}\n                      {% if attrs.id %}id=\"{{ attrs.id }}\"{% endif %}\n                      {% if attrs.name %}name=\"{{ attrs.name }}\"{% endif %}\n                      {% if attrs.type %}type=\"{{ attrs.type }}\"{% endif %}\n                      class=\"btn\n{% if 'success' in attrs.tags %}btn-success\n{% elif 'warning' in attrs.tags %}btn-warning\n{% elif 'secondary' in attrs.tags %}btn-secondary\n{% elif 'danger' in attrs.tags %}btn-danger\n{% elif 'primary' in attrs.tags %}btn-primary\n{% else %}btn-primary\n{% endif %}\"\n>\n  {% slot %}\n  {% endslot %}\n  </{% if attrs.href %}a{% else %}button{% endif %}>{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/allauth/elements/field.html",
    "content": "{% raw %}{% load allauth %}\n{% load crispy_forms_tags %}\n\n{% if attrs.type == \"textarea\" %}\n  <div class=\"row mb-3\">\n    <div class=\"col-sm-10\">\n      <label for=\"{{ attrs.id }}\">\n        {% slot label %}\n      {% endslot %}\n    </label>\n  </div>\n  <textarea {% if attrs.required %}required{% endif %}\n            {% if attrs.rows %}rows=\"{{ attrs.rows }}\"{% endif %}\n            {% if attrs.disabled %}disabled{% endif %}\n            {% if attrs.readonly %}readonly{% endif %}\n            {% if attrs.checked %}checked{% endif %}\n            {% if attrs.name %}name=\"{{ attrs.name }}\"{% endif %}\n            {% if attrs.id %}id=\"{{ attrs.id }}\"{% endif %}\n            {% if attrs.placeholder %}placeholder=\"{{ attrs.placeholder }}\"{% endif %}\n            class=\"form-control\">{% slot value %}{% endslot %}</textarea>\n</div>\n{% elif attrs.type == \"radio\" %}\n<div class=\"row mb-3\">\n  <div class=\"col-sm-10\">\n    <div class=\"form-check\">\n      <input {% if attrs.required %}required{% endif %}\n             {% if attrs.disabled %}disabled{% endif %}\n             {% if attrs.readonly %}readonly{% endif %}\n             {% if attrs.checked %}checked{% endif %}\n             {% if attrs.name %}name=\"{{ attrs.name }}\"{% endif %}\n             {% if attrs.id %}id=\"{{ attrs.id }}\"{% endif %}\n             {% if attrs.placeholder %}placeholder=\"{{ attrs.placeholder }}\"{% endif %}\n             {% if attrs.autocomplete %}autocomplete=\"{{ attrs.autocomplete }}\"{% endif %}\n             value=\"{{ attrs.value|default_if_none:\"\" }}\"\n             type=\"{{ attrs.type }}\" />\n      <label class=\"form-check-label\" for=\"{{ attrs.id }}\">\n        {% slot label %}\n      {% endslot %}\n    </label>\n  </div>\n</div>\n</div>\n{% else %}\n<div class=\"col-sm-10\">\n  <label for=\"{{ attrs.id }}\">\n    {% slot label %}\n  {% endslot %}\n</label>\n</div>\n<div class=\"col-sm-10\">\n  <input {% if attrs.required %}required{% endif %}\n         {% if attrs.disabled %}disabled{% endif %}\n         {% if attrs.readonly %}readonly{% endif %}\n         {% if attrs.checked %}checked{% endif %}\n         {% if attrs.name %}name=\"{{ attrs.name }}\"{% endif %}\n         {% if attrs.id %}id=\"{{ attrs.id }}\"{% endif %}\n         {% if attrs.placeholder %}placeholder=\"{{ attrs.placeholder }}\"{% endif %}\n         {% if attrs.autocomplete %}autocomplete=\"{{ attrs.autocomplete }}\"{% endif %}\n         value=\"{{ attrs.value|default_if_none:\"\" }}\"\n         type=\"{{ attrs.type }}\"\n         class=\"form-control\" />\n</div>\n{% endif %}\n{% if slots.help_text %}\n  <div class=\"form-text\">{% slot help_text %}{% endslot %}</div>\n{% endif %}{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/allauth/elements/fields.html",
    "content": "{% raw %}{% load crispy_forms_tags %}\n\n{{ attrs.form|crispy }}{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/allauth/elements/panel.html",
    "content": "{% raw %}{% load allauth %}\n\n<section>\n  <div class=\"card mb-4\">\n    <div class=\"card-body\">\n      <h2 class=\"card-title\">\n        {% slot title %}\n      {% endslot %}\n    </h2>\n    {% slot body %}\n  {% endslot %}\n  {% if slots.actions %}\n    <ul>\n      {% for action in slots.actions %}<li>{{ action }}</li>{% endfor %}\n    </ul>\n  {% endif %}\n</div>\n</div>\n</section>{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/allauth/elements/table.html",
    "content": "{% raw %}{% load allauth %}\n\n<table class=\"table\">\n  {% slot %}\n{% endslot %}\n</table>{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/allauth/layouts/entrance.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n{% load i18n %}\n{% block bodyclass %}bg-light{% endblock bodyclass %}\n\n{% block css %}{{ block.super }}{% endblock css %}\n{% block title %}\n  {% block head_title %}\n    {% trans \"Sign In\" %}\n  {% endblock head_title %}\n{% endblock title %}\n{% block body %}\n  <div class=\"d-flex justify-content-center h-100 py-4\">\n    <div class=\"col-md-4 py-4 my-4 px-4\">\n      {% if messages %}\n        {% for message in messages %}\n          <div class=\"alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}\">\n            {{ message }}\n            <button type=\"button\"\n                    class=\"btn-close\"\n                    data-bs-dismiss=\"alert\"\n                    aria-label=\"Close\"></button>\n          </div>\n        {% endfor %}\n      {% endif %}\n      {% block content %}\n      {% endblock content %}\n      {% block extra_body %}\n      {% endblock extra_body %}\n    </div>\n  </div>\n{% endblock body %}{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/allauth/layouts/manage.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n\n{% block main %}\n  {% block content %}\n  {% endblock content %}\n{% endblock main %}{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html",
    "content": "{% raw %}\n{% load static i18n {% endraw %}\n\n{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}compress{%- endif %}{% raw %}%}{% endraw %}\n  {%- if cookiecutter.frontend_pipeline == 'Webpack' %}{% raw %}\n    {% load render_bundle from webpack_loader %}\n\n  {% endraw %}\n{%- endif %}{% raw %}<!DOCTYPE html>\n{% get_current_language as LANGUAGE_CODE %}\n<html lang=\"{{ LANGUAGE_CODE }}\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"x-ua-compatible\" content=\"ie=edge\" />\n    <title>\n      {% block title %}\n      {% endraw %}{{ cookiecutter.project_name }}{% raw %}\n    {% endblock title %}\n  </title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n  <meta name=\"description\"\n        content=\"{% endraw %}{{ cookiecutter.description }}{% raw %}\" />\n  <meta name=\"author\"\n        content=\"{% endraw %}{{ cookiecutter.author_name }}{% raw %}\" />\n  <link rel=\"icon\" href=\"{% static 'images/favicons/favicon.ico' %}\" />\n  {% block css %}\n  {%- endraw %}\n  {%- if cookiecutter.frontend_pipeline in ['None', 'Django Compressor'] %}\n    {%- raw %}\n    <!-- Latest compiled and minified Bootstrap CSS -->\n    <link rel=\"stylesheet\"\n          href=\"https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css\"\n          integrity=\"sha512-SbiR/eusphKoMVVXysTKG/7VseWii+Y3FdHrt0EpKgpToZeemhqHeZeLWLhJutz/2ut2Vw1uQEj2MbRF+TVBUA==\"\n          crossorigin=\"anonymous\"\n          referrerpolicy=\"no-referrer\" />\n  {%- endraw %}\n{%- endif %}\n{%- raw %}\n<!-- Your stuff: Third-party CSS libraries go here -->\n<!-- This file stores project-specific CSS -->\n{%- endraw %}\n{% if cookiecutter.frontend_pipeline == 'None' %}\n  {% raw %}\n  <link href=\"{% static 'css/project.css' %}\" rel=\"stylesheet\" />\n{%- endraw %}\n{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}\n{% raw %}\n{% compress css %}\n  <link href=\"{% static 'css/project.css' %}\" rel=\"stylesheet\" />\n{% endcompress %}\n{%- endraw %}\n{% elif cookiecutter.frontend_pipeline == 'Gulp' %}\n{% raw %}\n<link href=\"{% static 'css/project.min.css' %}\" rel=\"stylesheet\" />\n{%- endraw %}\n{% elif cookiecutter.frontend_pipeline == \"Webpack\" %}\n{% raw %}\n{% render_bundle 'project' 'css' %}\n{%- endraw %}\n{% endif %}\n{% raw %}\n{% endblock css %}\n<!-- Le javascript\n    ================================================== -->\n{# Placed at the top of the document so pages load faster with defer #}\n{% block javascript %}\n{%- endraw %}\n{% if cookiecutter.frontend_pipeline == 'Gulp' %}\n  {% raw %}\n  <!-- Vendor dependencies bundled as one file -->\n  <script defer src=\"{% static 'js/vendors.min.js' %}\"></script>\n{%- endraw %}\n{% elif cookiecutter.frontend_pipeline == \"Webpack\" %}\n{% raw %}\n<!-- Vendor dependencies bundled as one file -->\n{% render_bundle 'vendors' 'js' attrs='defer' %}\n{%- endraw %}\n{% else %}\n{% raw %}\n<!-- Bootstrap JS -->\n<script defer\n        src=\"https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.min.js\"\n        integrity=\"sha512-1/RvZTcCDEUjY/CypiMz+iqqtaoQfAITmNSJY17Myp4Ms5mdxPS5UV7iOfdZoxcGhzFbOm6sntTKJppjvuhg4g==\"\n        crossorigin=\"anonymous\"\n        referrerpolicy=\"no-referrer\"></script>\n<!-- Your stuff: Third-party javascript libraries go here -->\n{%- endraw %}\n{% endif %}\n{% raw %}\n<!-- place project specific Javascript in this file -->\n{%- endraw %}\n{% if cookiecutter.frontend_pipeline == 'None' %}\n  {% raw %}\n  <script defer src=\"{% static 'js/project.js' %}\"></script>\n{%- endraw %}\n{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}\n{% raw %}\n{% compress js %}\n  <script defer src=\"{% static 'js/project.js' %}\"></script>\n{% endcompress %}\n{%- endraw %}\n{% elif cookiecutter.frontend_pipeline == 'Gulp' %}\n{% raw %}\n<script defer src=\"{% static 'js/project.min.js' %}\"></script>\n{%- endraw %}\n{% elif cookiecutter.frontend_pipeline == \"Webpack\" %}\n{% raw %}\n{% render_bundle 'project' 'js' attrs='defer' %}\n{%- endraw %}\n{% endif %}\n{% raw %}\n{% endblock javascript %}\n</head>\n<body class=\"{% block bodyclass %}{% endblock bodyclass %}\">\n  {% block body %}\n  <div class=\"mb-1\">\n    <nav class=\"navbar navbar-expand-md navbar-light bg-light\">\n      <div class=\"container-fluid\">\n        <button class=\"navbar-toggler navbar-toggler-right\"\n                type=\"button\"\n                data-bs-toggle=\"collapse\"\n                data-bs-target=\"#navbarSupportedContent\"\n                aria-controls=\"navbarSupportedContent\"\n                aria-expanded=\"false\"\n                aria-label=\"Toggle navigation\">\n          <span class=\"navbar-toggler-icon\"></span>\n        </button>\n        <a class=\"navbar-brand\" href=\"{% url 'home' %}\">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a>\n        <div class=\"collapse navbar-collapse\" id=\"navbarSupportedContent\">\n          <ul class=\"navbar-nav mr-auto\">\n            <li class=\"nav-item active\">\n              <a class=\"nav-link\" href=\"{% url 'home' %}\">Home <span class=\"visually-hidden\">(current)</span></a>\n            </li>\n            <li class=\"nav-item\">\n              <a class=\"nav-link\" href=\"{% url 'about' %}\">About</a>\n            </li>\n            {% if request.user.is_authenticated %}\n              <li class=\"nav-item\">\n                <a class=\"nav-link\"\n                   href=\"{% endraw %}{% if cookiecutter.username_type == \"email\" %}{% raw %}{% url 'users:detail' request.user.pk %}{% endraw %}{% else %}{% raw %}{% url 'users:detail' request.user.username %}{% endraw %}{% endif %}{% raw %}\">{% translate \"My Profile\" %}</a>\n              </li>\n              <li class=\"nav-item\">\n                {# URL provided by django-allauth/account/urls.py #}\n                <a class=\"nav-link\" href=\"{% url 'account_logout' %}\">{% translate \"Sign Out\" %}</a>\n              </li>\n            {% else %}\n              {% if ACCOUNT_ALLOW_REGISTRATION %}\n                <li class=\"nav-item\">\n                  {# URL provided by django-allauth/account/urls.py #}\n                  <a id=\"sign-up-link\" class=\"nav-link\" href=\"{% url 'account_signup' %}\">{% translate \"Sign Up\" %}</a>\n                </li>\n              {% endif %}\n              <li class=\"nav-item\">\n                {# URL provided by django-allauth/account/urls.py #}\n                <a id=\"log-in-link\" class=\"nav-link\" href=\"{% url 'account_login' %}\">{% translate \"Sign In\" %}</a>\n              </li>\n            {% endif %}\n          </ul>\n        </div>\n      </div>\n    </nav>\n  </div>\n  <div class=\"container\">\n    {% if messages %}\n      {% for message in messages %}\n        <div class=\"alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}\">\n          {{ message }}\n          <button type=\"button\"\n                  class=\"btn-close\"\n                  data-bs-dismiss=\"alert\"\n                  aria-label=\"Close\"></button>\n        </div>\n      {% endfor %}\n    {% endif %}\n    {% block main %}\n      {% block content %}\n        <p>Use this document as a way to quick start any new project.</p>\n      {% endblock content %}\n    {% endblock main %}\n\n  </div>\n  {% endblock body %}\n  <!-- /container -->\n  {% block modal %}\n  {% endblock modal %}\n  {% block inline_javascript %}\n    {% comment %}\n    Script tags with only code, no src (defer by default). To run\n    with a \"defer\" so that you run inline code:\n    <script>\n      window.addEventListener('DOMContentLoaded', () => {\n        /* Run whatever you want */\n      });\n    </script>\n    {% endcomment %}\n  {% endblock inline_javascript %}\n</body>\n</html>\n{%- endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/about.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n\n{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/home.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n\n{% endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_detail.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n\n{% load static %}\n\n{% block title %}\n  User: {% endraw %}\n  {% if cookiecutter.username_type == \"email\" %}\n    {% raw %}{{ object.name }}{% endraw %}\n  {% else %}\n    {% raw %}{{ object.username }}{% endraw %}\n  {% endif %}\n  {% raw %}\n{% endblock title %}\n{% block content %}\n  <div class=\"container\">\n    <div class=\"row\">\n      <div class=\"col-sm-12\">\n        <h2>\n        {% endraw %}\n        {% if cookiecutter.username_type == \"email\" %}\n          {% raw %}{{ object.name }}{% endraw %}\n        {% else %}\n          {% raw %}{{ object.username }}{% endraw %}\n        {% endif %}\n      </h2>\n      {%- if cookiecutter.username_type == \"username\" %}\n      {%- raw %}\n      {% if object.name %}\n        <p>{{ object.name }}</p>\n      {% endif %}\n      {%- endraw %}\n      {%- endif %}\n    </div>\n  </div>\n  {%- raw %}\n  {% if object == request.user %}\n    <!-- Action buttons -->\n    <div class=\"row\">\n      <div class=\"col-sm-12\">\n        <a class=\"btn btn-primary\" href=\"{% url 'users:update' %}\" role=\"button\">My Info</a>\n        <a class=\"btn btn-primary\"\n           href=\"{% url 'account_email' %}\"\n           role=\"button\">E-Mail</a>\n        <a class=\"btn btn-primary\"\n           href=\"{% url 'mfa_index' %}\"\n           role=\"button\">MFA</a>\n        <!-- Your Stuff: Custom user template urls -->\n      </div>\n    </div>\n    <!-- End Action buttons -->\n  {% endif %}\n</div>\n{% endblock content %}\n{%- endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_form.html",
    "content": "{% raw %}{% extends \"base.html\" %}\n\n{% load crispy_forms_tags %}\n\n{% block title %}\n{% endraw %}\n{% if cookiecutter.username_type == \"email\" %}\n  {% raw %}{{ user.name }}{% endraw %}\n{% else %}\n  {% raw %}{{ user.username }}{% endraw %}\n{% endif %}\n{% raw %}\n{% endblock title %}\n{% block content %}\n  <h1>\n  {% endraw %}\n  {% if cookiecutter.username_type == \"email\" %}\n    {% raw %}{{ user.name }}{% endraw %}\n  {% else %}\n    {% raw %}{{ user.username }}{% endraw %}\n  {% endif %}\n  {% raw %}\n</h1>\n<form class=\"form-horizontal\"\n      method=\"post\"\n      action=\"{% url 'users:update' %}\">\n  {% csrf_token %}\n  {{ form|crispy }}\n  <div class=\"control-group\">\n    <div class=\"controls\">\n      <button type=\"submit\" class=\"btn btn-primary\">Update</button>\n    </div>\n  </div>\n</form>\n{% endblock content %}\n{%- endraw %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/__init__.py",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/adapters.py",
    "content": "from __future__ import annotations\n\nimport typing\n\nfrom allauth.account.adapter import DefaultAccountAdapter\nfrom allauth.socialaccount.adapter import DefaultSocialAccountAdapter\nfrom django.conf import settings\n\nif typing.TYPE_CHECKING:\n    from allauth.socialaccount.models import SocialLogin\n    from django.http import HttpRequest\n\n    from {{cookiecutter.project_slug}}.users.models import User\n\n\nclass AccountAdapter(DefaultAccountAdapter):\n    def is_open_for_signup(self, request: HttpRequest) -> bool:\n        return getattr(settings, \"ACCOUNT_ALLOW_REGISTRATION\", True)\n\n\nclass SocialAccountAdapter(DefaultSocialAccountAdapter):\n    def is_open_for_signup(\n        self,\n        request: HttpRequest,\n        sociallogin: SocialLogin,\n    ) -> bool:\n        return getattr(settings, \"ACCOUNT_ALLOW_REGISTRATION\", True)\n\n    def populate_user(\n        self,\n        request: HttpRequest,\n        sociallogin: SocialLogin,\n        data: dict[str, typing.Any],\n    ) -> User:\n        \"\"\"\n        Populates user information from social provider info.\n\n        See: https://docs.allauth.org/en/latest/socialaccount/advanced.html#creating-and-populating-user-instances\n        \"\"\"\n        user = super().populate_user(request, sociallogin, data)\n        if not user.name:\n            if name := data.get(\"name\"):\n                user.name = name\n            elif first_name := data.get(\"first_name\"):\n                user.name = first_name\n                if last_name := data.get(\"last_name\"):\n                    user.name += f\" {last_name}\"\n        return user\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/admin.py",
    "content": "from allauth.account.decorators import secure_admin_login\nfrom django.conf import settings\nfrom django.contrib import admin\nfrom django.contrib.auth import admin as auth_admin\nfrom django.utils.translation import gettext_lazy as _\n\nfrom .forms import UserAdminChangeForm\nfrom .forms import UserAdminCreationForm\nfrom .models import User\n\nif settings.DJANGO_ADMIN_FORCE_ALLAUTH:\n    # Force the `admin` sign in process to go through the `django-allauth` workflow:\n    # https://docs.allauth.org/en/latest/common/admin.html#admin\n    admin.autodiscover()\n    admin.site.login = secure_admin_login(admin.site.login)  # type: ignore[method-assign]\n\n\n@admin.register(User)\nclass UserAdmin(auth_admin.UserAdmin):\n    form = UserAdminChangeForm\n    add_form = UserAdminCreationForm\n    fieldsets = (\n        {%- if cookiecutter.username_type == \"email\" %}\n        (None, {\"fields\": (\"email\", \"password\")}),\n        (_(\"Personal info\"), {\"fields\": (\"name\",)}),\n        {%- else %}\n        (None, {\"fields\": (\"username\", \"password\")}),\n        (_(\"Personal info\"), {\"fields\": (\"name\", \"email\")}),\n        {%- endif %}\n        (\n            _(\"Permissions\"),\n            {\n                \"fields\": (\n                    \"is_active\",\n                    \"is_staff\",\n                    \"is_superuser\",\n                    \"groups\",\n                    \"user_permissions\",\n                ),\n            },\n        ),\n        (_(\"Important dates\"), {\"fields\": (\"last_login\", \"date_joined\")}),\n    )\n    list_display = [\"{{cookiecutter.username_type}}\", \"name\", \"is_superuser\"]\n    search_fields = [\"name\"]\n    {%- if cookiecutter.username_type == \"email\" %}\n    ordering = [\"id\"]\n    add_fieldsets = (\n        (\n            None,\n            {\n                \"classes\": (\"wide\",),\n                \"fields\": (\"email\", \"password1\", \"password2\"),\n            },\n        ),\n    )\n    {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/__init__.py",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/schema.py",
    "content": "from django.urls import reverse\nfrom ninja import ModelSchema\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\n\nclass UpdateUserSchema(ModelSchema):\n    class Meta:\n        model = User\n        {%- if cookiecutter.username_type == \"email\" %}\n        fields = [\"name\"]\n        {%- else %}\n        fields = [\"username\", \"name\"]\n        {%- endif %}\n\n\nclass UserSchema(ModelSchema):\n    url: str\n\n    class Meta:\n        model = User\n        {%- if cookiecutter.username_type == \"email\" %}\n        fields = [\"email\", \"name\"]\n        {%- else %}\n        fields = [\"username\", \"email\", \"name\"]\n        {%- endif %}\n\n    @staticmethod\n    def resolve_url(obj: User):\n        {%- if cookiecutter.username_type == \"email\" %}\n        return reverse(\"api:retrieve_user\", kwargs={\"pk\": obj.pk})\n        {%- else %}\n        return reverse(\"api:retrieve_user\", kwargs={\"username\": obj.username})\n        {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/serializers.py",
    "content": "from rest_framework import serializers\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\n\nclass UserSerializer(serializers.ModelSerializer[User]):\n    class Meta:\n        model = User\n        {%- if cookiecutter.username_type == \"email\" %}\n        fields = [\"name\", \"url\"]\n\n        extra_kwargs = {\n            \"url\": {\"view_name\": \"api:user-detail\", \"lookup_field\": \"pk\"},\n        }\n        {%- else %}\n        fields = [\"username\", \"name\", \"url\"]\n\n        extra_kwargs = {\n            \"url\": {\"view_name\": \"api:user-detail\", \"lookup_field\": \"username\"},\n        }\n        {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/views.py",
    "content": "{% if cookiecutter.rest_api == 'DRF' -%}\nfrom rest_framework import status\nfrom rest_framework.decorators import action\nfrom rest_framework.mixins import ListModelMixin\nfrom rest_framework.mixins import RetrieveModelMixin\nfrom rest_framework.mixins import UpdateModelMixin\nfrom rest_framework.response import Response\nfrom rest_framework.viewsets import GenericViewSet\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\nfrom .serializers import UserSerializer\n\n\nclass UserViewSet(RetrieveModelMixin, ListModelMixin, UpdateModelMixin, GenericViewSet):\n    serializer_class = UserSerializer\n    queryset = User.objects.all()\n    {%- if cookiecutter.username_type == \"email\" %}\n    lookup_field = \"pk\"\n    {%- else %}\n    lookup_field = \"username\"\n    {%- endif %}\n\n    def get_queryset(self, *args, **kwargs):\n        assert isinstance(self.request.user.id, int)\n        return self.queryset.filter(id=self.request.user.id)\n\n    @action(detail=False)\n    def me(self, request):\n        serializer = UserSerializer(request.user, context={\"request\": request})\n        return Response(status=status.HTTP_200_OK, data=serializer.data)\n{%- elif cookiecutter.rest_api == 'Django Ninja' -%}\nfrom django.db.models import QuerySet\nfrom django.shortcuts import get_object_or_404\nfrom ninja import Router\n\nfrom {{ cookiecutter.project_slug }}.users.api.schema import UpdateUserSchema\nfrom {{ cookiecutter.project_slug }}.users.api.schema import UserSchema\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\nrouter = Router(tags=[\"users\"])\n\n\ndef _get_users_queryset(request) -> QuerySet[User]:\n    return User.objects.filter(pk=request.user.pk)\n\n\n@router.get(\"/\", response=list[UserSchema])\ndef list_users(request):\n    return _get_users_queryset(request)\n{%- if cookiecutter.username_type == \"email\" %}\n\n\n@router.get(\"/me/\", response=UserSchema)\ndef retrieve_current_user(request):\n    return request.user\n\n\n@router.get(\"/{pk}/\", response=UserSchema)\ndef retrieve_user(request, pk: int):\n    users_qs = _get_users_queryset(request)\n    return get_object_or_404(users_qs, pk=pk)\n{%- else %}\n\n\n@router.get(\"/me/\", response=UserSchema)\ndef retrieve_current_user(request):\n    return request.user\n\n\n@router.get(\"/{username}/\", response=UserSchema)\ndef retrieve_user(request, username: str):\n    users_qs = _get_users_queryset(request)\n    return get_object_or_404(users_qs, username=username)\n{%- endif %}\n\n\n@router.patch(\"/me/\", response=UserSchema)\ndef update_current_user(request, data: UpdateUserSchema):\n    user = request.user\n    user.name = data.name\n    {%- if cookiecutter.username_type == \"username\" %}\n    user.username = data.username\n    {%- endif %}\n    user.save()\n    return user\n{%- if cookiecutter.username_type == \"email\" %}\n\n\n@router.patch(\"/{pk}/\", response=UserSchema)\ndef update_user(request, pk: int, data: UpdateUserSchema):\n    users_qs = _get_users_queryset(request)\n    user = get_object_or_404(users_qs, pk=pk)\n    user.name = data.name\n    user.save()\n    return user\n{%- else %}\n\n\n@router.patch(\"/{username}/\", response=UserSchema)\ndef update_user(request, username: str, data: UpdateUserSchema):\n    users_qs = _get_users_queryset(request)\n    user = get_object_or_404(users_qs, username=username)\n    user.name = data.name\n    user.username = data.username\n    user.save()\n    return user\n{%- endif %}\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/apps.py",
    "content": "from django.apps import AppConfig\nfrom django.utils.translation import gettext_lazy as _\n\n\nclass UsersConfig(AppConfig):\n    name = \"{{ cookiecutter.project_slug }}.users\"\n    verbose_name = _(\"Users\")\n\n    def ready(self):\n        \"\"\"\n        Override this method in subclasses to run code when Django starts.\n        \"\"\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/context_processors.py",
    "content": "from django.conf import settings\n\n\ndef allauth_settings(request):\n    \"\"\"Expose some settings from django-allauth in templates.\"\"\"\n    return {\n        \"ACCOUNT_ALLOW_REGISTRATION\": settings.ACCOUNT_ALLOW_REGISTRATION,\n    }\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/forms.py",
    "content": "from allauth.account.forms import SignupForm\nfrom allauth.socialaccount.forms import SignupForm as SocialSignupForm\nfrom django.contrib.auth import forms as admin_forms\n{%- if cookiecutter.username_type == \"email\" %}\nfrom django.forms import EmailField\n{%- endif %}\nfrom django.utils.translation import gettext_lazy as _\n\nfrom .models import User\n\n\nclass UserAdminChangeForm(admin_forms.UserChangeForm):\n    class Meta(admin_forms.UserChangeForm.Meta):\n        model = User\n        {%- if cookiecutter.username_type == \"email\" %}\n        field_classes = {\"email\": EmailField}\n        {%- endif %}\n\n\nclass UserAdminCreationForm(admin_forms.AdminUserCreationForm):\n    \"\"\"\n    Form for User Creation in the Admin Area.\n    To change user signup, see UserSignupForm and UserSocialSignupForm.\n    \"\"\"\n\n    class Meta(admin_forms.UserCreationForm.Meta):\n        model = User\n        {%- if cookiecutter.username_type == \"email\" %}\n        fields = (\"email\",)\n        field_classes = {\"email\": EmailField}\n        error_messages = {\n            \"email\": {\"unique\": _(\"This email has already been taken.\")},\n        }\n        {%- else %}\n        error_messages = {\n            \"username\": {\"unique\": _(\"This username has already been taken.\")},\n        }\n        {%- endif %}\n\n\nclass UserSignupForm(SignupForm):\n    \"\"\"\n    Form that will be rendered on a user sign up section/screen.\n    Default fields will be added automatically.\n    Check UserSocialSignupForm for accounts created from social.\n    \"\"\"\n\n\nclass UserSocialSignupForm(SocialSignupForm):\n    \"\"\"\n    Renders the form when user has signed up using social accounts.\n    Default fields will be added automatically.\n    See UserSignupForm otherwise.\n    \"\"\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/managers.py",
    "content": "from typing import TYPE_CHECKING\n\nfrom django.contrib.auth.hashers import make_password\nfrom django.contrib.auth.models import UserManager as DjangoUserManager\n\nif TYPE_CHECKING:\n    from .models import User  # noqa: F401\n\n\nclass UserManager(DjangoUserManager[\"User\"]):\n    \"\"\"Custom manager for the User model.\"\"\"\n\n    def _create_user(self, email: str, password: str | None, **extra_fields):\n        \"\"\"\n        Create and save a user with the given email and password.\n        \"\"\"\n        if not email:\n            msg = \"The given email must be set\"\n            raise ValueError(msg)\n        email = self.normalize_email(email)\n        user = self.model(email=email, **extra_fields)\n        user.password = make_password(password)\n        user.save(using=self._db)\n        return user\n\n    def create_user(self, email: str, password: str | None = None, **extra_fields):  # type: ignore[override]\n        extra_fields.setdefault(\"is_staff\", False)\n        extra_fields.setdefault(\"is_superuser\", False)\n        return self._create_user(email, password, **extra_fields)\n\n    def create_superuser(self, email: str, password: str | None = None, **extra_fields):  # type: ignore[override]\n        extra_fields.setdefault(\"is_staff\", True)\n        extra_fields.setdefault(\"is_superuser\", True)\n\n        if extra_fields.get(\"is_staff\") is not True:\n            msg = \"Superuser must have is_staff=True.\"\n            raise ValueError(msg)\n        if extra_fields.get(\"is_superuser\") is not True:\n            msg = \"Superuser must have is_superuser=True.\"\n            raise ValueError(msg)\n\n        return self._create_user(email, password, **extra_fields)\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py",
    "content": "import django.contrib.auth.models\nimport django.contrib.auth.validators\nimport django.utils.timezone\nfrom django.db import migrations\nfrom django.db import models\n\nimport {{cookiecutter.project_slug}}.users.models\n\n\nclass Migration(migrations.Migration):\n\n    initial = True\n\n    dependencies = [\n        (\"auth\", \"0012_alter_user_first_name_max_length\"),\n    ]\n\n    operations = [\n        migrations.CreateModel(\n            name=\"User\",\n            fields=[\n                (\n                    \"id\",\n                    models.BigAutoField(\n                        auto_created=True,\n                        primary_key=True,\n                        serialize=False,\n                        verbose_name=\"ID\",\n                    ),\n                ),\n                (\"password\", models.CharField(max_length=128, verbose_name=\"password\")),\n                (\n                    \"last_login\",\n                    models.DateTimeField(\n                        blank=True, null=True, verbose_name=\"last login\",\n                    ),\n                ),\n                (\n                    \"is_superuser\",\n                    models.BooleanField(\n                        default=False,\n                        help_text=\"Designates that this user has all permissions without explicitly assigning them.\",\n                        verbose_name=\"superuser status\",\n                    ),\n                ),\n                {%- if cookiecutter.username_type == \"username\" -%}\n                (\n                    \"username\",\n                    models.CharField(\n                        error_messages={\n                            \"unique\": \"A user with that username already exists.\"\n                        },\n                        help_text=\"Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.\",\n                        max_length=150,\n                        unique=True,\n                        validators=[\n                            django.contrib.auth.validators.UnicodeUsernameValidator()\n                        ],\n                        verbose_name=\"username\",\n                    ),\n                ),\n                (\n                    \"email\",\n                    models.EmailField(\n                        blank=True, max_length=254, verbose_name=\"email address\",\n                    ),\n                ),\n                {%- else %}\n                (\n                    \"email\",\n                    models.EmailField(\n                        unique=True, max_length=254, verbose_name=\"email address\",\n                    ),\n                ),\n                {%- endif %}\n                (\n                    \"is_staff\",\n                    models.BooleanField(\n                        default=False,\n                        help_text=\"Designates whether the user can log into this admin site.\",\n                        verbose_name=\"staff status\",\n                    ),\n                ),\n                (\n                    \"is_active\",\n                    models.BooleanField(\n                        default=True,\n                        help_text=\"Designates whether this user should be treated as active. Unselect this instead of deleting accounts.\",\n                        verbose_name=\"active\",\n                    ),\n                ),\n                (\n                    \"date_joined\",\n                    models.DateTimeField(\n                        default=django.utils.timezone.now, verbose_name=\"date joined\",\n                    ),\n                ),\n                (\n                    \"name\",\n                    models.CharField(\n                        blank=True, max_length=255, verbose_name=\"Name of User\",\n                    ),\n                ),\n                (\n                    \"groups\",\n                    models.ManyToManyField(\n                        blank=True,\n                        help_text=\"The groups this user belongs to. A user will get all permissions granted to each of their groups.\",\n                        related_name=\"user_set\",\n                        related_query_name=\"user\",\n                        to=\"auth.Group\",\n                        verbose_name=\"groups\",\n                    ),\n                ),\n                (\n                    \"user_permissions\",\n                    models.ManyToManyField(\n                        blank=True,\n                        help_text=\"Specific permissions for this user.\",\n                        related_name=\"user_set\",\n                        related_query_name=\"user\",\n                        to=\"auth.Permission\",\n                        verbose_name=\"user permissions\",\n                    ),\n                ),\n            ],\n            options={\n                \"verbose_name\": \"user\",\n                \"verbose_name_plural\": \"users\",\n                \"abstract\": False,\n            },\n            managers=[\n                {%- if cookiecutter.username_type == \"email\" %}\n                (\"objects\", {{cookiecutter.project_slug}}.users.models.UserManager()),\n                {%- else %}\n                (\"objects\", django.contrib.auth.models.UserManager()),\n                {%- endif %}\n            ],\n        ),\n    ]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/__init__.py",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py",
    "content": "{%- if cookiecutter.username_type == \"email\" %}\nfrom typing import ClassVar\n\n{% endif -%}\nfrom django.contrib.auth.models import AbstractUser\nfrom django.db.models import CharField\n{%- if cookiecutter.username_type == \"email\" %}\nfrom django.db.models import EmailField\n{%- endif %}\nfrom django.urls import reverse\nfrom django.utils.translation import gettext_lazy as _\n{%- if cookiecutter.username_type == \"email\" %}\n\nfrom .managers import UserManager\n{%- endif %}\n\n\nclass User(AbstractUser):\n    \"\"\"\n    Default custom user model for {{cookiecutter.project_name}}.\n    If adding fields that need to be filled at user signup,\n    check forms.SignupForm and forms.SocialSignupForms accordingly.\n    \"\"\"\n\n    # First and last name do not cover name patterns around the globe\n    name = CharField(_(\"Name of User\"), blank=True, max_length=255)\n    first_name = None  # type: ignore[assignment]\n    last_name = None  # type: ignore[assignment]\n    {%- if cookiecutter.username_type == \"email\" %}\n    email = EmailField(_(\"email address\"), unique=True)\n    username = None  # type: ignore[assignment]\n\n    USERNAME_FIELD = \"email\"\n    REQUIRED_FIELDS = []\n\n    objects: ClassVar[UserManager] = UserManager()\n    {%- endif %}\n\n    def get_absolute_url(self) -> str:\n        \"\"\"Get URL for user's detail view.\n\n        Returns:\n            str: URL for user detail.\n\n        \"\"\"\n        {%- if cookiecutter.username_type == \"email\" %}\n        return reverse(\"users:detail\", kwargs={\"pk\": self.id})\n        {%- else %}\n        return reverse(\"users:detail\", kwargs={\"username\": self.username})\n        {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tasks.py",
    "content": "from celery import shared_task\n\nfrom .models import User\n\n\n@shared_task()\ndef get_users_count():\n    \"\"\"A pointless Celery task to demonstrate usage.\"\"\"\n    return User.objects.count()\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/__init__.py",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/api/__init__.py",
    "content": ""
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/api/test_openapi.py",
    "content": "from http import HTTPStatus\n\nimport pytest\nfrom django.urls import reverse\n\n\ndef test_api_docs_accessible_by_admin(admin_client):\n    {%- if cookiecutter.rest_api == 'DRF' %}\n    url = reverse(\"api-docs\")\n    {%- elif cookiecutter.rest_api == 'Django Ninja' %}\n    url = reverse(\"api:openapi-view\")\n    {%- endif %}\n    response = admin_client.get(url)\n    assert response.status_code == HTTPStatus.OK\n\n\n@pytest.mark.django_db\ndef test_api_docs_not_accessible_by_anonymous_users(client):\n    {%- if cookiecutter.rest_api == 'DRF' %}\n    url = reverse(\"api-docs\")\n    response = client.get(url)\n    assert response.status_code == HTTPStatus.FORBIDDEN\n    {%- elif cookiecutter.rest_api == 'Django Ninja' %}\n    url = reverse(\"api:openapi-view\")\n    response = client.get(url)\n    assert response.status_code == HTTPStatus.FOUND\n    assert response.url == \"/admin/login/?next=/api/docs\"\n    {%- endif %}\n\n\ndef test_api_schema_generated_successfully(admin_client):\n    {%- if cookiecutter.rest_api == 'DRF' %}\n    url = reverse(\"api-schema\")\n    {%- elif cookiecutter.rest_api == 'Django Ninja' %}\n    url = reverse(\"api:openapi-json\")\n    {%- endif %}\n    response = admin_client.get(url)\n    assert response.status_code == HTTPStatus.OK\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/api/test_urls.py",
    "content": "from django.urls import resolve\nfrom django.urls import reverse\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\n{%- if cookiecutter.rest_api == 'DRF' %}\n\n\ndef test_user_detail(user: User):\n    {%- if cookiecutter.username_type == \"email\" %}\n    assert (\n        reverse(\"api:user-detail\", kwargs={\"pk\": user.pk}) == f\"/api/users/{user.pk}/\"\n    )\n    assert resolve(f\"/api/users/{user.pk}/\").view_name == \"api:user-detail\"\n    {%- else %}\n    assert (\n        reverse(\"api:user-detail\", kwargs={\"username\": user.username})\n        == f\"/api/users/{user.username}/\"\n    )\n    assert resolve(f\"/api/users/{user.username}/\").view_name == \"api:user-detail\"\n    {%- endif %}\n\n\ndef test_user_list():\n    assert reverse(\"api:user-list\") == \"/api/users/\"\n    assert resolve(\"/api/users/\").view_name == \"api:user-list\"\n\n\ndef test_user_me():\n    assert reverse(\"api:user-me\") == \"/api/users/me/\"\n    assert resolve(\"/api/users/me/\").view_name == \"api:user-me\"\n{%- elif cookiecutter.rest_api == 'Django Ninja' %}\n\n\ndef test_user_detail(user: User):\n    {%- if cookiecutter.username_type == \"email\" %}\n    assert (\n        reverse(\"api:retrieve_user\", kwargs={\"pk\": user.pk}) == f\"/api/users/{user.pk}/\"\n    )\n    assert resolve(f\"/api/users/{user.pk}/\").view_name == \"api:retrieve_user\"\n    {%- else %}\n    assert (\n        reverse(\"api:retrieve_user\", kwargs={\"username\": user.username})\n        == f\"/api/users/{user.username}/\"\n    )\n    assert resolve(f\"/api/users/{user.username}/\").view_name == \"api:retrieve_user\"\n    {%- endif %}\n\n\ndef test_user_list():\n    assert reverse(\"api:list_users\") == \"/api/users/\"\n    assert resolve(\"/api/users/\").view_name == \"api:list_users\"\n\n\ndef test_current_user():\n    assert reverse(\"api:retrieve_current_user\") == \"/api/users/me/\"\n    assert resolve(\"/api/users/me/\").view_name == \"api:retrieve_current_user\"\n\n\ndef test_update_user():\n    {%- if cookiecutter.username_type == \"email\" %}\n    assert reverse(\"api:update_user\", kwargs={\"pk\": 123}) == \"/api/users/123/\"\n    assert resolve(\"/api/users/123/\").view_name == \"api:retrieve_user\"\n    {%- else %}\n    assert reverse(\"api:update_user\", kwargs={\"username\": \"john\"}) == \"/api/users/john/\"\n    assert resolve(\"/api/users/john/\").view_name == \"api:retrieve_user\"\n    {%- endif %}\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/api/test_views.py",
    "content": "{% if cookiecutter.rest_api == 'DRF' -%}\nimport pytest\nfrom rest_framework.test import APIRequestFactory\n\nfrom {{ cookiecutter.project_slug }}.users.api.views import UserViewSet\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\n\nclass TestUserViewSet:\n    @pytest.fixture\n    def api_rf(self) -> APIRequestFactory:\n        return APIRequestFactory()\n\n    def test_get_queryset(self, user: User, api_rf: APIRequestFactory):\n        view = UserViewSet()\n        request = api_rf.get(\"/fake-url/\")\n        request.user = user\n\n        view.request = request\n\n        assert user in view.get_queryset()\n\n    def test_me(self, user: User, api_rf: APIRequestFactory):\n        view = UserViewSet()\n        request = api_rf.get(\"/fake-url/\")\n        request.user = user\n\n        view.request = request\n\n        response = view.me(request)  # type: ignore[call-arg, arg-type, misc]\n\n        assert response.data == {\n            {%- if cookiecutter.username_type == \"email\" %}\n            \"url\": f\"http://testserver/api/users/{user.pk}/\",\n            {%- else %}\n            \"username\": user.username,\n            \"url\": f\"http://testserver/api/users/{user.username}/\",\n            {%- endif %}\n            \"name\": user.name,\n        }\n{%- elif cookiecutter.rest_api == 'Django Ninja' -%}\nfrom http import HTTPStatus\n\nimport pytest\nfrom django.test import Client\nfrom django.urls import reverse\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\nfrom {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory\n\npytestmark = pytest.mark.django_db\n\n\n@pytest.fixture\ndef user():\n    return UserFactory.create()\n\n\ndef test_list_users_as_anonymous_user(client: Client):\n    response = client.get(reverse(\"api:list_users\"))\n\n    assert response.status_code == HTTPStatus.UNAUTHORIZED\n\n\ndef test_list_users_as_authenticated_user(client: Client, user: User):\n    client.force_login(user)\n    # Another user, excluded from the response\n    UserFactory.create()\n\n    response = client.get(reverse(\"api:list_users\"))\n\n    assert response.status_code == HTTPStatus.OK\n    assert response.json() == [\n        {\n            \"email\": user.email,\n            \"name\": user.name,\n            {%- if cookiecutter.username_type == \"email\" %}\n            \"url\": f\"/api/users/{user.pk}/\",\n            {%- else %}\n            \"url\": f\"/api/users/{user.username}/\",\n            \"username\": user.username,\n            {%- endif %}\n        },\n    ]\n{%- if cookiecutter.username_type == \"email\" %}\n\n\ndef test_retrieve_current_user(client: Client, user: User):\n    client.force_login(user)\n\n    response = client.get(\n        reverse(\"api:retrieve_current_user\"),\n    )\n\n    assert response.status_code == HTTPStatus.OK\n    assert response.json() == {\n        \"email\": user.email,\n        \"name\": user.name,\n        \"url\": f\"/api/users/{user.pk}/\",\n    }\n\n\ndef test_retrieve_user(client: Client, user: User):\n    client.force_login(user)\n\n    response = client.get(\n        reverse(\"api:retrieve_user\", kwargs={\"pk\": user.pk}),\n    )\n\n    assert response.status_code == HTTPStatus.OK\n    assert response.json() == {\n        \"email\": user.email,\n        \"name\": user.name,\n        \"url\": f\"/api/users/{user.pk}/\",\n    }\n{%- else %}\n\n\ndef test_retrieve_current_user(client: Client, user: User):\n    client.force_login(user)\n\n    response = client.get(\n        reverse(\"api:retrieve_current_user\"),\n    )\n\n    assert response.status_code == HTTPStatus.OK\n    assert response.json() == {\n        \"email\": user.email,\n        \"name\": user.name,\n        \"url\": f\"/api/users/{user.username}/\",\n        \"username\": user.username,\n    }\n\n\ndef test_retrieve_user(client: Client, user: User):\n    client.force_login(user)\n\n    response = client.get(\n        reverse(\"api:retrieve_user\", kwargs={\"username\": user.username}),\n    )\n\n    assert response.status_code == HTTPStatus.OK\n    assert response.json() == {\n        \"email\": user.email,\n        \"name\": user.name,\n        \"url\": f\"/api/users/{user.username}/\",\n        \"username\": user.username,\n    }\n{%- endif %}\n\n\ndef test_retrieve_another_user(client: Client, user: User):\n    client.force_login(user)\n    user_2 = UserFactory.create()\n\n    response = client.get(\n        {%- if cookiecutter.username_type == \"email\" %}\n        reverse(\"api:retrieve_user\", kwargs={\"pk\": user_2.pk}),\n        {%- else %}\n        reverse(\"api:retrieve_user\", kwargs={\"username\": user_2.username}),\n        {%- endif %}\n    )\n\n    assert response.status_code == HTTPStatus.NOT_FOUND\n    assert response.json() == {\"detail\": \"Not Found\"}\n\n\ndef test_update_current_user(client: Client):\n    user = UserFactory.create(name=\"Old\")\n    client.force_login(user)\n\n    response = client.patch(\n        reverse(\"api:update_current_user\"),\n        {%- if cookiecutter.username_type == \"email\" %}\n        data='{\"name\": \"New Name\"}',\n        {%- else %}\n        data='{\"name\": \"New Name\", \"username\": \"old\"}',\n        {%- endif %}\n        content_type=\"application/json\",\n    )\n\n    assert response.status_code == HTTPStatus.OK, response.json()\n    assert response.json() == {\n        \"email\": user.email,\n        \"name\": \"New Name\",\n        {%- if cookiecutter.username_type == \"email\" %}\n        \"url\": f\"/api/users/{user.pk}/\",\n        {%- else %}\n        \"username\": \"old\",\n        \"url\": \"/api/users/old/\",\n        {%- endif %}\n    }\n\n\n{%- if cookiecutter.username_type == \"email\" %}\n\n\ndef test_update_user(client: Client):\n    user = UserFactory.create(name=\"Old\")\n    client.force_login(user)\n\n    response = client.patch(\n        reverse(\"api:update_user\", kwargs={\"pk\": user.pk}),\n        data='{\"name\": \"New Name\"}',\n        content_type=\"application/json\",\n    )\n\n    assert response.status_code == HTTPStatus.OK, response.json()\n    assert response.json() == {\n        \"email\": user.email,\n        \"name\": \"New Name\",\n        \"url\": f\"/api/users/{user.pk}/\",\n    }\n{%- else %}\n\n\ndef test_update_user(client: Client):\n    user = UserFactory.create(name=\"Old\", username=\"old\")\n    client.force_login(user)\n\n    response = client.patch(\n        reverse(\"api:update_user\", kwargs={\"username\": \"old\"}),\n        data='{\"name\": \"New Name\", \"username\": \"old\"}',\n        content_type=\"application/json\",\n    )\n\n    assert response.status_code == HTTPStatus.OK, response.json()\n    assert response.json() == {\n        \"email\": user.email,\n        \"name\": \"New Name\",\n        \"url\": \"/api/users/old/\",\n        \"username\": \"old\",\n    }\n{%- endif %}\n{%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/factories.py",
    "content": "from __future__ import annotations\n\nfrom factory import Faker\nfrom factory import post_generation\nfrom factory.django import DjangoModelFactory\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\n\nclass UserFactory(DjangoModelFactory[User]):\n    {%- if cookiecutter.username_type == \"username\" %}\n    username = Faker(\"user_name\")\n    {%- endif %}\n    email = Faker(\"email\")\n    name = Faker(\"name\")\n\n    @post_generation\n    def password(self: User, create: bool, extracted: str | None, **kwargs):  # noqa: FBT001\n        password = (\n            extracted\n            if extracted\n            else Faker(\n                \"password\",\n                length=42,\n                special_chars=True,\n                digits=True,\n                upper_case=True,\n                lower_case=True,\n            ).evaluate(None, None, extra={\"locale\": None})\n        )\n        self.set_password(password)\n        if create:\n            self.save()\n\n    class Meta:\n        model = User\n        django_get_or_create = [\"{{cookiecutter.username_type}}\"]\n        skip_postgeneration_save = True\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_admin.py",
    "content": "import contextlib\nfrom http import HTTPStatus\nfrom importlib import reload\n\nimport pytest\nfrom django.contrib import admin\nfrom django.contrib.auth.models import AnonymousUser\nfrom django.urls import reverse\nfrom pytest_django.asserts import assertRedirects\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\n\nclass TestUserAdmin:\n    def test_changelist(self, admin_client):\n        url = reverse(\"admin:users_user_changelist\")\n        response = admin_client.get(url)\n        assert response.status_code == HTTPStatus.OK\n\n    def test_search(self, admin_client):\n        url = reverse(\"admin:users_user_changelist\")\n        response = admin_client.get(url, data={\"q\": \"test\"})\n        assert response.status_code == HTTPStatus.OK\n\n    def test_add(self, admin_client):\n        url = reverse(\"admin:users_user_add\")\n        response = admin_client.get(url)\n        assert response.status_code == HTTPStatus.OK\n\n        response = admin_client.post(\n            url,\n            data={\n                {%- if cookiecutter.username_type == \"email\" %}\n                \"email\": \"new-admin@example.com\",\n                {%- else %}\n                \"username\": \"test\",\n                {%- endif %}\n                \"password1\": \"My_R@ndom-P@ssw0rd\",\n                \"password2\": \"My_R@ndom-P@ssw0rd\",\n            },\n        )\n        assert response.status_code == HTTPStatus.FOUND\n        {%- if cookiecutter.username_type == \"email\" %}\n        assert User.objects.filter(email=\"new-admin@example.com\").exists()\n        {%- else %}\n        assert User.objects.filter(username=\"test\").exists()\n        {%- endif %}\n\n    def test_view_user(self, admin_client):\n        {%- if cookiecutter.username_type == \"email\" %}\n        user = User.objects.get(email=\"admin@example.com\")\n        {%- else %}\n        user = User.objects.get(username=\"admin\")\n        {%- endif %}\n        url = reverse(\"admin:users_user_change\", kwargs={\"object_id\": user.pk})\n        response = admin_client.get(url)\n        assert response.status_code == HTTPStatus.OK\n\n    @pytest.fixture\n    def _force_allauth(self, settings):\n        settings.DJANGO_ADMIN_FORCE_ALLAUTH = True\n        # Reload the admin module to apply the setting change\n        import {{ cookiecutter.project_slug }}.users.admin as users_admin  # noqa: PLC0415\n\n        with contextlib.suppress(admin.sites.AlreadyRegistered):  # type: ignore[attr-defined]\n            reload(users_admin)\n\n    @pytest.mark.django_db\n    @pytest.mark.usefixtures(\"_force_allauth\")\n    def test_allauth_login(self, rf, settings):\n        request = rf.get(\"/fake-url\")\n        request.user = AnonymousUser()\n        response = admin.site.login(request)\n\n        # The `admin` login view should redirect to the `allauth` login view\n        target_url = reverse(settings.LOGIN_URL) + \"?next=\" + request.path\n        assertRedirects(response, target_url, fetch_redirect_response=False)\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_forms.py",
    "content": "\"\"\"Module for all Form Tests.\"\"\"\n\nfrom django.utils.translation import gettext_lazy as _\n\nfrom {{ cookiecutter.project_slug }}.users.forms import UserAdminCreationForm\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\n\nclass TestUserAdminCreationForm:\n    \"\"\"\n    Test class for all tests related to the UserAdminCreationForm\n    \"\"\"\n\n    def test_username_validation_error_msg(self, user: User):\n        \"\"\"\n        Tests UserAdminCreation Form's unique validator functions correctly by testing:\n            1) A new user with an existing username cannot be added.\n            2) Only 1 error is raised by the UserCreation Form\n            3) The desired error message is raised\n        \"\"\"\n\n        # The user already exists,\n        # hence cannot be created.\n        form = UserAdminCreationForm(\n            {\n                {%- if cookiecutter.username_type == \"email\" %}\n                \"email\": user.email,\n                {%- else %}\n                \"username\": user.username,\n                {%- endif %}\n                \"password1\": user.password,\n                \"password2\": user.password,\n            },\n        )\n\n        assert not form.is_valid()\n        assert len(form.errors) == 1\n        {%- if cookiecutter.username_type == \"email\" %}\n        assert \"email\" in form.errors\n        assert form.errors[\"email\"][0] == _(\"This email has already been taken.\")\n        {%- else %}\n        assert \"username\" in form.errors\n        assert form.errors[\"username\"][0] == _(\"This username has already been taken.\")\n        {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_managers.py",
    "content": "from io import StringIO\n\nimport pytest\nfrom django.core.management import call_command\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\n\n@pytest.mark.django_db\nclass TestUserManager:\n    def test_create_user(self):\n        user = User.objects.create_user(\n            email=\"john@example.com\",\n            password=\"something-r@nd0m!\",  # noqa: S106\n        )\n        assert user.email == \"john@example.com\"\n        assert not user.is_staff\n        assert not user.is_superuser\n        assert user.check_password(\"something-r@nd0m!\")\n        assert user.username is None\n\n    def test_create_superuser(self):\n        user = User.objects.create_superuser(\n            email=\"admin@example.com\",\n            password=\"something-r@nd0m!\",  # noqa: S106\n        )\n        assert user.email == \"admin@example.com\"\n        assert user.is_staff\n        assert user.is_superuser\n        assert user.username is None\n\n    def test_create_superuser_username_ignored(self):\n        user = User.objects.create_superuser(\n            email=\"test@example.com\",\n            password=\"something-r@nd0m!\",  # noqa: S106\n        )\n        assert user.username is None\n\n\n@pytest.mark.django_db\ndef test_createsuperuser_command():\n    \"\"\"Ensure createsuperuser command works with our custom manager.\"\"\"\n    out = StringIO()\n    command_result = call_command(\n        \"createsuperuser\",\n        \"--email\",\n        \"henry@example.com\",\n        interactive=False,\n        stdout=out,\n    )\n\n    assert command_result is None\n    assert out.getvalue() == \"Superuser created successfully.\\n\"\n    user = User.objects.get(email=\"henry@example.com\")\n    assert not user.has_usable_password()\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_models.py",
    "content": "from {{ cookiecutter.project_slug }}.users.models import User\n\n\ndef test_user_get_absolute_url(user: User):\n    {%- if cookiecutter.username_type == \"email\" %}\n    assert user.get_absolute_url() == f\"/users/{user.pk}/\"\n    {%- else %}\n    assert user.get_absolute_url() == f\"/users/{user.username}/\"\n    {%- endif %}\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_tasks.py",
    "content": "import pytest\nfrom celery.result import EagerResult\n\nfrom {{ cookiecutter.project_slug }}.users.tasks import get_users_count\nfrom {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory\n\npytestmark = pytest.mark.django_db\n\n\ndef test_user_count(settings):\n    \"\"\"A basic test to execute the get_users_count Celery task.\"\"\"\n    batch_size = 3\n    UserFactory.create_batch(batch_size)\n    settings.CELERY_TASK_ALWAYS_EAGER = True\n    task_result = get_users_count.delay()\n    assert isinstance(task_result, EagerResult)\n    assert task_result.result == batch_size\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_urls.py",
    "content": "from django.urls import resolve\nfrom django.urls import reverse\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\n\ndef test_detail(user: User):\n    {%- if cookiecutter.username_type == \"email\" %}\n    assert reverse(\"users:detail\", kwargs={\"pk\": user.pk}) == f\"/users/{user.pk}/\"\n    assert resolve(f\"/users/{user.pk}/\").view_name == \"users:detail\"\n    {%- else %}\n    assert (\n        reverse(\"users:detail\", kwargs={\"username\": user.username})\n        == f\"/users/{user.username}/\"\n    )\n    assert resolve(f\"/users/{user.username}/\").view_name == \"users:detail\"\n    {%- endif %}\n\n\ndef test_update():\n    assert reverse(\"users:update\") == \"/users/~update/\"\n    assert resolve(\"/users/~update/\").view_name == \"users:update\"\n\n\ndef test_redirect():\n    assert reverse(\"users:redirect\") == \"/users/~redirect/\"\n    assert resolve(\"/users/~redirect/\").view_name == \"users:redirect\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_views.py",
    "content": "from http import HTTPStatus\n\nimport pytest\nfrom django.conf import settings\nfrom django.contrib import messages\nfrom django.contrib.auth.models import AnonymousUser\nfrom django.contrib.messages.middleware import MessageMiddleware\nfrom django.contrib.sessions.middleware import SessionMiddleware\nfrom django.http import HttpRequest\nfrom django.http import HttpResponseRedirect\nfrom django.test import RequestFactory\nfrom django.urls import reverse\nfrom django.utils.translation import gettext_lazy as _\n\nfrom {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm\nfrom {{ cookiecutter.project_slug }}.users.models import User\nfrom {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory\nfrom {{ cookiecutter.project_slug }}.users.views import UserRedirectView\nfrom {{ cookiecutter.project_slug }}.users.views import UserUpdateView\nfrom {{ cookiecutter.project_slug }}.users.views import user_detail_view\n\npytestmark = pytest.mark.django_db\n\n\nclass TestUserUpdateView:\n    \"\"\"\n    TODO:\n        extracting view initialization code as class-scoped fixture\n        would be great if only pytest-django supported non-function-scoped\n        fixture db access -- this is a work-in-progress for now:\n        https://github.com/pytest-dev/pytest-django/pull/258\n    \"\"\"\n\n    def dummy_get_response(self, request: HttpRequest):\n        return None\n\n    def test_get_success_url(self, user: User, rf: RequestFactory):\n        view = UserUpdateView()\n        request = rf.get(\"/fake-url/\")\n        request.user = user\n\n        view.request = request\n\n        {%- if cookiecutter.username_type == \"email\" %}\n        assert view.get_success_url() == f\"/users/{user.pk}/\"\n        {%- else %}\n        assert view.get_success_url() == f\"/users/{user.username}/\"\n        {%- endif %}\n\n    def test_get_object(self, user: User, rf: RequestFactory):\n        view = UserUpdateView()\n        request = rf.get(\"/fake-url/\")\n        request.user = user\n\n        view.request = request\n\n        assert view.get_object() == user\n\n    def test_form_valid(self, user: User, rf: RequestFactory):\n        view = UserUpdateView()\n        request = rf.get(\"/fake-url/\")\n\n        # Add the session/message middleware to the request\n        SessionMiddleware(self.dummy_get_response).process_request(request)\n        MessageMiddleware(self.dummy_get_response).process_request(request)\n        request.user = user\n\n        view.request = request\n\n        # Initialize the form\n        form = UserAdminChangeForm()\n        form.cleaned_data = {}\n        form.instance = user\n        view.form_valid(form)\n\n        messages_sent = [m.message for m in messages.get_messages(request)]\n        assert messages_sent == [_(\"Information successfully updated\")]\n\n\nclass TestUserRedirectView:\n    def test_get_redirect_url(self, user: User, rf: RequestFactory):\n        view = UserRedirectView()\n        request = rf.get(\"/fake-url\")\n        request.user = user\n\n        view.request = request\n\n        {%- if cookiecutter.username_type == \"email\" %}\n        assert view.get_redirect_url() == f\"/users/{user.pk}/\"\n        {%- else %}\n        assert view.get_redirect_url() == f\"/users/{user.username}/\"\n        {%- endif %}\n\n\nclass TestUserDetailView:\n    def test_authenticated(self, user: User, rf: RequestFactory):\n        request = rf.get(\"/fake-url/\")\n        request.user = UserFactory.create()\n\n        {%- if cookiecutter.username_type == \"email\" %}\n        response = user_detail_view(request, pk=user.pk)\n        {%- else %}\n        response = user_detail_view(request, username=user.username)\n        {%- endif %}\n\n        assert response.status_code == HTTPStatus.OK\n\n    def test_not_authenticated(self, user: User, rf: RequestFactory):\n        request = rf.get(\"/fake-url/\")\n        request.user = AnonymousUser()\n\n        {%- if cookiecutter.username_type == \"email\" %}\n        response = user_detail_view(request, pk=user.pk)\n        {%- else %}\n        response = user_detail_view(request, username=user.username)\n        {%- endif %}\n        login_url = reverse(settings.LOGIN_URL)\n\n        assert isinstance(response, HttpResponseRedirect)\n        assert response.status_code == HTTPStatus.FOUND\n        assert response.url == f\"{login_url}?next=/fake-url/\"\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/urls.py",
    "content": "from django.urls import path\n\nfrom .views import user_detail_view\nfrom .views import user_redirect_view\nfrom .views import user_update_view\n\napp_name = \"users\"\nurlpatterns = [\n    path(\"~redirect/\", view=user_redirect_view, name=\"redirect\"),\n    path(\"~update/\", view=user_update_view, name=\"update\"),\n    {%- if cookiecutter.username_type == \"email\" %}\n    path(\"<int:pk>/\", view=user_detail_view, name=\"detail\"),\n    {%- else %}\n    path(\"<str:username>/\", view=user_detail_view, name=\"detail\"),\n    {%- endif %}\n]\n"
  },
  {
    "path": "{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py",
    "content": "from django.contrib.auth.mixins import LoginRequiredMixin\nfrom django.contrib.messages.views import SuccessMessageMixin\nfrom django.db.models import QuerySet\nfrom django.urls import reverse\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views.generic import DetailView\nfrom django.views.generic import RedirectView\nfrom django.views.generic import UpdateView\n\nfrom {{ cookiecutter.project_slug }}.users.models import User\n\n\nclass UserDetailView(LoginRequiredMixin, DetailView):\n    model = User\n    {%- if cookiecutter.username_type == \"email\" %}\n    slug_field = \"id\"\n    slug_url_kwarg = \"id\"\n    {%- else %}\n    slug_field = \"username\"\n    slug_url_kwarg = \"username\"\n    {%- endif %}\n\n\nuser_detail_view = UserDetailView.as_view()\n\n\nclass UserUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):\n    model = User\n    fields = [\"name\"]\n    success_message = _(\"Information successfully updated\")\n\n    def get_success_url(self) -> str:\n        assert self.request.user.is_authenticated  # type guard\n        return self.request.user.get_absolute_url()\n\n    def get_object(self, queryset: QuerySet | None = None) -> User:\n        assert self.request.user.is_authenticated  # type guard\n        return self.request.user\n\n\nuser_update_view = UserUpdateView.as_view()\n\n\nclass UserRedirectView(LoginRequiredMixin, RedirectView):\n    permanent = False\n\n    def get_redirect_url(self) -> str:\n        {%- if cookiecutter.username_type == \"email\" %}\n        return reverse(\"users:detail\", kwargs={\"pk\": self.request.user.pk})\n        {%- else %}\n        return reverse(\"users:detail\", kwargs={\"username\": self.request.user.username})\n        {%- endif %}\n\n\nuser_redirect_view = UserRedirectView.as_view()\n"
  }
]