lingthio / Flask-User

Customizable User Authorization & User Management: Register, Confirm, Login, Change username/password, Forgot password and more.
http://flask-user.readthedocs.io/
MIT License
1.06k stars 292 forks source link

Working example of custom DB adapter? #241

Open adm271828 opened 6 years ago

adm271828 commented 6 years ago

Hi,

is there a working exemple of custom DB Adapter somewhere (with app factory pattern)?

It seems to me that calling UserManager.init_app() requires db to be a predefined or custom adapter, and thus the adapter to be created first. But if I try to create an adapter first, I need an app and the app needs to have a user_manager already initialized (requirement in adapter interface base class).

Best regards.

ghost commented 5 years ago

As far as I see, you don't need app to create an adapter.. db_adapter = SQLAlchemyAdapter(db, User) Then you pass an adapter and the app to the UserManager() class user_manager = UserManager(db_adapter, app)

adm271828 commented 5 years ago

Yes, you're right. My question was not clear.

The point is that I wan't a custom DB adapter that does not inherit from the already provided ones, i.e a SQL adapter not using FlaskSQLAlchemy. And it's seems it is not possible. It will raise an exception line 75 of db_manager.py.

I was expecting I could provide my own DB adapter, but it's not accepted, even if the adapter complies with the interface.

Best regards.

ghost commented 5 years ago

Alright, I see.. I assume that you have create your own adapter with all the implementations as any other db_adapter has in this project.

Then, you can either modify source code or override init functions for DBAdapter and UserManager.

If you modify source code, it's easy, just add next after line 63:

        if self.db_adapter is None: 
            try:
                from MyOwnDBLibrary import OwnDBObject

                if isinstance(db, OwnDBObject):
                    self.db_adapter = MyOwnDBAdapter(app, db)
            except ImportError:
                pass 

Where MyOwnDBLibrary is whatever library you're using for your DB and OwnDBObject is a base object of your DB library. They simply use your own adapter MyOwnDBAdapter to create an adapter.

If you would like to go with override way(no source code modifications). Then that would be almost the same, but you will create:

  1. Create a CustomDBManager(DBManager) and override the __init__ with the addition in the beggining of this comment. it'll look something like
    
    from flask_user.db_manager import DBManager

create cusotm DB manager with initoverride

class CustomDBManager(DBManage): def init(self, app, db, UserClass, UserEmailClass=None, UserInvitationClass=None, RoleClass=None): def init(self, app, db, UserClass): super().init(app, db, UserClass) # or if decide to owerride the whole method, copy paste the source code and remove calling parend init

here I'm not sure what whould be the best to override, never tried to override init method, but yoou get the idea

2. Create a custom UserManger object inheriting the default `UserManager` object and overriding `init_app` . Technicaly copying the whole `init_app()` method but changing only one line
``` python
# ........................
#line #182 in the source code
self.db_manager = CustomDBManager(app, db, UserClass, UserEmailClass, UserInvitationClass, RoleClass)
# ........................