Tag Archives: Flask

Validando campos no SQLAlchemy (Python) com decorators, no estilo Java Bean Validation

Já faz uns 4 anos que decidi experimentar Python e não deu outra: foi paixão arrebatadora. Mas algumas funcionalidades de outras linguagens e bibliotecas despertam saudades, uma delas foi o Bean Validation do Java EE.

Em um projeto que decidi usar Flask, Flask-Restless e SQLAlchemy, senti falta de algo parecido para fazer as validações de campos. O SQLAlchemy tem um decorator para validar campos, mas você precisa escrever dentro da função a validação. Para auxiliar na tarefa, criei uma biblioteca, chamada osirisvalidator, com decorators para auxiliar nessa validação.

Você pode clonar o código fonte em: https://github.com/davidaug/osirisvalidator (e contribuir com novas validações) ou instalar pelo comando:

pip install osirisvalidator

Sintaxe

Vamos considerar a classe User, que é um objeto Model do SQLAlchemy:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    cpf = db.Column(db.String(11), unique=True, nullable=False)

Para validar um campo no SQLAlchemy, é necessário fazer uma função com o decorator @validates , passando o nome do campo e criando os parâmetros key e value na função alvo.

 class User(db.Model):

    [...]

    @validates('email')
    def validate_email(self, key, email):
        return email

Mais informações em: https://docs.sqlalchemy.org/en/13/orm/mapped_attributes.html

Com o osirisvalidator, podemos adicionar os decorators já prontos, como no exemplo abaixo:

from osirisvalidator.internet import valid_email

[...]
class User(db.Model):

    [...]

    @validates('email')
    @not_blank(field='email')
    @valid_email(field='email', message='email deve ser válido!')
    def validate_email(self, key, email):
        return email

O USO DO “@validates(‘nomecampo’)” É OBRIGATÓRIO!

O parâmetro “field” no decorator é obrigatório, e “message” é opcional, sendo que todas as validações já possuem uma mensagem padrão. Outros validadores possuem atributos próprios, como o osirisvalidator.string.string_len e o osirisvalidator.string.match_regex :

    @validates('telefone')
    @is_digit(field='Telefone')
    @string_len(field='Telefone', min=10, max=11)
    def validate_telefone(self, key, telefone):
        return telefone
    @validates("sexo")
    @match_regex(field='Sexo', regex=r'^[FMfm]$', message='Sexo deve ser F ou M')
    def validate_sexo(self, key, sexo):
        if sexo is not None:
            return sexo.upper()

Exemplo Completo em Flask

Para facilitar o entendimento, criei um script já completo utilizando Flask, basta instalar as dependências, que estão descritas no requirements.txt e rodar o arquivo app.py.

https://github.com/davidaug/osirisvalidator-flask-example

Caso seja encontrado algum erro de validação, uma ValidationException é disparada e é possível disponibilizar o erro ao consumidor:

except ValidationException as ve:
    return jsonify({"status": 400, "message": "erro de validação!", "errors": ve.errors}), 400

O osirisvalidator funciona em conjunto com o SQLAlchemy, logo, pode ser utilizado em qualquer lugar para validação de campos, incluindo uma aplicação Qt.

Validadores Implementados

osirisvalidator.string

  • not_empty
  • not_blank
  • is_alpha
  • is_alpha_space (alpha characters and space)
  • is_alnum
  • is_alnum_space (alphanumeric characters and space)
  • is_digit
  • string_len (mandatory parameters: min and max)
  • match_regex (mandatory parameter: regex)

osirisvalidator.number

  • min_max (mandatory parameters: min and max)
  • not_null

osirisvalidator.internet

  • valid_email

osiris.intl.br

  • valid_cpf
  • valid_cnpj