Commit 55db18f2 authored by Serge S. Koval's avatar Serge S. Koval

Model admin is working.

parent 24115621
from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy
from flask.ext import adminex
from flask.ext.adminex.ext import sqlamodel
# Create application
app = Flask(__name__)
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.sqlite'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
# Create model
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)
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)
title = db.Column(db.String(120))
text = db.Column(db.Text)
user_id = db.Column(db.Integer, db.ForeignKey(User.id))
user = db.relationship(User, backref='posts')
# Flask routes
@app.route('/')
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
if __name__ == '__main__':
# Create admin
admin = adminex.Admin()
admin.add_view(sqlamodel.ModelView(User, db.session, category='News'))
admin.add_view(sqlamodel.ModelView(Post, db.session, category='News'))
admin.apply(app)
# Create DB
db.create_all()
# Start app
app.debug = True
app.run()
...@@ -200,8 +200,5 @@ class Admin(object): ...@@ -200,8 +200,5 @@ class Admin(object):
category.add_child(self.MenuItem(v.name, v)) category.add_child(self.MenuItem(v.name, v))
print repr(self._menu)
def menu(self): def menu(self):
return self._menu return self._menu
from sqlalchemy.orm.properties import RelationshipProperty, ColumnProperty from sqlalchemy.orm.properties import RelationshipProperty, ColumnProperty
from sqlalchemy.orm.interfaces import MANYTOONE from sqlalchemy.orm.interfaces import MANYTOONE
from sqlalchemy import exc
from wtforms.ext.sqlalchemy.orm import model_form, ModelConverter from wtforms.ext.sqlalchemy.orm import model_form, ModelConverter
from wtforms.ext.sqlalchemy.fields import QuerySelectField from wtforms.ext.sqlalchemy.fields import QuerySelectField
...@@ -45,12 +46,21 @@ class AdminModelConverter(ModelConverter): ...@@ -45,12 +46,21 @@ class AdminModelConverter(ModelConverter):
class ModelView(BaseView): class ModelView(BaseView):
def __init__(self, session, model, name=None, endpoint=None, url=None, def __init__(self, model, session, name=None, category=None, endpoint=None, url=None,
can_create=True, can_edit=True, can_delete=True, can_create=True, can_edit=True, can_delete=True,
list_template='admin/model/list.html', list_template='admin/model/list.html',
edit_template='admin/model/edit.html', edit_template='admin/model/edit.html',
create_template='admin/model/edit.html'): create_template='admin/model/edit.html'):
super(ModelView, self).__init__(name, endpoint, url)
# If name not provided, it is modelname
if name is None:
name = '%s' % self._prettify_name(model.__name__)
# If endpoint not provided, it is modelname + 'view'
if endpoint is None:
endpoint = ('%sview' % model.__name__).lower()
super(ModelView, self).__init__(name, category, endpoint, url)
self.session = session self.session = session
self.model = model self.model = model
...@@ -80,7 +90,7 @@ class ModelView(BaseView): ...@@ -80,7 +90,7 @@ class ModelView(BaseView):
for p in mapper.iterate_properties: for p in mapper.iterate_properties:
if isinstance(p, RelationshipProperty): if isinstance(p, RelationshipProperty):
if p.direction is MANYTOONE: if p.direction is MANYTOONE:
self.list_columns.append(p.key) columns.append(p.key)
elif isinstance(p, ColumnProperty): elif isinstance(p, ColumnProperty):
# TODO: Check for multiple columns # TODO: Check for multiple columns
column = p.columns[0] column = p.columns[0]
...@@ -99,7 +109,7 @@ class ModelView(BaseView): ...@@ -99,7 +109,7 @@ class ModelView(BaseView):
return self.scaffold_form() return self.scaffold_form()
def scaffold_edit_form(self): def scaffold_edit_form(self):
return self.scaffold_edit_form() return self.scaffold_form()
# Database-related API # Database-related API
def get_list(self): def get_list(self):
...@@ -110,6 +120,7 @@ class ModelView(BaseView): ...@@ -110,6 +120,7 @@ class ModelView(BaseView):
# Model handlers # Model handlers
def create_model(self, form): def create_model(self, form):
# TODO: Error handling
model = self.model() model = self.model()
form.populate_obj(model) form.populate_obj(model)
self.session.add(model) self.session.add(model)
...@@ -143,7 +154,7 @@ class ModelView(BaseView): ...@@ -143,7 +154,7 @@ class ModelView(BaseView):
return render_template(self.create_template, view=self, form=form) return render_template(self.create_template, view=self, form=form)
@expose('/edit/<int:id>/', methods=('GET', 'POST')) @expose('/edit/<int:id>/', methods=('GET', 'POST'))
def edit_view(self): def edit_view(self, id):
if not self.can_edit: if not self.can_edit:
return redirect(url_for('.index_view')) return redirect(url_for('.index_view'))
...@@ -161,7 +172,7 @@ class ModelView(BaseView): ...@@ -161,7 +172,7 @@ class ModelView(BaseView):
return render_template(self.edit_template, view=self, form=form) return render_template(self.edit_template, view=self, form=form)
@expose('/delete/<int:id>/') @expose('/delete/<int:id>/')
def delete_view(self): def delete_view(self, id):
# TODO: Use post # TODO: Use post
if not self.can_delete: if not self.can_delete:
return redirect(url_for('.index_view')) return redirect(url_for('.index_view'))
......
{% extends 'admin/master.html' %}
{% block body %}
<form action="" method="POST">
{{ form.csrf }}
<table class="form">
{% for f in form if f.label.text != 'Csrf' %}
<tr>
<td>
{{ f.label }}
</td>
<td>
{{ f }}
</td>
</tr>
{% endfor %}
<tr>
<td>
</td>
<td>
{% if form.errors %}
<ul>
{% for fn, fe in form.errors.items() if fe %}
{% for e in fe %}
<li>{{ e }}</li>
{% endfor %}
{% endfor %}
</ul>
{% endif %}
<input type="submit" class="btn btn-primary btn-large" />
</td>
</tr>
</table>
</form>
{% endblock %}
{% extends 'admin/master.html' %}
{% block body %}
<table class="table table-striped table-bordered">
<thead>
<tr>
<th></th>
{% for c in view.list_columns %}
<th>{{ c }}</th>
{% endfor %}
</tr>
</thead>
{% for row in data %}
<tr>
<td>
{% if view.can_edit %}<a href="{{ url_for('.edit_view', id=row.id) }}">Edit</a>{% endif %}
{% if view.can_delete %}<a href="{{ url_for('.delete_view', id=row.id) }}">Delete</a>{% endif %}
</td>
{% for c in view.list_columns %}
<td>{{ row[c] }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% if view.can_create %}
<a class="btn btn-primary btn-large" href="{{ url_for('.create_view') }}">Create New</a>
{% endif %}
{% endblock %}
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