123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- import os
- import os.path as op
- from flask import Flask, url_for
- from flask_sqlalchemy import SQLAlchemy
- from sqlalchemy.event import listens_for
- from jinja2 import Markup
- from flask_admin import Admin, form
- from flask_admin.form import rules
- from flask_admin.contrib import sqla
- # Create application
- app = Flask(__name__, static_folder='files')
- # set flask admin swatch
- app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
- # Create dummy secrey key so we can use sessions
- app.config['SECRET_KEY'] = '123456790'
- # Create in-memory database
- app.config['DATABASE_FILE'] = 'sample_db.sqlite'
- app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
- app.config['SQLALCHEMY_ECHO'] = True
- db = SQLAlchemy(app)
- # Create directory for file fields to use
- file_path = op.join(op.dirname(__file__), 'files')
- try:
- os.mkdir(file_path)
- except OSError:
- pass
- # Create models
- class File(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- name = db.Column(db.Unicode(64))
- path = db.Column(db.Unicode(128))
- def __unicode__(self):
- return self.name
- class Image(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- name = db.Column(db.Unicode(64))
- path = db.Column(db.Unicode(128))
- def __unicode__(self):
- return self.name
- class User(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- first_name = db.Column(db.Unicode(64))
- last_name = db.Column(db.Unicode(64))
- email = db.Column(db.Unicode(128))
- phone = db.Column(db.Unicode(32))
- city = db.Column(db.Unicode(128))
- country = db.Column(db.Unicode(128))
- notes = db.Column(db.UnicodeText)
- # Delete hooks for models, delete files if models are getting deleted
- @listens_for(File, 'after_delete')
- def del_file(mapper, connection, target):
- if target.path:
- try:
- os.remove(op.join(file_path, target.path))
- except OSError:
- # Don't care if was not deleted because it does not exist
- pass
- @listens_for(Image, 'after_delete')
- def del_image(mapper, connection, target):
- if target.path:
- # Delete image
- try:
- os.remove(op.join(file_path, target.path))
- except OSError:
- pass
- # Delete thumbnail
- try:
- os.remove(op.join(file_path,
- form.thumbgen_filename(target.path)))
- except OSError:
- pass
- # Administrative views
- class FileView(sqla.ModelView):
- # Override form field to use Flask-Admin FileUploadField
- form_overrides = {
- 'path': form.FileUploadField
- }
- # Pass additional parameters to 'path' to FileUploadField constructor
- form_args = {
- 'path': {
- 'label': 'File',
- 'base_path': file_path,
- 'allow_overwrite': False
- }
- }
- class ImageView(sqla.ModelView):
- def _list_thumbnail(view, context, model, name):
- if not model.path:
- return ''
- return Markup('<img src="%s">' % url_for('static',
- filename=form.thumbgen_filename(model.path)))
- column_formatters = {
- 'path': _list_thumbnail
- }
- # Alternative way to contribute field is to override it completely.
- # In this case, Flask-Admin won't attempt to merge various parameters for the field.
- form_extra_fields = {
- 'path': form.ImageUploadField('Image',
- base_path=file_path,
- thumbnail_size=(100, 100, True))
- }
- class UserView(sqla.ModelView):
- """
- This class demonstrates the use of 'rules' for controlling the rendering of forms.
- """
- form_create_rules = [
- # Header and four fields. Email field will go above phone field.
- rules.FieldSet(('first_name', 'last_name', 'email', 'phone'), 'Personal'),
- # Separate header and few fields
- rules.Header('Location'),
- rules.Field('city'),
- # String is resolved to form field, so there's no need to explicitly use `rules.Field`
- 'country',
- # Show macro from Flask-Admin lib.html (it is included with 'lib' prefix)
- rules.Container('rule_demo.wrap', rules.Field('notes'))
- ]
- # Use same rule set for edit page
- form_edit_rules = form_create_rules
- create_template = 'rule_create.html'
- edit_template = 'rule_edit.html'
- # Flask views
- @app.route('/')
- def index():
- return '<a href="/admin/">Click me to get to Admin!</a>'
- # Create admin
- admin = Admin(app, 'Example: Bootswatch', template_mode='bootstrap2')
- # Add views
- admin.add_view(FileView(File, db.session))
- admin.add_view(ImageView(Image, db.session))
- admin.add_view(UserView(User, db.session, name='User'))
- def build_sample_db():
- """
- Populate a small db with some example entries.
- """
- import random
- import string
- db.drop_all()
- db.create_all()
- first_names = [
- 'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie','Sophie', 'Mia',
- 'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
- 'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
- ]
- last_names = [
- 'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas',
- 'Roberts', 'Khan', 'Lewis', 'Jackson', 'Clarke', 'James', 'Phillips', 'Wilson',
- 'Ali', 'Mason', 'Mitchell', 'Rose', 'Davis', 'Davies', 'Rodriguez', 'Cox', 'Alexander'
- ]
- locations = [
- ("Shanghai", "China"),
- ("Istanbul", "Turkey"),
- ("Karachi", "Pakistan"),
- ("Mumbai", "India"),
- ("Moscow", "Russia"),
- ("Sao Paulo", "Brazil"),
- ("Beijing", "China"),
- ("Tianjin", "China"),
- ("Guangzhou", "China"),
- ("Delhi", "India"),
- ("Seoul", "South Korea"),
- ("Shenzhen", "China"),
- ("Jakarta", "Indonesia"),
- ("Tokyo", "Japan"),
- ("Mexico City", "Mexico"),
- ("Kinshasa", "Democratic Republic of the Congo"),
- ("Bangalore", "India"),
- ("New York City", "United States"),
- ("London", "United Kingdom"),
- ("Bangkok", "Thailand"),
- ("Tehran", "Iran"),
- ("Dongguan", "China"),
- ("Lagos", "Nigeria"),
- ("Lima", "Peru"),
- ("Ho Chi Minh City", "Vietnam"),
- ]
- for i in range(len(first_names)):
- user = User()
- user.first_name = first_names[i]
- user.last_name = last_names[i]
- user.email = user.first_name.lower() + "@example.com"
- tmp = ''.join(random.choice(string.digits) for i in range(10))
- user.phone = "(" + tmp[0:3] + ") " + tmp[3:6] + " " + tmp[6::]
- user.city = locations[i][0]
- user.country = locations[i][1]
- db.session.add(user)
- images = ["Buffalo", "Elephant", "Leopard", "Lion", "Rhino"]
- for name in images:
- image = Image()
- image.name = name
- image.path = name.lower() + ".jpg"
- db.session.add(image)
- for i in [1, 2, 3]:
- file = File()
- file.name = "Example " + str(i)
- file.path = "example_" + str(i) + ".pdf"
- db.session.add(file)
- db.session.commit()
- return
- if __name__ == '__main__':
- # Build a sample db on the fly, if one does not exist yet.
- app_dir = op.realpath(os.path.dirname(__file__))
- database_path = op.join(app_dir, app.config['DATABASE_FILE'])
- if not os.path.exists(database_path):
- build_sample_db()
- # Start app
- app.run(debug=True, use_reloader=True)
|