|
| 1 | +============================================================== |
| 2 | +How to override project and app file structure using templates |
| 3 | +============================================================== |
| 4 | + |
| 5 | + |
| 6 | +Introduction |
| 7 | +============ |
| 8 | + |
| 9 | +The first command you will run when setting up a django project is |
| 10 | +:djadmin:`startproject`. Having set up your project, you will then start |
| 11 | +creating your apps with :djadmin:`startapp`. Each of these commands will create |
| 12 | +a file structure that is based on default templates within the Django |
| 13 | +repository. |
| 14 | + |
| 15 | +However, you can create your own templates so that when you run |
| 16 | +:djadmin:`startproject` or :djadmin:`startapp` it creates the app and project |
| 17 | +structure that is best for you. |
| 18 | + |
| 19 | +What the defaults look like |
| 20 | +=========================== |
| 21 | + |
| 22 | +The command :djadmin:`startproject` will create the ``manage.py`` file, along |
| 23 | +with a folder named after the ``project_name`` parameter passed in the initial |
| 24 | +command. Here the command is run with the project name as ``myproject``: |
| 25 | + |
| 26 | +.. console:: |
| 27 | + |
| 28 | + $ django-admin startproject myproject . |
| 29 | + |
| 30 | +The resulting file structure is based on the default template-file structure in |
| 31 | +(:source:`django/conf/project_templates`). There, each file has the extension |
| 32 | +``.py-tpl`` to denote the file as a template. Each template contains template |
| 33 | +tags that end up being filled from the command and django version context. The |
| 34 | +template context is detailed at the end of the documentation for |
| 35 | +:djadmin:`startproject`. |
| 36 | + |
| 37 | +The resulting files all have the ``.py`` file extension and are ready to be |
| 38 | +used: |
| 39 | + |
| 40 | +.. code-block:: none |
| 41 | + |
| 42 | + myproject/ |
| 43 | + manage.py |
| 44 | + myproject/ |
| 45 | + __init__.py |
| 46 | + asgi.py |
| 47 | + settings.py |
| 48 | + urls.py |
| 49 | + wsgi.py |
| 50 | + |
| 51 | +A similar thing happens when you run :djadmin:`startapp`. Both commands inherit |
| 52 | +from the same ``TemplateCommand`` class (in |
| 53 | +:source:`django/core/management/templates.py`), but they discern between app |
| 54 | +and project. |
| 55 | + |
| 56 | +A typical command to initialize an app with the name ``myapp``: |
| 57 | + |
| 58 | +.. console:: |
| 59 | + |
| 60 | + $ python manage.py startapp myapp . |
| 61 | + |
| 62 | +This creates an app in the current directory with the default file structure |
| 63 | +found in (:source:`django/conf/app_templates`). As above, each template has |
| 64 | +the extension ``.py-tpl`` to denote the file as a template, but is copied over |
| 65 | +as a python file. Each template contains template tags for the variables that |
| 66 | +will be passed. |
| 67 | + |
| 68 | +.. code-block:: none |
| 69 | + |
| 70 | + myapp/ |
| 71 | + __init__.py |
| 72 | + admin.py |
| 73 | + apps.py |
| 74 | + migrations/ |
| 75 | + __init__.py |
| 76 | + models.py |
| 77 | + tests.py |
| 78 | + views.py |
| 79 | + |
| 80 | + |
| 81 | +Creating your own Project and App Templates |
| 82 | +=========================================== |
| 83 | + |
| 84 | +The default project and app file structures are the ones suggested by django, |
| 85 | +but not the only ones that can be used. Because django does not require a |
| 86 | +specific file structure for the ``settings`` or ``urls`` files, you can create |
| 87 | +your own structure. The only thing to watch out for is that the imports and |
| 88 | +references to other modules is correct. As long as the files find each other, |
| 89 | +it doesn't matter where they are placed. |
| 90 | + |
| 91 | +The folders that contain your templates can have any naming convention. |
| 92 | +``new_django_template`` is as valid as ``files_structure``. You can even have |
| 93 | +them as a directory, as a zip file or a compressed or uncompressed archive. In |
| 94 | +addition, you can pull them from the web as long as they are in a valid format. |
| 95 | + |
| 96 | +File and folder naming conventions |
| 97 | +---------------------------------- |
| 98 | + |
| 99 | +There is, however, a specific naming convention that needs to be followed in |
| 100 | +order to have your project name as the folder name enclosing the settings |
| 101 | +files. In the project template, the folder that uses the name you pass in the |
| 102 | +:djadmin:`startproject` command must be named ``project_name``. This name is |
| 103 | +then replaced by the name you enter when you run the command. In the example at |
| 104 | +the top of the page the template folder ``project_name`` would be replaced |
| 105 | +with ``myapp``. |
| 106 | + |
| 107 | +For the :djadmin:`startapp` command, this is not necessary, as the folder |
| 108 | +enclosing the files ``admin.py`` and ``urls.py`` is the folder of the app |
| 109 | +template, and the command will take the contents of this folder, and move them |
| 110 | +to a folder with the name passed in the command. |
| 111 | + |
| 112 | +However, you can leverage the app name or project name if you have a file or |
| 113 | +folder that needs to use the name. Because this substitution happens using |
| 114 | +Python's string ``replace`` function, you can have something like a separate |
| 115 | +settings folder in your template with the name ``project_name_settings`` and |
| 116 | +the folder name will be changed, as in the above example to |
| 117 | +``myproject_settings``. The same is true for files with ``project_name`` as |
| 118 | +part of their name. For apps, you should have folders or files with |
| 119 | +``app_name`` within their name. In our example, ``app_name`` would be replaced |
| 120 | +by ``myapp`` and ``app_name_utilities`` would be replaced by |
| 121 | +``myapp_utilities``. |
| 122 | + |
| 123 | +File structure of the templates |
| 124 | +------------------------------- |
| 125 | + |
| 126 | +Neither the :djadmin:`startproject` nor the :djadmin:`startapp` commands |
| 127 | +generate the code in the files. They only copy existing files and (when |
| 128 | +applicable) insert the context. When the files are copied from a custom project |
| 129 | +template, they are copied directly without any code modifications from the |
| 130 | +default templates. It is up to the developer to make sure that the template |
| 131 | +file structure and code actually works, and that they contain up-to-date code, |
| 132 | +settings, and variables for the version of django being used. When updating the |
| 133 | +Django version, it is recommended to double-check against the default project |
| 134 | +or app template files to see what has been added or changed. It is highly |
| 135 | +recommended to start a django project first, make sure that the files work |
| 136 | +together, and then create a template based on that file structure and content. |
| 137 | + |
| 138 | +As a example, a flat Django project can look like this, with all of the files |
| 139 | +normally found in the project folder outside that folder, and at the same level |
| 140 | +as ``manage.py``: |
| 141 | + |
| 142 | +.. code-block:: none |
| 143 | + |
| 144 | + myproject/ |
| 145 | + asgi.py |
| 146 | + manage.py |
| 147 | + settings.py |
| 148 | + urls.py |
| 149 | + wsgi.py |
| 150 | + |
| 151 | + |
| 152 | +In this particular instance, to make the files work with each other, you'd have |
| 153 | +to adapt the settings reference in ``manage.py`` to refer to ``"settings"`` |
| 154 | +instead of ``"myproject.settings"`` since your ``settings.py`` file is no |
| 155 | +longer in the created ``myproject`` folder, but at the same level as |
| 156 | +``manage.py``. Likewise in ``settings.py``, you'd have to change the value of |
| 157 | +:settings:`ROOT_URLCONF` from ``"myproject.urls"`` to simply ``"urls"`` and |
| 158 | +:settings:`WSGI_APPLICATION` from ``"myproject.wsgi.application"`` to |
| 159 | +``"wsgi.application"``. |
| 160 | + |
| 161 | +For the :djadmin:`startapp` command, there is less that can be customized since |
| 162 | +it is a single folder with files and a migrations folder within. If certain |
| 163 | +files are not needed they can be left out. For example, if no models will be |
| 164 | +used, the ``models.py`` file and the ``migrations`` folder can be left out. In |
| 165 | +this case the ``admin.py`` file could also be left off. Conversely, if you |
| 166 | +always use custom managers, you could add a ``managers.py`` file to your custom |
| 167 | +structure to make sure the file is always there. |
| 168 | + |
| 169 | +Template suffixes |
| 170 | +----------------- |
| 171 | + |
| 172 | +For convenience, python files used in the templates use the suffix ``.py-tpl``. |
| 173 | +During the process of creating the project or app files, the suffix is changed |
| 174 | +to ``.py``. However, this is not absolutely necessary, since any files with the |
| 175 | +``.py`` suffix can have the context changed by the templating engine if they |
| 176 | +contain template tags that are variables. |
| 177 | + |
| 178 | + |
| 179 | +Templating non-Python files |
| 180 | +--------------------------- |
| 181 | + |
| 182 | +Since the commands that use the templates just copy files, you can have any |
| 183 | +type of file in the project or app template. This is especially useful if you |
| 184 | +want to set up frontend or infrastructure files within the project template. |
| 185 | + |
| 186 | +Any type of file is supported as long as it doesn't end with ``.pyo``, |
| 187 | +``.pyc``, or ``.py.class``. Any type of directory is supported as long as it |
| 188 | +doesn't begin with a period ``.`` (hidden directory) or is a ``__pycache__`` |
| 189 | +file. |
| 190 | + |
| 191 | +You can even use the template engine to fill in ``{{ project_name }}`` in |
| 192 | +places where the project name would be commonly used by other apps, such as in |
| 193 | +Kubernetes or Docker files. |
| 194 | + |
| 195 | + |
| 196 | +Excluding parts of files from templating |
| 197 | +---------------------------------------- |
| 198 | + |
| 199 | +The templating engine will overwrite any context variables found in the project |
| 200 | +or app template. Sometimes, for the purposes of documentation, you want to |
| 201 | +leave the variables visible in the produced app or project structure. To have |
| 202 | +``{{ django_version }}`` or ``{{ project_name }}`` still visible in the |
| 203 | +resulting file, you can wrap that part of the file, or even the whole file with |
| 204 | +the template tags ``{% verbatim %}`` and ``{% endverbatim %}``. The templating |
| 205 | +engine will end up removing them from the finished file. |
| 206 | + |
| 207 | + |
| 208 | +Using your templates |
| 209 | +==================== |
| 210 | + |
| 211 | +The basic command to start your project using your new template is: |
| 212 | + |
| 213 | +.. console:: |
| 214 | + |
| 215 | + $ django-admin startproject myproject . |
| 216 | + |
| 217 | +To add non-python files to the templating engine, add the names to the |
| 218 | +``extension`` flag like so: |
| 219 | + |
| 220 | +.. console:: |
| 221 | + |
| 222 | + $ django-admin startproject myproject . --extension js,toml |
| 223 | + |
| 224 | +So now all Javascript and toml files will be run through the templating engine |
| 225 | +to replace any variables. |
| 226 | + |
| 227 | +If you are using any non-python files that you need run through the templating |
| 228 | +engine that do not have extensions, such as ``Dockerfile`` or ``.gitignore``, |
| 229 | +or for files with extensions in which only some files should go through the |
| 230 | +template engine, you can add them individually after the ``name`` flag: |
| 231 | + |
| 232 | +.. console:: |
| 233 | + |
| 234 | + $ django-admin startproject myproject . --name Dockerfile,.gitignore |
| 235 | + |
| 236 | +To exclude any directories from being affected by the template engine, you can |
| 237 | +use the ``exclude`` flag and they will be removed from the folders to go |
| 238 | +through templating: |
| 239 | + |
| 240 | +.. console:: |
| 241 | + |
| 242 | + $ django-admin startproject myproject . --exclude frontend,reference |
| 243 | + |
| 244 | +The flag usage above holds true for ``python manage.py startapp .``, but, |
| 245 | +instead, you would be working on the app level instead of the project level. |
| 246 | + |
| 247 | +For more information, you can visit the documentation for |
| 248 | +:djadmin:`startproject` and :djadmin:`startapp`. |
0 commit comments