      def explain_query(self):
          result = list(self.execute_sql())
          # Some backends return 1 item tuples with strings, and others return
          # tuples with integers and strings. Flatten them out into strings.
          output_formatter = json.dumps if self.query.explain_format == 'json' else str
          for row in result[0]:
              if not isinstance(row, str):
                  yield ' '.join(output_formatter(c) for c in row)
              else:
                  yield row
 
</s> remove                     self.query.explain_format,
                    **self.query.explain_options
 </s> add                     self.query.explain_info.format,
                    **self.query.explain_info.options </s> remove         q.explain_query = True
        q.explain_format = format
        q.explain_options = options
 </s> add         q.explain_info = ExplainInfo(format, options) </s> remove         self.explain_query = False
        self.explain_format = None
        self.explain_options = {}
 </s> add         self.explain_info = None </s> remove             if self.query.explain_query:
 </s> add             if self.query.explain_info:
        output_formatter = json.dumps if self.query.explain_info.format == 'json' else str
      def explain_query(self):
          result = list(self.execute_sql())
          # Some backends return 1 item tuples with strings, and others return
          # tuples with integers and strings. Flatten them out into strings.
        output_formatter = json.dumps if self.query.explain_info.format == 'json' else str
          for row in result[0]:
              if not isinstance(row, str):
                  yield ' '.join(output_formatter(c) for c in row)
              else:
                  yield row
keep keep keep keep replace keep keep keep keep keep
 Refs #27624 -- Changed Query.explain_info to namedtuple. 
django/db/models/sql/compiler.py