app.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import os
  2. import os.path as op
  3. from flask import Flask, url_for
  4. from flask_sqlalchemy import SQLAlchemy
  5. from sqlalchemy.event import listens_for
  6. from jinja2 import Markup
  7. from flask_admin import Admin, form
  8. from flask_admin.form import rules
  9. from flask_admin.contrib import sqla
  10. # Create application
  11. app = Flask(__name__, static_folder='files')
  12. # set flask admin swatch
  13. app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
  14. # Create dummy secrey key so we can use sessions
  15. app.config['SECRET_KEY'] = '123456790'
  16. # Create in-memory database
  17. app.config['DATABASE_FILE'] = 'sample_db.sqlite'
  18. app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
  19. app.config['SQLALCHEMY_ECHO'] = True
  20. db = SQLAlchemy(app)
  21. # Create directory for file fields to use
  22. file_path = op.join(op.dirname(__file__), 'files')
  23. try:
  24. os.mkdir(file_path)
  25. except OSError:
  26. pass
  27. # Create models
  28. class File(db.Model):
  29. id = db.Column(db.Integer, primary_key=True)
  30. name = db.Column(db.Unicode(64))
  31. path = db.Column(db.Unicode(128))
  32. def __unicode__(self):
  33. return self.name
  34. class Image(db.Model):
  35. id = db.Column(db.Integer, primary_key=True)
  36. name = db.Column(db.Unicode(64))
  37. path = db.Column(db.Unicode(128))
  38. def __unicode__(self):
  39. return self.name
  40. class User(db.Model):
  41. id = db.Column(db.Integer, primary_key=True)
  42. first_name = db.Column(db.Unicode(64))
  43. last_name = db.Column(db.Unicode(64))
  44. email = db.Column(db.Unicode(128))
  45. phone = db.Column(db.Unicode(32))
  46. city = db.Column(db.Unicode(128))
  47. country = db.Column(db.Unicode(128))
  48. notes = db.Column(db.UnicodeText)
  49. # Delete hooks for models, delete files if models are getting deleted
  50. @listens_for(File, 'after_delete')
  51. def del_file(mapper, connection, target):
  52. if target.path:
  53. try:
  54. os.remove(op.join(file_path, target.path))
  55. except OSError:
  56. # Don't care if was not deleted because it does not exist
  57. pass
  58. @listens_for(Image, 'after_delete')
  59. def del_image(mapper, connection, target):
  60. if target.path:
  61. # Delete image
  62. try:
  63. os.remove(op.join(file_path, target.path))
  64. except OSError:
  65. pass
  66. # Delete thumbnail
  67. try:
  68. os.remove(op.join(file_path,
  69. form.thumbgen_filename(target.path)))
  70. except OSError:
  71. pass
  72. # Administrative views
  73. class FileView(sqla.ModelView):
  74. # Override form field to use Flask-Admin FileUploadField
  75. form_overrides = {
  76. 'path': form.FileUploadField
  77. }
  78. # Pass additional parameters to 'path' to FileUploadField constructor
  79. form_args = {
  80. 'path': {
  81. 'label': 'File',
  82. 'base_path': file_path,
  83. 'allow_overwrite': False
  84. }
  85. }
  86. class ImageView(sqla.ModelView):
  87. def _list_thumbnail(view, context, model, name):
  88. if not model.path:
  89. return ''
  90. return Markup('<img src="%s">' % url_for('static',
  91. filename=form.thumbgen_filename(model.path)))
  92. column_formatters = {
  93. 'path': _list_thumbnail
  94. }
  95. # Alternative way to contribute field is to override it completely.
  96. # In this case, Flask-Admin won't attempt to merge various parameters for the field.
  97. form_extra_fields = {
  98. 'path': form.ImageUploadField('Image',
  99. base_path=file_path,
  100. thumbnail_size=(100, 100, True))
  101. }
  102. class UserView(sqla.ModelView):
  103. """
  104. This class demonstrates the use of 'rules' for controlling the rendering of forms.
  105. """
  106. form_create_rules = [
  107. # Header and four fields. Email field will go above phone field.
  108. rules.FieldSet(('first_name', 'last_name', 'email', 'phone'), 'Personal'),
  109. # Separate header and few fields
  110. rules.Header('Location'),
  111. rules.Field('city'),
  112. # String is resolved to form field, so there's no need to explicitly use `rules.Field`
  113. 'country',
  114. # Show macro from Flask-Admin lib.html (it is included with 'lib' prefix)
  115. rules.Container('rule_demo.wrap', rules.Field('notes'))
  116. ]
  117. # Use same rule set for edit page
  118. form_edit_rules = form_create_rules
  119. create_template = 'rule_create.html'
  120. edit_template = 'rule_edit.html'
  121. # Flask views
  122. @app.route('/')
  123. def index():
  124. return '<a href="/admin/">Click me to get to Admin!</a>'
  125. # Create admin
  126. admin = Admin(app, 'Example: Bootswatch', template_mode='bootstrap3')
  127. # Add views
  128. admin.add_view(FileView(File, db.session))
  129. admin.add_view(ImageView(Image, db.session))
  130. admin.add_view(UserView(User, db.session, name='User'))
  131. def build_sample_db():
  132. """
  133. Populate a small db with some example entries.
  134. """
  135. import random
  136. import string
  137. db.drop_all()
  138. db.create_all()
  139. first_names = [
  140. 'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie','Sophie', 'Mia',
  141. 'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
  142. 'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
  143. ]
  144. last_names = [
  145. 'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas',
  146. 'Roberts', 'Khan', 'Lewis', 'Jackson', 'Clarke', 'James', 'Phillips', 'Wilson',
  147. 'Ali', 'Mason', 'Mitchell', 'Rose', 'Davis', 'Davies', 'Rodriguez', 'Cox', 'Alexander'
  148. ]
  149. locations = [
  150. ("Shanghai", "China"),
  151. ("Istanbul", "Turkey"),
  152. ("Karachi", "Pakistan"),
  153. ("Mumbai", "India"),
  154. ("Moscow", "Russia"),
  155. ("Sao Paulo", "Brazil"),
  156. ("Beijing", "China"),
  157. ("Tianjin", "China"),
  158. ("Guangzhou", "China"),
  159. ("Delhi", "India"),
  160. ("Seoul", "South Korea"),
  161. ("Shenzhen", "China"),
  162. ("Jakarta", "Indonesia"),
  163. ("Tokyo", "Japan"),
  164. ("Mexico City", "Mexico"),
  165. ("Kinshasa", "Democratic Republic of the Congo"),
  166. ("Bangalore", "India"),
  167. ("New York City", "United States"),
  168. ("London", "United Kingdom"),
  169. ("Bangkok", "Thailand"),
  170. ("Tehran", "Iran"),
  171. ("Dongguan", "China"),
  172. ("Lagos", "Nigeria"),
  173. ("Lima", "Peru"),
  174. ("Ho Chi Minh City", "Vietnam"),
  175. ]
  176. for i in range(len(first_names)):
  177. user = User()
  178. user.first_name = first_names[i]
  179. user.last_name = last_names[i]
  180. user.email = user.first_name.lower() + "@example.com"
  181. tmp = ''.join(random.choice(string.digits) for i in range(10))
  182. user.phone = "(" + tmp[0:3] + ") " + tmp[3:6] + " " + tmp[6::]
  183. user.city = locations[i][0]
  184. user.country = locations[i][1]
  185. db.session.add(user)
  186. images = ["Buffalo", "Elephant", "Leopard", "Lion", "Rhino"]
  187. for name in images:
  188. image = Image()
  189. image.name = name
  190. image.path = name.lower() + ".jpg"
  191. db.session.add(image)
  192. for i in [1, 2, 3]:
  193. file = File()
  194. file.name = "Example " + str(i)
  195. file.path = "example_" + str(i) + ".pdf"
  196. db.session.add(file)
  197. db.session.commit()
  198. return
  199. if __name__ == '__main__':
  200. # Build a sample db on the fly, if one does not exist yet.
  201. app_dir = op.realpath(os.path.dirname(__file__))
  202. database_path = op.join(app_dir, app.config['DATABASE_FILE'])
  203. if not os.path.exists(database_path):
  204. build_sample_db()
  205. # Start app
  206. app.run(debug=True, use_reloader=True)