5
respostas

Lista de Presença com Django - Editar e trazer o checkbox marcado ou desmarcado

Há 1 semana perguntei aqui no fórum como eu deveria fazer uma lista de presença que gera múltiplos inputs e envia tudo pro banco de uma vez só, com checkbox marcado ou desmarcado. Embora ninguém tenha conseguido me ajudar, arrumei uma solução. Colocarei abaixo todo meu código na esperança de alguém poder me ajudar na edição. Gostaria que alguém me ajudasse a renderizar o formulário de edição com os checkbox marcados ou desmarcados, a depender do valor do banco, a única complicação é que tem o input hidden que traz o valor='F' e o input checkbox que traz o value='P'... Aceito sugestões, obrigado desde já.

HTML:

<form action="{% url 'cadastra_presenca' %}" method="POST" enctype="multipart/form-data"> 
                    {% csrf_token %} 
                {% for alunos in curso %}

  <tr class="tbody-row">
 <td class="tbody-column" style="display:none;">
<label style="display: flex; justify-content: center;display: none;">

 <input type="text"  class="input-3" value="{{alunos.id}}"  name="id_matricula_presenca"/>

     </label>
     </td>

 <td class="tbody-column">{{alunos.alunos.nome_aluno}}
  <label style="display: flex; justify-content: center;display: none;">

    <input type="text"  class="input-3" value="{{alunos.alunos.nome_aluno}}" name="nome_aluno_presenca"/>

         </label>
   </td>

  <td class="tbody-column">

 <input type="date" class="input-3" value="{{data_presenca}}" readonly  name="data_presenca_aluno">



  </td>                           
<td class="tbody-column">
<label style="display: flex; justify-content: center;">
<input type="checkbox"   class="presenca" checked multiple value="P" name="confirma_presenca_aluno">
 <input class="ausencia" type='hidden' disabled value='F' multiple  name='confirma_presenca_aluno'>

            </label>
          </td>                 
       </tr> 

      {% endfor %}

     <div style="display: flex; justify-content: center;position:relative;">
                <input type="submit" class="botao-presenca" value="OK">                     
    </div>



   </form>  

JAVA SCRIPT (responsável por dar valor F quando checkbox estiver desmarcado, de outra forma ele não envia nenhum valor pro backend):


presenca.forEach(function(p){

    p.addEventListener('click',function(){

        var ausente=p.parentNode.querySelector('.ausencia');
        if(ausente.disabled==true){
            ausente.disabled=false;
        }else if(ausente.disabled==false){
            ausente.disabled=true;
        }

    });

});

Django (Captura dados e joga no banco):

def cadastra_presenca(request):
    if request.method=='POST':

        id_matricula_presenca=request.POST.getlist('id_matricula_presenca')

        lista_matricula=request.POST.getlist('nome_aluno_presenca')
        lista_presenca=request.POST.getlist('confirma_presenca_aluno')
        lista_data=request.POST.getlist('data_presenca_aluno')
        lista_final=[]

        contador=0

        for i in lista_data:

            if contador<= len(lista_data):
                lista_final.append([id_matricula_presenca[contador],lista_matricula[contador],lista_presenca[contador],lista_data[contador]])

                contador+=1

        con=0

        for j in lista_final:

            matricula=Matricula.objects.get(pk=j[0]) 
            id_aluno=matricula.alunos.id


            attendance=ListaPresenca.objects.filter(identificador_usuario=request.user.id).filter(matricula=matricula)           
            if  attendance.filter(dia_presenca=j[3]).exists():
                messages.error(request,'Presença já cadastrada para esse(s) aluno(s)')
                return redirect('filtro_presenca')

            dar_presenca=ListaPresenca.objects.create(identificador_usuario=request.user.id,matricula=matricula,
            dia_presenca=j[3],presenca=j[2])

            dar_presenca.save()


        #print(lista_presenca)
        messages.success(request,'Presença cadastrada com sucesso')
        return redirect('filtro_presenca')
5 respostas

Oiii Raul, como você está? Espero que esteja tudo bem por aí ^-^

Sinto muito pela demora em obter um retorno.

Na edição, a ideia é que: se o valor do banco for verdadeiro, o atributo checked do html irá ser ativado. Porém, caso o valor do banco seja falso, ficará unchecked. Pelo que entendi do seu código, o verdadeiro é o valor P, certo?

Então, no código do formulário de edição teremos algo similar ao trecho abaixo:

<input type="checkbox" class="presenca" multiple name="confirma_presenca_aluno" value="P"  {% if lista_presenca == "P" %} checked {% endif %}>

Usamos a cláusula if para fazermos o teste do valor que é trago do banco. E caso seja verdadeiro, adicionamos ao input o atributo checked. Já em caso negativo, ficará unchecked que é o padrão.

Em relação ao cadastro, achei incrível sua abordagem de utilizar o Javascript para manipular a DOM, mas é um caminho mais verboso, é possível fazer isso somente com código Python e HTML.

O primeiro passo é criar uma variável (em models.py) do tipo BooleanField que irá armazenar o valor do checkbox. Exemplo:

lista_presenca =  models.BooleanField(default=False)

Agora, voltando ao HTML, no atributo value iremos enviar o valor True para quando o campo estiver marcado, dessa forma:

 <input type="checkbox"   class="presenca"  multiple value="{{ True }}" name="confirma_presenca_aluno" id="valor_da_presenca">

E por padrão, quando o input estiver desmarcado o valor não será enviado, sendo assim, podemos testar na requisição se aquele valor de fato existe, e caso não exista, iremos atribuir False para a variável que armazena o valor do checkbox :

 if 'valor_da_presenca' in request.POST:
            lista_presenca = request.POST['valor_da_presenca']
        else:
            lista_presenca = False

Com isso, irá conseguir adicionar valor no banco sem a necessidade do Javascript, não que seja errado, é apenas mais um modo de fazer.

Sei que são muitas informações, mas fique tranquilo, qualquer dúvida estou por aqui.

Grande abraço!

Puts, realmente muito mais simples rsrsrs. Eu dei uma volta tremenda para resolver esse problema. Muito obrigado, em breve vou tentar atualizar pra esse jeito de fazer, pq o que eu fiz gerou alguns erros. POr exemplo, quando e clico na seta de voltar do navegador e tento reenviar o formulário, ao invéz de ele mostrar a mensagem de erro programada por mim, aparece aqueles erros do próprio Django falando "list out of index". Mas se eu volto na seta, dou refresh na página, o erro não acontece.

Mais uma dúvida, como gerei meio que uma lista de inputs com o mesmo name, eu devo ainda assim capturar essa lista como eu fiz ou de outra forma? O maior problema é capturar as informações e relacioná-las com os devidos alunos.

Ps: Com relação a demora. As vezes é bom demorar, pois a gente se esforça mais e aprende mais para gerar uma solução. Obrigado!!!

"Mais uma dúvida, como gerei meio que uma lista de inputs com o mesmo name, eu devo ainda assim capturar essa lista como eu fiz ou de outra forma? "

Por hora, deixa da forma como está e tente fazer a edição dos dados trazendo os valores do checkbox da forma como foi explicado. Após fazer a funcionalidade da edição funcionar, refatore o seu código, ou seja, aplique melhorias no mesmo.

Deixo abaixo algumas sugestões de melhorias:

  • Ao invés de utilizar índices auxiliares como o caso da variável contador , utilize diretamente um range no tamanho da lista, já que o que você precisa são os índices da mesma. Por exemplo:
for indice in range(len(lista_data)):
    lista_final.append([id_matricula_presenca[indice],lista_matricula[indice],lista_presenca[indice],lista_data[indice]])
  • Ao invés de utilizar o tipo lista como uma lista_final, utilize uma lista de dicionários para que fique claro a chave que você deseja acessar, pois, ficará bem mais legível algo como pk=item[0]['id_matricula'] do que pk=item[0].

Qualquer dúvida estou por aqui, a gente vai se falando.

Abraços =)