Can model views in Flask-Admin hyperlink to other model views?
Question:
Let’s suppose we have a model, Foo
, that references another model, User
– and there are Flask-Admin’s ModelView
for both.
On the Foo
admin view page
I would like the entries in the User
column to be linked to the corresponding User
model view.
Do I need to modify one of Flask-Admin’s templates to achieve this?
(This is possible in the Django admin interface by simply outputting HTML for a given field and setting allow_tags
(ref) True to bypass Django’s HTML tag filter)
Answers:
Use column_formatters
for this: https://flask-admin.readthedocs.org/en/latest/api/mod_model/#flask.ext.admin.model.BaseModelView.column_formatters
Idea is pretty simple: for a field that you want to display as hyperlink, either generate a HTML string and wrap it with Jinja2 Markup
class (so it won’t be escaped in templates) or use macro
helper: https://github.com/mrjoes/flask-admin/blob/master/flask_admin/model/template.py
Macro helper allows you to use custom Jinja2 macros in overridden template, which moves presentational logic to templates.
As far as URL is concerned, all you need is to find endpoint name generated (or provided) for the User
model and do url_for('userview.edit_view', id=model.id)
to generate the link.
Some example code based on Joes’ answer:
class MyFooView(ModelView):
def _user_formatter(view, context, model, name):
return Markup(
u"<a href='%s'>%s</a>" % (
url_for('user.edit_view', id=model.user.id),
model.user
)
) if model.user else u""
column_formatters = {
'user': _user_formatter
}
extra information for @wodow, notice that model.user
is wrong if you use pymongo as the backend, because the model in pymongo is a dict type, you can just use model['name']
to replace it
Adding this code to each of your models that have referenced by other models and flask-admin and jinja will take care of the name you want to display on the screen, just replace that with whatever you prefer:
def __unicode__(self):
return self.name # or self.id or whatever you prefer
for example:
class Role(db.Document, RoleMixin):
name = db.StringField(max_length=80, unique=True)
description = db.StringField(max_length=255)
def __unicode__(self):
return self.name
class MasterUser(db.Document, UserMixin):
email = db.StringField(max_length=255)
password = db.StringField(max_length=255)
active = db.BooleanField(default=True)
confirmed_at = db.DateTimeField()
roles = db.ListField(db.ReferenceField(Role), default=[])
Let’s suppose we have a model, Foo
, that references another model, User
– and there are Flask-Admin’s ModelView
for both.
On the Foo
admin view page
I would like the entries in the User
column to be linked to the corresponding User
model view.
Do I need to modify one of Flask-Admin’s templates to achieve this?
(This is possible in the Django admin interface by simply outputting HTML for a given field and setting allow_tags
(ref) True to bypass Django’s HTML tag filter)
Use column_formatters
for this: https://flask-admin.readthedocs.org/en/latest/api/mod_model/#flask.ext.admin.model.BaseModelView.column_formatters
Idea is pretty simple: for a field that you want to display as hyperlink, either generate a HTML string and wrap it with Jinja2 Markup
class (so it won’t be escaped in templates) or use macro
helper: https://github.com/mrjoes/flask-admin/blob/master/flask_admin/model/template.py
Macro helper allows you to use custom Jinja2 macros in overridden template, which moves presentational logic to templates.
As far as URL is concerned, all you need is to find endpoint name generated (or provided) for the User
model and do url_for('userview.edit_view', id=model.id)
to generate the link.
Some example code based on Joes’ answer:
class MyFooView(ModelView):
def _user_formatter(view, context, model, name):
return Markup(
u"<a href='%s'>%s</a>" % (
url_for('user.edit_view', id=model.user.id),
model.user
)
) if model.user else u""
column_formatters = {
'user': _user_formatter
}
extra information for @wodow, notice that model.user
is wrong if you use pymongo as the backend, because the model in pymongo is a dict type, you can just use model['name']
to replace it
Adding this code to each of your models that have referenced by other models and flask-admin and jinja will take care of the name you want to display on the screen, just replace that with whatever you prefer:
def __unicode__(self):
return self.name # or self.id or whatever you prefer
for example:
class Role(db.Document, RoleMixin):
name = db.StringField(max_length=80, unique=True)
description = db.StringField(max_length=255)
def __unicode__(self):
return self.name
class MasterUser(db.Document, UserMixin):
email = db.StringField(max_length=255)
password = db.StringField(max_length=255)
active = db.BooleanField(default=True)
confirmed_at = db.DateTimeField()
roles = db.ListField(db.ReferenceField(Role), default=[])