E 'OK usare i form (WTF) per validare contro roba da DB?

2

Le classi del modulo sono intese (IMO) per i dati inviati rispetto alle regole. Ad esempio: le password sono uguali, la data di fine è successiva alla data di inizio.

submitted data--->|Form|

Va bene per le classi Modulo convalidare i dati inviati rispetto ai dati recuperati da un database? Questo sembra un problema di responsabilità , la classe Form dovrebbe essere responsabile della convalida e della pulizia della submission da sola e il controllo del DB appartiene al di fuori della classe.

submitted data--->|Form|<---data from DB

Ecco il mio esempio in WTForms in Python: controlla se l'id utente è un numero intero, quindi interroga il DB per verificare che esista.

class ClientForm(Form):
    name = StringField(validators=[DataRequired(message="Invalid value")])
    user = IntegerField(validators=[DataRequired(message="Invalid value")])
    zone = IntegerField(validators=[AnyOf([i[0] for i in ZONES], message="Invalid value")])

    #validate user as real
    def validate_user(form, field):
        user = db.session.query(User).filter(User.id==form.user.data).first()
        if not user:
            raise ValidationError('Invalid user')

Il vantaggio di aggiungere questo assegno al modulo è conveniente, WTForms gestisce tutti gli aspetti degli errori, anche nel renderli:

form = ClientForm(post_data)
if not form.validate():
    # render the form again with errors highlighted
    return render("client_registration_form.html", form=form)
else:
    return render("success.html")
    
posta aitchnyu 03.09.2015 - 12:22
fonte

2 risposte

1

Facendo riferimento direttamente al tuo database, e specialmente afferrandolo da un globale, stai strettamente accoppiando il tuo livello di presentazione con il tuo livello di persistenza. Dovremmo invece affrontare questo problema con un occhio ai principi SOLID.

Invece di raggiungere un oggetto globale per ottenere la connessione al database, dovremmo inserire tale dipendenza nel validatore del modulo. In questo modo, possiamo dipendere dall'astrazione di un database piuttosto che dalla concrezione di un pezzo di stato globale. Il codice diventa più flessibile e testabile poiché la dipendenza può essere scambiata.

Il modo migliore per ottenere ciò sarebbe creare un oggetto intermedio per disaccoppiare completamente la convalida del modulo dal database. Questo oggetto intermedio avrebbe la connessione al database iniettato in esso, quindi sarebbe iniettato nel validatore del modulo. Ciò consentirebbe al validatore di moduli di avere una dipendenza flessibile. Potrebbe sembrare:

class UserIDExists:
    def __init__(self, db):
        self["db"] = db

    def check(self, user_id):
        user = db.session.query(User).filter(User.id == user_id).first()
        return bool(user)

Quindi la tua classe WTForms userebbe il metodo check per determinare se dovrebbe aumentare o meno.

Ma c'è un modo ancora migliore. Invece di creare una classe arbitraria, potremmo creare una classe che sia un validatore di WTForms personalizzato . Lo inietteremmo comunque, ma si integrerebbe in un modo molto più pulito e più trasparente con il resto dei validatori che già utilizzi.

    
risposta data 08.12.2015 - 03:37
fonte
0

Penso che sia corretto utilizzare WTForms per convalidare i dati non inviati direttamente da un utente. Sembra molto strano convalidare i dati dal tuo database: il database e il DAL dovrebbero averlo già convalidato.

Non è irragionevole usare WTForms per convalidare una combinazione di dati e dati inviati dall'utente dal database. Tuttavia, per un modulo interattivo, preferirei che l'utente veda un modulo che per sua stessa struttura impedisce l'inserimento di dati non validi, in base al contenuto del database. Probabilmente, a volte non è possibile o pratico.

Posso facilmente vedere usando WTForms per convalidare i dati provenienti da es. sistemi esterni che non sono invii di moduli, come i file di input analizzati.

    
risposta data 03.09.2015 - 17:08
fonte

Leggi altre domande sui tag