Description:
The Func class allows for rendering SQL functions with access to the model's meta, fields, and columns variables. However, there is currently no direct way to access ManyToMany fields by their name. The only available approach requires using positional indexing, which can lead to fragile code when models are altered.
For example, to access a ManyToMany field, users currently have to use:
{{meta.many_to_many[0].remote_field.through._meta.db_table}}
Proposed Solution:
To improve this, we can modify the render method in the Func class to include a many_to_many argument, allowing access to ManyToMany fields by name:
def render(self, model: models.Model) -> str:
"""
Render the SQL of the function.
Args:
model: The model.
Returns:
The rendered SQL.
"""
fields = utils.AttrDict({field.name: field for field in model._meta.fields})
columns = utils.AttrDict({field.name: field.column for field in model._meta.fields})
many_to_many = utils.AttrDict({field.name: field for field in model._meta.many_to_many})
return self.func.format(meta=model._meta, fields=fields, columns=columns, many_to_many=many_to_many)
Then, in Func, it would be possible to use:
# Assuming we have models A and B and A has a M2M to B called b_items,
# and A is an abstract model that can be inherited.
pgtrigger.Func(f"""
...
SELECT array_agg(model_a_to_b.b_id)
INTO b_ids
FROM {{many_to_many['b_items'].remote_field.through._meta.db_table}} model_a_to_b
WHERE model_a_to_b.{{meta.model_name}}_id = NEW.id;
...
""")
Benefits:
- Better Maintainability: Accessing fields by name reduces the risk of breaking code when the field order changes.
- Ease of Use: Simplifies the syntax for accessing
ManyToMany fields.
- Dynamic Models: Particularly useful for models that inherit from abstract base classes where
related_name attributes are set dynamically.
Version Info:
- Django: 5.0.7
- django-pgtrigger: 4.12.2
PS: Just wanted to say a big thank you to the authors for creating such an amazing library! It’s been a huge help in our projects, and we really appreciate all the hard work you put into it. Keep up the great work! 🙌
Description:
The
Funcclass allows for rendering SQL functions with access to the model'smeta,fields, andcolumnsvariables. However, there is currently no direct way to accessManyToManyfields by their name. The only available approach requires using positional indexing, which can lead to fragile code when models are altered.For example, to access a
ManyToManyfield, users currently have to use:{{meta.many_to_many[0].remote_field.through._meta.db_table}}Proposed Solution:
To improve this, we can modify the
rendermethod in theFuncclass to include amany_to_manyargument, allowing access toManyToManyfields by name:Then, in
Func, it would be possible to use:Benefits:
ManyToManyfields.related_nameattributes are set dynamically.Version Info:
PS: Just wanted to say a big thank you to the authors for creating such an amazing library! It’s been a huge help in our projects, and we really appreciate all the hard work you put into it. Keep up the great work! 🙌