jayvdb / django-dunder

Django app to attach usable __repr__ and __str__ to any and all Django models, using unmigrated __unicode__ on Python 3
MIT License
2 stars 2 forks source link

Add custom str() formats #2

Open jayvdb opened 4 years ago

jayvdb commented 4 years ago

The current format is User(...) .

The format closer to Django's default is <User: ...>.

The project should be able to define their own format string+formatters comprising at least variables model and attrs.

jayvdb commented 4 years ago

I've switched it to <User: ...> style, but not made it customisable using any public (non-_) or documented API.

The easiest sane way to make it customisable would be to have a global hook for a repr and str processor function, and provide helpers. Maybe try to get https://github.com/magopian/django-inspect-model to be Dj2-3 compatible, and expose that to the hooks.

Especially with str(), the way to make the representation more intuitive for human with lower entropy is to not make the logic formulaic. That is the underlying reason why __str__ exists in the first place. e.g. https://github.com/jayvdb/django-dunder/issues/9

Exposing format strings for project customisation wont work.

jayvdb commented 4 years ago

Need to look into whether https://boltons.readthedocs.io/en/latest/formatutils.html is helpful.

jayvdb commented 4 years ago

Also rformat

jayvdb commented 4 years ago

so, against my own advice, I built a string formatting voodoo, mostly to allow formatting of attributes, especially trimming for https://github.com/jayvdb/django-dunder/issues/1

https://github.com/jayvdb/django-dunder/commit/fcf14efcbaebe9c10f13a51c149c8d451a54441e

It is a bit like https://github.com/angmorpri/hformat/blob/master/language.md because this needs understandable format strings like @angmorpri . It isnt as complete or formal of a mini-language as hformat, and switching to hformat is worth considering once it has been published on PyPI.

Currently it is only used on each {name}={value} - it isnt used to build the final representation of the model instance, which needs to combine the name=value pairs, and probably also should be allowed to post-process them from the raw pairs.

If doing that with format strings, the top level format string might look like <{model}: {attrs}>, with attrs being a list of tuples or something. The wrapper voodoo (or replacement) would need to be expanded/tested to supports that datastructure, and the wrapper voodoo would need to be given the format string to use for each {name}={value}. That is where rformat recursiveness might come in handy.

But all that sort-of breaks when trying to achieve https://github.com/jayvdb/django-dunder/issues/9 (<Model x>), because then we would need

<{model}{attrs.take_if_only_one.prefix_with_space(' ')}{attrs.ignore_if_only_one.prefix(': ')}>

While the custom formatting can sort-of be expressed there, and it is using generic bits, that only handles one special case. There will be more, and then it gets messy.

Essentially a template language with branching is needed to effectively allow presentation control of complex structure. And that would be over-engineering this problem.

The above approach is still acceptable, as the default format strings is quite literate for simple cases, and users can resort to <{model}{attrs.distill()} with a custom distill function that does whatever they need.