Ensure no flattened relation has sub-field include/exclude on its target. Whole-relation include/exclude at the parent level is allowed; only sub-field selection on the flattened child is flagged. :param source_model: model from which flatten paths are rooted
(self, source_model: type["Model"])
| 808 | return excludable |
| 809 | |
| 810 | def validate_flatten_vs_excludable(self, source_model: type["Model"]) -> None: |
| 811 | """ |
| 812 | Ensure no flattened relation has sub-field include/exclude on its target. |
| 813 | Whole-relation include/exclude at the parent level is allowed; only |
| 814 | sub-field selection on the flattened child is flagged. |
| 815 | |
| 816 | :param source_model: model from which flatten paths are rooted |
| 817 | :type source_model: type[Model] |
| 818 | :raises QueryDefinitionError: when a flattened relation has sub-field |
| 819 | include/exclude on its target model |
| 820 | """ |
| 821 | for parts in self._flatten_paths: |
| 822 | table_prefix, target_model, _, _ = get_relationship_alias_model_and_str( |
| 823 | source_model=source_model, |
| 824 | related_parts=list(parts), |
| 825 | ) |
| 826 | child = self.items.get(self._make_key(target_model, table_prefix)) |
| 827 | if not child: |
| 828 | continue |
| 829 | conflicts = (child.include | child.exclude) - {...} |
| 830 | if conflicts: |
| 831 | raise QueryDefinitionError( |
| 832 | f"Flatten conflict: relation '{join_path(parts)}' is " |
| 833 | f"flattened but include/exclude specifies children " |
| 834 | f"{sorted(conflicts)}. A flattened relation renders only " |
| 835 | f"its primary key and cannot have children selected." |
| 836 | ) |
| 837 | |
| 838 | |
| 839 | def join_path(parts: PathParts, tail: Optional[str] = None) -> str: |