Skip to content

Commit 94b04ad

Browse files
committed
Allow queries with same slug; "enabled" flag added
1 parent 1c4677a commit 94b04ad

File tree

6 files changed

+132
-3
lines changed

6 files changed

+132
-3
lines changed

CHANGELOG.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
History
44
=======
55

6+
v1.2.5
7+
------
8+
- "enabled" boolean field added
9+
- "slug" is no longer unique, and a Query.objects.get_query_for_slug(query_name)
10+
is available for retriving the active query associated with a certain slug
11+
and detect any duplication
12+
613
v1.2.4
714
------
815
* QUERY_INSPECTOR_QUERY_STOCK_QUERIES can be either a list, or a callable which returns a list

query_inspector/admin.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
@admin.register(Query)
2424
class QueryAdmin(admin.ModelAdmin):
2525

26-
list_display = ("slug", 'stock', "title", "list_parameters", )
27-
list_filter = ('stock', 'from_view', 'from_materialized_view', )
26+
list_display = ("slug", 'is_duplicated', 'enabled', 'stock', "title", "list_parameters", )
27+
list_editable = ('enabled', )
28+
list_filter = ('enabled', 'stock', 'from_view', 'from_materialized_view', )
29+
search_fields = ['slug', ]
2830
save_on_top = True
2931

3032
fieldsets = (
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by Django 4.1.11 on 2024-02-22 09:25
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("query_inspector", "0006_query_from_materialized_view_query_from_view"),
9+
]
10+
11+
operations = [
12+
migrations.AddField(
13+
model_name="query",
14+
name="enabled",
15+
field=models.BooleanField(default=True),
16+
),
17+
migrations.AlterField(
18+
model_name="query",
19+
name="slug",
20+
field=models.SlugField(),
21+
),
22+
]

query_inspector/models.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,45 @@
1010
_named_parameters_sqlite_re = re.compile(r"\$([^ )]+)")
1111

1212

13+
class QueryManager(models.Manager):
14+
15+
def get_active_query_from_slug(self, slug):
16+
"""
17+
Since slug is no longer unique, you can use this helper to identify the active query
18+
associated with a certain slug (thus excluding all disabled queries);
19+
in case of ambiguity it returns None
20+
21+
Example:
22+
23+
my_query = Query.objects.get_query_for_slug(query_name)
24+
25+
"""
26+
queryset = (
27+
self.get_queryset()
28+
.filter(
29+
enabled=True,
30+
#slug=slug,
31+
)
32+
)
33+
return queryset.get(slug=slug)
34+
# if queryset.count() == 1:
35+
# return queryset.first()
36+
# return None
37+
38+
1339
class Query(models.Model):
1440
title = models.CharField(blank=True, max_length=128)
15-
slug = models.SlugField(unique=True)
41+
slug = models.SlugField(unique=False)
42+
enabled = models.BooleanField(null=False, default=True)
1643
sql = models.TextField(null=False, blank=True)
1744
default_parameters = models.JSONField(null=False, default=dict, blank=True)
1845
notes = models.TextField(null=False, blank=True)
1946
stock = models.BooleanField(null=False, default=False, editable=False)
2047
from_view = models.BooleanField(null=False, default=False, editable=False)
2148
from_materialized_view = models.BooleanField(null=False, default=False, editable=False)
2249

50+
objects = QueryManager()
51+
2352
class Meta:
2453
abstract = False
2554
verbose_name = _("Query")
@@ -40,6 +69,22 @@ def can_execute(self, request):
4069
return True
4170
return False
4271

72+
@property
73+
def is_duplicated(self):
74+
"""
75+
Returns True iif this query is enabled, and another enabled query
76+
having the same slug has been detected
77+
"""
78+
duplicated = False
79+
if self.enabled:
80+
try:
81+
the_query = Query.objects.get_active_query_from_slug(self.slug)
82+
except Query.MultipleObjectsReturned:
83+
duplicated = True
84+
except Exception as e:
85+
pass
86+
return duplicated
87+
4388
def extract_named_parameters(self):
4489

4590
def is_sqlite_engine():
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{% load i18n query_inspector_tags %}
2+
3+
<style>
4+
.duplicated, .duplicated a { color: #DD4646 !important; }
5+
.dimmed, .dimmed a { color: #ccc !important; }
6+
</style>
7+
8+
{% if result_hidden_fields %}
9+
<div class="hiddenfields">{# DIV for HTML validation #}
10+
{% for item in result_hidden_fields %}{{ item }}{% endfor %}
11+
</div>
12+
{% endif %}
13+
{% if results %}
14+
<div class="results">
15+
<table id="result_list">
16+
<thead>
17+
<tr>
18+
{% for header in result_headers %}
19+
<th scope="col"{{ header.class_attrib }}>
20+
{% if header.sortable %}
21+
{% if header.sort_priority > 0 %}
22+
<div class="sortoptions">
23+
<a class="sortremove" href="{{ header.url_remove }}" title="{% translate "Remove from sorting" %}"></a>
24+
{% if num_sorted_fields > 1 %}<span class="sortpriority" title="{% blocktranslate with priority_number=header.sort_priority %}Sorting priority: {{ priority_number }}{% endblocktranslate %}">{{ header.sort_priority }}</span>{% endif %}
25+
<a href="{{ header.url_toggle }}" class="toggle {% if header.ascending %}ascending{% else %}descending{% endif %}" title="{% translate "Toggle sorting" %}"></a>
26+
</div>
27+
{% endif %}
28+
{% endif %}
29+
<div class="text">{% if header.sortable %}<a href="{{ header.url_primary }}">{{ header.text|capfirst }}</a>{% else %}<span>{{ header.text|capfirst }}</span>{% endif %}</div>
30+
<div class="clear"></div>
31+
</th>{% endfor %}
32+
</tr>
33+
</thead>
34+
<tbody>
35+
{% for result in results %}
36+
{% if result.form and result.form.non_field_errors %}
37+
<tr><td colspan="{{ result|length }}">{{ result.form.non_field_errors }}</td></tr>
38+
{% endif %}
39+
40+
{% obj_from_result_list cl.result_list forloop.counter0 as query_obj %}
41+
<tr class="{% if not query_obj.enabled %}dimmed {% endif %}{% if query_obj.is_duplicated %}duplicated {% endif %}">
42+
{% for item in result %}{{ item }}{% endfor %}
43+
</tr>
44+
45+
{% endfor %}
46+
</tbody>
47+
</table>
48+
</div>
49+
{% endif %}

query_inspector/templatetags/query_inspector_tags.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ def ipdb(element):
4343
ipdb.set_trace()
4444
return element
4545

46+
@register.simple_tag
47+
def obj_from_result_list(result_list, index):
48+
instance = result_list[index]
49+
return instance
4650

4751
@register.filter
4852
def format_datetime(dt, include_time=True, include_seconds=False, exclude_date=False):

0 commit comments

Comments
 (0)