Skip to content

Commit a50ea41

Browse files
committed
Documentation update
1 parent b064788 commit a50ea41

File tree

9 files changed

+105
-93
lines changed

9 files changed

+105
-93
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ EllarSQL Module adds support for `SQLAlchemy` and `Alembic` package to your Ella
2020
$(venv) pip install ellar-sql
2121
```
2222

23+
This library was inspired by [Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/3.1.x/){target="_blank"}
24+
2325
## Features
2426

2527
- Migration

docs/migrations/env.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
In the generated migration template, EllarSQL adopts an async-first approach for handling migration file generation.
44
This approach simplifies the execution of migrations for both `Session`, `Engine`, `AsyncSession`, and `AsyncEngine`,
55
but it also introduces a certain level of complexity.
6+
67
```python
78
from logging.config import fileConfig
89

docs/migrations/index.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# **Migrations**
2-
EllarSQL also extends Alembic package
3-
to add migration functionality to your application and make database operations available through EllarCLI commandline interface.
2+
EllarSQL also extends **Alembic** package
3+
to add migration functionality and make database operations accessible through **EllarCLI** commandline interface.
44

5-
EllarSQL with Alembic does not override Alembic action rather provide Alembic all the configs/information
6-
it needs to for a proper migration operation in your application.
5+
**EllarSQL** with Alembic does not override Alembic action rather provide Alembic all the configs/information
6+
it needs to for a proper migration/database operations.
77
Its also still possible to use Alembic outside EllarSQL setup when necessary.
88

99
This section is inspired by [`Flask Migrate`](https://flask-migrate.readthedocs.io/en/latest/#)
1010

1111
## **Quick Example**
12-
We assume you have set up `EllarSQLModule` in your application and you have specified `migration_options`.
12+
We assume you have set up `EllarSQLModule` in your application, and you have specified `migration_options`.
1313

1414
Create a simple `User` model as shown below:
1515

docs/models/configuration.md

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
# **EllarSQLModule Config**
2+
**`EllarSQLModule`** is an Ellar Dynamic Module that offers two ways of configuration:
23

3-
**`EllarSQLModule`** is a versatile module, allowing configuration through the application `Config`.
4-
This configuration can be done either using `EllarSQLModule.register_setup()` within your application setup or directly
5-
during module registration with `EllarSQLModule.setup()`.
4+
- `EllarSQLModule.register_setup()`: This method registers a `ModuleSetup` that depends on the application config.
5+
- `EllarSQLModule.setup()`: This method immediately sets up the module with the provided options.
66

7-
While examples have been provided for using `EllarSQLModule.setup()`, this section will shed light
8-
on the usage of `EllarSQLModule.register_setup()`. Before diving into that, let's first explore
9-
the setup options available for `EllarSQLModule`.
7+
While we've explored many examples using `EllarSQLModule.setup()`, this section will focus on the usage of `EllarSQLModule.register_setup()`.
108

9+
Before delving into that, let's first explore the setup options available for `EllarSQLModule`.
1110
## **EllarSQLModule Configuration Parameters**
1211

1312
- **databases**: _typing.Union[str, typing.Dict[str, typing.Any]]_:
@@ -128,16 +127,17 @@ For more in-depth information
128127
on [dealing with disconnects](https://docs.sqlalchemy.org/core/pooling.html#dealing-with-disconnects){target="_blank"},
129128
refer to SQLAlchemy's documentation on handling connection issues.
130129

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 from the application config will be passed `EllarSQLModule` setup action
135-
which validates and initializes the module.
130+
## **EllarSQLModule RegisterSetup**
131+
As mentioned earlier, **EllarSQLModule** can be configured from the 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 and validates the data before passing it to `EllarSQLModule` for setup.
136135

137-
It's important to note
138-
that `ELLAR_SQL` will be a dictionary object with the above [configuration parameters](#ellarsqlmodule-configuration-parameters) as keys.
136+
It's essential to note
137+
that `ELLAR_SQL` will be a dictionary object with the [configuration parameters](#ellarsqlmodule-configuration-parameters)
138+
mentioned above as keys.
139139

140-
A Quick example:
140+
Here's a quick example:
141141
```python title="db_learning/root_module.py"
142142
from ellar.common import Module, exception_handler, IExecutionContext, JSONResponse, Response, IApplicationStartup
143143
from ellar.app import App
@@ -180,8 +180,10 @@ class DevelopmentConfig(BaseConfig):
180180
'models': []
181181
}
182182
```
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.
185184

186-
But with this approach,
187-
we can seamlessly change **EllarSQLModule** configuration in any 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`.

docs/models/index.md

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# **Quick Start**
2-
In this section,
3-
we shall go over how to set up **EllarSQL** in your ellar application
4-
and have all necessary service registered and configuration set and ready to use.
2+
In this segment, we will walk through the process of configuring **EllarSQL** within your Ellar application,
3+
ensuring that all essential services are registered, configurations are set, and everything is prepared for immediate use.
54

6-
Before we proceed, we assume you have a clear understanding
7-
of how [Ellar Modules](https://python-ellar.github.io/ellar/basics/dynamic-modules/#module-dynamic-setup){target="_blank"} work.
5+
Before we delve into the setup instructions, it is assumed that you possess a comprehensive
6+
understanding of how [Ellar Modules](https://python-ellar.github.io/ellar/basics/dynamic-modules/#module-dynamic-setup){target="_blank"}
7+
operate.
88

99
## **Installation**
10-
Let's install all necessary packages. Also assuming your python environment has been configured:
10+
Let us install all the required packages, assuming that your Python environment has been properly configured:
1111

1212
#### **For Existing Project:**
1313
```shell
@@ -99,10 +99,10 @@ class UsersController(ecm.ControllerBase):
9999
```
100100

101101
## **EllarSQLModule Setup**
102-
In `root_module.py`, we need to do two things:
102+
In the `root_module.py` file, two main tasks need to be performed:
103103

104-
- Register `UsersController` to have `/users` available when we start the application
105-
- configure `EllarSQLModule` to configure and register all necessary services such as `EllarSQLService`, `Session` and `Engine`
104+
1. Register the `UsersController` to make the `/users` endpoint available when starting the application.
105+
2. Configure the `EllarSQLModule`, which will set up and register essential services such as `EllarSQLService`, `Session`, and `Engine`.
106106

107107
```python title="db_learning/root_module.py"
108108
from ellar.common import Module, exception_handler, IExecutionContext, JSONResponse, Response, IApplicationStartup
@@ -111,7 +111,6 @@ from ellar.core import ModuleBase
111111
from ellar_sql import EllarSQLModule, EllarSQLService
112112
from .controller import UsersController
113113

114-
115114
@Module(
116115
modules=[EllarSQLModule.setup(
117116
databases={
@@ -133,19 +132,19 @@ class ApplicationModule(ModuleBase, IApplicationStartup):
133132
def exception_404_handler(cls, ctx: IExecutionContext, exc: Exception) -> Response:
134133
return JSONResponse(dict(detail="Resource not found."), status_code=404)
135134
```
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.
139135

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.
142141

143-
At this point, we are ready to test the application.
142+
With these configurations, the application is now ready for testing.
144143
```shell
145144
ellar runserver --reload
146145
```
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.
150148

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"}.

docs/models/models.md

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,55 @@
11
# **Models and Tables**
2-
`Model` from `ellar_sql.model.Model` package is a factory class for creating `SQLAlchemy` model.
3-
It also manages a model database key and associates it to its Metadata and engine.
2+
The `ellar_sql.model.Model` class acts as a factory for creating `SQLAlchemy` models, and
3+
associating the generated models with the corresponding **Metadata** through their designated **`__database__`** key.
44

5-
`Model` can be by defining `__base_config__` at the class level. This is necessary for a
6-
case where we want to make a `Base` class that will be inherited through the application or change the declarative type
7-
such as [DeclarativeBase](https://docs.sqlalchemy.org/en/20/orm/mapping_api.html#sqlalchemy.orm.DeclarativeBase){target="_blank"} or
8-
[DeclarativeBaseNoMeta](https://docs.sqlalchemy.org/en/20/orm/mapping_api.html#sqlalchemy.orm.DeclarativeBaseNoMeta){target="_blank"}
95

10-
`Model` configuration parameters:
6+
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`.
119

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`:
1411

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: [])*
1514

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`.
1919

20-
Let's create a class with **DeclarativeBase**
2120
```python
2221
from ellar_sql import model, ModelBaseConfig
2322

2423

2524
class Base(model.Model):
2625
__base_config__ = ModelBaseConfig(as_base=True, use_bases=[model.DeclarativeBase])
26+
27+
28+
assert issubclass(Base, model.DeclarativeBase)
2729
```
28-
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:
3033

3134
```python
3235
from ellar_sql import model, ModelBaseConfig
3336

3437

3538
class Base(model.Model):
3639
__base_config__ = ModelBaseConfig(as_base=True, use_bases=[model.DeclarativeBase, model.MappedAsDataclass])
40+
41+
assert issubclass(Base, model.MappedAsDataclass)
3742
```
3843

39-
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:
4353

4454
```python
4555
from ellar_sql import model, ModelBaseConfig
@@ -55,10 +65,12 @@ class Base(model.Model):
5565
"pk": "pk_%(table_name)s"
5666
})
5767
```
68+
5869
## **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.
6274

6375
```python
6476
from datetime import datetime, timezone
@@ -98,9 +110,8 @@ class Book(model.Model, TimestampModel):
98110
```
99111

100112
## **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.
104115

105116
```python
106117
from ellar_sql import model
@@ -125,12 +136,12 @@ For a comprehensive guide on defining model classes declaratively, refer to
125136
This resource provides detailed information and insights into the declarative approach for defining model classes.
126137

127138
## **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.
129140

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.
132143

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.
134145
In such cases, the association table doesn't need its dedicated model class; rather, it can be conveniently accessed
135146
through the relevant relationship attributes on the associated models.
136147

@@ -145,14 +156,13 @@ author_book_m2m = model.Table(
145156
```
146157

147158
## **Quick Tutorial**
148-
In this section, we'll delve into straightforward CRUD operations using the ORM objects.
159+
In this section, we'll delve into straightforward **CRUD** operations using the ORM objects.
149160
However, if you're not well-acquainted with SQLAlchemy,
150161
feel free to explore their tutorial
151162
on [ORM](https://docs.sqlalchemy.org/tutorial/orm_data_manipulation.html){target="_blank"}
152163
for a more comprehensive understanding.
153164

154-
### **Create a Model**
155-
Having understood, `Model` usage. Let's create a User model
165+
Having understood, `Model` usage. Let's create a `User` model
156166

157167
```python
158168
from ellar_sql import model
@@ -264,6 +274,7 @@ In the process of `EllarSQLModule` setup, three services are registered to the E
264274
- `Session`SQLAlchemy Session of the default database configuration
265275

266276
Although with `EllarSQLService` you can get the `engine` and `session`. It's there for easy of access.
277+
267278
```python
268279
import sqlalchemy as sa
269280
import sqlalchemy.orm as sa_orm

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy