Flask/Javascript-预览图像时更新数据库中的图像

Flask/Javascript-预览图像时更新数据库中的图像,javascript,python,ajax,image,flask,Javascript,Python,Ajax,Image,Flask,我正在尝试做一个博客应用,你可以发布和上传图片。我希望能够编辑我已经上传的图像。我还希望能够在更新图像时预览它们 create.html <form method='post' class="formPost" enctype='multipart/form-data'> <label for='title'>Title</label> <input name="title" id="title&

我正在尝试做一个博客应用,你可以发布和上传图片。我希望能够编辑我已经上传的图像。我还希望能够在更新图像时预览它们

create.html

<form method='post' class="formPost" enctype='multipart/form-data'>
  <label for='title'>Title</label>
  <input name="title" id="title" value="{{ request.form['title'] }}">
  <label for="body">Body</label>
  <div class="body">
    <textarea name="body" id="body">{{ request.form['body'] }}</textarea>
    <div class="gallery">
      <label for="file">
        <svg viewBox="0 0 1920 1792">
          <path d="M640 576q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm1024 384v448h-1408v-192l320-320 160 160 512-512zm96-704h-1600q-13 0-22.5 9.5t-9.5 22.5v1216q0 13 9.5 22.5t22.5 9.5h1600q13 0 22.5-9.5t9.5-22.5v-1216q0-13-9.5-22.5t-22.5-9.5zm160 32v1216q0 66-47 113t-113 47h-1600q-66 0-113-47t-47-113v-1216q0-66 47-113t113-47h1600q66 0 113 47t47 113z"/>
        </svg>
      </label>
      <input id='file' type='file' name='file[]' accept="image/*" onchange="previewFiles()" multiple>
    </div>
  </div>
  <input class="interact" type="submit" value="Save" style="float: right;">
</form>

标题
身体
{{request.form['body']}
script.js

var queue = []

function previewFiles() {
  var files = document.querySelector('input[type=file]').files
  var maxFiles = 4

  function readAndPreview(file){
    if (/\.(jpe?g|png|gif)$/i.test(file.name)){
      var reader = new FileReader()
      reader.addEventListener('load', function(){
        queue.push(file)
        toggleLabel()
        var picture = document.createElement('picture')
        picture.style.backgroundImage = `url('${this.result}')`
        button = document.createElement('button')
        button.type = 'button'
        $($.parseHTML('<svg viewBox="0 0 100 100"><path d="M45 0 L45 45 L0 45 L0 55 L45 55 L45 100 L55 100 L55 55 L100 55 L100 45 L55 45 L55 0 Z" fill="currentColor" stroke="currentColor" transform="rotate(45 50 50)"></path></svg>')).appendTo(button)
        button.addEventListener('click', function(){
          $(this.parentElement).remove()
          queue.splice(queue.indexOf(file), 1)
          toggleLabel()
        })
        picture.appendChild(button)
        
        document.querySelector('div.gallery').insertBefore(picture, document.querySelector('label[for=file]'))
      }, false)
      reader.readAsDataURL(file)
    }
  }

  function toggleLabel(){
    if (queue.length >= maxFiles){
      $('label[for=file]').hide()
    } else {
      $('label[for=file]').show()
    }
  }

  if(files){
    if(queue.length <= maxFiles){
      [].forEach.call(files, readAndPreview)
    } else {
      alert(`Max number of files is ${maxFiles}`)
    }
  }
}

var form = document.querySelector('.formPost')

$(form).submit(function(event){
  var formData = new FormData(this)
  formData.append('file[]', queue)

  $.ajax({
    type: 'POST',
    url: '/',
    data: formData
  })

  event.preventDefault()
})
var队列=[]
函数previewFiles(){
var files=document.querySelector('input[type=file]')。files
var maxFiles=4
函数readAndPreview(文件){
if(/\(jpe?g | png | gif)$/i.test(file.name)){
var reader=new FileReader()
reader.addEventListener('load',function()){
queue.push(文件)
toggleLabel()
var picture=document.createElement('picture')
picture.style.backgroundImage=`url('${this.result}'))`
button=document.createElement('button')
button.type='button'
$($.parseHTML(“”)).appendTo(按钮)
addEventListener('click',function(){
$(this.parentElement).remove()
queue.splice(queue.indexOf(文件),1)
toggleLabel()
})
picture.appendChild(按钮)
document.querySelector('div.gallery').insertBefore(picture,document.querySelector('label[for=file]))
},错)
reader.readAsDataURL(文件)
}
}
函数toggleLabel(){
如果(queue.length>=maxFiles){
$('label[for=file]')。hide()
}否则{
$('label[for=file]')。show()
}
}
如果(文件){
如果(队列长度0:
文件路径=[]
对于文件中的文件:
filename=get\u random\u文件名(20,file.filename)
保存(os.path.join(路径到上传,文件名))
file_path.append(os.path.join(当前_app.config['POST_UPLOAD_FOLDER'],文件名))
文件列表=分隔符.join(文件路径)
执行(
'插入帖子(标题、正文、作者id、图像、分隔符)'
“值(?,,,,,)”,
(标题,正文,g.user['id'],文件列表,分隔符)
)
其他:
执行(
'插入帖子(标题、正文、作者id)'
“值(?,?)”,
(标题、正文、g.user['id'])
)
db.commit()
返回重定向(url_for('blog.index'))
返回呈现模板('blog/create.html')
def get_post(id,check_author=True):
post=get_db()。执行(
'选择p.id、标题、正文、已创建、作者id、用户名、图像、分隔符'
'从post p加入用户u ON p.author_id=u.id'
'其中p.id=?',
(身份证号码)
).fetchone()
如果post为无:
中止(404,“~Post id{0}不存在。”.format(id))
如果选中作者并发布['author\u id']!=g.user['id']:
中止(403,“~访问被拒绝”)
回程站
允许的def_文件(文件名):
在文件名和文件名中返回“.”。rsplit(“.”,1)[1]。在允许的扩展名中返回lower()
@路由('/post//edit',方法=('GET','post'))
@需要登录
def编辑(id):
post=获取职位(id)
如果request.method==“POST”:
title=请求。表单['title']
body=请求。表单['body']
错误=无
如果不是标题:
错误='需要标题。'
如果错误不是无:
闪光(错误)
其他:
db=get_db()
执行(
'更新帖子集标题=?,正文=?'
'其中id=?',
(标题、正文、id)
)
db.commit()
返回重定向(url_for('blog.index'))
返回呈现模板('blog/edit.html',post=post)
我不知道该怎么办。我想我可以只向ajax发送一个FileStorage对象,但我无法实现。发送链接与我的预览代码不兼容。我不知道如何更改文件输入的值。图像由js发送,由flask作为FileStorage对象接收

我该怎么办

@bp.route('/create', methods=('GET', 'POST'))
@login_required
def create():
  if request.method == 'POST':
    title = request.form['title']
    body = request.form['body']
    files = request.files.getlist('file[]')
    error = None
    separator = '&!@%'
    path_to_uploads = os.path.join(os.path.dirname(os.path.realpath(__file__)), current_app.static_folder, current_app.config['POST_UPLOAD_FOLDER'])

    for file in files:
      if file.filename == '':
        files.remove(file)
      elif not allowed_file(file.filename):
        error = 'Invalid File'
        
    if not title and not body and not files:
      error = 'Fill out any of the three fields'
      
    if error is not None:
      flash(error)
    else:
      db = get_db()
      if len(files) > 0:
        file_paths = []
        for file in files:
          filename = get_random_filename(20, file.filename)
          file.save(os.path.join(path_to_uploads, filename))
          file_paths.append(os.path.join(current_app.config['POST_UPLOAD_FOLDER'], filename))
        file_list = separator.join(file_paths)
        db.execute(
          'INSERT INTO post (title, body, author_id, images, separator)'
          ' VALUES (?, ?, ?, ?, ?)',
          (title, body, g.user['id'], file_list, separator)
        )
      else:
        db.execute(
          'INSERT INTO post (title, body, author_id)'
          ' VALUES (?, ?, ?)',
          (title, body, g.user['id'])
        )
      db.commit()
      return redirect(url_for('blog.index'))

  return render_template('blog/create.html')

def get_post(id, check_author=True):
  post = get_db().execute(
    'SELECT p.id, title, body, created, author_id, username, images, separator'
    ' FROM post p JOIN user u ON p.author_id = u.id'
    ' WHERE p.id = ?',
    (id,)
  ).fetchone()

  if post is None:
    abort(404, "~Post id {0} doesn't exist.".format(id))

  if check_author and post['author_id'] != g.user['id']:
    abort(403, "~Access Denied.")
    
  return post

def allowed_file(filename):
  return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@bp.route('/post/<int:id>/edit', methods=('GET', 'POST'))
@login_required
def edit(id):
  post = get_post(id)

  if request.method == 'POST':
    title = request.form['title']
    body = request.form['body']
    error = None

    if not title:
      error = 'Title is required.'

    if error is not None:
      flash(error)
    else:
      db = get_db()
      db.execute(
        'UPDATE post SET title = ?, body = ?'
        ' WHERE id = ?',
        (title, body, id)
      )
      db.commit()
      return redirect(url_for('blog.index'))

  return render_template('blog/edit.html', post=post)