You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -128,16 +127,17 @@ For more in-depth information
128
127
on [dealing with disconnects](https://docs.sqlalchemy.org/core/pooling.html#dealing-with-disconnects){target="_blank"},
129
128
refer to SQLAlchemy's documentation on handling connection issues.
130
129
131
-
## **EllarSQLModule With App Config**
132
-
As stated above, **EllarSQLModule** can be configured from application through `EllarSQLModule.register_setup`.
133
-
This will register a [ModuleSetup](https://python-ellar.github.io/ellar/basics/dynamic-modules/#modulesetup){target="_blank"} factory that checks for `ELLAR_SQL` in application config.
134
-
The value of `ELLAR_SQL` read fromthe application config will be passed `EllarSQLModule` setup action
135
-
which validates andinitializes the module.
130
+
## **EllarSQLModule RegisterSetup**
131
+
As mentioned earlier, **EllarSQLModule** can be configured fromthe application through `EllarSQLModule.register_setup`.
132
+
This process registers a [ModuleSetup](https://python-ellar.github.io/ellar/basics/dynamic-modules/#modulesetup){target="_blank"} factory
133
+
that depends on the Application Config object.
134
+
The factory retrieves the `ELLAR_SQL` attribute from the config andvalidates the data before passing it to `EllarSQLModule`for setup.
136
135
137
-
It's important to note
138
-
that `ELLAR_SQL` will be a dictionary objectwith the above [configuration parameters](#ellarsqlmodule-configuration-parameters) as keys.
136
+
It's essential to note
137
+
that `ELLAR_SQL` will be a dictionary objectwith the [configuration parameters](#ellarsqlmodule-configuration-parameters)
138
+
mentioned above as keys.
139
139
140
-
A Quick example:
140
+
Here's a quick example:
141
141
```python title="db_learning/root_module.py"
142
142
from ellar.common import Module, exception_handler, IExecutionContext, JSONResponse, Response, IApplicationStartup
143
143
from ellar.app import App
@@ -180,8 +180,10 @@ class DevelopmentConfig(BaseConfig):
180
180
'models': []
181
181
}
182
182
```
183
-
We have added config for**EllarSQLModule** through `ELLAR_SQL`. And from there, the rest of the actions
184
-
will be the same as to normal registration with`EllarSQLModule.setup()`.
183
+
The registered ModuleSetup factory reads the `ELLAR_SQL` value and configures the `EllarSQLModule` appropriately.
185
184
186
-
But with this approach,
187
-
we can seamlessly change **EllarSQLModule** configuration inany environment like CI, Development, Staging or Production.
185
+
This approach is particularly useful when dealing with multiple environments.
186
+
It allows for seamless modification of the **ELLAR_SQL** values in various environments such as
187
+
Continuous Integration (CI), Development, Staging, or Production.
188
+
You can easily change the settings for each environment
189
+
and export the configurations as a string to be imported into `ELLAR_CONFIG_MODULE`.
return JSONResponse(dict(detail="Resource not found."), status_code=404)
135
134
```
136
-
In the above illustration,
137
-
we registered `UserController` and `EllarSQLModule` with some configurations on database and migration options.
138
-
See more on `EllarSQLModule` configurations.
139
135
140
-
Also, on the `on_startup` function, we retrieved `EllarSQLService` registered into the system through `EllarSQLModule`,
141
-
and call the `create_all()` function to create the SQLAlchemy tables.
136
+
In the provided code snippet:
137
+
138
+
- We registered `UserController` and `EllarSQLModule` with specific configurations for the database and migration options. For more details on [`EllarSQLModule` configurations](./configuration.md#ellarsqlmodule-config).
139
+
140
+
- In the `on_startup` method, we obtained the `EllarSQLService` from the Ellar Dependency Injection container using `EllarSQLModule`. Subsequently, we invoked the `create_all()` method to generate the necessary SQLAlchemy tables.
142
141
143
-
At this point, we are ready to test the application.
142
+
With these configurations, the application is now ready for testing.
144
143
```shell
145
144
ellar runserver --reload
146
145
```
147
-
Also,
148
-
remember to uncomment the `OpenAPIModule` configurations
149
-
in `server.py` to be able to visualize and interact with the `/users` the endpoint.
146
+
Additionally, please remember to uncomment the configurations for the `OpenAPIModule` in the `server.py`
147
+
file to enable visualization and interaction with the `/users` endpoint.
150
148
151
-
With that said, visit [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs){target="_blank"}
149
+
Once done,
150
+
you can access the OpenAPI documentation at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs){target="_blank"}.
This class can be configured through the `__base_config__` attribute, allowing you to specify how your `SQLAlchemy` model should be created.
7
+
The `__base_config__` attribute can be of type `ModelBaseConfig`, which is a dataclass, or a dictionary with keys that
8
+
match the attributes of `ModelBaseConfig`.
11
9
12
-
-**as_base**: Indicates if the class should be treated as a Base class for other model definitions. `Default: True`
13
-
-**use_base**: Indicates base classes that will be used to create a model base. `Default=[]`
10
+
Attributes of `ModelBaseConfig`:
14
11
12
+
-**as_base**: Indicates whether the class should be treated as a `Base` class for other model definitions, similar to creating a Base from a [DeclarativeBase](https://docs.sqlalchemy.org/en/20/orm/mapping_api.html#sqlalchemy.orm.DeclarativeBase){target="_blank"} or [DeclarativeBaseNoMeta](https://docs.sqlalchemy.org/en/20/orm/mapping_api.html#sqlalchemy.orm.DeclarativeBaseNoMeta){target="_blank"} class. *(Default: False)*
13
+
-**use_base**: Specifies the base classes that will be used to create the `SQLAlchemy` model. *(Default: [])*
15
14
16
-
## **Base Class**
17
-
`Model` treats each model as a standalone model. This means each `model.Model` has a separate **declarative** base created for it
18
-
and the `__database__` key is used to determine its Metadata reference.
15
+
## **Creating a Base Class**
16
+
`Model` treats each model as a standalone entity. Each instance of `model.Model` creates a distinct **declarative** base for itself, using the `__database__` key as a reference to determine its associated **Metadata**. Consequently, models sharing the same `__database__` key will utilize the same **Metadata** object.
17
+
18
+
Let's explore how we can create a `Base` model using `Model`, similar to the approach in traditional `SQLAlchemy`.
If desired, you can enable [SQLAlchemy’s native support for data classes](https://docs.sqlalchemy.org/en/20/changelog/whatsnew_20.html#native-support-for-dataclasses-mapped-as-orm-models){target="_blank"}
29
-
by adding MappedAsDataclass as an additional parent class.
30
+
31
+
If you are interested in [SQLAlchemy’s native support for data classes](https://docs.sqlalchemy.org/en/20/changelog/whatsnew_20.html#native-support-for-dataclasses-mapped-as-orm-models){target="_blank"},
32
+
then you can add `MappedAsDataclass` to `use_bases` as shown below:
Optionally, you have the flexibility to construct the SQLAlchemy object with a custom [`MetaData`](https://docs.sqlalchemy.org/en/20/core/metadata.html#sqlalchemy.schema.MetaData){target="_blank"} object.
40
-
This customization enables you to define a specific **naming convention** for constraints.
41
-
This becomes particularly valuable as it ensures consistency and predictability in constraint names.
42
-
This predictability proves especially beneficial when utilizing migrations, as detailed by [Alembic](https://alembic.sqlalchemy.org/en/latest/naming.html){target="_blank"}.
44
+
In the examples above, `Base` classes are created, all subclassed from the `use_bases` provided, and with the `as_base`
45
+
option, the factory creates the `Base` class as a `Base`.
46
+
47
+
## Create base with MetaData
48
+
You can also configure the SQLAlchemy object with a custom [`MetaData`](https://docs.sqlalchemy.org/en/20/core/metadata.html#sqlalchemy.schema.MetaData){target="_blank"} object.
49
+
For instance, you can define a specific **naming convention** for constraints, ensuring consistency and predictability in constraint names.
50
+
This can be particularly beneficial during migrations, as detailed by [Alembic](https://alembic.sqlalchemy.org/en/latest/naming.html){target="_blank"}.
51
+
52
+
For example:
43
53
44
54
```python
45
55
from ellar_sql import model, ModelBaseConfig
@@ -55,10 +65,12 @@ class Base(model.Model):
55
65
"pk": "pk_%(table_name)s"
56
66
})
57
67
```
68
+
58
69
## **Abstract Models and Mixins**
59
-
If the desired behavior is applicable only to specific models rather than all models, consider using an abstract model base class to customize only those models.
60
-
For instance, if certain models need to track their creation or update timestamps,
61
-
this approach allows for targeted customization.
70
+
If the desired behavior is only applicable to specific models rather than all models,
71
+
you can use an abstract model base class to customize only those models.
72
+
For example, if certain models need to track their creation or update **timestamps**, t
73
+
his approach allows for targeted customization.
62
74
63
75
```python
64
76
from datetime import datetime, timezone
@@ -98,9 +110,8 @@ class Book(model.Model, TimestampModel):
98
110
```
99
111
100
112
## **Defining Models**
101
-
Unlike plain SQLAlchemy, EllarSQL model will automatically generate a table name
102
-
if `__tablename__` is not set and a primary key column is defined.
103
-
This can be **disabled** by setting a value for `__tablename__` or defining `__tablename__` as a **declarative_attr**
113
+
Unlike plain SQLAlchemy, **EllarSQL** models will automatically generate a table name if the `__tablename__` attribute is not set,
114
+
provided a primary key column is defined.
104
115
105
116
```python
106
117
from ellar_sql import model
@@ -125,12 +136,12 @@ For a comprehensive guide on defining model classes declaratively, refer to
125
136
This resource provides detailed information and insights into the declarative approach for defining model classes.
126
137
127
138
## **Defining Tables**
128
-
The table class is designed to receive a table name, followed by columns and other table components such as constraints.
139
+
The table class is designed to receive a table name, followed by **columns** and other table **components** such as constraints.
129
140
130
-
EllarSQL enhances the functionality of the SQLAlchemy Table by facilitating the creation or
131
-
selection of metadata based on the `__database__` argument.
141
+
EllarSQL enhances the functionality of the SQLAlchemy Table
142
+
by facilitating the selection of **Metadata** based on the `__database__` argument.
132
143
133
-
Directly creating a table proves particularly valuable when establishing many-to-many relationships.
144
+
Directly creating a table proves particularly valuable when establishing **many-to-many** relationships.
134
145
In such cases, the association table doesn't need its dedicated model class; rather, it can be conveniently accessed
135
146
through the relevant relationship attributes on the associated models.
0 commit comments