@@ -553,19 +553,35 @@ def get_engine(self):
553
553
echo = self ._app .config ['SQLALCHEMY_ECHO' ]
554
554
if (uri , echo ) == self ._connected_for :
555
555
return self ._engine
556
- info = make_url (uri )
557
- options = {'convert_unicode' : True }
558
- self ._sa .apply_pool_defaults (self ._app , options )
559
- self ._sa .apply_driver_hacks (self ._app , info , options )
560
- if echo :
561
- options ['echo' ] = echo
562
- self ._engine = rv = sqlalchemy .create_engine (info , ** options )
556
+
557
+ sa_url = make_url (uri )
558
+ options = self .get_options (sa_url , echo )
559
+ self ._engine = rv = self ._sa .create_engine (sa_url , options )
560
+
563
561
if _record_queries (self ._app ):
564
562
_EngineDebuggingSignalEvents (self ._engine ,
565
563
self ._app .import_name ).register ()
564
+
566
565
self ._connected_for = (uri , echo )
566
+
567
567
return rv
568
568
569
+ def get_options (self , sa_url , echo ):
570
+ options = {'convert_unicode' : True }
571
+ self ._sa .apply_pool_defaults (self ._app , options )
572
+ self ._sa .apply_driver_hacks (self ._app , sa_url , options )
573
+ if echo :
574
+ options ['echo' ] = echo
575
+
576
+ # Give the config options set by a developer explicitly priority
577
+ # over decisions FSA makes.
578
+ options .update (self ._app .config ['SQLALCHEMY_ENGINE_OPTIONS' ])
579
+
580
+ # Give options set in SQLAlchemy.__init__() ultimate priority
581
+ options .update (self ._sa ._engine_options )
582
+
583
+ return options
584
+
569
585
570
586
def get_state (app ):
571
587
"""Gets the state for the application"""
@@ -644,6 +660,12 @@ class User(db.Model):
644
660
to be passed to the session constructor. See :class:`~sqlalchemy.orm.session.Session`
645
661
for the standard options.
646
662
663
+ The ``engine_options`` parameter, if provided, is a dict of parameters
664
+ to be passed to create engine. See :func:`~sqlalchemy.create_engine`
665
+ for the standard options. The values given here will be merged with and
666
+ override anything set in the ``'SQLALCHEMY_ENGINE_OPTIONS'`` config
667
+ variable or othewise set by this library.
668
+
647
669
.. versionadded:: 0.10
648
670
The `session_options` parameter was added.
649
671
@@ -663,6 +685,9 @@ class to be used in place of :class:`Model`.
663
685
664
686
.. versionchanged:: 2.1
665
687
Utilise the same query class across `session`, `Model.query` and `Query`.
688
+
689
+ .. versionadded:: 2.4
690
+ The `engine_options` parameter was added.
666
691
"""
667
692
668
693
#: Default query class used by :attr:`Model.query` and other queries.
@@ -671,14 +696,16 @@ class to be used in place of :class:`Model`.
671
696
Query = None
672
697
673
698
def __init__ (self , app = None , use_native_unicode = True , session_options = None ,
674
- metadata = None , query_class = BaseQuery , model_class = Model ):
699
+ metadata = None , query_class = BaseQuery , model_class = Model ,
700
+ engine_options = None ):
675
701
676
702
self .use_native_unicode = use_native_unicode
677
703
self .Query = query_class
678
704
self .session = self .create_scoped_session (session_options )
679
705
self .Model = self .make_declarative_base (model_class , metadata )
680
706
self ._engine_lock = Lock ()
681
707
self .app = app
708
+ self ._engine_options = engine_options or {}
682
709
_include_sqlalchemy (self , query_class )
683
710
684
711
if app is not None :
@@ -790,6 +817,7 @@ def init_app(self, app):
790
817
track_modifications = app .config .setdefault (
791
818
'SQLALCHEMY_TRACK_MODIFICATIONS' , None
792
819
)
820
+ app .config .setdefault ('SQLALCHEMY_ENGINE_OPTIONS' , {})
793
821
794
822
if track_modifications is None :
795
823
warnings .warn (FSADeprecationWarning (
@@ -819,7 +847,7 @@ def _setdefault(optionkey, configkey):
819
847
_setdefault ('pool_recycle' , 'SQLALCHEMY_POOL_RECYCLE' )
820
848
_setdefault ('max_overflow' , 'SQLALCHEMY_MAX_OVERFLOW' )
821
849
822
- def apply_driver_hacks (self , app , info , options ):
850
+ def apply_driver_hacks (self , app , sa_url , options ):
823
851
"""This method is called before engine creation and used to inject
824
852
driver specific hacks into the options. The `options` parameter is
825
853
a dictionary of keyword arguments that will then be used to call
@@ -829,15 +857,15 @@ def apply_driver_hacks(self, app, info, options):
829
857
like pool sizes for MySQL and sqlite. Also it injects the setting of
830
858
`SQLALCHEMY_NATIVE_UNICODE`.
831
859
"""
832
- if info .drivername .startswith ('mysql' ):
833
- info .query .setdefault ('charset' , 'utf8' )
834
- if info .drivername != 'mysql+gaerdbms' :
860
+ if sa_url .drivername .startswith ('mysql' ):
861
+ sa_url .query .setdefault ('charset' , 'utf8' )
862
+ if sa_url .drivername != 'mysql+gaerdbms' :
835
863
options .setdefault ('pool_size' , 10 )
836
864
options .setdefault ('pool_recycle' , 7200 )
837
- elif info .drivername == 'sqlite' :
865
+ elif sa_url .drivername == 'sqlite' :
838
866
pool_size = options .get ('pool_size' )
839
867
detected_in_memory = False
840
- if info .database in (None , '' , ':memory:' ):
868
+ if sa_url .database in (None , '' , ':memory:' ):
841
869
detected_in_memory = True
842
870
from sqlalchemy .pool import StaticPool
843
871
options ['poolclass' ] = StaticPool
@@ -860,7 +888,7 @@ def apply_driver_hacks(self, app, info, options):
860
888
861
889
# if it's not an in memory database we make the path absolute.
862
890
if not detected_in_memory :
863
- info .database = os .path .join (app .root_path , info .database )
891
+ sa_url .database = os .path .join (app .root_path , sa_url .database )
864
892
865
893
unu = app .config ['SQLALCHEMY_NATIVE_UNICODE' ]
866
894
if unu is None :
@@ -897,6 +925,16 @@ def get_engine(self, app=None, bind=None):
897
925
898
926
return connector .get_engine ()
899
927
928
+ def create_engine (self , sa_url , engine_opts ):
929
+ """
930
+ Override this method to have final say over how the SQLAlchemy engine
931
+ is created.
932
+
933
+ In most cases, you will want to use ``'SQLALCHEMY_ENGINE_OPTIONS'``
934
+ config variable or set ``engine_options`` for :func:`SQLAlchemy`.
935
+ """
936
+ return sqlalchemy .create_engine (sa_url , ** engine_opts )
937
+
900
938
def get_app (self , reference_app = None ):
901
939
"""Helper method that implements the logic to look up an
902
940
application."""
0 commit comments