              if hasattr(f, 'rel') and f.rel and f.rel.to == related.model and \
                      (link_field_name is None or link_field_name == f.name):
                  setattr(self, cache_attr, getattr(f, attr))
                  return getattr(self, cache_attr)
          # We only reach here if we're given an invalid field name via the
          # `through_fields` argument
          raise FieldDoesNotExist(link_field_name)
  
      def _get_m2m_reverse_attr(self, related, attr):
          "Function that can be curried to provide the related accessor or DB column name for the m2m table"
          cache_attr = '_m2m_reverse_%s_cache' % attr
          if hasattr(self, cache_attr):
 
</s> remove         try:
            return getattr(self, cache_attr)
        except AttributeError:
            # We only reach here if we're given an invalid reverse field
            # name via the `through_fields` argument
            raise FieldDoesNotExist(link_field_name)
 </s> add         return getattr(self, cache_attr) </s> remove         elif self.rel.through_fields is not None:
            if not len(self.rel.through_fields) >= 2 or not (self.rel.through_fields[0] and self.rel.through_fields[1]):
                errors.append(
                    checks.Error(
                        ("The field is given an iterable for through_fields, "
                         "which does not provide the names for both link fields "
                         "that Django should use for the relation through model "
                         "'%s'.") % qualified_model_name,
                        hint=None,
                        obj=self,
                        id='fields.E337',
                    )
                )

        elif not isinstance(self.rel.through, six.string_types):
 </s> add         else: </s> remove * **fields.E337**: The field is given an iterable for through_fields, which does not provide the names for both link fields that Django should use for the relation through <model>.
 </s> add * **fields.E337**: Field specifies ``through_fields`` but does not provide the names of the two link fields that should be used for the relation through ``<model>``.
* **fields.E338**: The intermediary model ``<through model>`` has no field ``<field name>``.
* **fields.E339**: ``<model>.<field name>`` is not a foreign key to ``<model>``. </s> remove   to the target model (this would be ``Person`` in our example), or you must
 </s> add   to the source model (this would be ``Group`` in our example), or you must </s> remove                 ("The field is given an iterable for through_fields, "
                 "which does not provide the names for both link fields "
                 "that Django should use for the relation through model "
                 "'invalid_models_tests.Invitation'."),
                hint=None,
 </s> add                 ("Field specifies 'through_fields' but does not provide the names "
                 "of the two link fields that should be used for the relation "
                 "through model 'invalid_models_tests.Invitation'."),
                hint=("Make sure you specify 'through_fields' as "
                      "through_fields=('field1', 'field2')"),
              if hasattr(f, 'rel') and f.rel and f.rel.to == related.model and \
                      (link_field_name is None or link_field_name == f.name):
                  setattr(self, cache_attr, getattr(f, attr))
                  return getattr(self, cache_attr)



  
      def _get_m2m_reverse_attr(self, related, attr):
          "Function that can be curried to provide the related accessor or DB column name for the m2m table"
          cache_attr = '_m2m_reverse_%s_cache' % attr
          if hasattr(self, cache_attr):
keep keep keep keep replace replace replace keep keep keep keep keep
 Fixed #22217 - ManyToManyField.through_fields fixes.

- Docs description of arguments mix up.
- Keep it from erroneously masking E332 check.
- Add checks E338 and E339, tweak message of E337. 
django/db/models/fields/related.py