Example #1
0
    def setUp(self):
        from flask import Flask
        from flask.ext.appbuilder.baseapp import BaseApp
        from flask.ext.appbuilder.models.datamodel import SQLAModel
        from flask.ext.appbuilder.views import GeneralView

        self.app = Flask(__name__)
        self.basedir = os.path.abspath(os.path.dirname(__file__))
        self.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'
        self.app.config['CSRF_ENABLED'] = False
        self.app.config['SECRET_KEY'] = 'thisismyscretkey'
        self.app.config['WTF_CSRF_ENABLED'] = False

        self.db = SQLAlchemy(self.app)

        class Model1View(GeneralView):
            datamodel = SQLAModel(Model1, self.db.session)

        class Model2View(GeneralView):
            datamodel = SQLAModel(Model2, self.db.session)
            related_views = [Model1View]

        self.baseapp = BaseApp(self.app, self.db)
        self.baseapp.add_view(Model1View(), "Model1")
        self.baseapp.add_view(Model2View(), "Model2")
        self.baseapp.add_view(Model2View(), "Model2 Add", href='/model2view/add')
Example #2
0
class FlaskTestCase(unittest.TestCase):

    def setUp(self):
        from flask import Flask
        from flask.ext.appbuilder.baseapp import BaseApp
        from flask.ext.appbuilder.models.datamodel import SQLAModel
        from flask.ext.appbuilder.views import GeneralView

        self.app = Flask(__name__)
        self.basedir = os.path.abspath(os.path.dirname(__file__))
        self.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'
        self.app.config['CSRF_ENABLED'] = False
        self.app.config['SECRET_KEY'] = 'thisismyscretkey'
        self.app.config['WTF_CSRF_ENABLED'] = False

        self.db = SQLAlchemy(self.app)

        class Model1View(GeneralView):
            datamodel = SQLAModel(Model1)

        class Model2View(GeneralView):
            datamodel = SQLAModel(Model2)
            related_views = [Model1View]

        class Model1Filtered1View(GeneralView):
            datamodel = SQLAModel(Model1)
            base_filters = [['field_string', FilterStartsWith, 'a']]

        class Model1Filtered2View(GeneralView):
            datamodel = SQLAModel(Model1, self.db.session)
            base_filters = [['field_integer', FilterEqual, 0]]


        self.baseapp = BaseApp(self.app, self.db)
        self.baseapp.add_view(Model1View, "Model1")
        self.baseapp.add_view(Model1Filtered1View, "Model1Filtered1")
        self.baseapp.add_view(Model1Filtered2View, "Model1Filtered2")

        self.baseapp.add_view(Model2View, "Model2")
        self.baseapp.add_view(Model2View, "Model2 Add", href='/model2view/add')


    def tearDown(self):
        self.baseapp = None
        self.app = None
        self.db = None
        log.debug("TEAR DOWN")


    """ ---------------------------------
            TEST HELPER FUNCTIONS
        ---------------------------------
    """
    def login(self, client, username, password):
        # Login with default admin
        return client.post('/login/', data=dict(
            username=username,
            password=password
        ), follow_redirects=True)

    def logout(self, client):
        return client.get('/logout/')

    def insert_data(self):
        for x,i in zip(string.ascii_letters[:23], range(23)):
            model = Model1(field_string="%stest" % (x), field_integer=i)
            self.db.session.add(model)
            self.db.session.commit()


    def test_fab_views(self):
        """
            Test views creation and registration
        """
        eq_(len(self.baseapp.baseviews), 15)  # current minimal views are 11


    def test_model_creation(self):
        """
            Test Model creation
        """
        from sqlalchemy.engine.reflection import Inspector

        engine = self.db.session.get_bind(mapper=None, clause=None)
        inspector = Inspector.from_engine(engine)
        # Check if tables exist
        ok_('model1' in inspector.get_table_names())
        ok_('model2' in inspector.get_table_names())

    def test_index(self):
        """
            Test initial access and index message
        """
        client = self.app.test_client()

        # Check for Welcome Message
        rv = client.get('/')
        data = rv.data.decode('utf-8')
        ok_(DEFAULT_INDEX_STRING in data)

    def test_sec_login(self):
        """
            Test Security Login, Logout, invalid login, invalid access
        """
        client = self.app.test_client()

        # Try to List and Redirect to Login
        rv = client.get('/model1view/list/')
        eq_(rv.status_code, 302)
        rv = client.get('/model2view/list/')
        eq_(rv.status_code, 302)

        # Login and list with admin
        self.login(client, DEFAULT_ADMIN_USER, DEFAULT_ADMIN_PASSWORD)
        rv = client.get('/model1view/list/')
        eq_(rv.status_code, 200)
        rv = client.get('/model2view/list/')
        eq_(rv.status_code, 200)

        # Logout and and try to list
        self.logout(client)
        rv = client.get('/model1view/list/')
        eq_(rv.status_code, 302)
        rv = client.get('/model2view/list/')
        eq_(rv.status_code, 302)

        # Invalid Login
        rv = self.login(client, DEFAULT_ADMIN_USER, 'password')
        data = rv.data.decode('utf-8')
        ok_(INVALID_LOGIN_STRING in data)

    def test_sec_reset_password(self):
        """
            Test Security reset password
        """
        client = self.app.test_client()

        # Try Reset My password
        rv = client.get('/users/action/resetmypassword/1', follow_redirects=True)
        data = rv.data.decode('utf-8')
        ok_(ACCESS_IS_DENIED in data)

        #Reset My password
        rv = self.login(client, DEFAULT_ADMIN_USER, DEFAULT_ADMIN_PASSWORD)
        rv = client.get('/users/action/resetmypassword/1', follow_redirects=True)
        data = rv.data.decode('utf-8')
        ok_("Reset Password Form" in data)
        rv = client.post('/resetmypassword/form',
                         data=dict(password='******', conf_password='******'), follow_redirects=True)
        eq_(rv.status_code, 200)
        self.logout(client)
        self.login(client, DEFAULT_ADMIN_USER, 'password')
        rv = client.post('/resetmypassword/form',
                         data=dict(password=DEFAULT_ADMIN_PASSWORD, conf_password=DEFAULT_ADMIN_PASSWORD),
                         follow_redirects=True)
        eq_(rv.status_code, 200)



    def test_model_crud(self):
        """
            Test Model add, delete, edit
        """
        client = self.app.test_client()
        rv = self.login(client, DEFAULT_ADMIN_USER, DEFAULT_ADMIN_PASSWORD)

        rv = client.post('/model1view/add',
                         data=dict(field_string='test1', field_integer='1'), follow_redirects=True)
        eq_(rv.status_code, 200)

        model = self.db.session.query(Model1).first()
        eq_(model.field_string, u'test1')
        eq_(model.field_integer, 1)

        rv = client.post('/model1view/edit/1',
                         data=dict(field_string='test2', field_integer='2'), follow_redirects=True)
        eq_(rv.status_code, 200)

        model = self.db.session.query(Model1).first()
        eq_(model.field_string, u'test2')
        eq_(model.field_integer, 2)

        rv = client.get('/model1view/delete/1', follow_redirects=True)
        eq_(rv.status_code, 200)
        model = self.db.session.query(Model1).first()
        eq_(model, None)

    def test_model_add_validation(self):
        """
            Test Model add validations
        """
        client = self.app.test_client()
        self.login(client, 'admin', 'general')

        rv = client.post('/model1view/add',
                         data=dict(field_string='test1', field_integer='1'), follow_redirects=True)
        eq_(rv.status_code, 200)

        rv = client.post('/model1view/add',
                         data=dict(field_string='test1', field_integer='2'), follow_redirects=True)
        eq_(rv.status_code, 200)
        data = rv.data.decode('utf-8')
        ok_(UNIQUE_VALIDATION_STRING in data)

        model = self.db.session.query(Model1).all()
        eq_(len(model), 1)

        rv = client.post('/model1view/add',
                         data=dict(field_string='', field_integer='1'), follow_redirects=True)
        eq_(rv.status_code, 200)
        data = rv.data.decode('utf-8')
        ok_(NOTNULL_VALIDATION_STRING in data)

        model = self.db.session.query(Model1).all()
        eq_(len(model), 1)

    def test_model_edit_validation(self):
        """
            Test Model edit validations
        """
        client = self.app.test_client()
        self.login(client, 'admin', 'general')

        client.post('/model1view/add',
                         data=dict(field_string='test1', field_integer='1'), follow_redirects=True)
        client.post('/model1view/add',
                         data=dict(field_string='test2', field_integer='1'), follow_redirects=True)
        rv = client.post('/model1view/edit/1',
                         data=dict(field_string='test2', field_integer='2'), follow_redirects=True)
        eq_(rv.status_code, 200)
        data = rv.data.decode('utf-8')
        ok_(UNIQUE_VALIDATION_STRING in data)

        rv = client.post('/model1view/edit/1',
                         data=dict(field_string='', field_integer='2'), follow_redirects=True)
        eq_(rv.status_code, 200)
        data = rv.data.decode('utf-8')
        ok_(NOTNULL_VALIDATION_STRING in data)

    def test_model_base_filter(self):
        """
            Test Model base filtered views
        """
        client = self.app.test_client()
        self.login(client, DEFAULT_ADMIN_USER, DEFAULT_ADMIN_PASSWORD)
        self.insert_data()
        models = self.db.session.query(Model1).all()
        eq_(len(models), 23)

        # Base filter string starts with
        rv = client.get('/model1filtered1view/list/')
        data = rv.data.decode('utf-8')
        ok_('atest' in data)
        ok_('btest' not in data)

        # Base filter integer equals
        rv = client.get('/model1filtered2view/list/')
        data = rv.data.decode('utf-8')
        ok_('atest' in data)
        ok_('btest' not in data)
Example #3
0
    label_columns = ContactGeneralView.label_columns
    group_by_columns = ["group", "gender"]
    datamodel = SQLAModel(Contact, db.session)


class ContactTimeChartView(TimeChartView):
    chart_title = "Grouped Birth contacts"
    chart_type = "AreaChart"
    label_columns = ContactGeneralView.label_columns
    group_by_columns = ["birthday"]
    datamodel = SQLAModel(Contact, db.session)


class GroupGeneralView(GeneralView):
    datamodel = SQLAModel(Group, db.session)
    related_views = [ContactGeneralView]


fixed_translations_import = [_("List Groups"), _("List Contacts"), _("Contacts Chart"), _("Contacts Birth Chart")]


fill_gender()
genapp = BaseApp(app, db)
genapp.add_view(
    GroupGeneralView(), "List Groups", icon="fa-folder-open-o", category="Contacts", category_icon="fa-envelope"
)
genapp.add_view(ContactGeneralView(), "List Contacts", icon="fa-envelope", category="Contacts")
genapp.add_separator("Contacts")
genapp.add_view(ContactChartView(), "Contacts Chart", icon="fa-dashboard", category="Contacts")
genapp.add_view(ContactTimeChartView(), "Contacts Birth Chart", icon="fa-dashboard", category="Contacts")
Example #4
0
    list_widget = ListBlock
    show_widget = ShowBlockWidget

    label_columns = {'photo_img': 'Photo'}

    list_columns = ['name', 'photo_img', 'price_label']
    search_columns = ['name', 'price', 'product_type']

    show_fieldsets = [
        ('Summary', {'fields': ['name', 'price_label', 'photo_img', 'product_type']}),
        (
            'Description',
            {'fields': ['description'], 'expanded': True}),
    ]

class ProductView(GeneralView):
    datamodel = SQLAModel(Product)

class ProductTypeView(GeneralView):
    datamodel = SQLAModel(ProductType)
    related_views = [ProductView]


baseapp = BaseApp(app, db)

baseapp.add_view(ProductPubView, "Our Products", icon="fa-folder-open-o")
baseapp.add_view(ProductView, "List Products", icon="fa-folder-open-o", category="Management")
baseapp.add_separator("Management")
baseapp.add_view(ProductTypeView, "List Product Types", icon="fa-envelope", category="Management")

Example #5
0
from flask.ext.appbuilder.baseviews import expose
from flask.ext.appbuilder.security.decorators import has_access
from app import app, db


class MyView(BaseView):

    default_view = "method1"

    @expose("/method1/")
    @has_access
    def method1(self):
        # do something with param1
        # and return to previous page or index
        return "Hello"

    @expose("/method2/<string:param1>")
    @has_access
    def method2(self, param1):
        # do something with param1
        # and render template with param
        param1 = "Goodbye %s" % (param1)
        return param1


genapp = BaseApp(app, db)
genapp.add_view(MyView(), "Method1", category="My View")
# genapp.add_view(MyView(), "Method2", href='/myview/method2/jonh', category='My View')
# Use add link instead there is no need to create MyView twice.
genapp.add_link("Method2", href="/myview/method2/jonh", category="My View")
Example #6
0
class ProjectFilesGeneralView(GeneralView):
    datamodel = SQLAModel(ProjectFiles)

    label_columns = {'file_name': 'File Name', 'download': 'Download'}
    add_columns = ['file', 'description','project']
    edit_columns = ['file', 'description','project']
    list_columns = ['file_name', 'download']
    show_columns = ['file_name', 'download']


class ProjectGeneralView(CompactCRUDMixin, GeneralView):
    datamodel = SQLAModel(Project)
    related_views = [ProjectFilesGeneralView]

    show_template = 'appbuilder/general/model/show_cascade.html'
    edit_template = 'appbuilder/general/model/edit_cascade.html'

    add_columns = ['name']
    edit_columns = ['name']
    list_columns = ['name', 'created_by', 'created_on', 'changed_by', 'changed_on']
    show_fieldsets = [
        ('Info', {'fields': ['name']}),
        ('Audit', {'fields': ['created_by', 'created_on', 'changed_by', 'changed_on'], 'expanded': False})
    ]


baseapp = BaseApp(app, db)
baseapp.add_view(ProjectGeneralView, "List Projects", icon="fa-table", category="Projects")
baseapp.add_view_no_menu(ProjectFilesGeneralView)
Example #7
0
from flask.ext.appbuilder.baseapp import BaseApp
from flask.ext.appbuilder.baseviews import BaseView
from flask.ext.appbuilder.baseviews import expose
from app import app, db

class MyView(BaseView):
    route_base = "/myview"

    @expose('/method1/<string:param1>')
    def method1(self, param1):
            # do something with param1
            # and return to previous page or index
        param1 = 'Hello %s' % (param1)
        return param1

    @expose('/method2/<string:param1>')
    def method2(self, param1):
        # do something with param1
        # and render template with param
        param1 = 'Goodbye %s' % (param1)
        return param1

genapp = BaseApp(app, db)
genapp.add_view_no_menu(MyView())


Example #8
0
from flask import render_template
from flask.ext.appbuilder.baseapp import BaseApp
from flask.ext.appbuilder.models.datamodel import SQLAModel
from flask.ext.appbuilder.views import GeneralView, BaseView, expose
from app import app, db

class FABView(BaseView):
    """
        A simple view that implements the index for the site
    """

    route_base = ''
    default_view = 'index'
    index_template = 'index.html'

    @expose('/')
    def index(self):
        return render_template(self.index_template, baseapp = self.baseapp)

class ContactsView(BaseView):
    route_base = "/contacts"
    index_template = 'contacts.html'
    @expose('/')
    def index(self):
        return render_template(self.index_template, baseapp = self.baseapp)


baseapp = BaseApp(app, db, indexview = FABView)
baseapp.add_view(ContactsView(), "Contacts", href='/contacts',icon='earphone',category='Info')
Example #9
0
        ('Summary', {'fields': ['name', 'photo', 'address', 'group']}),
        ('Personal Info',
         {'fields': ['birthday', 'personal_phone', 'personal_celphone', 'personal_email'], 'expanded': False}),
        ('Professional Info',
         {'fields': ['business_function', 'business_phone', 'business_celphone', 'business_email'], 'expanded': False}),
        ('Extra', {'fields': ['notes'], 'expanded': False}),
    ]


class GroupGeneralView(GeneralView):
    datamodel = SQLAModel(Group, db.session)
    related_views = [PersonGeneralView]

    label_columns = {'phone1': 'Phone (1)', 'phone2': 'Phone (2)', 'taxid': 'Tax ID'}
    list_columns = ['name', 'notes']


class PersonChartView(ChartView):
    route_base = '/persons'
    datamodel = SQLAModel(Person, db.session)
    chart_title = 'Grouped Persons'
    label_columns = PersonGeneralView.label_columns
    group_by_columns = ['group']
    search_columns = ['name', 'group']


baseapp = BaseApp(app, db)
baseapp.add_view(GroupGeneralView(), "List Groups", icon="fa-folder-open-o", category="Contacts")
baseapp.add_view(PersonGeneralView(), "List Contacts", icon="fa-envelope", category="Contacts")
baseapp.add_view(PersonChartView(), "Contacts Chart", icon="fa-dashboard", category="Contacts")
Example #10
0
from flask.ext.appbuilder.models.datamodel import SQLAModel
from flask.ext.appbuilder.views import GeneralView
from flask_appbuilder.charts.views import DirectChartView

from app import app, db
from models import CountryStats, Country


class CountryStatsGeneralView(GeneralView):
    datamodel = SQLAModel(CountryStats)
    list_columns = ['country', 'stat_date', 'population', 'unemployed', 'college']

class CountryGeneralView(GeneralView):
    datamodel = SQLAModel(Country)


class CountryStatsDirectChart(DirectChartView):
    datamodel = SQLAModel(CountryStats)
    chart_title = 'Statistics'
    chart_type = 'LineChart'
    direct_columns = {'General Stats': ('stat_date', 'population', 'unemployed', 'college')}
    base_order = ('stat_date', 'asc')


genapp = BaseApp(app, db)
genapp.add_view(CountryGeneralView, "List Countries", icon="fa-folder-open-o", category="Statistics")
genapp.add_view(CountryStatsGeneralView, "List Country Stats", icon="fa-folder-open-o", category="Statistics")
genapp.add_separator("Statistics")
genapp.add_view(CountryStatsDirectChart, "Show Country Chart", icon="fa-dashboard", category="Statistics")

Example #11
0
class GroupGeneralView(GeneralView):
    datamodel = SQLAModel(Group, db.session)
    related_views = [ContactGeneralView()]

    list_columns = ['name']
    order_columns = ['name']
    search_columns = ['name']

class ContactChartView(ChartView):
    
    chart_title = 'Grouped contacts'
    label_columns = ContactGeneralView.label_columns
    group_by_columns = ['group']
    datamodel = SQLAModel(Contact, db.session)

class ContactTimeChartView(TimeChartView):
    
    chart_title = 'Grouped Birth contacts'
    label_columns = ContactGeneralView.label_columns
    group_by_columns = ['birthday']
    datamodel = SQLAModel(Contact, db.session)


genapp = BaseApp(app, db)
genapp.add_view(GroupGeneralView(), "List Groups",icon = "th-large",category = "Contacts")
genapp.add_view(ContactGeneralView(), "List Contacts",icon = "earphone",category = "Contacts")
genapp.add_separator("Contacts")
genapp.add_view(ContactChartView(), "Contacts Chart","/contactchartview/chart","signal","Contacts")
genapp.add_view(ContactTimeChartView(), "Contacts Birth Chart","/contacttimechartview/chart/month","signal","Contacts")

Example #12
0
                 ('Summary',{'fields':['name','photo','address', 'group']}),
                 ('Personal Info',{'fields':['birthday','personal_phone','personal_celphone','personal_email'],'expanded':False}),
                 ('Professional Info',{'fields':['business_function','business_phone','business_celphone','business_email'],'expanded':False}),
                 ('Extra',{'fields':['notes'],'expanded':False}),
                 ]


class GroupGeneralView(GeneralView):
    datamodel = SQLAModel(Group, db.session)
    related_views = [PersonGeneralView()]    

    label_columns = { 'phone1':'Phone (1)','phone2':'Phone (2)','taxid':'Tax ID'}
    list_columns = ['name','notes']
    show_columns = ['name','address','phone1','phone2','taxid','notes']
    order_columns = ['name','notes']
    search_columns = ['name']

class PersonChartView(ChartView):
    route_base = '/persons'
    datamodel = SQLAModel(Person, db.session)
    chart_title = 'Grouped Persons'
    label_columns = PersonGeneralView.label_columns
    group_by_columns = ['group']
    search_columns = ['name','group']
    

baseapp = BaseApp(app, db)
baseapp.add_view(GroupGeneralView(), "List Groups",icon = "th-large",category = "Contacts")
baseapp.add_view(PersonGeneralView(), "List Contacts",icon = "earphone",category = "Contacts")
baseapp.add_view(PersonChartView(), "Contacts Chart","/persons/chart","earphone","Contacts")
Example #13
0

class GroupGeneralView(GeneralView):
    route_base = '/groups'
    datamodel = SQLAModel(Group, db.session)
    related_views = [PersonGeneralView()]

    list_title = 'List Groups'
    show_title = 'Show Group'
    add_title = 'Add Group'
    edit_title = 'Edit Group'

    label_columns = { 'name':'Name','address':'Address','phone1':'Phone (1)','phone2':'Phone (2)','taxid':'Tax ID','notes':'Notes'}
    list_columns = ['name','notes']
    show_columns = ['name','address','phone1','phone2','taxid','notes']
    order_columns = ['name','notes']
    search_columns = ['name']

class PersonChartView(ChartView):
    
    route_base = '/persons'
    chart_title = 'Grouped Persons'
    label_columns = PersonGeneralView.label_columns
    group_by_columns = ['group']
    datamodel = SQLAModel(Person, db.session)

baseapp = BaseApp(app)
baseapp.add_view(GroupGeneralView, "List Groups","/groups/list","th-large","Contacts")
baseapp.add_view(PersonGeneralView, "List Contacts","/persons/list","earphone","Contacts")
baseapp.add_view(PersonChartView, "Contacts Chart","/persons/chart","earphone","Contacts")