Opened 5 months ago
Last modified 5 months ago
#35641 closed New feature
Pattern matching on model objects — at Version 2
Reported by: | Johan Dahlin | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 5.0 |
Severity: | Normal | Keywords: | |
Cc: | Johan Dahlin | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
It would be nice if I could use pattern matching on Django model fields, this is especially important in context where I don't know what the model is, for example in a global post_save() handler where I want to do some specific logic based on a subclass.
class Person(Model): name = TextField(...) age = IntegerField(...) class Company(Model): address = TextField(...)
I would then be able to do
@receiver(pre_save) def pre_save(sender, instance, ....): # model comes in via signals or some other way, we don't know which subclass it is match model: # equivalent to isinstance(model, Person) and model.age > 10: case Person(age) if age> 10: .... # equivalent to isinstance(model, Company) and model.name.endswith('Street') case Company(address) if name.endswith('Street'): .... # or just extract and return a value case Person(name): return name
Since match_args must be a tuple, the attribute must be generated inside a metaclass.
{{{#!python
@property
def match_args(self) -> tuple[str, ...]:
return tuple(f.name for f in self._meta.get_fields())
}}}
Happy to create a PR if this is interesting.
I removed an earlier comment about a simple/straight-forward implementation using a @property but it won't work as, match_args needs to be a tuple and cannot be a property, so my suggested implementation above is too simplistic. I real one would have to be a bit more involved and generate the values and create a tuple inside the models metaclass.