def test_different_types(self, categories, applications): model_instances = categories[:2] + applications grouped_instances = { cls: list(instances) for cls, instances in groupby( model_instances, key=lambda instance: instance.__class__) } for cls, instances in grouped_instances.items(): self.assert_not_cached( get_queryable_property_descriptor(cls, 'version_count'), *instances) prefetch_queryable_properties(model_instances, 'version_count') for cls, instances in grouped_instances.items(): self.assert_cached( get_queryable_property_descriptor(cls, 'version_count'), *instances)
def test_2o_relation_property(self): descriptor = get_queryable_property_descriptor( ApplicationWithClassBasedProperties, 'version_count') versions = list( VersionWithClassBasedProperties.objects.select_related( 'application')) self.assert_not_cached(descriptor, *(version.application for version in versions)) prefetch_queryable_properties(versions, 'application__version_count') self.assert_cached(descriptor, *(version.application for version in versions))
def test_annotation_based_on_queryable_property(self, model, property_name, annotation, expected_count, record_checker): queryset = model.objects.annotate(annotation=annotation) assert queryset.count() == len(queryset) == expected_count assert all(record_checker(obj) for obj in queryset) if '__' not in property_name: # Check that a property annotation used implicitly by another # annotation does not lead to a selection of the property # annotation descriptor = get_queryable_property_descriptor(model, property_name) assert all(not descriptor.has_cached_value(obj) for obj in queryset)
def test_select_query(self, model, property_name, filters, expected_count): queryset = model.objects.filter(filters) assert property_name in queryset.query.annotations assert queryset.count() == len(queryset) == expected_count if '__' not in property_name: # Check that a property annotation used implicitly by a filter does # not lead to a selection of the property annotation. descriptor = get_queryable_property_descriptor( model, property_name) assert all(not descriptor.has_cached_value(app) for app in queryset)
def test_2m_relation_property(self): descriptor = get_queryable_property_descriptor( ApplicationWithClassBasedProperties, 'version_count') categories = list( CategoryWithClassBasedProperties.objects.prefetch_related( 'applications')) for category in categories: self.assert_not_cached(descriptor, *category.applications.all()) prefetch_queryable_properties(categories, 'applications__version_count') for category in categories: self.assert_cached(descriptor, *category.applications.all())
def test_local_property(self, applications, property_names): descriptors = [ get_queryable_property_descriptor( ApplicationWithClassBasedProperties, name) for name in property_names ] applications = applications[:2] for descriptor in descriptors: self.assert_not_cached(descriptor, *applications) prefetch_queryable_properties(applications, *property_names) for descriptor in descriptors: self.assert_cached(descriptor, *applications)
def test_refresh_cache(self): """ Test that prefetch_queryable_properties can be used to update already cached values on instances. """ descriptor = get_queryable_property_descriptor( ApplicationWithClassBasedProperties, 'version_count') application = ApplicationWithClassBasedProperties.objects.select_properties( 'version_count')[0] self.assert_cached(descriptor, application) application.versions.all().delete() assert application.version_count > 0 # The cached value is still present prefetch_queryable_properties([application], 'version_count') self.assert_cached(descriptor, application)
def test_select_query(self, model, property_name, filters, expected_count, expected_distinct_count, record_checker): queryset = model.objects.filter(filters) assert property_name in queryset.query.annotations assert queryset.distinct().count() == expected_distinct_count assert len(queryset) == expected_count if record_checker: assert all(record_checker(obj) for obj in queryset) if '__' not in property_name: # Check that a property annotation used implicitly by a filter does # not lead to a selection of the property annotation. descriptor = get_queryable_property_descriptor( model, property_name) assert all(not descriptor.has_cached_value(version) for version in queryset)
def test_select_query(self, model, property_name, filters, expected_count, record_checker): version_model = (VersionWithClassBasedProperties if 'ClassBased' in model.__name__ else VersionWithDecoratorBasedProperties) # Delete one version to create distinct constellations version_model.objects.get(version='2.0.0', application__name__contains='cool').delete() queryset = model.objects.filter(filters) assert property_name in queryset.query.annotations assert queryset.count() == len(queryset) == expected_count if '__' not in property_name: # Check that a property annotation used implicitly by a filter does # not lead to a selection of the property annotation. descriptor = get_queryable_property_descriptor( model, property_name) assert all(not descriptor.has_cached_value(version) for version in queryset)
def test_exception(self, model, property_name): with pytest.raises(QueryablePropertyDoesNotExist): get_queryable_property_descriptor(model, property_name)
def test_property_found(self, model, property_name): descriptor = get_queryable_property_descriptor(model, property_name) assert isinstance(descriptor, QueryablePropertyDescriptor)