@@ -21,29 +21,26 @@ joined-table inheritance.
2121
2222.. code-block :: python 
2323
24-     from  flask_sqlalchemy.model import  Model 
25-     import  sqlalchemy as  sa 
26-     import  sqlalchemy.orm 
24+     from  sqlalchemy import  Integer, String, ForeignKey 
25+     from  sqlalchemy.orm import  DeclarativeBase, Mapped, mapped_column, declared_attr 
2726
28-     class  IdModel (Model ): 
29-         @sa.orm.declared_attr  
27+     class  Base (DeclarativeBase ): 
28+         @declared_attr.cascading  
29+         @ classmethod  
3030        def  id (cls  
3131            for  base in  cls .__mro__ [1 :- 1 ]: 
3232                if  getattr (base, " __table__" None ) is  not  None : 
33-                     type  =  sa.ForeignKey(base.id) 
34-                     break  
35-             else : 
36-                 type  =  sa.Integer 
33+                         return  mapped_column(ForeignKey(base.id), primary_key = True ) 
34+                 else : 
35+                     return  mapped_column(Integer, primary_key = True ) 
3736
38-             return  sa.Column(type , primary_key = True ) 
39- 
40-     db =  SQLAlchemy(model_class = IdModel) 
37+     db =  SQLAlchemy(app, model_class = Base) 
4138
4239    class  User (db .Model ): 
43-         name  =  db.Column(db. String) 
40+         name: Mapped[ str ]  =  mapped_column( String) 
4441
4542    class  Employee (User ): 
46-         title  =  db.Column(db. String) 
43+         title: Mapped[ str ]  =  mapped_column( String) 
4744
4845
4946
@@ -56,28 +53,49 @@ they are created or updated.
5653.. code-block :: python 
5754
5855    from  datetime import  datetime 
56+     from  sqlalchemy import  DateTime, Integer, String 
57+     from  sqlalchemy.orm import  DeclarativeBase, Mapped, mapped_column, declared_attr 
5958
6059    class  TimestampModel (db .Model ): 
6160        __abstract__ =  True  
62-         created  =  db.Column(db. DateTime, nullable = False , default = datetime.utcnow) 
63-         updated  =  db.Column(db. DateTime, onupdate = datetime.utcnow) 
61+         created: Mapped[datetime]  =  mapped_column( DateTime, nullable = False , default = datetime.utcnow) 
62+         updated: Mapped[datetime]  =  mapped_column( DateTime,  default = datetime.utcnow , onupdate = datetime.utcnow) 
6463
6564    class  Author (db .Model ): 
66-         ...  
65+         id : Mapped[int ] =  mapped_column(Integer, primary_key = True ) 
66+         username: Mapped[str ] =  mapped_column(String, unique = True , nullable = False ) 
6767
6868    class  Post (TimestampModel ): 
69-         ...  
69+         id : Mapped[int ] =  mapped_column(Integer, primary_key = True ) 
70+         title: Mapped[str ] =  mapped_column(String, nullable = False ) 
7071
7172db.Model `` separately.
7273
7374.. code-block :: python 
7475
7576    class  TimestampMixin : 
76-         created  =  db.Column(db. DateTime, nullable = False , default = datetime.utcnow) 
77-         updated  =  db.Column(db. DateTime, onupdate = datetime.utcnow) 
77+         created: Mapped[datetime]  =  mapped_column( DateTime, nullable = False , default = datetime.utcnow) 
78+         updated: Mapped[datetime]  =  mapped_column( DateTime,  default = datetime.utcnow , onupdate = datetime.utcnow) 
7879
7980    class  Post (TimestampMixin , db .Model ): 
80-         ...  
81+         id : Mapped[int ] =  mapped_column(Integer, primary_key = True ) 
82+         title: Mapped[str ] =  mapped_column(String, nullable = False ) 
83+ 
84+ 
85+ 
86+ ------------------------------- 
87+ 
88+ Some projects prefer to set each model's ``__tablename__ `` manually rather than relying
89+ on Flask-SQLAlchemy's detection and generation. The simple way to achieve that is to
90+ set each ``__tablename__ `` and not modify the base class. However, the table name
91+ generation can be disabled by setting `disable_autonaming=True ` in the `SQLAlchemy ` constructor.
92+ 
93+ .. code-block :: python 
94+ 
95+     class  Base (sa_orm .DeclarativeBase ): 
96+         pass  
97+ 
98+     db =  SQLAlchemy(app, model_class = Base, disable_autonaming = True ) 
8199
82100
83101
@@ -158,73 +176,3 @@ To customize only ``session.query``, pass the ``query_cls`` key to the
158176.. code-block :: python 
159177
160178    db =  SQLAlchemy(session_options = {" query_cls"  
161- 
162- 
163- 
164- --------------- 
165- 
166- .. warning ::
167-     Metaclasses are an advanced topic, and you probably don't need to customize them to
168-     achieve what you want. It is mainly documented here to show how to disable table
169-     name generation.
170- 
171- The model metaclass is responsible for setting up the SQLAlchemy internals when defining
172- model subclasses. Flask-SQLAlchemy adds some extra behaviors through mixins; its default
173- metaclass, :class: `~.DefaultMeta `, inherits them all.
174- 
175- -   :class: `.BindMetaMixin `: ``__bind_key__ `` sets the bind to use for the model.
176- -   :class: `.NameMetaMixin `: If the model does not specify a ``__tablename__ `` but does
177-     specify a primary key, a name is automatically generated.
178- 
179- You can add your own behaviors by defining your own metaclass and creating the
180- declarative base yourself. Be sure to still inherit from the mixins you want (or just
181- inherit from the default metaclass).
182- 
183- Passing a declarative base class instead of a simple model base class to ``model_class ``
184- will cause Flask-SQLAlchemy to use this base instead of constructing one with the
185- default metaclass.
186- 
187- .. code-block :: python 
188- 
189-     from  sqlalchemy.orm import  declarative_base 
190-     from  flask_sqlalchemy import  SQLAlchemy 
191-     from  flask_sqlalchemy.model import  DefaultMeta, Model 
192- 
193-     class  CustomMeta (DefaultMeta ): 
194-         def  __init__ (cls name , bases , d ): 
195-             #  custom class setup could go here 
196- 
197-             #  be sure to call super 
198-             super (CustomMeta, cls ).__init__ (name, bases, d) 
199- 
200-         #  custom class-only methods could go here 
201- 
202-     CustomModel =  declarative_base(cls = Model, metaclass = CustomMeta, name = " Model"  
203-     db =  SQLAlchemy(model_class = CustomModel) 
204- 
205- 
206- :func: `~sqlalchemy.orm.declarative_base ` to customize the base class.
207- 
208- 
209- Disabling Table Name Generation
210- ``````````````````````````````` 
211- 
212- Some projects prefer to set each model's ``__tablename__ `` manually rather than relying
213- on Flask-SQLAlchemy's detection and generation. The simple way to achieve that is to
214- set each ``__tablename__ `` and not modify the base class. However, the table name
215- generation can be disabled by defining a custom metaclass with only the
216- ``BindMetaMixin `` and not the ``NameMetaMixin ``.
217- 
218- .. code-block :: python 
219- 
220-     from  sqlalchemy.orm import  DeclarativeMeta, declarative_base 
221-     from  flask_sqlalchemy.model import  BindMetaMixin, Model 
222- 
223-     class  NoNameMeta (BindMetaMixin , DeclarativeMeta ): 
224-         pass  
225- 
226-     CustomModel =  declarative_base(cls = Model, metaclass = NoNameMeta, name = " Model"  
227-     db =  SQLAlchemy(model_class = CustomModel) 
228- 
229- __bind_key__ `` feature but does not
230- generate table names.
0 commit comments