Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

First pass at self-contained, runnable SQLAlchemy example.

  • Loading branch information...
commit 8ac1f54402236c895aa146cea3fffc43d3c8aa0a 1 parent 94f4c02
@wylee authored
View
1  MANIFEST.in
@@ -1 +1,2 @@
include *.txt
+recursive-include examples *
View
3  README.txt
@@ -4,6 +4,9 @@ pyramid_restler
pyramid_restler is a somewhat-opinionated toolkit for building RESTful Web
services and applications on top of the Pyramid framework.
+Take a look in the examples/ directory for self-contained, runnable
+examples.
+
See http://packages.python.org/pyramid_restler/ for detailed documentation
of interfaces, APIs, and usage.
View
151 examples/example.mako
@@ -0,0 +1,151 @@
+<html>
+ <head>
+ <title>pyramid_restler Example</title>
+ <style>
+ table {
+ border-collapse: collapse;
+ }
+ table, th, td {
+ border: 1px solid black;
+ }
+ form {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
+ <script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
+ </head>
+
+ <body>
+ <h2>Things</h2>
+
+ <table id="things">
+ <tr>
+ <th>ID</th>
+ <th>Title</th>
+ <th>Description</th>
+ <th>GET</th>
+ <th>DELETE</th>
+ </tr>
+ % for thing in things:
+ ${self.thing(thing)}
+ % endfor
+ </table>
+
+ <p>
+ <a href="/thing.json">GET collection as JSON</a>
+ </p>
+
+ <h2>Create Thing</h2>
+
+ <form id="create-member-form" method="POST" action="/thing">
+ Title: <input type="text" name="title" /><br />
+ Description: <input type="text" name="description" /><br />
+ <input type="submit" value="POST /thing" />
+ </form>
+
+ <h2>Edit Thing</h2>
+
+ <form id="edit-member-form" method="POST" action="#">
+ <input type="text" name="id" /> ID of Thing to edit<br />
+ <input type="text" name="title" /> Title<br />
+ <input type="text" name="description" /> Description<br />
+ <input type="hidden" name="$method" value="PUT" />
+ <input type="submit" value="PUT /thing/{ID}" />
+ </form>
+
+ <script id="thing-template" type="text/x-jquery-tmpl">
+ ${self.thing(Thing(id='${id}', title='${title}', description='${description}'))}
+ </script>
+
+ <script>//<![CDATA[
+ $(document).ready(function () {
+
+ function onCreate (location) {
+ $.ajax(location, {
+ dataType: 'json',
+ success: function (data) {
+ var thing = data.results;
+ var row = $('#thing-template').tmpl(thing).appendTo('#things');
+ registerDeleteFormHandlers('#thing-' + thing.id);
+ }
+ });
+ }
+
+ function onUpdate (id, fields) {
+ var tr = $('#thing-' + id);
+ $.each(fields, function (i, item) {
+ var name = item.name;
+ if (name === 'title' || name === 'description') {
+ tr.find('td.thing-field-' + name).html(item.value);
+ }
+ });
+ }
+
+ $('form#create-member-form').submit(function (e) {
+ e.preventDefault();
+ $.ajax(this.action, {
+ type: 'POST',
+ data: $(this).serialize(),
+ context: this,
+ success: function (data, status, xhr) {
+ onCreate(xhr.getResponseHeader('Location'));
+ }
+ });
+ });
+
+ $('form#edit-member-form').submit(function (e) {
+ e.preventDefault();
+ var id = $(this).find('input[name=id]').first().val();
+ var action = '/thing/' + id;
+ var fields = $(this).serializeArray();
+ $.ajax(action, {
+ type: this.method,
+ data: $(this).serialize(),
+ success: function (data, status, xhr) {
+ if (xhr.status == 204) {
+ onUpdate(id, fields);
+ } else if (xhr.status == 201) {
+ onCreate(xhr.getResponseHeader('Location'));
+ }
+ }
+ });
+ });
+
+ function registerDeleteFormHandlers (selector) {
+ selector = selector || 'form.delete-member-form';
+ $(selector).submit(function (e) {
+ e.preventDefault();
+ $.ajax(this.action, {
+ type: this.method,
+ data: $(this).serialize(),
+ context: this,
+ success: function () {
+ $(this).closest('tr').remove();
+ }
+ });
+ });
+ }
+
+ registerDeleteFormHandlers();
+ });
+ //]]</script>
+ </body>
+</html>
+
+
+<%def name="thing(thing)">
+ <tr id="thing-${thing.id}">
+ <td class="thing-field-id">${thing.id}</td>
+ <td class="thing-field-title">${thing.title}</td>
+ <td class="thing-field-description">${thing.description}</td>
+ <td><a class="thing-get-link" href="/thing/${thing.id}">GET /thing/${thing.id}</a></td>
+ <td>
+ <form class="delete-member-form" method="POST" action="/thing/${thing.id}">
+ <input type="hidden" name="$method" value="DELETE" />
+ <input type="submit" value="DELETE /thing/${thing.id}" />
+ </form>
+ </td>
+ </tr>
+</%def>
View
87 examples/sqlalchemy_orm_example.py
@@ -0,0 +1,87 @@
+"""
+SQLAlchemy ORM Example
+======================
+
+To run this example, first install pyramid_restler and SQLAlchemy (perhaps
+in a virtualenv). Once that's done, cd into the examples/ directory, run
+`python sqlalchemy_orm_example.py`, and open http://localhost:5000/ in
+your browser. From there, you can play around with CRUD from a very simple
+UI.
+
+Note: a temporary SQLite database is created in the current working
+directory every time this module is run; it is removed automatically when
+the server is shut down normally (e.g., via Ctrl-C). The `DB_NAME` global
+specifies the name of this database.
+
+"""
+import os
+
+from paste.httpserver import serve
+
+from pyramid.config import Configurator
+
+from pyramid_restler.model import SQLAlchemyORMContext
+
+from sqlalchemy.engine import create_engine
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.orm import sessionmaker
+from sqlalchemy.schema import Column
+from sqlalchemy.types import Integer, String
+
+
+DB_NAME = 'pyramid_restler_example.db'
+
+engine = create_engine('sqlite:///{0}'.format(DB_NAME))
+Session = sessionmaker(bind=engine)
+Base = declarative_base(bind=engine)
+
+
+class MyThing(Base):
+
+ __tablename__ = 'my_thing'
+
+ id = Column(Integer, primary_key=True)
+ title = Column(String(100), nullable=False)
+ description = Column(String)
+
+
+class MyThingContextFactory(SQLAlchemyORMContext):
+
+ entity = MyThing
+
+ def session_factory(self):
+ return Session()
+
+
+def root_view(context, request):
+ things = Session().query(MyThing).all()
+ return dict(things=things, Thing=MyThing)
+
+
+def main(**settings):
+ create_and_populate_database()
+ config = Configurator(settings=settings)
+ config.add_route('root', '/')
+ config.add_view(route_name='root', view=root_view, renderer='example.mako')
+ config.include('pyramid_restler')
+ config.add_restful_routes('thing', MyThingContextFactory)
+ config.enable_POST_tunneling()
+ return config.make_wsgi_app()
+
+
+def create_and_populate_database():
+ Base.metadata.create_all()
+ session = Session()
+ session.add_all([
+ MyThing(title='One'),
+ MyThing(title='Two'),
+ MyThing(title='Three'),
+ ])
+ session.commit()
+
+
+if __name__ == '__main__':
+ settings = {'mako.directories': '.'}
+ app = main(**settings)
+ serve(app, host='0.0.0.0', port=5000)
+ os.remove(DB_NAME)
Please sign in to comment.
Something went wrong with that request. Please try again.