Skip to content

Instantly share code, notes, and snippets.

@rochacon
Last active August 29, 2015 13:56
Show Gist options
  • Save rochacon/9244596 to your computer and use it in GitHub Desktop.
Save rochacon/9244596 to your computer and use it in GitHub Desktop.
Simple URL shortener built with Pyramid (just for fun)
# -*- coding: utf-8 -*-
"""
Simple URL shortener built with Pyramid.
# Setup
## Dependencies
* pyramid>=1.5a3
* sqlalchemy>=0.9
* pyramid_tm
* zope.sqlalchemy
* gunicorn (or another WSGI container)
## Setup DB
python -c "from shortener import create_app, Base; a = create_app(); Base.metadata.create_all(a.registry.dbmaker().bind)"
# Run
gunicorn shortener
"""
import random
import string
from pyramid.config import Configurator
from pyramid.httpexceptions import HTTPFound, HTTPNotFound, HTTPPreconditionFailed
from pyramid.view import view_config
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from zope.sqlalchemy import ZopeTransactionExtension
# Model
Base = declarative_base()
class URL(Base):
__tablename__ = 'urls'
id = Column(Integer, primary_key=True)
key = Column(String(10), unique=True)
url = Column(String(255))
@classmethod
def generate_key(cls):
return ''.join(random.choice(string.ascii_letters + string.digits) for x in range(10))
# Views
def get_url(request):
key = request.matchdict.get('key')
url = request.db.query(URL).filter_by(key=key).first()
if url is None:
raise HTTPNotFound()
# TODO return would be better for the redirect
raise HTTPFound(url.url)
def put_url(request):
if 'url' not in request.json:
raise HTTPPreconditionFailed()
url = URL(key=URL.generate_key(), url=request.json['url'])
request.db.add(url)
return {'url': url.url, 'key': url.key}
def delete_url(request):
key = request.matchdict.get('key')
url = request.db.query(URL).filter_by(key=key).first()
if url is None:
raise HTTPNotFound()
request.db.delete(url)
return {}
def list_urls(request):
urls = request.db.query(URL).all()
return [{"key": u.key, "url": u.url, "href": request.route_url('url', key=u.key)} for u in urls]
# App
def create_app():
cfg = Configurator()
cfg.include('pyramid_tm')
engine = create_engine('sqlite:///pyramidurlshortener.db')
cfg.registry.dbmaker = sessionmaker(bind=engine, extension=ZopeTransactionExtension())
def db(request):
"""db request method"""
maker = request.registry.dbmaker
session = maker()
def cleanup(request):
session.close()
request.add_finished_callback(cleanup)
return session
cfg.add_request_method(db, reify=True)
cfg.add_route('root', '/')
cfg.add_view(list_urls, route_name='root', renderer='json', request_method='GET')
cfg.add_view(put_url, route_name='root', renderer='json', request_method='PUT')
cfg.add_route('url', '/{key}')
cfg.add_view(get_url, route_name='url', request_method='GET')
cfg.add_view(delete_url, route_name='url', renderer='json', request_method='DELETE')
return cfg.make_wsgi_app()
application = create_app()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment