Repository navigation
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Hi @opus10! I'm not sure whether this is something that might be interesting to include or mention in the documentation:
import pgtrigger
from django.template import Context, Template
class TemplateFunc(pgtrigger.Func):
def render(self, model):
fields = {field.name: field for field in model._meta.fields}
columns = {field.name: field.column for field in model._meta.fields}
template = Template(self.func)
context = Context({"meta": model._meta, "fields": fields, "columns": columns})
return template.render(context)It allows you to use Django's template engine to write trigger functions. I had the following use case:
class Meta:
triggers = [
pgtrigger.Trigger(
name="product_upsert",
operation=pgtrigger.Insert,
timing=pgtrigger.Immediate,
when=pgtrigger.After,
func=TemplateFunc(
"""
IF EXISTS (
SELECT *
FROM {{ meta.db_table }}
WHERE {{ columns.gtin }}=NEW.{{ columns.gtin }} OR (
{{ columns.category }}=NEW.{{ columns.category }} AND
{{ columns.subcategory }}=NEW.{{ columns.subcategory }} AND
{{ columns.vendor }}=NEW.{{ columns.vendor }} AND
{{ columns.model }}=NEW.{{ columns.model }}
)
) THEN
UPDATE {{ meta.db_table }} SET
{% for column in columns %}
{% if column != "id" and column != "created" %}
{{ column }}=NEW.{{ column }}{% if not forloop.last %},{% endif %}
{% endif %}
{% endfor %}
WHERE {{ columns.gtin }}=NEW.{{ columns.gtin }} OR (
{{ columns.category }}=NEW.{{ columns.category }} AND
{{ columns.subcategory }}=NEW.{{ columns.subcategory }} AND
{{ columns.vendor }}=NEW.{{ columns.vendor }} AND
{{ columns.model }}=NEW.{{ columns.model }}
);
RETURN NULL;
ELSE
RETURN NEW;
END IF;
"""
),
),
]Reacted by Michael Rosner
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
adonig commentedon Feb 20, 2023
Here's a typed version that allows to specify an extra context:
wesleykendall commentedon Jun 8, 2023
@adonig I really like this suggestion!
I'm happy to accept this as a PR to
django-pgtriggeras is. I can also open a PR and add you as aCo-authored-byin the comment.One suggestion - I wonder if there's a way to grab these variables for other models. It's common to write a trigger across a few tables.
Could also throw in a basic template tag for people that want to write functions over other models:
Not sure if that's totally correct, but I hope it makes sense.
adonig commentedon Jun 9, 2023
@wesleykendall I'm glad it turns out to become useful. The template tag sounds like a good idea. It might look like this: