diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5f57bfb..5bf9120 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,14 +10,14 @@ jobs: strategy: matrix: python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] - postgresql-version: [12, 13, 14, 15, 16] + postgresql-version: [13, 14, 15, 16] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - uses: actions/cache@v2 + - uses: actions/cache@v3 name: Configure pip caching with: path: ~/.cache/pip @@ -47,9 +47,9 @@ jobs: runs-on: ubuntu-latest needs: [test] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: "3.12" - uses: actions/cache@v2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c86b176..a3c2474 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,14 +8,14 @@ jobs: strategy: matrix: python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] - postgresql-version: [12, 13, 14, 15, 16] + postgresql-version: [13, 14, 15, 16] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - uses: actions/cache@v2 + - uses: actions/cache@v3 name: Configure pip caching with: path: ~/.cache/pip @@ -43,4 +43,3 @@ jobs: pytest - name: Check formatting run: black . --check - diff --git a/django_sql_dashboard/admin.py b/django_sql_dashboard/admin.py index c9fef63..ad62770 100644 --- a/django_sql_dashboard/admin.py +++ b/django_sql_dashboard/admin.py @@ -6,7 +6,7 @@ from .models import Dashboard, DashboardQuery -class DashboardQueryInline(admin.TabularInline): +class DashboardQueryInline(admin.StackedInline): model = DashboardQuery extra = 1 @@ -16,10 +16,12 @@ def has_change_permission(self, request, obj=None): return obj.user_can_edit(request.user) def get_readonly_fields(self, request, obj=None): + readonly_fields = ["created_at"] if not request.user.has_perm("django_sql_dashboard.execute_sql"): - return ("sql",) - else: - return tuple() + readonly_fields.extend( + ["sql", "title", "description", "settings", "template"] + ) + return readonly_fields @admin.register(Dashboard) diff --git a/django_sql_dashboard/migrations/0005_add_description_to_query.py b/django_sql_dashboard/migrations/0005_add_description_to_query.py new file mode 100644 index 0000000..da845f7 --- /dev/null +++ b/django_sql_dashboard/migrations/0005_add_description_to_query.py @@ -0,0 +1,54 @@ +# Generated by Django 3.2.8 on 2023-04-14 16:44 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + dependencies = [ + ("django_sql_dashboard", "0004_add_description_help_text"), + ] + + operations = [ + migrations.AddField( + model_name="dashboardquery", + name="created_at", + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name="dashboardquery", + name="description", + field=models.TextField( + blank=True, help_text="Optional description (Markdown allowed)" + ), + ), + migrations.AddField( + model_name="dashboardquery", + name="settings", + field=models.JSONField( + blank=True, + default=dict, + help_text="Settings for this query (JSON). These settings are passed to the template.", + null=True, + ), + ), + migrations.AddField( + model_name="dashboardquery", + name="template", + field=models.CharField( + blank=True, + help_text="Template to use for rendering this query. Leave blank to use the default template or fetch based on the column names.", + max_length=255, + ), + ), + migrations.AddField( + model_name="dashboardquery", + name="title", + field=models.CharField(blank=True, max_length=128), + ), + migrations.AlterField( + model_name="dashboardquery", + name="sql", + field=models.TextField(verbose_name="SQL query"), + ), + ] diff --git a/django_sql_dashboard/models.py b/django_sql_dashboard/models.py index 3dd7007..583ca45 100644 --- a/django_sql_dashboard/models.py +++ b/django_sql_dashboard/models.py @@ -145,7 +145,23 @@ class DashboardQuery(models.Model): dashboard = models.ForeignKey( Dashboard, related_name="queries", on_delete=models.CASCADE ) - sql = models.TextField() + title = models.CharField(blank=True, max_length=128) + sql = models.TextField(verbose_name="SQL query") + created_at = models.DateTimeField(default=timezone.now) + description = models.TextField( + blank=True, help_text="Optional description (Markdown allowed)" + ) + template = models.CharField( + max_length=255, + blank=True, + help_text="Template to use for rendering this query. Leave blank to use the default template or fetch based on the column names.", + ) + settings = models.JSONField( + blank=True, + null=True, + default=dict, + help_text="Settings for this query (JSON). These settings are passed to the template.", + ) def __str__(self): return self.sql diff --git a/django_sql_dashboard/templates/django_sql_dashboard/widgets/_base_widget.html b/django_sql_dashboard/templates/django_sql_dashboard/widgets/_base_widget.html index 828595a..8184219 100644 --- a/django_sql_dashboard/templates/django_sql_dashboard/widgets/_base_widget.html +++ b/django_sql_dashboard/templates/django_sql_dashboard/widgets/_base_widget.html @@ -1,4 +1,12 @@ +{% load django_sql_dashboard %} +
{{ result.sql }}{% else %}