1
votes

I am having the hardest time trying to customize flask-admin to change the name of a thumbnail in my admin view. I've been looking around trying to find out how to do this and I think the answer lies within ImageUploadField's namegen and thumbgen properties but I'm not sure. Could someone assist? This is what I am trying to do.

Step 1:

This is my Model that I am generating for an admin view. Its an employee with fields.

class Employee(db.Model):
  __tablename__ = 'employees'
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(200))
  title = db.Column(db.String(200))
  email = db.Column(db.String(200))
  department = db.Column(db.String(200))
  path = db.Column(db.String(300))

  def __init__(self, name='', title='', email='', department='', path=''):
    self.name = name
    self.title = title
    self.email = email
    self.department = department
    self.path = path

  def __repr__(self):
    return '<Employee %r>' % self.name
admin.add_view(EmployeeView(Employee, db.session))

Step 2:

For this step a user uploads an employee's uploads information through a form. When they press submit some custom code happens which leads to step 3.

Step 3:

I have a listens_for callback that takes the name of the image they provide and changes the name of the file into the name of the employee. For example if I upload an image named me.jpg, this file will be changed to Daniel Rubio.jpg and will be stored as Daniel Rubio in the Employee's path field. This is the code:

@listens_for(Employee, 'before_insert')
def change_employee_path(mapper, connection, target):
    if target.path:
        os.rename(os.path.join(app.config['UPLOAD_FOLDER'], target.path), 'static/images/' + target.name + '.jpg')
        target.path = target.name + '.jpg'

Additionally this code will rename the me.jpg in my static/images/ folder to Daniel Rubio.jpg in static/images/

Step 4:

Next, I have this code taken from example code using Flask-Admin to show my model and the image it is associated with. This is the code:

class EmployeeView(ModelView):
def _list_thumbnail(view, context, model, name):
    if not model.path:
        return ''
    return Markup('<img src="%s">' % url_for('static',
                                              filename= 'images/' + form.thumbgen_filename(model.path)))
column_formatters = {
    'path': _list_thumbnail
}

form_extra_fields = {
    'path': form.ImageUploadField('Image', base_path=file_path, thumbnail_size=(100, 100, True))
}
def is_accessible(self):
    return flask_login.current_user.is_authenticated

I have wired everything so that the image is named correctly everywhere that it needs to be except in my 'static/images folder. After I submit an Employee through Flask-admin, my me.jpg generates a me_thumb.jpg instead of Daniel Rubio_thumb.jpg. I can't for the life of me figure out how to customize this so that this stops happening. I'm pretty sure that this happens in ImageUploadField found here Flask-Admin ImageUploadField but I can't get it to work. What can I try to get this to work? Help would be much appreciated.


Fix Attempt #1

Overriding ImageUploadField

class ImageOverride(form.ImageUploadField('Image', base_path=file_path, thumbnail_size=(100, 100, True))):
def __init__(self, thumbgen=None):
    self.thumbgen=self.path


class EmployeeView(ModelView):
    def _list_thumbnail(view, context, model, name):
        if not model.path:
            return ''
        return Markup('<img src="%s">' % url_for('static',
                                                  filename= 'images/' + form.thumbgen_filename(model.path)))
    column_formatters = {
        'path': _list_thumbnail
    }

    form_extra_fields = {
        'path': ImageOverride()
    }
    def is_accessible(self):
        return flask_login.current_user.is_authenticated

Result:

Error: `TypeError: 'UnboundField' object is not callable`
1
You're right - all you have to do is to inherit from the ImageUploadField, override these methods and use your field. - Joes
Joes, thanks for the reply. Can you take a look at my edit. Is this sort of what you had in mind. I'm new to both Python and Flask so I'm trying to figure out the best way for this to work. Is this what you meant? - Dan Rubio
No, you inherit from classes and ImageUploadField is a class. Then you override some methods (filename generation) and use ImageOverride instead of ImageUploadField in admin. - Joes
Joes, thanks for helping. Ultimately, I did a dirtier solution but I was able to get exactly what I needed. - Dan Rubio

1 Answers

2
votes

In the end I had to bypass the Joes suggestion and instead I came up with this solution:

class EmployeeView(ModelView):
def _list_thumbnail(view, context, model, name):
    if not model.path:
        return ''
    return Markup('<img height="100" width="100" src="%s">' % url_for('static',
                                              filename= 'images/' + model.path))
column_formatters = {
    'path': _list_thumbnail
}

form_extra_fields = {
    'path': form.ImageUploadField('Image', base_path=file_path)
}

def is_accessible(self):
    return flask_login.current_user.is_authenticated