Provide real support for virtual fields
|Reported by:||vzima||Owned by:|
|Component:||Database layer (models, ORM)||Version:||master|
|Cc:||pirosb3, michal.petrucha@…||Triage Stage:||Accepted|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
I have created a virtual field based on GenericForeignKey, but I found out that it can not be properly used for model initiation.
Altered example from my test:
class Managing(models.Model): shortcut = models.CharField(max_length=20) name_cs = TranslationProxyField('name', 'cs', False) class ManagingTranslation(models.Model): name = models.CharField(max_length=20) class TranslationProxyField(object): """ Descriptor that is a virtual field that provides access to translations. """ def __init__(self, field_name, language_code=None, fallback=False): self._field_name = field_name self._language_code = language_code self._fallback = fallback names = [field_name] if language_code is not None: names.append(language_code.replace('-', '_')) if fallback: names.append(FALLBACK_FIELD_SUFFIX) self.name = '_'.join(names) def contribute_to_class(self, cls, name): if self.name != name: raise ValueError('Field proxy %s is added to class under bad attribute name.' % self) self.model = cls cls._meta.add_virtual_field(self) # Connect myself as the descriptor for this field setattr(cls, name, self) # This results in Type error from Model.__init__, because of extra kwarg Managing(shortcut='name', name_cs='jméno')
I tried to use pre_init signal, but I found out that I will not get instance argument, so I can not use that. This way is truly usable only for virtual fields which are like GenericForeignKey built on real model fields of object. When it gets more complicated, it can not be used. Confusing on this path is that instance is in providing_args of pre_init signal.
Currently I solve this by quite a hack which is deriving of TranslationProxyField from property instead of object. This works because of setting properties is allowed in Model.__init__.
In my opinion, a stable solution would be either providing an instance argument in pre_init signal or enable setting of virtual field in model initiation. Second option would also enable removal of pre_init connection from GenericForeignKey.
Exact examples can be found at github: https://github.com/vzima/django-multilingual-ds9
Change History (21)
comment:1 Changed 5 years ago by bpeschier
- Needs documentation unset
- Needs tests unset
- Patch needs improvement unset
- Triage Stage changed from Unreviewed to Accepted
comment:3 Changed 2 years ago by pirosb3
- Cc pirosb3 added
- Owner changed from nobody to pirosb3
- Status changed from new to assigned
comment:20 Changed 3 weeks ago by timgraham
- Owner pirosb3 deleted
- Status changed from assigned to new