def _ensure_partition(self, partition_key): # Actually do the legwork for generating a partition logger.debug('Partition not found, generating') model_name = self._model_name_for_partition(partition_key) imp.acquire_lock() try: model = create_model( model_name, bases=(self.model,), attrs={PARTITION_KEY: partition_key}, module_path=self.model.__module__) for name, manager in self.get_managers(model): manager.contribute_to_class(model, name) # Make sure that we don't overwrite an existing name in the # module. Raise an AttributeError if we look like we're about # to. module = sys.modules[self.model.__module__] if getattr(module, model_name, _marker) is _marker: setattr(module, model_name, model) else: raise AttributeError('{} already exists in {}'.format( model_name, module)) logger.debug( '{} generated, processing PartitionForeignKeys'.format( model)) # Find any PartitionForeignKeys that point to our parent model, # and generate partitions of those source models pfks_to_remove = set() for pfk in self.registry.foreign_keys_referencing(self.model): if not hasattr(pfk.cls, '_partition_manager'): raise AttributeError( 'Source model {} does not have a partition ' 'manager'.format(pfk.cls)) child = pfk.cls._partition_manager.get_partition(partition_key) # Replace the placeholder with a real foreign key, and # make sure internal caches are populated correctly point(child, pfk.name, model, **pfk.kwargs) pfks_to_remove.add(pfk) self._fill_fields_cache(child._meta) # Make sure that there are no pfks hanging around for pkf in pfks_to_remove: for lst in (child._meta.fields, child._meta.local_fields): for field in lst: if field.name == pkf.name and isinstance( field, PartitionForeignKey): lst.remove(field) break finally: imp.release_lock() return model
def test_derived_model_point_base(self): # If we repoint a dfk on a base non-abstract class, subclasses # should see the change. class BaseClass3(models.Model): c = DeferredForeignKey() class DerivedModel3(BaseClass3): pass point(BaseClass3, 'c', ModelA) self.assertEqual(ModelA, DerivedModel3.c.field.rel.to)
def _ensure_partition(self, partition_key): # Actually do the legwork for generating a partition logger.debug('Partition not found, generating') model_name = self._model_name_for_partition(partition_key) imp.acquire_lock() try: model = create_model(model_name, bases=(self.model, ), attrs={PARTITION_KEY: partition_key}, module_path=self.model.__module__) for name, manager in self.get_managers(model): manager.contribute_to_class(model, name) # Make sure that we don't overwrite an existing name in the # module. Raise an AttributeError if we look like we're about # to. module = sys.modules[self.model.__module__] if getattr(module, model_name, _marker) is _marker: setattr(module, model_name, model) else: raise AttributeError('{} already exists in {}'.format( model_name, module)) logger.debug( '{} generated, processing PartitionForeignKeys'.format(model)) # Find any PartitionForeignKeys that point to our parent model, # and generate partitions of those source models pfks_to_remove = set() for pfk in self.registry.foreign_keys_referencing(self.model): if not hasattr(pfk.cls, '_partition_manager'): raise AttributeError( 'Source model {} does not have a partition ' 'manager'.format(pfk.cls)) child = pfk.cls._partition_manager.get_partition(partition_key) # Replace the placeholder with a real foreign key, and # make sure internal caches are populated correctly point(child, pfk.name, model, **pfk.kwargs) pfks_to_remove.add(pfk) self._fill_fields_cache(child._meta) # Make sure that there are no pfks hanging around for pkf in pfks_to_remove: for lst in (child._meta.fields, child._meta.local_fields): for field in lst: if field.name == pkf.name and isinstance( field, PartitionForeignKey): lst.remove(field) break finally: imp.release_lock() return model
def test_derived_model_abstract(self): # If the base model is abstract, then it's actually OK as # the field is local to the subclass anyway. class BaseClass2(models.Model): c = DeferredForeignKey() class Meta: abstract = True class DerivedModel2(BaseClass2): pass point(DerivedModel2, 'c', ModelA) self.assertEqual(ModelA, DerivedModel2.c.field.rel.to)
def test_options_caches_not_cleared_on_point(self): # Check that the relevant meta caches are not cleared after a point # if clear_caches=False class NewModelNoCache(models.Model): c = DeferredForeignKey() point(NewModelNoCache, 'c', ModelC, clean_caches=False) mdc_related = ModelC._meta.get_all_related_objects_with_model() found = False for rel, _ in mdc_related: if rel.model is NewModelNoCache: found = True self.assertEqual(False, found)
def test_options_caches_cleared_on_point(self): # Check that the relevant meta caches are cleared after a point # to ensure related field names are up to date. class NewModel(models.Model): c = DeferredForeignKey() point(NewModel, 'c', ModelC) mdc_related = ModelC._meta.get_all_related_objects_with_model() found = False for rel, _ in mdc_related: if rel.model is NewModel: found = True self.assertEqual(True, found)
def test_options_caches_cleaned(self): # Check that the relevant meta caches are cleared after # a direct call to clean_object_caches class NewModelNoCache2(models.Model): c = DeferredForeignKey() point(NewModelNoCache2, 'c', ModelC, clean_caches=False) mdc_related = ModelC._meta.get_all_related_objects_with_model() found = False for rel, _ in mdc_related: if rel.model is NewModelNoCache2: found = True assert not found clean_object_caches(NewModelNoCache2, ModelC) mdc_related = ModelC._meta.get_all_related_objects_with_model() for rel, _ in mdc_related: if rel.model is NewModelNoCache2: found = True self.assertEqual(True, found)
def test_not_a_model(self): self.assertRaises(AssertionError, repoint, ModelB, 'fk', NotAModel) def test_abstract(self): self.assertRaises(AssertionError, repoint, ModelB, 'fk', AbstractModel) class DeferredModelA(models.Model): user = DeferredForeignKey() class DeferredModelB(models.Model): user = DeferredForeignKey() # Point DeferredModelA's 'user' dfk to ModelA point(DeferredModelA, 'user', ModelA, related_name='foo_set') # Point ModelD's deferred fk to ModelA point_named('dfk', 'content', ModelA) # Point ModelCustomFiekld's deferred fk to ModelA point_named('dfk', 'content2', ModelA) class DeferredForeignKeyTestCase(TestCase): def test_specific_field(self): # Check that DeferredModelA's deferred field was correctly # processed m = ModelA.objects.create() a = DeferredModelA.objects.create(