Compute the necessary table joins for the passage through the fields given in 'names'. 'opts' is the Options class for the current model (which gives the table we are starting from), 'alias' is the alias for the table to start the joining from. The 'can_reus
(
self,
names,
opts,
alias,
can_reuse=None,
allow_many=True,
)
| 1888 | return path, final_field, targets, names[pos + 1 :] |
| 1889 | |
| 1890 | def setup_joins( |
| 1891 | self, |
| 1892 | names, |
| 1893 | opts, |
| 1894 | alias, |
| 1895 | can_reuse=None, |
| 1896 | allow_many=True, |
| 1897 | ): |
| 1898 | """ |
| 1899 | Compute the necessary table joins for the passage through the fields |
| 1900 | given in 'names'. 'opts' is the Options class for the current model |
| 1901 | (which gives the table we are starting from), 'alias' is the alias for |
| 1902 | the table to start the joining from. |
| 1903 | |
| 1904 | The 'can_reuse' defines the reverse foreign key joins we can reuse. It |
| 1905 | can be None in which case all joins are reusable or a set of aliases |
| 1906 | that can be reused. Note that non-reverse foreign keys are always |
| 1907 | reusable when using setup_joins(). |
| 1908 | |
| 1909 | If 'allow_many' is False, then any reverse foreign key seen will |
| 1910 | generate a MultiJoin exception. |
| 1911 | |
| 1912 | Return the final field involved in the joins, the target field (used |
| 1913 | for any 'where' constraint), the final 'opts' value, the joins, the |
| 1914 | field path traveled to generate the joins, and a transform function |
| 1915 | that takes a field and alias and is equivalent to |
| 1916 | `field.get_col(alias)` in the simple case but wraps field transforms if |
| 1917 | they were included in names. |
| 1918 | |
| 1919 | The target field is the field containing the concrete value. Final |
| 1920 | field can be something different, for example foreign key pointing to |
| 1921 | that value. Final field is needed for example in some value |
| 1922 | conversions (convert 'obj' in fk__id=obj to pk val using the foreign |
| 1923 | key field for example). |
| 1924 | """ |
| 1925 | joins = [alias] |
| 1926 | # The transform can't be applied yet, as joins must be trimmed later. |
| 1927 | # To avoid making every caller of this method look up transforms |
| 1928 | # directly, compute transforms here and create a partial that converts |
| 1929 | # fields to the appropriate wrapped version. |
| 1930 | |
| 1931 | def final_transformer(field, alias): |
| 1932 | if not self.alias_cols: |
| 1933 | alias = None |
| 1934 | return field.get_col(alias) |
| 1935 | |
| 1936 | # Try resolving all the names as fields first. If there's an error, |
| 1937 | # treat trailing names as lookups until a field can be resolved. |
| 1938 | last_field_exception = None |
| 1939 | for pivot in range(len(names), 0, -1): |
| 1940 | try: |
| 1941 | path, final_field, targets, rest = self.names_to_path( |
| 1942 | names[:pivot], |
| 1943 | opts, |
| 1944 | allow_many, |
| 1945 | fail_on_missing=True, |
| 1946 | ) |
| 1947 | except FieldError as exc: |
no test coverage detected