22PolymorphicQuerySet support functions
33"""
44
5- import copy
65from collections import deque
76
87from django .apps import apps
@@ -80,6 +79,35 @@ def tree_node_correct_field_specs(my_model, node):
8079 return potential_q_object
8180
8281
82+ def _deepcopy_q_object (q ):
83+ """
84+ Make a deepcopy of a Q-object.
85+ """
86+
87+ def _copy_child (child ):
88+ if isinstance (child , tuple ):
89+ return child # tuples are immutable, no need to make a copy.
90+ elif isinstance (child , Q ):
91+ return _deepcopy_q_object (child )
92+ else :
93+ raise RuntimeError ("Unknown child type: %s" , type (child ))
94+
95+ children = [_copy_child (c ) for c in q .children ]
96+
97+ if hasattr (q , "copy" ): # Django 4.2+
98+ obj = q .copy ()
99+ # This assignment of obj.children from children (created above)
100+ # is required for test_query_filter_exclude_is_immutable to pass
101+ # because somehow the capitalization changed for q_to_reuse?
102+ #
103+ # assert q_to_reuse.children == untouched_q_object.children
104+ # AssertionError: assert [('model2b__f... 'something')] == [('Model2B___... 'something')]
105+ obj .children = children
106+ else :
107+ obj = Q (* children , _connector = q .connector , _negated = q .negated )
108+ return obj
109+
110+
83111def translate_polymorphic_filter_definitions_in_args (queryset_model , args , using = DEFAULT_DB_ALIAS ):
84112 """
85113 Translate the non-keyword argument list for PolymorphicQuerySet.filter()
@@ -92,7 +120,8 @@ def translate_polymorphic_filter_definitions_in_args(queryset_model, args, using
92120 Returns: modified Q objects
93121 """
94122 return [
95- translate_polymorphic_Q_object (queryset_model , copy .deepcopy (q ), using = using ) for q in args
123+ translate_polymorphic_Q_object (queryset_model , _deepcopy_q_object (q ), using = using )
124+ for q in args
96125 ]
97126
98127
0 commit comments