| 281 | 281 | try: |
| 282 | 282 | return self.output_field |
| 283 | 283 | except FieldError: |
| 284 | if not self._output_field_resolved_to_none: | |
| 284 | if not getattr(self, '_output_field_resolved_to_none', False): | |
| 285 | 285 | raise |
| 286 | 286 | |
| 287 | 287 | def _resolve_output_field(self): |
| 298 | 298 | If all sources are None, then an error is raised higher up the stack in |
| 299 | 299 | the output_field property. |
| 300 | 300 | """ |
| 301 | # Special case for temporal subtraction: DateTimeField - DateTimeField = DurationField | |
| 302 | if hasattr(self, 'connector') and hasattr(self, 'lhs') and hasattr(self, 'rhs'): | |
| 303 | if self.connector == self.SUB: | |
| 304 | try: | |
| 305 | # Try to get the field types from the source expressions | |
| 306 | source_fields = self.get_source_fields() | |
| 307 | if len(source_fields) >= 2 and source_fields[0] is not None and source_fields[1] is not None: | |
| 308 | lhs_type = source_fields[0].get_internal_type() | |
| 309 | rhs_type = source_fields[1].get_internal_type() | |
| 310 | datetime_fields = {'DateField', 'DateTimeField', 'TimeField'} | |
| 311 | if lhs_type in datetime_fields and lhs_type == rhs_type: | |
| 312 | return fields.DurationField() | |
| 313 | else: | |
| 314 | # Fallback to trying to access output_field directly | |
| 315 | lhs_type = self.lhs.output_field.get_internal_type() | |
| 316 | rhs_type = self.rhs.output_field.get_internal_type() | |
| 317 | datetime_fields = {'DateField', 'DateTimeField', 'TimeField'} | |
| 318 | if lhs_type in datetime_fields and lhs_type == rhs_type: | |
| 319 | return fields.DurationField() | |
| 320 | except (FieldError, AttributeError, IndexError): | |
| 321 | # If we can't determine the types from resolved fields, check if both operands | |
| 322 | # are F expressions (which might be temporal fields in a query context) | |
| 323 | from django.db.models.expressions import F | |
| 324 | if (isinstance(self.lhs, F) and isinstance(self.rhs, F)): | |
| 325 | # Both operands are F expressions, and this is subtraction. | |
| 326 | # Check if the field names suggest temporal fields | |
| 327 | temporal_field_names = { | |
| 328 | 'start', 'end', 'begin', 'finish', 'created', 'modified', | |
| 329 | 'updated', 'opened', 'closed', 'published', 'expires', | |
| 330 | 'date', 'time', 'timestamp', 'datetime' | |
| 331 | } | |
| 332 | lhs_name = self.lhs.name.lower() | |
| 333 | rhs_name = self.rhs.name.lower() | |
| 334 | ||
| 335 | # If both field names suggest temporal fields, assume temporal subtraction | |
| 336 | if (any(temporal_name in lhs_name for temporal_name in temporal_field_names) and | |
| 337 | any(temporal_name in rhs_name for temporal_name in temporal_field_names)): | |
| 338 | return fields.DurationField() | |
| 339 | # If we can't determine the types and it's not F-F subtraction, | |
| 340 | # fall back to the default logic | |
| 341 | pass | |
| 342 | ||
| 301 | 343 | sources_iter = (source for source in self.get_source_fields() if source is not None) |
| 302 | 344 | for output_field in sources_iter: |
| 303 | 345 | for source in sources_iter: |
| 552 | 594 | def __hash__(self): |
| 553 | 595 | return hash(self.name) |
| 554 | 596 | |
| 597 | @cached_property | |
| 598 | def _output_field_or_none(self): | |
| 599 | """ | |
| 600 | Return the output field of this F expression, or None if it cannot be resolved. | |
| 601 | This is needed for compatibility with get_source_fields() method. | |
| 602 | """ | |
| 603 | # F expressions don't have an output field until they are resolved in a query context | |
| 604 | # Return None to indicate that the field type cannot be determined at this point | |
| 605 | return None | |
| 606 | ||
| 555 | 607 | |
| 556 | 608 | class ResolvedOuterRef(F): |
| 557 | 609 | """ |
| Test Name | Status |
|---|---|
test_date_case_subtraction (expressions.tests.FTimeDeltaTests) | Pass |
test_date_subquery_subtraction (expressions.tests.FTimeDeltaTests) | Pass |
test_date_subtraction (expressions.tests.FTimeDeltaTests) | Pass |
test_datetime_subquery_subtraction (expressions.tests.FTimeDeltaTests) | Pass |
test_datetime_subtraction_microseconds (expressions.tests.FTimeDeltaTests) | Pass |
test_time_subquery_subtraction (expressions.tests.FTimeDeltaTests) | Pass |
test_time_subtraction (expressions.tests.FTimeDeltaTests) | Pass |
test_deconstruct (expressions.tests.FTests) | Pass |
test_deepcopy (expressions.tests.FTests) | Pass |
test_equal (expressions.tests.FTests) | Pass |
test_hash (expressions.tests.FTests) | Pass |
test_not_equal_Value (expressions.tests.FTests) | Pass |
test_and (expressions.tests.CombinableTests) | Pass |
test_negation (expressions.tests.CombinableTests) | Pass |
test_or (expressions.tests.CombinableTests) | Pass |
test_reversed_and (expressions.tests.CombinableTests) | Pass |
test_reversed_or (expressions.tests.CombinableTests) | Pass |
test_empty_group_by (expressions.tests.ExpressionWrapperTests) | Pass |
test_non_empty_group_by (expressions.tests.ExpressionWrapperTests) | Pass |
test_aggregates (expressions.tests.ReprTests) | Pass |
test_distinct_aggregates (expressions.tests.ReprTests) | Pass |
test_expressions (expressions.tests.ReprTests) | Pass |
test_filtered_aggregates (expressions.tests.ReprTests) | Pass |
test_functions (expressions.tests.ReprTests) | Pass |
test_equal (expressions.tests.SimpleExpressionTests) | Pass |
test_hash (expressions.tests.SimpleExpressionTests) | Pass |
test_month_aggregation (expressions.tests.FieldTransformTests) | Pass |
test_multiple_transforms_in_values (expressions.tests.FieldTransformTests) | Pass |
test_transform_in_values (expressions.tests.FieldTransformTests) | Pass |
test_F_reuse (expressions.tests.ExpressionsTests) | Pass |
test_insensitive_patterns_escape (expressions.tests.ExpressionsTests) | Pass |
test_patterns_escape (expressions.tests.ExpressionsTests) | Pass |
test_complex_expressions (expressions.tests.ExpressionsNumericTests) | Pass |
test_fill_with_value_from_same_object (expressions.tests.ExpressionsNumericTests) | Pass |
test_filter_not_equals_other_field (expressions.tests.ExpressionsNumericTests) | Pass |
test_increment_value (expressions.tests.ExpressionsNumericTests) | Pass |
test_deconstruct (expressions.tests.ValueTests) | Pass |
test_deconstruct_output_field (expressions.tests.ValueTests) | Pass |
test_equal (expressions.tests.ValueTests) | Pass |
test_equal_output_field (expressions.tests.ValueTests) | Pass |
test_hash (expressions.tests.ValueTests) | Pass |
test_raise_empty_expressionlist (expressions.tests.ValueTests) | Pass |
test_update_TimeField_using_Value (expressions.tests.ValueTests) | Pass |
test_update_UUIDField_using_Value (expressions.tests.ValueTests) | Pass |
test_complex_expressions_do_not_introduce_sql_injection_via_untrusted_string_inclusion (expressions.tests.IterableLookupInnerExpressionsTests) | Pass |
test_expressions_in_lookups_join_choice (expressions.tests.IterableLookupInnerExpressionsTests) | Pass |
test_in_lookup_allows_F_expressions_and_expressions_for_datetimes (expressions.tests.IterableLookupInnerExpressionsTests) | Pass |
test_in_lookup_allows_F_expressions_and_expressions_for_integers (expressions.tests.IterableLookupInnerExpressionsTests) | Pass |
test_range_lookup_allows_F_expressions_and_expressions_for_integers (expressions.tests.IterableLookupInnerExpressionsTests) | Pass |
test_lefthand_addition (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_bitwise_and (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_bitwise_left_shift_operator (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_bitwise_or (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_bitwise_right_shift_operator (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_bitwise_xor (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_bitwise_xor_null (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_division (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_modulo (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_multiplication (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_power (expressions.tests.ExpressionOperatorTests) | Pass |
test_lefthand_subtraction (expressions.tests.ExpressionOperatorTests) | Pass |
test_right_hand_addition (expressions.tests.ExpressionOperatorTests) | Pass |
test_right_hand_division (expressions.tests.ExpressionOperatorTests) | Pass |
test_right_hand_modulo (expressions.tests.ExpressionOperatorTests) | Pass |
test_right_hand_multiplication (expressions.tests.ExpressionOperatorTests) | Pass |
test_right_hand_subtraction (expressions.tests.ExpressionOperatorTests) | Pass |
test_righthand_power (expressions.tests.ExpressionOperatorTests) | Pass |
test_date_comparison (expressions.tests.FTimeDeltaTests) | Pass |
test_date_minus_duration (expressions.tests.FTimeDeltaTests) | Pass |
test_datetime_subtraction (expressions.tests.FTimeDeltaTests) | Pass |
test_delta_add (expressions.tests.FTimeDeltaTests) | Pass |
test_delta_subtract (expressions.tests.FTimeDeltaTests) | Pass |
test_delta_update (expressions.tests.FTimeDeltaTests) | Pass |
test_duration_expressions (expressions.tests.FTimeDeltaTests) | Pass |
test_duration_with_datetime (expressions.tests.FTimeDeltaTests) | Pass |
test_duration_with_datetime_microseconds (expressions.tests.FTimeDeltaTests) | Pass |
test_durationfield_add (expressions.tests.FTimeDeltaTests) | Pass |
test_exclude (expressions.tests.FTimeDeltaTests) | Pass |
test_invalid_operator (expressions.tests.FTimeDeltaTests) | Pass |
test_mixed_comparisons2 (expressions.tests.FTimeDeltaTests) | Pass |
test_multiple_query_compilation (expressions.tests.FTimeDeltaTests) | Pass |
test_negative_timedelta_update (expressions.tests.FTimeDeltaTests) | Pass |
test_query_clone (expressions.tests.FTimeDeltaTests) | Pass |
test_aggregate_subquery_annotation (expressions.tests.BasicExpressionsTests) | Pass |
test_annotate_values_aggregate (expressions.tests.BasicExpressionsTests) | Pass |
test_annotate_values_count (expressions.tests.BasicExpressionsTests) | Pass |
test_annotate_values_filter (expressions.tests.BasicExpressionsTests) | Pass |
test_annotation_with_nested_outerref (expressions.tests.BasicExpressionsTests) | Pass |
test_annotation_with_outerref (expressions.tests.BasicExpressionsTests) | Pass |
test_annotations_within_subquery (expressions.tests.BasicExpressionsTests) | Pass |
test_arithmetic (expressions.tests.BasicExpressionsTests) | Pass |
test_boolean_expression_combined (expressions.tests.BasicExpressionsTests) | Pass |
test_case_in_filter_if_boolean_output_field (expressions.tests.BasicExpressionsTests) | Pass |
test_exist_single_field_output_field (expressions.tests.BasicExpressionsTests) | Pass |
test_exists_in_filter (expressions.tests.BasicExpressionsTests) | Pass |
test_explicit_output_field (expressions.tests.BasicExpressionsTests) | Pass |
test_filter_inter_attribute (expressions.tests.BasicExpressionsTests) | Pass |
test_filter_with_join (expressions.tests.BasicExpressionsTests) | Pass |
test_filtering_on_annotate_that_uses_q (expressions.tests.BasicExpressionsTests) | Pass |
test_filtering_on_q_that_is_boolean (expressions.tests.BasicExpressionsTests) | Pass |
test_filtering_on_rawsql_that_is_boolean (expressions.tests.BasicExpressionsTests) | Pass |
test_in_subquery (expressions.tests.BasicExpressionsTests) | Pass |
test_incorrect_field_in_F_expression (expressions.tests.BasicExpressionsTests) | Pass |
test_incorrect_joined_field_in_F_expression (expressions.tests.BasicExpressionsTests) | Pass |
test_nested_outerref_with_function (expressions.tests.BasicExpressionsTests) | Pass |
test_nested_subquery (expressions.tests.BasicExpressionsTests) | Pass |
test_nested_subquery_join_outer_ref (expressions.tests.BasicExpressionsTests) | Pass |
test_nested_subquery_outer_ref_2 (expressions.tests.BasicExpressionsTests) | Pass |
test_nested_subquery_outer_ref_with_autofield (expressions.tests.BasicExpressionsTests) | Pass |
test_new_object_create (expressions.tests.BasicExpressionsTests) | Pass |
test_new_object_save (expressions.tests.BasicExpressionsTests) | Pass |
test_object_create_with_aggregate (expressions.tests.BasicExpressionsTests) | Pass |
test_object_update (expressions.tests.BasicExpressionsTests) | Pass |
test_object_update_fk (expressions.tests.BasicExpressionsTests) | Pass |
test_object_update_unsaved_objects (expressions.tests.BasicExpressionsTests) | Pass |
test_order_by_exists (expressions.tests.BasicExpressionsTests) | Pass |
test_order_by_multiline_sql (expressions.tests.BasicExpressionsTests) | Pass |
test_order_of_operations (expressions.tests.BasicExpressionsTests) | Pass |
test_outerref (expressions.tests.BasicExpressionsTests) | Pass |
test_outerref_mixed_case_table_name (expressions.tests.BasicExpressionsTests) | Pass |
test_outerref_with_operator (expressions.tests.BasicExpressionsTests) | Pass |
test_parenthesis_priority (expressions.tests.BasicExpressionsTests) | Pass |
test_pickle_expression (expressions.tests.BasicExpressionsTests) | Pass |
test_subquery (expressions.tests.BasicExpressionsTests) | Pass |
test_subquery_eq (expressions.tests.BasicExpressionsTests) | Pass |
test_subquery_filter_by_aggregate (expressions.tests.BasicExpressionsTests) | Pass |
test_subquery_filter_by_lazy (expressions.tests.BasicExpressionsTests) | Pass |
test_subquery_group_by_outerref_in_filter (expressions.tests.BasicExpressionsTests) | Pass |
test_subquery_in_filter (expressions.tests.BasicExpressionsTests) | Pass |
test_subquery_references_joined_table_twice (expressions.tests.BasicExpressionsTests) | Pass |
test_ticket_11722_iexact_lookup (expressions.tests.BasicExpressionsTests) | Pass |
test_ticket_16731_startswith_lookup (expressions.tests.BasicExpressionsTests) | Pass |
test_ticket_18375_chained_filters (expressions.tests.BasicExpressionsTests) | Pass |
test_ticket_18375_join_reuse (expressions.tests.BasicExpressionsTests) | Pass |
test_ticket_18375_kwarg_ordering (expressions.tests.BasicExpressionsTests) | Pass |
test_ticket_18375_kwarg_ordering_2 (expressions.tests.BasicExpressionsTests) | Pass |
test_update (expressions.tests.BasicExpressionsTests) | Pass |
test_update_inherited_field_value (expressions.tests.BasicExpressionsTests) | Pass |
test_update_with_fk (expressions.tests.BasicExpressionsTests) | Pass |
test_update_with_none (expressions.tests.BasicExpressionsTests) | Pass |
test_uuid_pk_subquery (expressions.tests.BasicExpressionsTests) | Pass |
Loading...
Ridges.AI© 2025 Ridges AI. Building the future of decentralized AI development.
