Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Validando Form/Dados - Erro

Pessoal, bom dia. Nesta validação, tentei inserir um usuário que já existe. Até ai tudo bem, conseguir até dar um print na mensagem que informa que o usuário já existe.

Ocorre que estou tendo o erro abaixo:

AttributeError at /registrar/
'NoneType' object has no attribute 'setdefault'
Request Method:    POST
Request URL:    http://localhost:8082/registrar/
Django Version:    1.7.4
Exception Type:    AttributeError
Exception Value:    
'NoneType' object has no attribute 'setdefault'
Exception Location:    C:\Projetos\safepass\usuarios\forms.py in adiciona_erro, line 36
Python Executable:    C:\Python27\python.exe

A linha 36, do forms.py é essa:

errors = self._errors.setdefault(forms.forms.NON_FIELD_ERRORS, forms.utils.ErrorList())

Segue o forms.py completo:

# -*- coding: utf-8 -*-
from django import forms
from django.contrib.auth.models import User

class RegistrarUsuarioForm(forms.Form):

    ds_login = forms.CharField(required = True)
    cpf_cgc = forms.CharField(required = True)
    nome_razao = forms.CharField(required = True)
    senha = forms.CharField(required = True)
    email = forms.EmailField(required = True)
    telefone = forms.CharField(required = False)
    site = forms.CharField(required = False)

    def is_valid(self):

        valid = True

        if not super(RegistrarUsuarioForm, self).is_valid:
            self.adiciona_erro('Por favor, verifique os dados informados!')
            valid = False

        usuario_existe = User.objects.filter(username=self.data['ds_login']).exists()

        if usuario_existe:
            nome_usuario_existe = self.data['ds_login']
            msg_usuario_existe = "Usuario ja existente: %s " %(nome_usuario_existe)  
            print(msg_usuario_existe)
            self.adiciona_erro(msg_usuario_existe)
            valid = False 

        return valid

    def adiciona_erro(self, message):
        errors = self._errors.setdefault(forms.forms.NON_FIELD_ERRORS, forms.utils.ErrorList())
        errors.append(message)

Se puderem me dar um help! Grato,

Trevisolli

2 respostas

Apenas como complemento, eu descobri como o código "Funcionar", porém, gostaria de saber o porquê dessa situação:

Se no meu forms acima (class RegistrarUsuarioForm(forms.Form)), eu retirar a linha contendo :

 ds_login = forms.CharField(required = True)

Vai funcionar. O porquê que adicionei esse ds_login? Para que na hora do registro, o usuário que está sendo registrado escolha um login personalizado.

Como foi desenvolvida essa funcionalidade?

1) No meu Models, seguindo o que foi feito no curso, para o atributo email, eu adicionei o atributo, como abaixo (o nomeei de username, não havendo mais o nome "ds_login"):

from django.db import models
from django.contrib.auth.models import User

class LoginUsuario(models.Model):
    cpf_cgc = models.CharField(max_length=20, null=False, unique = True, blank = False)
    nome_razao = models.CharField(max_length=255, null=False)
    telefone = models.CharField(max_length=15, null=True)
    site = models.CharField(max_length=255, null=True)
    usuario = models.OneToOneField(User, related_name='loginusuario')

    @property
    def email(self):
        return self.usuario.email
    @property
    def username(self):
        return self.usuario.username

2) O meu registrar.html ficou da seguinte forma:

{% extends "base_login.html" %}
{% block body %}
 <form class="form-signin" role="form" action="{% url 'registrar' %}" method="post">
        {% csrf_token %}

        <h2 class="form-signin-heading">Criar Login</h2>

        <input type="text" id="id_login" name="username" class="form-control" placeholder="Login *" required autofocus>

        <input type="text" id="id_cpf_cgc" name="cpf_cgc" class="form-control" placeholder="CPF/CGC *" required>

        <input type="text" id="id_nome_razao" name="nome_razao" class="form-control" placeholder="Nome/Razão Social *" required>

        <input type="text" id="id_email" name="email" class="form-control" placeholder="Email *" required>

        <input type="password" id="id_senha" name="senha" class="form-control" placeholder="Senha *" required>

        <hr />

        <input type="text" id="id_telefone" name="telefone" class="form-control" placeholder="Telefone ">

        <input type="text" id="id_site" name="site" class="form-control" placeholder="Site ">

        <hr/>

        {% if form.errors %}
            <div class="alert alert-danger">
                <button type="button" class="close">&times;</button>
                {{ form.non_field_errors }}
            </div>
        {% endif %}

        <button class="btn btn-lg btn-primary btn-block" type="submit" value="Registrar">Registrar</button>

    </form>

{% endblock %}

3) A View ficou da seguinte forma:

from django.shortcuts import render
from django.shortcuts import redirect 
from django.contrib.auth.models import User
from django.views.generic.base import View
from logins.models import LoginUsuario 
from usuarios.forms import RegistrarUsuarioForm

#Class based view: View baseada em classe
class RegistrarUsuarioView(View):

    template_name = 'registrar.html'

    def get(self, request):
        return render(request, self.template_name)

    def post(self, request):

        form = RegistrarUsuarioForm(request.POST)

        if form.is_valid():
            print("Entrou form valido da View -- " )
            dados_form = form.data

            usuario = User.objects.create_user(dados_form['username'], 
                dados_form['email'],
                dados_form['senha'])

            loginusuario = LoginUsuario(cpf_cgc=dados_form['cpf_cgc'],
                nome_razao=dados_form['nome_razao'],
                telefone=dados_form['telefone'],
                site=dados_form['site'],
                usuario=usuario)

            loginusuario.save()

            return redirect('index')

        return render(request, self.template_name, {'form' : form})

4) E o meu Forms (Agora sem erro, porquê comentei o atributo username):

# -*- coding: utf-8 -*-
from django import forms
from django.contrib.auth.models import User

class RegistrarUsuarioForm(forms.Form):

    cpf_cgc = forms.CharField(required = True)
    nome_razao = forms.CharField(required = True)
    telefone = forms.CharField(required = False)
    site = forms.CharField(required = False)
    senha = forms.CharField(required = True)
    email = forms.EmailField(required = True)
    #username = forms.CharField(required = True)    


    def is_valid(self):

        valid = True

        if not super(RegistrarUsuarioForm, self).is_valid:
            self.adiciona_erro('Por favor, verifique os dados informados!')
            valid = False

        campo_validar = self.data['cpf_cgc']
        usuario_existe = User.objects.filter(username=campo_validar).exists()
        print("Usuario existe 1:  ", campo_validar)
        if usuario_existe:
            print("Usuario existe 2")
            msg_usuario_existe = "Usuario ja existente: %s " %(campo_validar)  
            print("Erro 1")
            print(msg_usuario_existe)
            self.adiciona_erro(msg_usuario_existe)
            print("Erro 2")
            valid = False 

        return valid

    def adiciona_erro(self, message):
        print("Erro 3")
        errors = self._errors.setdefault(forms.forms.NON_FIELD_ERRORS, forms.utils.ErrorList())
        print("Erro 4")
        errors.append(message)

Dessa forma, comentado e trocando o campo de validação de usuário existente, tudo funciona perfeitamente, porém, caso eu queira mostrar o erro, quando um login duplicado for passado, não funciona (habilitando o #username do meu forms), dando erro de 'NonType' informado na abertura dessa dúvida.

Gostaria de saber como proceder nesse caso, para que o erro "programado" seja exibido em minha tela, dizendo que o login que estou tentando utilizar já existe, e não aparecendo o erro inesperado: 'NoneType' object has no attribute 'setdefault', que é quando habilito no forms o:

username = forms.CharField(required = True)

Obrigado,

Trevisolli

solução!

Pessoal,

Após algumas pesquisas, consegui Resolver!

Problema: Qualquer login que já existisse cadastrado, dava erro se fosse tentá-lo cadastrar novamente. (Qualquer LOGIN não cadatrado, quando cadastrado pela PRIMEIRA vez, tudo ok, sem problemas)

Solução: Na função adiciona_erro , depois de buscas na internet, coloquei, logo no início: self.full_clean()

def adiciona_erro(self, message):
        self.full_clean()
        print("def adiciona_erro do form: 1:  ")
        errors = self._errors.setdefault(forms.forms.NON_FIELD_ERRORS, forms.utils.ErrorList())
        print("def adiciona_erro do form: 2:  ")
        errors.append(message)

Daí o erro de já existente apareceu no HTML Corretamente!

Fica a dica!

Trevisolli