Skip to content

Commit bca0577

Browse files
committed
docs: Update docs to add new way to add conditions
1 parent f2c6b80 commit bca0577

File tree

2 files changed

+80
-18
lines changed

2 files changed

+80
-18
lines changed

docs/advanced.md

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
These are available on your model instance when the mixin or extend the base model is used.
66

7-
| Method | Details |
8-
|:-------------:|:-------------:|
9-
| `has_changed(field_name: str) -> bool` | Return a boolean indicating whether the field's value has changed since the model was initialized |
10-
| `initial_value(field_name: str) -> bool` | Return the value of the field when the model was first initialized |
7+
| Method | Details |
8+
|:----------------------------------------:|:-------------------------------------------------------------------------------------------------:|
9+
| `has_changed(field_name: str) -> bool` | Return a boolean indicating whether the field's value has changed since the model was initialized |
10+
| `initial_value(field_name: str) -> bool` | Return the value of the field when the model was first initialized |
1111

1212
### Example
1313
You can use these methods for more advanced checks, for example:
@@ -29,6 +29,33 @@ class UserAccount(LifecycleModel):
2929

3030
```
3131

32+
## Custom conditions <a id="custom-conditions"></a>
33+
Custom conditions can be created as long as they respect condition signature
34+
```python
35+
def changes_to_ned_flanders(instance, update_fields=None):
36+
...
37+
```
38+
39+
To allow your custom conditions to be chainable, create a class based condition inheriting `ChainableCondition`.
40+
```python
41+
from django_lifecycle import BEFORE_SAVE
42+
from django_lifecycle.conditions import WhenFieldHasChanged
43+
from django_lifecycle.conditions.base import ChainableCondition
44+
45+
46+
class IsNedFlanders(ChainableCondition):
47+
def __call__(self, instance, update_fields=None):
48+
return instance.first_name == "Ned" and instance.last_name == "Flanders"
49+
50+
51+
@hook(
52+
BEFORE_SAVE,
53+
condition=WhenFieldHasChanged("first_name") & WhenFieldHasChanged("last_name") & IsNedFlanders()
54+
)
55+
def foo():
56+
...
57+
```
58+
3259
## Suppressing Hooked Methods <a id="suppressing"></a>
3360

3461
To prevent the hooked methods from being called, pass `skip_hooks=True` when calling save:

docs/hooks_and_conditions.md

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,22 @@ set up conditions for when the method should fire.
77
## Decorator Signature
88

99
```python
10-
@hook(
11-
moment: str,
12-
when: str = None,
13-
when_any: List[str] = None,
14-
has_changed: bool = None,
15-
is_now: Any = '*',
16-
is_not: Any = None,
17-
was: Any = '*',
18-
was_not: Any = None,
19-
changes_to: Any = None,
20-
priority: int = DEFAULT_PRIORITY,
21-
on_commit: Optional[bool] = None
22-
):
10+
@hook(
11+
moment: str,
12+
condition: Optional[types.Condition] = None,
13+
priority: int = DEFAULT_PRIORITY,
14+
on_commit: Optional[bool] = None,
15+
16+
# Legacy parameters
17+
when: str = None,
18+
when_any: List[str] = None,
19+
has_changed: bool = None,
20+
is_now: Any = '*',
21+
is_not: Any = None,
22+
was: Any = '*',
23+
was_not: Any = None,
24+
changes_to: Any = None,
25+
)
2326
```
2427

2528
## Lifecycle Moments
@@ -40,7 +43,39 @@ Below is a full list of hooks, in the same order in which they will get called d
4043
All of hook constants are strings containing the specific hook name, for example `AFTER_UPDATE` is string
4144
`"after_update"` - preferably way is to use hook constant.
4245

43-
## Condition Keyword Arguments
46+
## Conditions
47+
48+
You can add a condition to specify in which case the hook will be fired or not, depending on the initial or current
49+
state of a model instance's fields.
50+
51+
There are some conditions already implemented, but you can provide your own condition, or even chain them using `&` and `|`.
52+
53+
- `WhenFieldChangesTo(field_name, has_changed)`
54+
- `WhenFieldIsNow(field_name, is_now)`
55+
- `WhenFieldIsNot(field_name, is_not)`
56+
- `WhenFieldWas(field_name, was)`
57+
- `WhenFieldWasNot(field_name, was_not)`
58+
- `WhenFieldChangesTo(field_name, changes_to)`
59+
60+
### Chaining conditions
61+
Conditions can be chained using `&` and `|` boolean operators
62+
63+
```python
64+
from django_lifecycle.conditions import WhenFieldChangesTo
65+
from django_lifecycle import hook, BEFORE_UPDATE
66+
67+
@hook(
68+
BEFORE_UPDATE,
69+
condition=(
70+
WhenFieldChangesTo("first_name", changes_to="Ned")
71+
& WhenFieldChangesTo("last_name", changes_to="Flanders")
72+
)
73+
)
74+
def do_something(self):
75+
...
76+
```
77+
78+
## Legacy Condition Keyword Arguments
4479

4580
If you do not use any conditional parameters, the hook will fire every time the lifecycle moment occurs. You can use the keyword arguments below to conditionally fire the method depending on the initial or current state of a model instance's fields.
4681

0 commit comments

Comments
 (0)