MCPcopy
hub / github.com/tortoise/tortoise-orm / F

Class F

tortoise/expressions.py:113–225  ·  view source on GitHub ↗

F() can be used to reference a model field, field of a related model, annotation or an attribute of a JSON field. It can be used in the following ways: - as a field reference, e.g. F("id") - as a related field reference, e.g. F("related_field__field") will return the value of the f

Source from the content-addressed store, hash-verified

111
112
113class F(Expression):
114 """
115 F() can be used to reference a model field, field of a related model, annotation or
116 an attribute of a JSON field. It can be used in the following ways:
117
118 - as a field reference, e.g. F("id")
119 - as a related field reference, e.g. F("related_field__field") will return the value of the field
120 of the related model.
121 - as a JSON field reference, e.g. F("json_field__attribute") will return the value of the "attribute"
122 property of the JSON field value. The reference can be nested, e.g. F("json_field__attribute__subattribute")
123 - as a JSON field array element reference, e.g. F("json_field__0") will return the first element of the array.
124
125 :param name: The name of the field to reference.
126 """
127
128 def __init__(self, name: str) -> None:
129 self.name = name
130
131 def resolve(self, resolve_context: ResolveContext) -> ResolveResult:
132 term: Term
133 joins: list[TableCriterionTuple] = []
134 output_field = None
135
136 main_name_part, __, rest_name_parts = self.name.partition("__")
137 if main_name_part in resolve_context.model._meta.fetch_fields:
138 # field in the format of "related_field__field" or "related_field__another_rel_field__field"
139 term, joins, output_field = resolve_nested_field(
140 resolve_context.model, resolve_context.table, self.name
141 )
142 elif (
143 rest_name_parts
144 and main_name_part in resolve_context.model._meta.fields_map
145 and isinstance(resolve_context.model._meta.fields_map[main_name_part], JSONField)
146 ):
147 # Accessing a JSON field, e.g. F("json_field__a__b")
148 key_parts = [
149 int(item) if item.isdigit() else str(item) for item in rest_name_parts.split("__")
150 ]
151 term = resolve_field_json_path(
152 PypikaField(resolve_context.model._meta.fields_db_projection[main_name_part]),
153 key_parts,
154 )
155 elif self.name in resolve_context.annotations:
156 # reference to another annotation, e.g. M.annotate(f1=...).annotate(f2=F("f1")).values('field')
157 annotation = resolve_context.annotations[self.name]
158 if isinstance(annotation, Term):
159 term = annotation
160 else:
161 term = annotation.resolve(resolve_context).term
162 else:
163 # a regular model field, e.g. F("id")
164 try:
165 meta = resolve_context.model._meta
166 term = PypikaField(meta.fields_db_projection[self.name])
167
168 if (output_field := meta.fields_map.get(self.name, None)) and (
169 func := output_field.get_for_dialect(
170 meta.db.capabilities.dialect, "function_cast"

Calls

no outgoing calls