# Dinja
Dinja is a small tool for creating any text file format from a [DBML](https://dbml.dbdiagram.io/home/)
database definition using [Jinja2](https://jinja.palletsprojects.com/en/stable/) templates. It can
be used to auto-generate e.g. DDL, database access code or schema documentation from a single DBML
file, maintaining a single source of truth for your database schema definition.
Its name is made from "**D**BML" and "J**inja**2", but it's also name of
[Cucumis melo](https://en.wikipedia.org/wiki/Cucumis_melo) (a melon) 🍈 🍉 in Croatian.
## Installation
Dinja is available on [PyPI](https://pypi.org/project/dinja-tool/), so you can install it with pip:
```
pip install dinja-tool
```
## Usage
### 1. Create your Jinja2 template(s)
The template files are of the destination file format but contain some special markers that Dinja
replaces with the real database schema data. Their file names must end with either `.jinja` or
`.in`. See the [Jinja2 template documentation](https://jinja.palletsprojects.com/en/stable/templates/)
for how to write such a template.
The Python data structures provided to the templates are documented in the
[dinja.api](https://codeberg.org/Aardjon/dinja/src/branch/main/src/dinja/api.py) module.
Dinja can render several template files at once - simply put them all into a single directory.
### 2. Run Dinja on your DBML file
The following command converts the `dbschema.dbml` file by rendering all template files inside the
`jinja_templates` directory, storing the resulting files into the `generated` directory (creating
one rendered file for each template).
```
$ dinja dbschema.dbml jinja_templates generated
```
The result files have the same names as their corresponding template files, but without the `.jinja`
or `.in` suffix. Existing files are overwritten without a warning.
`dinja -h` or `dinja --help` prints a summary of all possible options and arguments.
## Examples
Let's create and render a template for the example tables from the
[DBML introduction](https://dbml.dbdiagram.io/home/):
```dbml
Table users {
id integer
username varchar
role varchar
created_at timestamp
}
Table posts {
id integer [primary key]
title varchar
body text [note: 'Content of the post']
user_id integer
status integer
created_at timestamp
}
```
Store this into the local file `example.dbml`.
For example, the following Jinja2 template generates SQLite2 DDL:
```
{% for table in tables %}
CREATE TABLE {{table.name}} (
{% for column in table.columns %}
"{{column.name}}" {{column.type.upper()}}
{{-" PRIMARY KEY" if column.primary_key}}
{{-" UNIQUE" if column.unique}}
{{-" NOT NULL" if not column.nullable}}
{{-" AUTOINCREMENT" if column.autoincrement}}
{{-"," if not loop.last or table.primary_key or table.unique_constraints or table.references}}
{% endfor %}
{% if table.primary_key %}
PRIMARY KEY({{table.primary_key|join(", ")}})
{{-"," if table.unique_constraints or table.references}}
{%endif %}
{% for columns in table.unique_constraints %}
UNIQUE({{columns|join(", ")}})
{{- "," if not loop.last or table.references}}
{% endfor %}
{% for ref in table.references %}
FOREIGN KEY("{{ref.local_columns|join(", ")}}") REFERENCES "{{ref.table_name}}" ("{{ref.remote_columns|join(", ")}}")
{{-" ON DELETE {}".format(ref.delete_action) if ref.delete_action}}
{{-"," if not loop.last}}
{% endfor %}
);
{% endfor %}
```
Store it into a local file named `schema_creation.sql.in` within the `templates` directory, and run
```
$ dinja example.dbml templates .
```
This will create a new file `schema_creation.sql` with the following SQL content:
```
CREATE TABLE users (
"id" INTEGER,
"username" VARCHAR,
"role" VARCHAR,
"created_at" TIMESTAMP
);
CREATE TABLE posts (
"id" INTEGER PRIMARY KEY,
"title" VARCHAR,
"body" TEXT,
"user_id" INTEGER,
"status" INTEGER,
"created_at" TIMESTAMP
);
```
By creating Jinja2 templates according to your needs, you can generate literally any text-based file
format from your DBML definition.
## Copyright & License
Copyright 2025 by Thomas Wesenigk.
Licensed under the EUPL 1.2. Visit https://interoperable-europe.ec.europa.eu/collection/eupl/eupl-text-eupl-12
to read it in your favourite language.
Raw data
{
"_id": null,
"home_page": "https://codeberg.org/Aardjon/dinja",
"name": "dinja-tool",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "dbml, jinja, template, code generation, database, schema",
"author": "Thomas Wesenigk",
"author_email": "aardjon@noreply.codeberg.org",
"download_url": "https://files.pythonhosted.org/packages/20/f9/4f89cbab94e1e39651f0541aa641e2bfb62668afd324d9608842651b6aa1/dinja_tool-0.2.0.tar.gz",
"platform": null,
"description": "# Dinja\n\nDinja is a small tool for creating any text file format from a [DBML](https://dbml.dbdiagram.io/home/)\ndatabase definition using [Jinja2](https://jinja.palletsprojects.com/en/stable/) templates. It can\nbe used to auto-generate e.g. DDL, database access code or schema documentation from a single DBML\nfile, maintaining a single source of truth for your database schema definition.\n\nIts name is made from \"**D**BML\" and \"J**inja**2\", but it's also name of\n[Cucumis melo](https://en.wikipedia.org/wiki/Cucumis_melo) (a melon) \ud83c\udf48 \ud83c\udf49 in Croatian.\n\n## Installation\n\nDinja is available on [PyPI](https://pypi.org/project/dinja-tool/), so you can install it with pip:\n\n```\npip install dinja-tool\n```\n\n## Usage\n\n### 1. Create your Jinja2 template(s)\n\nThe template files are of the destination file format but contain some special markers that Dinja\nreplaces with the real database schema data. Their file names must end with either `.jinja` or\n`.in`. See the [Jinja2 template documentation](https://jinja.palletsprojects.com/en/stable/templates/)\nfor how to write such a template.\n\nThe Python data structures provided to the templates are documented in the\n[dinja.api](https://codeberg.org/Aardjon/dinja/src/branch/main/src/dinja/api.py) module.\n\nDinja can render several template files at once - simply put them all into a single directory.\n\n### 2. Run Dinja on your DBML file\n\nThe following command converts the `dbschema.dbml` file by rendering all template files inside the\n`jinja_templates` directory, storing the resulting files into the `generated` directory (creating\none rendered file for each template).\n\n```\n$ dinja dbschema.dbml jinja_templates generated\n```\n\nThe result files have the same names as their corresponding template files, but without the `.jinja`\nor `.in` suffix. Existing files are overwritten without a warning.\n\n`dinja -h` or `dinja --help` prints a summary of all possible options and arguments.\n\n## Examples\n\nLet's create and render a template for the example tables from the\n[DBML introduction](https://dbml.dbdiagram.io/home/):\n\n```dbml\nTable users {\n id integer\n username varchar\n role varchar\n created_at timestamp\n}\n\nTable posts {\n id integer [primary key]\n title varchar\n body text [note: 'Content of the post']\n user_id integer\n status integer\n created_at timestamp\n}\n```\n\nStore this into the local file `example.dbml`.\n\nFor example, the following Jinja2 template generates SQLite2 DDL:\n\n```\n{% for table in tables %}\nCREATE TABLE {{table.name}} (\n {% for column in table.columns %}\n \"{{column.name}}\" {{column.type.upper()}}\n {{-\" PRIMARY KEY\" if column.primary_key}}\n {{-\" UNIQUE\" if column.unique}}\n {{-\" NOT NULL\" if not column.nullable}}\n {{-\" AUTOINCREMENT\" if column.autoincrement}}\n {{-\",\" if not loop.last or table.primary_key or table.unique_constraints or table.references}}\n {% endfor %}\n {% if table.primary_key %}\n PRIMARY KEY({{table.primary_key|join(\", \")}})\n {{-\",\" if table.unique_constraints or table.references}}\n {%endif %}\n {% for columns in table.unique_constraints %}\n UNIQUE({{columns|join(\", \")}})\n {{- \",\" if not loop.last or table.references}}\n {% endfor %}\n {% for ref in table.references %}\n FOREIGN KEY(\"{{ref.local_columns|join(\", \")}}\") REFERENCES \"{{ref.table_name}}\" (\"{{ref.remote_columns|join(\", \")}}\")\n {{-\" ON DELETE {}\".format(ref.delete_action) if ref.delete_action}}\n {{-\",\" if not loop.last}}\n {% endfor %}\n);\n\n{% endfor %}\n\n```\n\nStore it into a local file named `schema_creation.sql.in` within the `templates` directory, and run\n\n```\n$ dinja example.dbml templates .\n```\n\nThis will create a new file `schema_creation.sql` with the following SQL content:\n\n```\nCREATE TABLE users (\n \"id\" INTEGER,\n \"username\" VARCHAR,\n \"role\" VARCHAR,\n \"created_at\" TIMESTAMP\n);\n\nCREATE TABLE posts (\n \"id\" INTEGER PRIMARY KEY,\n \"title\" VARCHAR,\n \"body\" TEXT,\n \"user_id\" INTEGER,\n \"status\" INTEGER,\n \"created_at\" TIMESTAMP\n);\n```\n\nBy creating Jinja2 templates according to your needs, you can generate literally any text-based file\nformat from your DBML definition.\n\n\n## Copyright & License\n\nCopyright 2025 by Thomas Wesenigk.\n\nLicensed under the EUPL 1.2. Visit https://interoperable-europe.ec.europa.eu/collection/eupl/eupl-text-eupl-12\nto read it in your favourite language.\n",
"bugtrack_url": null,
"license": "EUPL-1.2",
"summary": "Tool to create text files from DBML using Jinja2 templates.",
"version": "0.2.0",
"project_urls": {
"Homepage": "https://codeberg.org/Aardjon/dinja",
"Repository": "https://codeberg.org/Aardjon/dinja.git"
},
"split_keywords": [
"dbml",
" jinja",
" template",
" code generation",
" database",
" schema"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d776a68dacca6644683ed40885f5e4b67726b915cf580373f0d7a0e1d92292c5",
"md5": "16585c34906f3a23532f9d7da1653659",
"sha256": "1698d4ae91c989ba07e79bd167b968c6a488930323722da0ec2c25bcedabad99"
},
"downloads": -1,
"filename": "dinja_tool-0.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "16585c34906f3a23532f9d7da1653659",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 16240,
"upload_time": "2025-10-20T17:12:48",
"upload_time_iso_8601": "2025-10-20T17:12:48.552022Z",
"url": "https://files.pythonhosted.org/packages/d7/76/a68dacca6644683ed40885f5e4b67726b915cf580373f0d7a0e1d92292c5/dinja_tool-0.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "20f94f89cbab94e1e39651f0541aa641e2bfb62668afd324d9608842651b6aa1",
"md5": "64fe66935d74c93d061954fc59d752c2",
"sha256": "dfc62d0abbb89218c20a6192a7ff5c71d28e865d750562fea75f8ae849128412"
},
"downloads": -1,
"filename": "dinja_tool-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "64fe66935d74c93d061954fc59d752c2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 16881,
"upload_time": "2025-10-20T17:12:49",
"upload_time_iso_8601": "2025-10-20T17:12:49.977021Z",
"url": "https://files.pythonhosted.org/packages/20/f9/4f89cbab94e1e39651f0541aa641e2bfb62668afd324d9608842651b6aa1/dinja_tool-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-20 17:12:49",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": true,
"codeberg_user": "Aardjon",
"codeberg_project": "dinja",
"lcname": "dinja-tool"
}