Commit 989ac1c8 authored by Serge S. Koval's avatar Serge S. Koval

Added ability to change admin base URL.

parent 37ae5a07
......@@ -16,18 +16,16 @@ app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
# Create model
# Create models
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
# Required for administrative interface
def __unicode__(self):
return self.username
def __repr__(self):
return '<User %r>' % self.username
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
......@@ -41,32 +39,43 @@ class Post(db.Model):
return self.title
# Flask routes
# Flask views
@app.route('/')
def index():
db.session.query(Post).join(User).order_by(User.username).all()
return '<a href="/admin/">Click me to get to Admin!</a>'
# Customized Post model admin
class PostAdmin(sqlamodel.ModelView):
# Visible columns in the list view
list_columns = ('title', 'user')
# List of columns that can be sorted. For 'user' column, use User.username as
# a column.
sortable_columns = ('title', ('user', User.username))
rename_columns = dict(title='Tiiitle')
# Rename 'title' columns to 'Post Title' in list view
rename_columns = dict(title='Post Title')
# Pass arguments to WTForms. In this case, change label for text field to
# be 'Big Text' and add required() validator.
form_args = dict(
text=dict(label='Big Text', validators=[wtf.required()])
)
def __init__(self, session):
# Just call parent class with predefined model.
super(PostAdmin, self).__init__(Post, session)
if __name__ == '__main__':
# Create admin
admin = adminex.Admin('Simple Models')
# Add views
admin.add_view(sqlamodel.ModelView(User, db.session))
admin.add_view(PostAdmin(db.session))
# Associate with an app
admin.apply(app)
# Create DB
......
......@@ -105,30 +105,24 @@ class BaseView(object):
self.url = url
self.static_folder = static_folder
# Initialized from create_blueprint
self.admin = None
self.blueprint = None
self._create_blueprint()
def _set_admin(self, admin):
def create_blueprint(self, admin):
"""
Associate this view with Admin class instance.
`admin`
Admin instance
Create Flask blueprint.
"""
# Store admin instance
self.admin = admin
def _create_blueprint(self):
"""
Create Flask blueprint.
"""
# If endpoint name is not provided, get it from the class name
if self.endpoint is None:
self.endpoint = self.__class__.__name__.lower()
# If url is not provided, generate it from endpoint name
if self.url is None:
self.url = '/admin/%s' % self.endpoint
self.url = '%s/%s' % (self.admin.url, self.endpoint)
# If name is not povided, use capitalized endpoint name
if self.name is None:
......@@ -146,6 +140,8 @@ class BaseView(object):
getattr(self, name),
methods=methods)
return self.blueprint
def _prettify_name(self, name):
"""
Prettify class name by splitting name by capital characters. So, 'MySuperClass' will look like 'My Super Class'
......@@ -249,7 +245,7 @@ class Admin(object):
"""
Collection of the views. Also manages menu structure.
"""
def __init__(self, name=None, index_view=None):
def __init__(self, name=None, url=None, index_view=None):
"""
Constructor.
......@@ -265,6 +261,10 @@ class Admin(object):
name = 'Admin'
self.name = name
if url is None:
url = '/admin'
self.url = url
if index_view is None:
index_view = AdminIndexView()
......@@ -278,7 +278,6 @@ class Admin(object):
`view`
View to add.
"""
view._set_admin(self)
self._views.append(view)
def apply(self, app):
......@@ -291,7 +290,7 @@ class Admin(object):
self.app = app
for v in self._views:
app.register_blueprint(v.blueprint)
app.register_blueprint(v.create_blueprint(self))
self._refresh_menu()
......
......@@ -8,8 +8,6 @@ from wtforms.ext.sqlalchemy.fields import QuerySelectField, QuerySelectMultipleF
from flask import flash
from flaskext import wtf
from flask.ext.adminex.model import BaseModelView
from flask.ext.adminex.form import AdminForm
......
......@@ -7,17 +7,17 @@ class BaseModelView(BaseView):
"""
Base model view.
Does not make any assumptions on how models are stored or managed, but expects following:
View does not make any assumptions on how models are stored or managed, but expects following:
1. Model is an object
2. Model contains properties
3. Each model contains 'id' attribute which uniquely identifies it (TBD: Make it more flexible)
3. Each model contains attribute which uniquely identifies it (i.e. primary key for database model)
4. You can get list of sorted models with pagination applied from a data source
5. You can get one model by its 'id' from the data source
5. You can get one model by its identifier from the data source
Essentially, if you want to support new data store, all you have to do:
1. Derive from `BaseModelView` class
2. Implement various data-related methods (`get_list`, `get_one`, `create_model`, etc)
3. Implement automatic form generation from the model representation (`scaffold_form`, etc)
3. Implement automatic form generation from the model representation (`scaffold_form`)
"""
# Permissions
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment