Opened 8 years ago
Closed 8 years ago
#26799 closed New feature (duplicate)
Model related signals' receiver could not receive its proxy models
Reported by: | Yang Wang | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.9 |
Severity: | Normal | Keywords: | Model, Signal, Generation |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
We have to connect the same receiver to its all proxy models one by one
class TestModel(models.Model): field1 = models.CharField(max_length=64) field2 = models.CharField(max_length=64) class Meta: db_table = 'app_label_test_model' class ProxyTestModel(TestModel): class Meta: proxy = True from django.db.models.signals import pre_save def on_test_model_change(sender, instance, **kwargs): if not instance.field1.startswith('*'): instance.field1 = u'*' + instance.field1 pre_save.connect(on_test_model_change, sender=TestModel) # pre_save.connect(on_test_model_change, sender=ProxyTestModel) >>> t = TestModel() >>> t.save() >>> t.field1 u'*' >>> pt = ProxyTestModel() >>> pt.save() >>> pt.field1 u''
Otherwise, we should consider to split one Model to manage it more conveniently and safely.
As there is an attribute 'concrete_model' kept in Model's Option, could we take the benefits of it?
class RealTestModel1(models.Model): field1 = models.CharField(max_length=64) class Meta: managed = False db_table = 'app_label_test_model' class RealTestModel2(models.Model): field2 = models.CharField(max_length=64) class Meta: managed = False db_table = 'app_label_test_model'
In my project, i hacked like this for more admin site features which could be implemented in Model's generation process:
from django.db.models.base import ModelBase from django.dispatch import dispatcher # for adapting to sub-models _make_id = dispatcher._make_id def _new_make_id(target): if isinstance(target, ModelBase): return id(getattr(target, '_concrete_model', target._meta.concrete_model)) return _make_id(target) dispatcher._make_id = _new_make_id # ... class ABSModelBase(ModelBase): ''' Abstract Meta-Class to make new model performs as concrete model ''' _concrete_model = ModelBase def __subclasscheck__(cls, subclass): return issubclass(subclass, cls._concrete_model) def __instancecheck__(cls, instance): return isinstance(instance, cls._concrete_model) # ... # create new class new_class = ABSModelBase.__new__( ABSModelBase, name, tuple(bases), attrs, ) # register new_class as subclass of concrete_model new_class.__bases__ = (concrete_meta.model, ) + new_class.__bases__ # register subclass and instance checking new_class._concrete_model = concrete_meta.model
Note:
See TracTickets
for help on using tickets.
Looks like a duplicate of #9318.