Python OOP - Web App (Flask) - User registration class?
In general, your code seems to be in pretty good shape if you're hoping to move towards domain driven design, notably seen from your &quot;entity-like&quot; User object and the UserService.

Does it make sense to have2 separate classes? I am actually thinking to move all of my User methods to the UserService class and just have a UserService class with setters and getters.

First off, if you're anticipating your application to grow, a clear separation of concerns is what you'd want to achieve and to further achieve this, the two objects you have are fine. That is, one to represent a definition of what a user is and another to determine what you can do with a user object or related objects which in this case is the UserService. This naturally means that the methods on the User class should now be part of the UserService, considering them business logic of the application. I would use the words model to describe the User class and service to describe the UserService to define the types of components for the application.

I am confused about is where and when to interact with the database. Should I do it directly on my route.py vs create a new class?

One thing that you can also consider from domain driven design is also to include a repository object when your application becomes large enough. Repositories typically carry operations that might interact with a database, replacing what may be seen like an ORM that you have mentioned. Otherwise, if you're still small and nimble and don't have too many complex relationships in your database, you can keep it simple and keep the database queries in your model for simplicity for the time being. Both allows the user to be created from anywhere if needed and enables code re-use more than including them in the route. Designing from an interface perspective consider the following.
user_repository = UserRepository(db_conn)
user_service = UserService()
foo_user = user_service.register_user(...)

// using the repository
repository.save(foo_user)

// using the model
foo_user.save()

I'll end this with, it depends how large your application is growing, the larger it is, the more you want to re-evaluate your design so to better organize groups of functionality to better extend from and if possible re-use code. That said, what you may have could be good in the long run if your application doesn't really grow beyond those needs.