Getting Started with Cassandra & Python
presentation by:
Philip Doctor & Amber Doctor
DePy 2015 Conference
Tornado
Tornado is a Python web framework and asynchronous networking library. By using non-blocking network I/O, Tornado can scale to tens of thousands of open connections, making it ideal for long polling, WebSockets, and other applications that require a long-lived connection to each user.
Cassandra
The Apache Cassandra database is the right choice when you need scalability and high availability without compromising performance. Linear scalability and proven fault-tolerance on commodity hardware or cloud infrastructure make it the perfect platform for mission-critical data.
Set Up Tornado
- Create a project folder
- make sure there are no spaces in its name or path
- Install virtualenv
- $ pip install virtualenv
- Create your virtualenv
- $ virtualenv ct
- Activate virtualenv
- $ source ct/bin/activate
- Install Tornado
- $ pip install tornado
Hello DePy
from tornado.ioloop import IOLoop
from tornado.web import RequestHandler, Application, url
class HelloHandler(RequestHandler):
def get(self):
self.write("Hello DePy 2015!")
def make_app():
return Application([
url(r"/", HelloHandler),
])
def main():
app = make_app()
app.listen(8889)
IOLoop.current().start()
if __name__ == "__main__":
main()
Set Up Cassandra
- While in your virtualenv ct
- Install CCM dependancies
- $ pip install pyYaml
- $ pip install six
- $ brew install ant
- $ pip install psutil
- Create a folder to clone the CCM git repo
- Clone CCM
- $ git clone https://github.com/pcmanus/ccm.git
- Install Cassandra Driver for Python
- $ pip install cassandra-driver
Start Cassandra Server
- Create your cluster
- $ ccm create cassandra_dev_cluster -n 3 -v 2.1.2
- $ sudo ifconfig lo0 alias 127.0.0.2 up
- $ sudo ifconfig lo0 alias 127.0.0.3 up
- Start your cluster
- $ ccm start
Todo List Database
create_database.cql
CREATE KEYSPACE tornado_app
WITH REPLICATION =
{ 'class' : 'SimpleStrategy',
'replication_factor' : 2 };
use tornado_app;
CREATE TABLE todo_list (
user_name text,
id uuid,
todo text,
is_completed boolean,
PRIMARY KEY((user_name), id)
);
ccm node1 cqlsh < create_database.cql
Run above script from command line:
CQL
Cassandra Query Language
ccm node1 cqlsh
cqlsh> insert into tornado_app.todo_list (user_name, id, todo, is_completed)
values ('DePy2015', f6728f9c-0326-11e5-a758-b8e85644fe9b, 'test to do', false);
cqlsh> select * from tornado_app.todo_list;
cqlsh> select * from tornado_app.todo_list where user_name = 'DePy2015';
cqlsh> drop KEYSPACE tornado_app;
cqlsh> exit;
Sample CQL
Connect to database
Connect App to DB
todo_list.py
from cassandra.cluster import Cluster
# note: without defining parameters Cluster() connects to localhost
cassandra_cluster = Cluster()
# note: you don't have to provide a keyspace argument below
# but then you'd have to specify it in every query
session = cassandra_cluster.connect('tornado_app')
# use this if connected with keyspace as an argument
session.execute('SELECT id, todo, is_completed FROM todo_list
WHERE user_name = %s', (self.user_name,))
# if keyspace was not used as a connection argument,
# specify the keyspace in the query
session.execute('SELECT id, todo, is_completed FROM tornado_app.todo_list
WHERE user_name = %s', (self.user_name,))
Simple Get
todo_list.py
class ToDoList(RequestHandler):
user_name = "DePy2015"
def get(self):
rows = session.execute('SELECT id, todo, is_completed
FROM todo_list WHERE user_name = %s', (self.user_name,))
self.render("todo_list.html", user_name=self.user_name, todo_list=rows)
Using a Template
todo_list.html
<html><header>.....</header>
<body>
<h1>{{user_name}} To Do List</h1>
{% for item in todo_list %}
<div>
<input type="checkbox" name="todo" id="{{item.id}}"
{%if item.is_completed %}checked{% end %} >
<label>{{item.todo}}</label>
<button onclick="deleteCompletedItems('{{item.id}}')">Delete</button>
</div>
{% end %}
<form method="post">
<input type="text" name="new_todo" placeholder="New To Do Item">
<input type="submit" value="Add">
</form>
</body>
</html>
In the browser
localhost:8888
Simple Post
todo_list.html
<html><header>.....</header>
<body>.....
<form method="post">
<input type="text" name="new_todo" placeholder="New To Do Item">
<input type="submit" value="Add">
</form>
</body></html>
def post(self):
new_todo = self.get_argument('new_todo', '')
session.execute("INSERT INTO todo_list (user_name, id, todo, is_completed)
VALUES (%s, %s, %s, %s)", (self.user_name, uuid.uuid1(), new_todo, False))
self.redirect('/')
todo_list.py
Simple Put
todo_list.html
<header><script type="text/javascript">
$(function(){
$(":checkbox").click(function(){
$.ajax({
type: 'PUT',
data: "todo_id=" + this.id + "&is_completed_status=" + this.checked,
success: function(data) {
location.href = location.href;
}})})});
</script></header>
def put(self):
todo_id = uuid.UUID(self.get_argument('todo_id', ''))
is_completed =
True if self.get_argument('is_completed_status', '')==u'true' else False
session.execute("UPDATE todo_list SET is_completed = %s
WHERE id = %s AND user_name = %s", (is_completed, todo_id, self.user_name))
self.finish()
todo_list.py
Simple Delete
todo_list.html
<script>
function deleteCompletedItems(todo_id) {
$.ajax({
type: 'DELETE',
data: "todo_id=" + todo_id,
success: function(data) {
location.href = location.href;
}})};
</script>
def delete(self):
todo_id = uuid.UUID(self.get_argument('todo_id', ''))
session.execute("DELETE FROM todo_list WHERE id = %s
AND user_name = %s", (todo_id, self.user_name))
self.finish()
todo_list.py
is_deleted flag
- For many use cases in Cassandra you'll want to have your delete function set an is_deleted flag rather than deleting the record.
- You can manage your is_deleted flag just like the is_completed flag in the example To Do application.
- This helps to keep accurate historical records but not show them.
Amber
amberdoctor@gmail.com
Philip
philip.s.doctor@gmail.com
DePy 2015
Getting Started with Cassandra and Python
Getting Started with Cassandra & Python
By Philip Doctor
Getting Started with Cassandra & Python
A walk through on setting up a To Do application using Tornado, a python framework, and performing CRUD operations with Cassandra.
- 1,781