View class :
from sqlalchemy import desc
from datamodels.relational_tables import initialize_datamodels
from dataaccess.postgresql.database import (session_scope)
import datamodels.relational_tables
from flask.ext.admin import Admin, BaseView, expose
from akamai_env import get_akamai_config
from flask import request
import json
from sqlalchemy.sql.functions import now
from flask import Flask, redirect, url_for
import logging
_log = logging.getLogger(__name__)
akamai_config = get_akamai_config()
base_url = akamai_config['webserver']['base_url']
class RollBack(BaseView):
@expose('/')
def fetch_healthy_dataset_from_db(self):
initialize_datamodels()
with session_scope() as session:
epd_ip_dataset = datamodels.relational_tables.EpdIpDataset
qry = session.query(epd_ip_dataset).filter_by(dataset_state='healthy').order_by(
desc(epd_ip_dataset.dataset_id)).all()
qry_last = session.query(epd_ip_dataset).filter_by(dataset_state='healthy').order_by(
desc(epd_ip_dataset.dataset_id)).first()
url = url_for('.return_rollback_ui')
url_for('rollback.return_rollback_ui')
return self.render('airflow/base.html',
qry=qry,
dataset_id=qry_last.dataset_id,
base_url=base_url,
url=url)
@expose('/roll', methods=['POST'])
def return_rollback_ui(self):
if request.method == 'POST':
#body_req = request.json
body_req = request.get_data()
_log.error("Body of the request is ", body_req)
#data = json.dumps(body_req)
#self.initalize_db(body_req)
return '<html> <h1> Hi I am sending a response</h1></html>'
def initalize_db(self, body):
dataset_id = body
epdumppushrollback = datamodels.relational_tables.EpdUmpPushRollback
with session_scope() as session:
epdumppushrollback_obj = epdumppushrollback()
epdumppushrollback_obj.dataset_id = dataset_id
epdumppushrollback_obj.record_id = ''
epdumppushrollback_obj.operator_name = ''
epdumppushrollback_obj.activation_flag = 'active'
epdumppushrollback_obj.record_creation_time = now()
epdumppushrollback_obj.start_time = now()
epdumppushrollback_obj.end_time = ''
session.add(epdumppushrollback_obj)
session.flush()
class RollBackResume(BaseView):
# @expose('/')
# def index(self):
# return self.render('airflow/dags.html')
def fetch_audited_dataset_from_db(self):
initialize_datamodels()
with session_scope() as session:
epd_ip_dataset = datamodels.relational_tables.EpdIpDataset
qry = session.query(epd_ip_dataset).filter_by(dataset_state='audited'). \
order_by(desc(epd_ip_dataset.dataset_id)).all()
return qry
@expose('/')
def return_resume_ui(self):
qry = self.fetch_audited_dataset_from_db()
return self.render('airflow/rollback_resume.html',
qry=qry,
base_url=base_url)
@expose('/rollbackresume', methods=['POST'])
def return_rollback_ui(self):
if request.method == 'POST':
body_req = request.json
data = json.dumps(body_req)
def fetch_from_db(self):
dataset_id = None
initialize_datamodels()
with session_scope() as session:
epd_ump_push_rollback = datamodels.relational_tables.EpdUmpPushRollback
qry = session.query(epd_ump_push_rollback).filter_by(activation_flag='active'). \
order_by(desc(epd_ump_push_rollback.dataset_id)).first()
if qry:
dataset_id = qry.dataset_id
return dataset_id
def write_to_db(self):
dataset_id = self.fetch_from_db()
epd_ump_push_rollback = datamodels.relational_tables.EpdUmpPushRollback
with session_scope() as session:
qry = session.query(epd_ump_push_rollback)
for rows in qry:
if rows.dataset_id == dataset_id:
rows.activation_flag = 'inactive'
rows.end_time = now()
session.commit()
session.flush()
break
HTML Page :
<html>
<style>
p
{
opacity: 0;
}
</style>
<head>
<title>Roll back UI</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="{{base_url}}/admin/">Airflow</a>
</div>
<ul class="nav navbar-nav">
<li class="active"><a href="{{base_url}}/admin/">DAGs</a></li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Data Profiling <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="{{base_url}}/admin/queryview/">Ad Hoc query</a></li>
<li><a href="{{base_url}}/admin/chart/">Charts</a></li>
<li><a href="{{base_url}}/admin/knownevent/">Known Events</a></li>
</ul>
</li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Browse <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="{{base_url}}/admin/slamiss/">SLA Instances</a></li>
<li><a href="{{base_url}}/admin/taskinstance/">Task Instances</a></li>
<li><a href="{{base_url}}/admin/log/">Logs</a></li>
<li><a href="{{base_url}}/admin/basejob/">Jobs</a></li>
<li><a href="{{base_url}}/admin/dagrun/">DAG Runs</a></li>
</ul>
</li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Admin <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="{{base_url}}/admin/pool/">Pools</a></li>
<li><a href="{{base_url}}/admin/configurationview/">Configuration</a></li>
<li><a href="{{base_url}}/admin/user/">Users</a></li>
<li><a href="{{base_url}}/admin/connection/">Connections</a></li>
<li><a href="{{base_url}}/admin/variable/">Variables</a></li>
<li><a href="{{base_url}}/admin/xcom/">XComs</a></li>
</ul>
</li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Rollback <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="{{base_url}}/admin/rollback/">Rollback </a></li>
<li><a href="{{base_url}}/admin/rollbackresume/">Resume</a></li>
</ul>
</li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Docs <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Documentation</a></li>
<li><a href="#">Github</a></li>
</ul>
</li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">About <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="{{base_url}}/admin/versionview/">Version</a></li>
</ul>
</li>
</ul>
</div>
</nav>
<div class="container">
<h3>RollBack UI</h3>
<table class="table table-bordered">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col" >Dataset Id</th>
<th scope="col">Dataset State</th>
</tr>
</thead>
<tbody>
{% for i in qry%}
<tr>
<th scope="row"> </th>
<td> {{ i.dataset_id }} </td>
<td> {{ i.dataset_state }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<head>
<div class="container">
<button type="button" class="btn btn-primary" onclick="loadDoc()" id="myBtn"> Rollback to {{dataset_id}} </button>
</div>
<p id="dataset_id"> {{ dataset_id }}</p>
<script>
function loadDoc()
{
document.getElementById("myBtn").disabled = true;
var xhttp = new XMLHttpRequest();
var dataset_id = document.getElementById("dataset_id");
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("POST", "http://localhost:8085/admin/rollback/roll/", true);
xhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhttp.send("foo=bar&lorem=ipsum");
}
</script>
</head>
<body>
<h2> Url of the index is {{ url }} </h2>
</body>>
</html>
Explanation of code :
I have class RollBack
which returns a table after querying the database, there is a button present on that page; when I click on that button, I want to post some data to an endpoint which I am doing using XMLHttpRequest
in the html page.
When I click on that button, the post data is directing me to @expose('/')
method instead of @expose('/roll')
, since @expose('/')
method doesn't support post method it is throwing 405 error. I want my onclick action of button to redirect to @expose('/roll')
method.
The reason that your code is throwing a 405 is because you haven't configured your expose function to handle POST methods. The default is to handle only GET as explained in the docs.
Your code logic should look something like the following:
from flask import request
class RollBack(BaseView):
@expose('/', methods=('GET', 'POST'))
def fetch_healthy_dataset_from_db(self):
if request.method == 'POST':
# Anything within this block is processing a POST method
# make sure you eventually return a view
return "Success"
# Anything after this point is processing a GET method