Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrations #113

Merged
merged 4 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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