reflex-dev/reflex

[Question] `sqlalchemy.exc.ProgrammingError: (sqlite3.ProgrammingError) Error binding parameter 1: type 'StringCastedVar' is not supported`

Closed this issue · 2 comments

Hi,

I am trying to create a page of route .../user/[user_id] and then use the user_id value to obtain a row from a table in my database.

Something like:

...

from ..models import User

...

class UserState(rx.State):

    ...

    @classmethod
    def get_user_data(cls):
        with rx.session() as session:
            cls.user = session.exec(
                # This is where it errors (User is a model that I have defined elsewhere and a table in the db)
                User.select().where(User.user_id == rx.State.user_id)
            )

        ...

        data = do_stuff_with_user_data(cls.user)

        ...

        return data


@rx.page("/user/[user_id]")
def user_page():

    data = UserState.get_user_data()

    # display and modify the data in the frontend
    return rx.vstack(...)

However, even though I have tried many different ways of getting/passing this value into the query, I always get an error that relates to the value of rx.State.user_id being a Var or a StringCastedVar which is not supported by sqlalchemy (ProgrammingError).

There must be some fundamental missunderstanding from my end on how variables must be passed around and used between the front-end and back-end, but I have been stuck with this for a couple days now and I have found no solution online.

Is there something that I am missing? Is the whole approach wrong and I should interact with the database in a different way?

Thanks in advance!

After some trying out other stuff, instead of using the variable as established in a dynamic route, I have a previous page where the user kind of logs in and a user_id is saved in an AuthenticationState`.

Therefore what I try to do in the User page is to have a form where the user can modify its details (for now, first name and last name)

import reflex as rx

from ..components.authentication import AuthenticationState
from ..models import User


class UserState(rx.State):

    # AuthenticationState.user_id is saved in the previous page, where the user "logs in"
    # If I print the user_id in the previous page, when saving it i can see its value without any issue and
    # even use it to query the database further
    user_id: str | None = AuthenticationState.user_id

    ...

    @rx.event
    def handle_submit(self, form_data: dict):

        if self.user_id is None:
            raise ValueError("Not logged in")

        with rx.session() as session:
            user = session.exec(
                # This is where it errors (User is a model that I have defined elsewhere and a table in the db)
                user = User.select().where(User.user_id == self.user_id)
            ).one()
            user.first_name = form_data["first_name"]
            session.add(user)
            session.commit()


def form_when_logged_in() -> rx.Component:
    return rx.form(...)


def form_when_not_logged_in() -> rx.Component:
    return rx.form(...)


@rx.page("/user")
def user_page():

    consultant_id = AuthenticationState.consultant_id

    return rx.center(
        rx.cond(
            consultant_id,
            form_when_logged_in(),
            form_when_not_logged_in(),
        )
    )

    # display and modify the data in the frontend
    return rx.vstack(...)

The error keeps on being the same:

sqlalchemy.exc.ProgrammingError: (sqlite3.ProgrammingError) Error binding parameter 1: type 'StringCastedVar' is not supported

I feel like I have tried everything but I keep on getting stuck trying to use the state variables to query the database. I would appreciate a bit of guidance in this.

Thanks!

Apparently I didn't read deeply enough the documentation. Accessing var values from other states.

Using self.get_var_value(OtherState.another_var) solves it, but you have to use async/await.

class UserState(rx.State):
    user_id: str | None = None

    @rx.event
    async def handle_submit(self, form_data: dict):
         self.user_id = await self.get_var_value(AuthenticationState.user_id)
         ...