Forráskód Böngészése

app: addedd sqlite database backend

Nikola Kotur 10 éve
szülő
commit
35108f32e5

+ 1 - 0
.gitignore

@@ -3,4 +3,5 @@
 *.egg-info
 *.py[co]
 
+app.db
 uploads/*

+ 9 - 4
app.py

@@ -1,12 +1,12 @@
 """
-Flask Documentation:     http://flask.pocoo.org/docs/
-Jinja2 Documentation:    http://jinja.pocoo.org/2/documentation/
-Werkzeug Documentation:  http://werkzeug.pocoo.org/documentation/
 """
 
 import os
+
 from flask import Flask
+from flask.ext.sqlalchemy import SQLAlchemy
 
+here = os.path.abspath(os.path.dirname(__file__))
 
 app = Flask(__name__)
 
@@ -21,7 +21,6 @@ if app.config['DEBUG']:
 # End of configuration.
 
 # Uploads.
-here = os.path.abspath(os.path.dirname(__file__))
 app.config['UPLOAD_FOLDER'] = os.environ.get('UPLOAD_FOLDER', os.path.join(here, 'uploads'))
 app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
 
@@ -30,4 +29,10 @@ app.config['RECAPTCHA_USE_SSL'] = False
 app.config['RECAPTCHA_PUBLIC_KEY'] = '6LcrufQSAAAAALwUQKlvx2YKvMIQZ1mabsOgxTJR'
 app.config['RECAPTCHA_PRIVATE_KEY'] = '6LcrufQSAAAAAEfnYns8o-LPGjlD0s6u6veYWEc0'
 
+# Database.
+app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(here, 'app.db')
+app.config['SQLALCHEMY_MIGRATE_REPO'] = os.path.join(here, 'db_repository')
+db = SQLAlchemy(app)
+from database import models
+
 config = app.config

+ 2 - 0
database/__init__.py

@@ -0,0 +1,2 @@
+"""
+"""

+ 22 - 0
database/models.py

@@ -0,0 +1,22 @@
+from app import db
+
+JOB_PENDING = 0
+JOB_STARTED = 1
+JOB_FINISHED = 2
+JOB_DELETED = 3
+
+
+class Job(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    created = db.Column(db.DateTime)
+    finished = db.Column(db.DateTime)
+    expires = db.Column(db.DateTime)
+    uniqid = db.Column(db.String(10), index=True, unique=True)
+    email = db.Column(db.String(120))
+    mp3_name = db.Column(db.String(255), default="")
+    pic_name = db.Column(db.String(255), default="")
+    vid_name = db.Column(db.String(255), default="")
+    finished = db.Column(db.SmallInteger, default=JOB_PENDING)
+
+    def __repr__(self):
+        return '<Job %r>' % (self.uniqid)

+ 21 - 0
db_create.py

@@ -0,0 +1,21 @@
+#!/usr/bin/env python2
+
+import os.path
+
+from migrate.versioning import api
+
+from app import db, config
+
+db.create_all()
+
+if not os.path.exists(config['SQLALCHEMY_MIGRATE_REPO']):
+    api.create(config['SQLALCHEMY_MIGRATE_REPO'], 'database repository')
+    api.version_control(
+        config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO']
+    )
+else:
+    api.version_control(
+        config['SQLALCHEMY_DATABASE_URI'],
+        config['SQLALCHEMY_MIGRATE_REPO'],
+        api.version(config['SQLALCHEMY_MIGRATE_REPO'])
+    )

+ 16 - 0
db_downgrade.py

@@ -0,0 +1,16 @@
+#!/usr/bin/env python2
+
+from migrate.versioning import api
+from app import config
+
+v = api.db_version(
+    config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO']
+)
+api.downgrade(
+    config['SQLALCHEMY_DATABASE_URI'],
+    config['SQLALCHEMY_MIGRATE_REPO'],
+    v - 1
+)
+print 'Current database version: ' + str(api.db_version(
+    config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO']
+))

+ 15 - 0
db_migrate.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python2
+
+import imp
+from migrate.versioning import api
+from app import db, config
+
+migration = config['SQLALCHEMY_MIGRATE_REPO'] + '/versions/%03d_migration.py' % (api.db_version(config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO']) + 1)
+tmp_module = imp.new_module('old_model')
+old_model = api.create_model(config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO'])
+exec old_model in tmp_module.__dict__
+script = api.make_update_script_for_model(config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO'], tmp_module.meta, db.metadata)
+open(migration, "wt").write(script)
+api.upgrade(config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO'])
+print 'New migration saved as ' + migration
+print 'Current database version: ' + str(api.db_version(config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO']))

+ 4 - 0
db_repository/README

@@ -0,0 +1,4 @@
+This is a database migration repository.
+
+More information at
+http://code.google.com/p/sqlalchemy-migrate/

+ 0 - 0
db_repository/__init__.py


+ 5 - 0
db_repository/manage.py

@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+from migrate.versioning.shell import main
+
+if __name__ == '__main__':
+    main(six='<module 'six' from '/home/kotnik/code/snakepit/phosic/lib/python2.7/site-packages/six.pyc'>')

+ 25 - 0
db_repository/migrate.cfg

@@ -0,0 +1,25 @@
+[db_settings]
+# Used to identify which repository this database is versioned under.
+# You can use the name of your project.
+repository_id=database repository
+
+# The name of the database table used to track the schema version.
+# This name shouldn't already be used by your project.
+# If this is changed once a database is under version control, you'll need to
+# change the table name in each database too.
+version_table=migrate_version
+
+# When committing a change script, Migrate will attempt to generate the
+# sql for all supported databases; normally, if one of them fails - probably
+# because you don't have that database installed - it is ignored and the
+# commit continues, perhaps ending successfully.
+# Databases in this list MUST compile successfully during a commit, or the
+# entire commit will fail. List the databases your application will actually
+# be using to ensure your updates to that database work properly.
+# This must be a list; example: ['postgres','sqlite']
+required_dbs=[]
+
+# When creating new change scripts, Migrate will stamp the new script with
+# a version number. By default this is latest_version + 1. You can set this
+# to 'true' to tell Migrate to use the UTC timestamp instead.
+use_timestamp_numbering=False

+ 19 - 0
db_repository/versions/001_migration.py

@@ -0,0 +1,19 @@
+from sqlalchemy import *
+from migrate import *
+
+
+from migrate.changeset import schema
+pre_meta = MetaData()
+post_meta = MetaData()
+
+def upgrade(migrate_engine):
+    # Upgrade operations go here. Don't create your own engine; bind
+    # migrate_engine to your metadata
+    pre_meta.bind = migrate_engine
+    post_meta.bind = migrate_engine
+
+
+def downgrade(migrate_engine):
+    # Operations to reverse the above upgrade go here.
+    pre_meta.bind = migrate_engine
+    post_meta.bind = migrate_engine

+ 0 - 0
db_repository/versions/__init__.py


+ 9 - 0
db_upgrade.py

@@ -0,0 +1,9 @@
+#!/usr/bin/env python2
+
+from migrate.versioning import api
+from app import config
+
+api.upgrade(config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO'])
+print 'Current database version: ' + str(api.db_version(
+    config['SQLALCHEMY_DATABASE_URI'], config['SQLALCHEMY_MIGRATE_REPO']
+))

+ 6 - 0
requirements.txt

@@ -4,6 +4,12 @@
 flask
 Flask-WTF
 
+# ----------------------
+# Database
+# ----------------------
+flask-sqlalchemy
+sqlalchemy-migrate
+
 # ----------------------
 # Production Server
 # ----------------------

+ 38 - 14
routes/site.py

@@ -1,6 +1,9 @@
 import os
+import random
+import string
+import datetime
 
-from flask import render_template, redirect, url_for, abort
+from flask import render_template, redirect, url_for
 from flask_wtf import Form, RecaptchaField
 from flask_wtf.file import FileField, FileAllowed, FileRequired
 from werkzeug import secure_filename
@@ -8,10 +11,10 @@ from werkzeug import secure_filename
 from wtforms.fields.html5 import EmailField
 from wtforms.validators import email, DataRequired
 
-from app import app
+from app import app, db, models
 
 
-class MyForm(Form):
+class JobForm(Form):
     email = EmailField('Email', validators=[ DataRequired(), email() ])
     mp3 = FileField('MP3', validators=[
             FileRequired(), FileAllowed(['mp3'], 'Please upload MP3 only!')
@@ -23,28 +26,49 @@ class MyForm(Form):
     recaptcha = RecaptchaField()
 
 
+def generate_uniqid(length):
+    return ''.join(
+        random.choice(string.lowercase+string.digits) for i in range(length)
+    )
+
 @app.route('/',  methods=['GET', 'POST'])
 def home():
     """Render website's home page."""
-    form = MyForm()
+    form = JobForm()
 
     if form.validate_on_submit():
-        mp3filename = secure_filename(form.mp3.data.filename)
-        form.mp3.data.save(os.path.join(app.config['UPLOAD_FOLDER'] + "/" + mp3filename))
-        picfilename = secure_filename(form.pic.data.filename)
-        form.pic.data.save(os.path.join(app.config['UPLOAD_FOLDER'] + "/" + picfilename))
-        return redirect(url_for('jobs', job_id=1))
+        uniqid = generate_uniqid(10)
+        jobdir = app.config['UPLOAD_FOLDER'] + "/" + uniqid + "/"
+        os.makedirs(jobdir)
+
+        mp3_filename = secure_filename(form.mp3.data.filename)
+        form.mp3.data.save(jobdir + uniqid + ".mp3")
+        pic_filename = secure_filename(form.pic.data.filename)
+        _, pic_extension = os.path.splitext(pic_filename)
+        form.pic.data.save(jobdir + uniqid + pic_extension)
+
+        # TODO: Send job to processing
+
+        # Create database item
+        job = models.Job(
+            uniqid=uniqid,
+            email=form.email.data,
+            created=datetime.datetime.utcnow(),
+            mp3_name=mp3_filename[:255],
+            pic_name=pic_filename[:255],
+        )
+        db.session.add(job)
+        db.session.commit()
+
+        return redirect(url_for('jobs', job_id=job.uniqid))
 
     return render_template('home.html', form=form)
 
 @app.route('/jobs/<job_id>')
 def jobs(job_id):
     """Render the website's about page."""
-    print "Job ID: %s" % job_id
-    if job_id != "1":
-        abort(404)
-
-    return render_template('job.html')
+    job = models.Job.query.filter_by(uniqid=job_id).first_or_404()
+    return render_template('job.html', job=job)
 
 @app.route('/about/')
 def about():

+ 5 - 1
templates/job.html

@@ -4,5 +4,9 @@
 {% endblock %}
 
 {% block main %}
-I am a job
+<p>I am a job {{ job.id }}</p>
+<p>My id is {{ job.uniqid }}</p>
+<p>My pic is: {{ job.pic_name }}</p>
+<p>My mp3 is: {{ job.mp3_name }}</p>
+
 {% endblock %}