Search code examples
flaskinputwysiwyg

How to set the default directory for wysisyg editor insertImage in flask


I'm building a CMS in flask and I have built a simple wysiwyg editor using execcommands for creating and editing posts, and everything is working. For the insertImage command I'm using an input element to open a directory and choose an image. It works except of course it opens my computers default folder. I want it to open the uploads folder in the static directory where user images are stored in flask. How?

I have searched through flask docs, Python handling files documentation and there's no mention of this. This is a project I'm doing for a class. I'm going above and beyond the requirements for this project but that's how I keep things interesting. I mean it's supposed to be a CMS right. Well, CMS's always have wysiwyg's that open the default "uploads" folder to insert media. Also, when creating my upload functions I found that when uploading files flask needs the absolute path. But when serving them the relative path is necessary. Any point in the right direction would be greatly appreciated. Thank you.

Here's the structure

<div class="col-md-1 tools">
   <a href="#" data-command='insertImage'data-toggle="tooltip" title="Insert Media"><i class='material-icons'>add_photo_alternate</i>
   </a>
   <div class="editorInputs">
      <input type="file" name="media" id="insertImage" 
         accept="audio/*,video/*,image/*"/>
   </div>
</div>

Here's my js script

$('.tools a').mousedown(function(e){
let command = $(this).data('command');
 if(command == 'insertImage'){
  $(this).next().children('input').trigger('click');
      let input = $(this).next().children();
      input.on('change', function(e){
        let val = $(input).val();
        document.execCommand(command, false, val);
      })
    }
});

Here's how my uploads file is configured in flask

app.config['SITE_UPLOADS'] = 'D:/Courses/Development/Programming/Python/LaunchCode/LC101/unit2/build-a-blog/static/site/uploads/'
app.config['ADMIN_UPLOADS'] = 'D:/Courses/Development/Programming/Python/LaunchCode/LC101/unit2/build-a-blog/static/admin/uploads/'    
app.config['ALLOWED_IMAGE_EXTENSIONS'] = ['PNG', 'JPG', 'JPEG', 'SVG', 'GIF']
app.config['DATA_FILES'] = 'D:/Courses/Development/Programming/Python/LaunchCode/LC101/unit2/build-a-blog/data/'
app.config['RELATIVE_PATH_SITE'] = '../static/site/uploads/'
app.config['RELATIVE_PATH_ADMIN'] = '/static/admin/uploads/'

Solution

  • So, I realized that I have to create a function to pull images from the uploads folder, display them, get their URL and pass it to the execcommand. And I did.

    First, create the gallery structure with radio buttons to view files. Then put the gallery in a bootstrap modal to fire when the execccomand insertImage link is clicked. Grab the URL of the checked image. pass it to the execcomand function in my js.

    On the flask side get a list of all files in the uploads directory with os.listdir(absolute/path/to/directory), returns a python list of the files. Next create file urls and put info in a dict by looping over the filenames in the list and adding the relative path to the filename. Pass the dict to the jinja2 template and populate the gallery.

    Finally, execute the js.

    Here's my python code and js code.

    def get_uploads():
        list_images = os.listdir(app.config['ADMIN_UPLOADS'])
        images = []
        i =0
        length = len(list_images)
        while i < length:
            img = {}
            img['name'] = list_images[i]
            img['url'] = os.path.join(app.config['RELATIVE_PATH_ADMIN'], list_images[i])
            images.append(img)
            i+=1 
        return images
    

    Here's my js.

    if(command == 'insertImage'){
          $("#uploadsGallery").modal();
          $('.ftco-animate').addClass('fadeInUp ftco-animated')
          let check = $(this).next().find('input.form-check-input');
          let val;
            check.on('change', function(e){
           val = $(this).val();          
          });     
          $('#insertImg').click(function (e) {
            r.setStart(editDiv, lastCaretPos);
            r.setEnd(editDiv, lastCaretPos);
            s.removeAllRanges();
            s.addRange(r);
            document.execCommand(command, false, val);
            check.prop('checked',  false);
          });
    
        }