Warning: Parameter 1 to wp_default_scripts() expected to be a reference, value given in /home/crian734/public_html/blog.kolaborativa/wp-includes/plugin.php on line 601

Warning: Parameter 1 to wp_default_styles() expected to be a reference, value given in /home/crian734/public_html/blog.kolaborativa/wp-includes/plugin.php on line 601
Multiupload no Web2py

MultiUpload no Web2py

MultiUpload no Web2py

Upload de vários arquivos no mesmo form

Fala pessoal, tudo certo? Espero que sim!

Recentemente me vi frente à necessidade de criar um projeto no Web2py com upload de vários arquivos em uma página via ajax e após algumas buscas percebi que, apesar de haver material sobre o assunto, ainda é um pouco escasso e cada tutorial trata do assunto abordando de maneira diferente, diante disso eu peguei um pouco de cada artigo que li e resolvi montar um que atendesse melhor à minha demanda.

Talk is cheap, show me the code

Então sem mais conversa, vamos ao código:

Primeiro você precisa do Web2py rodando localmente, abra a interface administrativa e crie um novo projeto e chame como quiser (afinal o projeto é seu! ;-)).

O modelo

Agora vamos criar nosso modelo:

Para manter as coisas o mais simples possível, vou criar o modelo no arquivo models/db.py mesmo, mas você pode criar em qualquer arquivo dentro da pasta models.

db.define_table('album',
Field('titulo'),
Field('data_fotos', 'date'),
Field('fotos', 'list:reference arquivos'))
db.album.fotos.requires = IS_IN_DB(db, 'arquivos.id', 'arquivos.arquivo', multiple=True)
db.define_table('arquivos',
Field('arquivo', 'upload', autodelete=True))

O código acima cria as duas tabelas que iremos utilizar em nossa aplicação, a primeira tabela (linha 1 a 4) é referente ao álbum de fotos, onde poderemos inserir um titulo(linha 2), uma data (linha 3) e as fotos (linha 4), note que temos uma lista que referencia a tabela arquivos, na linha 5 estamos dizendo que o campo fotos deve estar relacionado com a tabela arquivos através do campo id e que será um campo de seleção multipla. A segunda tabela é bem simples e só tem um campo do tipo upload que é um tipo especial do web2py para lidar com upload de arquivos.

O controlador

O passo seguinte é criar o controlador, para isso basta criarmos um arquivo na pasta controllers, aqui chamarei de album.py e nele colocaremos o código abaixo:

# coding: utf8
def index():
  grid = SQLFORM.grid(db.album, user_signature=False)
  return dict(grid=grid)

def upload_file():
  try:
    id = db.arquivos.insert(arquivo=db.arquivos.arquivo.store(request.vars.file,request.vars.filename))
    return id
  except:
    return dict(message=T('Upload error'))

def delete_file():
  try:
    name = request.args[0]
    db(db.arquivos.arquivo==name).delete()
    return name
  except:
    return 'erro'

Temos 3 funções no controlador index, upload_file e delete_file, a primeira cria uma grid com as funções CRUD (Create, Read, Update, Delete) baseada nas regras que definimos no nosso modelo anteriormente, a segunda função tratará nossos uploads via ajax, e a terceira obviamente servirá para excluirmos os arquivos via ajax posteriormente.

Ao executarmos a aplicação e acessarmos a url http://localhost:8000/multiupload/album/index veremos a tela de cadastro dos Álbuns, clicando no botão (+Add) teremos a seguinte tela: ser

MultiUpload-no-Web2py-01

Quase tudo certo, porém falta justamente o campo de upload dos arquivos, motivo desse tutorial 😉

A Visualização

Vamos agora criar o arquivo da view onde será gerado nosso HTML, crie um arquivo chamado index.html dentro da pasta views, e insira o código abaixo:

{{response.files.extend([URL('static','css/custom.css'),URL('static','js/pekeUpload.js'),URL('static','js/album.js')])}}
{{extend 'layout.html'}}
{{=grid}}

No código acima estamos adicionando referência aos arquivos css e javascript do plugin responsável pelos uploads e o arquivo album.js que criaremos mais pra frente (linha 1).

O Plugin

Vamos agora baixar os arquivos do plugin que usaremos para gerenciar nossos uploads via ajax, clique aqui e baixe os arquivos custom.css e pekeUpload.js e salve nas pastas static/css e static/js.

O Javascript

Agora já temos quase tudo que precisaremos, falta somente o arquivo album.js que devemos criar dentro da pasta static/js com o seguinte código:

$(document).ready(function(){
  //Função para listar os arquivos existentes
  $('#album_fotos option:selected').each(function(){
    var file = $(this).text();
    var p = '

';
    p += '<a class="btn btn-success btn-download" href="http://'+window.location.host+'/multiupload/default/download/'+file+'">Arquivo</a>';
    p += '<button class="btn btn-danger excluir" type="button"></button>

';
    $('#album_fotos').parent().append(p);
  });
  //Função para excluir os arquivos
  $('button.excluir').click(function(){
      var arq = $(this).parent().attr('id');
      $(this).parent().hide();
      $.ajax({
          url: 'http://'+window.location.host+'/multiupload/album/delete_file/'+arq,
          type: 'post',
          data: arq,
          success: function(data){
            if (data != 'erro'){
              $('#album_fotos option:selected').each(function(){
                  var file = $(this).text();
                  if(file == data){
                  $(this).remove();
                  }
              });
            }else{
              alert('Erro ao excluir arquivo!');
            }
        },
        error: function(){
          alert('Erro ao excluir arquivo, verifique sua conexão!');
        }
      });
  });
  //Função para tratar os uploads via ajax
  arquivos = $('#album_fotos');
  arquivos.parent().append('<input class="upload" id="file_upload" type="file" name="file_upload" />');
  arquivos.hide();
  $('#file_upload').pekeUpload({
    btnText: 'Adicionar',
    url: 'http://' + window.location.host + '/multiupload/album/upload_file',
    theme: 'bootstrap',
    showErrorAlerts: false,
    onFileError: function(file,error){
      $('#album_fotos').append($('
', {value: error, text: error, selected: true}));      var div = '</pre>
<div class="alert alert-success">';
 div += '<button class="close" type="button" data-dismiss="alert">×</button>';
 div += '
'+file['name']+' adicionado com sucesso!</div>
<pre>'      $('div.pekecontainer').append(div);    }  });});

O código acima faz basicamente o seguinte, a primeira função (linhas 3 a 9) transforma cada arquivo selecionado no selectbox em um link para download e um botão para realizar a exclusão do mesmo.

A segunda função (linhas 11 a 34) faz uma chamada ajax para a função delete_file do controlador álbum e remove o arquivo da lista de seleção.

A terceira função (linhas 36 a 51) esconde o controle selectbox que lista os arquivos relacionados com o álbum, insere um botão de upload e passa algumas configurações ao pekeUpload (39 a 50).

Alguns detalhes muito importantes que devemos considerar são os seguintes:

Linha 41 – Passamos a URL com a chamada ao nosso controlador ‘album’, função ‘upload_file’.

Linha 42 – Definimos o tema para o plugin que pode utilizar o bootstrap para deixar mais bonito.

Linha 43 – Desligamos os alertas de erros, mas é por um bom motivo, explico:

O pekeUpload utiliza o retorno da função como 1 para dizer que o upload do arquivo foi feito com sucesso e qualquer outro retorno serve para indicar que aconteceu algum erro, porém precisamos retornar o id do arquivo adicionado para poder relacionar com o álbum ao qual ele pertence, dessa forma precisamos desligar os alertas de erros e tratar os uploads bem sucedidos na função onFileError (44 a 49) para exibir uma mensagem amigável ao usuário dizendo que o upload ocorreu com sucesso.

Espero que com o tempo consiga encontrar uma solução melhor para esse problema, inclusive aceito qualquer ajuda ou sugestão, mas enquanto isso, essa foi a melhor forma que encontrei de fazer isso!

Finalizando

Após as mudanças acima nossa aplicação ficará assim:

MultiUpload-no-Web2py-02

E após fazer o upload de alguns arquivos, teremos a seguinte tela:

MultiUpload-no-Web2py-03

Bom pessoal, espero que tenham gostado desse pequeno tutorial e que mandem sugestões de como melhorar essa singela aplicação.
A aplicação está hospedada no meu github

Sintam-se livres para clonar o repositório acima e modificar o que precisarem.

Abraço a todos e até a próxima. 😉

Author Description

Glauco Junior

Desenvolvedor Python, Javascript, PHP e C#. Atualmente trabalha desenvolvendo soluções para Digital Signage e WEB. Amante da Ciência e da Tecnologia e eterno aprendiz.

There are 2 comments. Add yours

  1. 29th setembro 2014 | José says: Responder
    Excelente. Muchas gracias por el ejemplo!

Join the Conversation