Repository: django/django
File: django/db/models/fields/related.py (Python)

Code before:
        return [
            *super().check(**kwargs),
            *self._check_on_delete(databases),
            *self._check_unique(),
        ]

    def _check_on_delete_db_support(self, on_delete, feature_flag, databases):
        errors = []
        for db in databases:
            if not router.allow_migrate_model(db, self.model):
                continue
            connection = connections[db]
            if not (
                feature_flag in self.model._meta.required_db_features
                or getattr(connection.features, feature_flag)
            ):
                no_db_option_name = on_delete.__name__.removeprefix("DB_")
                errors.append(
                    checks.Error(
                        f"{connection.display_name} does not support a "
                        f"{on_delete.__name__}.",
                        hint=f"Change the on_delete rule to {no_db_option_name}.",
                        obj=self,
                        id="fields.E324",
                    ),
                )
        return errors

    def _check_on_delete(self, databases):
        on_delete = getattr(self.remote_field, "on_delete", None)
        errors = []
        if on_delete == DB_CASCADE:
            errors.extend(
                self._check_on_delete_db_support(
                    on_delete, "supports_on_delete_db_cascade", databases
                )
            )
        if on_delete == DB_SET_NULL:
            errors.extend(
                self._check_on_delete_db_support(
                    on_delete, "supports_on_delete_db_null", databases
                )
            )
        if on_delete in [DB_SET_NULL, SET_NULL] and not self.null:
            errors.append(
                checks.Error(
                    f"Field specifies on_delete={on_delete.__name__}, but cannot be "
                    "null.",
                    hint=(
                        "Set null=True argument on the field, or change the on_delete "
                        "rule."

Review comment (refactor):
We could also make this helper method a generator and `yield` the `Error`s.

Code after:
        return [
            *super().check(**kwargs),
            *self._check_on_delete(databases),
            *self._check_unique(),
        ]

    def _check_on_delete_db_support(self, on_delete, feature_flag, databases):
        for db in databases:
            if not router.allow_migrate_model(db, self.model):
                continue
            connection = connections[db]
            if feature_flag in self.model._meta.required_db_features or getattr(
                connection.features, feature_flag
            ):
                continue
            no_db_option_name = on_delete.__name__.removeprefix("DB_")
            yield checks.Error(
                f"{connection.display_name} does not support a {on_delete.__name__}.",
                hint=f"Change the on_delete rule to {no_db_option_name}.",
                obj=self,
                id="fields.E324",
            )

    def _check_on_delete(self, databases):
        on_delete = getattr(self.remote_field, "on_delete", None)
        errors = []
        if on_delete == DB_CASCADE:
            errors.extend(
                self._check_on_delete_db_support(
                    on_delete, "supports_on_delete_db_cascade", databases
                )
            )
        if on_delete == DB_SET_NULL:
            errors.extend(
                self._check_on_delete_db_support(
                    on_delete, "supports_on_delete_db_null", databases
                )
            )
        if on_delete in [DB_SET_NULL, SET_NULL] and not self.null:
            errors.append(
                checks.Error(
                    f"Field specifies on_delete={on_delete.__name__}, but cannot be "
                    "null.",
                    hint=(
                        "Set null=True argument on the field, or change the on_delete "
                        "rule."
                    ),
                    obj=self,
                    id="fields.E320",
                )
            )