trafaret icon indicating copy to clipboard operation
trafaret copied to clipboard

Using function to validate username

Open Dreamsorcerer opened this issue 5 years ago • 7 comments

I couldn't find an example of this in the documentation, so is this the expected way to run a function to validate a value?

    def check_if_user_exists(username):
        if username == "reserved":
            raise t.DataError("Username already exists")
        return username
    signup_form = t.Dict({
        "username": t.String() & check_if_user_exists,
        "password": t.String()
    })

As an extension to that, is it possible to support async functions in some way? So, that code might end up looking like:

    async def check_if_user_exists(username):
        with db.connect() as conn:
            result = await conn.scalar(users.count().where(users.username == username))
        if result is not None:
            raise t.DataError("Username already exists")
        return username
    signup_form = t.Dict({
        "username": t.String() & t.Await(check_if_user_exists),
        "password": t.String()
    })

Dreamsorcerer avatar Apr 25 '20 17:04 Dreamsorcerer

OK, answer to second question is await signup_form.async_check(), which doesn't appear in the documentation, but found it in the source code.

Dreamsorcerer avatar Apr 25 '20 17:04 Dreamsorcerer

Worth noting however, that subdict(trafaret=func) does not use async.

Dreamsorcerer avatar Apr 26 '20 10:04 Dreamsorcerer

subdict is a function. We need to implement async_subdict then

Deepwalker avatar Apr 27 '20 18:04 Deepwalker

It was not documented possible because no one was really interested in async version.

Deepwalker avatar Apr 27 '20 18:04 Deepwalker

Well, I found this project as it was being used in some aiohttp demos, so I'm probably not the only one.

Dreamsorcerer avatar Apr 27 '20 19:04 Dreamsorcerer

Yes, but if you use trafaret for sanitising of input data then you will not need to call anything asynchronously. But of course if you need to make query to database, then you will need async version. That was my thought when I added async to trafaret. So, we probably need to update documentation then. BTW we have context argument, so you can place application object here for some deeply nested trafarets.

Deepwalker avatar Apr 27 '20 19:04 Deepwalker

Yes, in fact that's exactly what I've done. I pass the request object through as the context.

Dreamsorcerer avatar Apr 27 '20 20:04 Dreamsorcerer