Return a tuple of (lookup, field_to_validate). field_to_validate is set for non-text exact lookups so that invalid search terms can be skipped (preserving index usage).
(field_name)
| 1302 | |
| 1303 | # Apply keyword searches. |
| 1304 | def construct_search(field_name): |
| 1305 | """ |
| 1306 | Return a tuple of (lookup, field_to_validate). |
| 1307 | |
| 1308 | field_to_validate is set for non-text exact lookups so that |
| 1309 | invalid search terms can be skipped (preserving index usage). |
| 1310 | """ |
| 1311 | if field_name.startswith("^"): |
| 1312 | return "%s__istartswith" % field_name.removeprefix("^"), None |
| 1313 | elif field_name.startswith("="): |
| 1314 | return "%s__iexact" % field_name.removeprefix("="), None |
| 1315 | elif field_name.startswith("@"): |
| 1316 | return "%s__search" % field_name.removeprefix("@"), None |
| 1317 | # Use field_name if it includes a lookup. |
| 1318 | opts = queryset.model._meta |
| 1319 | lookup_fields = field_name.split(LOOKUP_SEP) |
| 1320 | # Go through the fields, following all relations. |
| 1321 | prev_field = None |
| 1322 | for path_part in lookup_fields: |
| 1323 | if path_part == "pk": |
| 1324 | path_part = opts.pk.name |
| 1325 | try: |
| 1326 | field = opts.get_field(path_part) |
| 1327 | except FieldDoesNotExist: |
| 1328 | # Use valid query lookups. |
| 1329 | if prev_field and prev_field.get_lookup(path_part): |
| 1330 | if path_part == "exact" and not isinstance( |
| 1331 | prev_field, (models.CharField, models.TextField) |
| 1332 | ): |
| 1333 | # Use prev_field to validate the search term. |
| 1334 | return field_name, prev_field |
| 1335 | return field_name, None |
| 1336 | else: |
| 1337 | prev_field = field |
| 1338 | if hasattr(field, "path_infos"): |
| 1339 | # Update opts to follow the relation. |
| 1340 | opts = field.path_infos[-1].to_opts |
| 1341 | # Otherwise, use the field with icontains. |
| 1342 | return "%s__icontains" % field_name, None |
| 1343 | |
| 1344 | may_have_duplicates = False |
| 1345 | search_fields = self.get_search_fields(request) |
nothing calls this directly
no test coverage detected