#22413 closed New feature (wontfix)
Allow model instance attributes in ModelAdmin.fields
Reported by: | Moritz Sichert | Owned by: | Moritz Sichert |
---|---|---|---|
Component: | contrib.admin | Version: | dev |
Severity: | Normal | Keywords: | ModelAdmin instance attribute field |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | yes | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Say your model uses __getattr__
like that:
class MyModel(models.Model): value = models.CharField(max_length=20) def __getattr__(self, name): if name == 'reversed_value': return self.value[::-1] else: raise AttributeError()
Then you can't use the attribute reversed_value
in ModelAdmin.fields
because the attribute is only defined in a model instance but not in the class itself.
I suggest adding a field model_instance_fields
in ModelAdmin
that contains the names of all fields that will be only defined in model instances.
Change History (5)
comment:1 by , 11 years ago
Has patch: | set |
---|---|
Needs tests: | set |
Owner: | changed from | to
Status: | new → assigned |
follow-up: 3 comment:2 by , 11 years ago
Forgive my ignorance (perhaps), but what's wrong with changing your code to this:
class MyModel(models.Model): value = models.CharField(max_length=20) @property def reversed_value(self): return self.value[::-1]
That would not require any changes to Django code.
comment:3 by , 11 years ago
Replying to timshaffer@…:
Forgive my ignorance (perhaps), but what's wrong with changing your code to this:
class MyModel(models.Model): value = models.CharField(max_length=20) @property def reversed_value(self): return self.value[::-1]That would not require any changes to Django code.
My example may be a bit trivial, here is another that hopefully shows, why it is necessary:
class MyBaseModel(models.Model): def __getattr__(self, name): if name.endswith('_to_upper'): return getattr(self, name[:-len('_to_upper')]).upper() elif name.endswith('_to_lower'): return getattr(self, name[:-len('_to_lower')]).lower() else: return AttributeError() class Meta: abstract = True class MyModel(MyBaseModel): val1 = models.CharField(max_length=20) val2 = models.CharField(max_length=20)
Now it works like this:
>>> m = MyModel() >>> m.val1 = 'Foo' >>> m.val2 = 'Bar' >>> m.val1_to_upper 'FOO' >>> m.val2_to_lower 'bar'
In this particular example you could still add properties for each combination of val1, val2 and to_upper, to_lower, but this won't be possible, if __getattr__
gets more complex.
follow-up: 5 comment:4 by , 11 years ago
Resolution: | → wontfix |
---|---|
Status: | assigned → closed |
Thanks for the proposal, but I don't feel this is a common enough use-case to justify the additional complexity. I don't think we should encourage writing really complex __getattr__
methods. As noted earlier, you can add proper methods or properties if you need something in fields
.
comment:5 by , 11 years ago
Replying to timo:
Thanks for the proposal, but I don't feel this is a common enough use-case to justify the additional complexity. I don't think we should encourage writing really complex
__getattr__
methods. As noted earlier, you can add proper methods or properties if you need something infields
.
How does this add complexity to django? It doesn't break or change the behaviour of ModelAdmin
.
Besides, I really consider
class MyModel(models.Model): # ... fields def __getattr__(self, name): # ... do_something
more pythonic than
class MyModel(models.Model): # ... fields @property def field1_do_something(self): return do_something(self.field1) @property def field2_do_something(self): return do_something(self.field2) ...
pull request: https://github.com/django/django/pull/2534
I will add tests later.