code: def ToCsv(self, columns_order=None, order_by=(), separator=","):
      csv_buffer = six.StringIO()
      writer = csv.writer(csv_buffer, delimiter=separator)
      if columns_order is None:
        columns_order = [col["id"] for col in self.__columns]
      col_dict = dict([(col["id"], col) for col in self.__columns])
      def ensure_str(s):
        "Compatibility function. Ensures using of str rather than unicode."
        if isinstance(s, str):
          return s
        return s.encode("utf-8")
      writer.writerow([ensure_str(col_dict[col]["label"])
                       for col in columns_order])
      for row, unused_cp in self._PreparedData(order_by):
        cells_list = []
        for col in columns_order:
          value = ""
          if col in row and row[col] is not None:
            value = self.CoerceValue(row[col], col_dict[col]["type"])
          if isinstance(value, tuple):
            if col_dict[col]["type"] in ["date", "datetime", "timeofday"]:
              cells_list.append(ensure_str(self.ToString(value[1])))
            else:
              cells_list.append(ensure_str(self.ToString(value[0])))
          else:
            cells_list.append(ensure_str(self.ToString(value)))
        writer.writerow(cells_list)
      return csv_buffer.getvalue()