Skip to content

Commit

Permalink
Merge pull request #113 from tarsil/feature/feature_integration
Browse files Browse the repository at this point in the history
Integrations
  • Loading branch information
tarsil authored Nov 30, 2023
2 parents 99cee03 + 670f2cb commit b30316e
Show file tree
Hide file tree
Showing 34 changed files with 1,139 additions and 309 deletions.
163 changes: 163 additions & 0 deletions docs/queries/queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -520,5 +520,168 @@ for user in users:
await User.query.bulk_update(users, fields=['is_active'])
```

## Operators

There are sometimes the need of adding some extra conditions like `AND`, or `OR` or even the `NOT`
into your queries and therefore Saffier provides a simple integration with those.

Saffier provides the [and_](#and), [or_](#or) and [not_](#not) operators directly for you to use, although
this ones come with a slighly different approach.

For all the examples, let us use the model below.

```python
{!> ../docs_src/queries/clauses/model.py !}
```

### SQLAlchemy style

Since Saffier is built on the top of SQL Alchemy core, that also means we can also use directly that
same functionality within our queries.

In other words, uses the [SQLAlchemy style](#sqlalchemy-style).

!!! Warning
The `or_`, `and_` and `not_` do not work with [related](./related-name.md) operations and only
directly with the model itself.

This might sound confusing so let us see some examples.

#### AND

As the name suggests, you want to add the `AND` explicitly.

```python
{!> ../docs_src/queries/clauses/and.py !}
```

As mentioned before, applying the [SQLAlchemy style](#sqlalchemy-style) also means you can do this.

```python
{!> ../docs_src/queries/clauses/and_two.py !}
```

And you can do nested `querysets` like multiple [filters](#filter).

```python
{!> ../docs_src/queries/clauses/and_m_filter.py !}
```

#### OR

The same principle as the [and_](#and) but applied to the `OR`.

```python
{!> ../docs_src/queries/clauses/or.py !}
```

As mentioned before, applying the [SQLAlchemy style](#sqlalchemy-style) also means you can do this.

```python
{!> ../docs_src/queries/clauses/or_two.py !}
```

And you can do nested `querysets` like multiple [filters](#filter).

```python
{!> ../docs_src/queries/clauses/or_m_filter.py !}
```

#### NOT

This is simple and direct, this is where you apply the `NOT`.

```python
{!> ../docs_src/queries/clauses/not.py !}
```

As mentioned before, applying the [SQLAlchemy style](#sqlalchemy-style) also means you can do this.

```python
{!> ../docs_src/queries/clauses/not_two.py !}
```

And you can do nested `querysets` like multiple [filters](#filter).

```python
{!> ../docs_src/queries/clauses/not_m_filter.py !}
```

### Saffier Style

This is the most common used scenario where you can use the [related](./related-name.md) for your
queries and all the great functionalities of Saffier while using the operands.

!!! Tip
The same way you apply the filters for the queries using the [related](./related-name.md), this
can also be done with the **Saffier style** but the same cannot be said for the
[SQLAlchemy style](#sqlalchemy-style-1). So if you want to leverage the full power of Saffier,
it is advised to go Saffier style.

#### AND

The `AND` operand with the syntax is the same as using the [filter](#filter) or any queryset
operatator but for visualisation purposes this is also available in the format of `and_`.

```python
{!> ../docs_src/queries/clauses/style/and_two.py !}
```

With multiple parameters.

```python
{!> ../docs_src/queries/clauses/style/and.py !}
```

And you can do nested `querysets` like multiple [filters](#filter).

```python
{!> ../docs_src/queries/clauses/style/and_m_filter.py !}
```

#### OR

The same principle as the [and_](#and-1) but applied to the `OR`.

```python
{!> ../docs_src/queries/clauses/style/or.py !}
```

With multiple `or_` or nultiple parametes in the same `or_`

```python
{!> ../docs_src/queries/clauses/style/or_two.py !}
```

And you can do nested `querysets` like multiple [filters](#filter).

```python
{!> ../docs_src/queries/clauses/style/or_m_filter.py !}
```

#### NOT

The `not_` as the same principle as the [exclude](#exclude) and like the [and](#and-1), for
representation purposes, Saffier also has that function.

```python
{!> ../docs_src/queries/clauses/style/not.py !}
```

With multiple `not_`.

```python
{!> ../docs_src/queries/clauses/style/not_two.py !}
```

And you can do nested `querysets` like multiple [filters](#filter).

```python
{!> ../docs_src/queries/clauses/style/not_m_filter.py !}
```

Internally, the `not_` is calling the [exclude](#exclude) and applying the operators so this is
more for *cosmetic* purposes than anything else, really.

[model]: ../models.md
[managers]: ../managers.md
2 changes: 1 addition & 1 deletion docs_src/models/pk_with_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


class User(saffier.Model):
id = saffier.UUIDField(max_length=255, primary_key=True, default=uuid.uuid4)
id = saffier.UUIDField(primary_key=True, default=uuid.uuid4)
age = saffier.IntegerField(minimum=18)
is_active = saffier.BooleanField(default=True)

Expand Down
11 changes: 11 additions & 0 deletions docs_src/queries/clauses/and.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import saffier

# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the and_
await User.query.filter(
saffier.and_(User.columns.name == "Adam", User.columns.email == "[email protected]"),
)
11 changes: 11 additions & 0 deletions docs_src/queries/clauses/and_m_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import saffier

# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the and_
await User.query.filter(saffier.and_(User.columns.name == "Adam")).filter(
saffier.and_(User.columns.email == "[email protected]")
)
13 changes: 13 additions & 0 deletions docs_src/queries/clauses/and_two.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import saffier

# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the and_
await User.query.filter(
saffier.and_(
User.columns.email.contains("saffier"),
)
)
13 changes: 13 additions & 0 deletions docs_src/queries/clauses/model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import saffier
from saffier import Database, Registry

database = Database("sqlite:///db.sqlite")
models = Registry(database=database)


class User(saffier.Model):
first_name: str = saffier.CharField(max_length=50, null=True)
email: str = saffier.EmailField(max_lengh=100, null=True)

class Meta:
registry = models
9 changes: 9 additions & 0 deletions docs_src/queries/clauses/not.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import saffier

# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the not_
await User.query.filter(saffier.not_(User.columns.name == "Adam"))
12 changes: 12 additions & 0 deletions docs_src/queries/clauses/not_m_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import saffier

# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")
await User.query.create(name="John", email="[email protected]")

# Query using the not_
await User.query.filter(saffier.not_(User.columns.name == "Adam")).filter(
saffier.not_(User.columns.email.contains("saffier"))
)
13 changes: 13 additions & 0 deletions docs_src/queries/clauses/not_two.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import saffier

# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the not_
await User.query.filter(
saffier.not_(
User.columns.email.contains("saffier"),
)
)
11 changes: 11 additions & 0 deletions docs_src/queries/clauses/or.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import saffier

# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the or_
await User.query.filter(
saffier.or_(User.columns.name == "Adam", User.columns.email == "[email protected]"),
)
11 changes: 11 additions & 0 deletions docs_src/queries/clauses/or_m_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import saffier

# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the or_
await User.query.filter(saffier.or_(User.columns.name == "Adam")).filter(
saffier.or_(User.columns.email == "[email protected]")
)
13 changes: 13 additions & 0 deletions docs_src/queries/clauses/or_two.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import saffier

# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the or_
await User.query.filter(
saffier.or_(
User.columns.email.contains("saffier"),
)
)
7 changes: 7 additions & 0 deletions docs_src/queries/clauses/style/and.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the and_
await User.query.and_(name="Adam", email="[email protected]")
7 changes: 7 additions & 0 deletions docs_src/queries/clauses/style/and_m_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the and_
await User.query.filter(name="Adam").and_(email="[email protected]")
7 changes: 7 additions & 0 deletions docs_src/queries/clauses/style/and_two.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the and_
await User.query.and_(email__icontains="saffier")
13 changes: 13 additions & 0 deletions docs_src/queries/clauses/style/model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import saffier
from saffier import Database, Registry

database = Database("sqlite:///db.sqlite")
models = Registry(database=database)


class User(saffier.Model):
first_name: str = saffier.CharField(max_length=50, null=True)
email: str = saffier.EmailField(max_lengh=100, null=True)

class Meta:
registry = models
7 changes: 7 additions & 0 deletions docs_src/queries/clauses/style/not.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the not_
await User.query.not_(name="Adam")
8 changes: 8 additions & 0 deletions docs_src/queries/clauses/style/not_m_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")
await User.query.create(name="John", email="[email protected]")

# Query using the not_
await User.query.filter(email__icontains="saffier").not_(name__iexact="Adam")
7 changes: 7 additions & 0 deletions docs_src/queries/clauses/style/not_two.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the not_
await User.query.not_(email__icontains="saffier").not_(name__icontains="a")
7 changes: 7 additions & 0 deletions docs_src/queries/clauses/style/or.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the or_
await User.query.or_(name="Adam", email="[email protected]")
7 changes: 7 additions & 0 deletions docs_src/queries/clauses/style/or_m_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the or_
await User.query.or_(name="Adam").filter(email="[email protected]")
10 changes: 10 additions & 0 deletions docs_src/queries/clauses/style/or_two.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Create some records

await User.query.create(name="Adam", email="[email protected]")
await User.query.create(name="Eve", email="[email protected]")

# Query using the multiple or_
await User.query.or_(email__icontains="saffier").or_(name__icontains="a")

# Query using the or_ with multiple fields
await User.query.or_(email__icontains="saffier", name__icontains="a")
Loading

0 comments on commit b30316e

Please sign in to comment.