(self, opts, mask, select_mask=None)
| 814 | self.extra_order_by = rhs.extra_order_by or self.extra_order_by |
| 815 | |
| 816 | def _get_defer_select_mask(self, opts, mask, select_mask=None): |
| 817 | if select_mask is None: |
| 818 | select_mask = {} |
| 819 | select_mask[opts.pk] = {} |
| 820 | # All concrete fields and related objects that are not part of the |
| 821 | # defer mask must be included. If a relational field is encountered it |
| 822 | # gets added to the mask for it be considered if `select_related` and |
| 823 | # the cycle continues by recursively calling this function. |
| 824 | for field in opts.concrete_fields + opts.related_objects: |
| 825 | field_mask = mask.pop(field.name, None) |
| 826 | field_att_mask = None |
| 827 | if field_attname := getattr(field, "attname", None): |
| 828 | field_att_mask = mask.pop(field_attname, None) |
| 829 | if field_mask is None and field_att_mask is None: |
| 830 | select_mask.setdefault(field, {}) |
| 831 | elif field_mask: |
| 832 | if not field.is_relation: |
| 833 | raise FieldError(next(iter(field_mask))) |
| 834 | # Virtual fields such as many-to-many and generic foreign keys |
| 835 | # cannot be effectively deferred. Historically, they were |
| 836 | # allowed to be passed to QuerySet.defer(). Ignore such field |
| 837 | # references until a layer of validation at mask alteration |
| 838 | # time is eventually implemented. |
| 839 | if field.many_to_many: |
| 840 | continue |
| 841 | field_select_mask = select_mask.setdefault(field, {}) |
| 842 | related_model = field.related_model._meta.concrete_model |
| 843 | self._get_defer_select_mask( |
| 844 | related_model._meta, field_mask, field_select_mask |
| 845 | ) |
| 846 | # Remaining defer entries must be references to filtered relations |
| 847 | # otherwise they are surfaced as missing field errors. |
| 848 | for field_name, field_mask in mask.items(): |
| 849 | if filtered_relation := self._filtered_relations.get(field_name): |
| 850 | relation = opts.get_field(filtered_relation.relation_name) |
| 851 | field_select_mask = select_mask.setdefault((field_name, relation), {}) |
| 852 | related_model = relation.related_model._meta.concrete_model |
| 853 | self._get_defer_select_mask( |
| 854 | related_model._meta, field_mask, field_select_mask |
| 855 | ) |
| 856 | else: |
| 857 | opts.get_field(field_name) |
| 858 | return select_mask |
| 859 | |
| 860 | def _get_only_select_mask(self, opts, mask, select_mask=None): |
| 861 | if select_mask is None: |
no test coverage detected