Remote model in Flask-Admin

The task is to show a model from another application in Flask-Admin. A way to do it is to overwrite BaseModelView and get the data through HTTP request. Here is a simple example for a sortable list with a pagination.

Suppose there is a model in app2

class MyModel(DynamicDocument):
    name = StringField()
    created_time = DateTimeField(default=datetime.utcnow)

To get the list of models it will require a endpoint

@api_blueprint.route('/mymodels', methods=['POST'])
def list_mymodels():
    data = request.get_json()
    objects = MyModel.objects
    count = objects.count()

    sort_field = data.get('sort_field')
    sort_desc = data.get('sort_desc')
    page = data.get('page', 0)
    page_size = data.get('page_size', 10)

    if sort_field:
    	if sort_desc:
        	sort_field = '-' + sort_field
        objects = objects.order_by(sort_field)

    objects = objects[page * page_size : (page + 1) * page_size]    

    return jsonify(count=count, objects=[{
    	'id': str(obj.id),
        'name': obj.name,
        'created_time': http_date(obj.created_time),
    } for obj in objects])

To request this data from Flask-Admin in app1

class DictModel(object):
    def __init__(self, **entries):
        self.__dict__.update(entries)

    def __getitem__(self, item):
        return self.__dict__.get(item)


class RestModelView(BaseModelView):
    can_edit = False
    can_create = False
    can_delete = False
    can_view_details = False
    page_size = 20

    def get_pk_value(self, model):
        return model['id']

    def get_list(self, page, sort_field, sort_desc, search, filters, page_size=None):
        if not page_size:
            page_size = self.page_size

        response = requests.post(
        	self.model.endpoint, 
        	data=json.dumps(dict(
            	page=page,
            	sort_field=sort_field,
            	sort_desc=sort_desc,
            	search=search,
            	filters=filters,
            	page_size=page_size
	        )), 
	        headers={'Content-Type': 'application/json'}).json()

        return response['count'], [self.model(**d) for d in response['objects']]

    def scaffold_form(self):
        return Form


class MyModelView(RestModelView):
    def scaffold_list_columns(self):
        return ['name', 'created_time']

    def scaffold_sortable_columns(self):
        return {'Created time': 'created_time'}

class MyModel(DictModel):
	endpoint = 'http://app2:8080/mymodels'

admin.add_view(MyModelView(MyModel))
comments powered by Disqus