Skip to content

Commit ef3a286

Browse files
authored
Merge branch 'master' into f213-patch-2
2 parents edaa72e + 264e051 commit ef3a286

File tree

10 files changed

+152
-156
lines changed

10 files changed

+152
-156
lines changed

{{ cookiecutter.name }}/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ lint-yaml:
4343
fi
4444

4545
test:
46+
@mkdir -p static # be sure dir for static files exists
4647
uv run pytest --dead-fixtures
4748
uv run pytest --create-db --exitfirst --numprocesses ${SIMULTANEOUS_TEST_JOBS}
4849

{{ cookiecutter.name }}/pyproject.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ dependencies = [
88
"bcrypt>=4.3.0",
99
"celery==5.4.0",
1010
"django-axes>=7.0.2",
11-
"django-behaviors>=0.5.1",
1211
"django-environ>=0.12.0",
1312
"django-filter>=25.1",
1413
"django-healthchecks>=1.5.0",
@@ -33,10 +32,11 @@ dev = [
3332
"django-stubs>=5.2.0",
3433
"djangorestframework-stubs>=3.16.0",
3534
"dotenv-linter>=0.7.0",
35+
"faker>=37.8.0",
3636
"freezegun>=1.5.1",
3737
"ipython>=9.2.0",
3838
"jedi>=0.19.2",
39-
"mixer>=7.2.2",
39+
"model-bakery>=1.20.5",
4040
"mypy>=1.15.0",
4141
"pymarkdownlnt>=0.9.29",
4242
"pytest-deadfixtures>=2.2.1",
@@ -160,6 +160,9 @@ combine-as-imports = true
160160
known-first-party = ["src"]
161161
lines-after-imports = 2
162162

163+
[tool.ruff.lint.mccabe]
164+
max-complexity = 6
165+
163166
[tool.ruff.lint.per-file-ignores]
164167
"*/factory.py" = [
165168
"ANN", # flake8-annotations
@@ -228,7 +231,6 @@ module = [
228231
"djangorestframework_camel_case.*",
229232
"drf_orjson_renderer.*",
230233
"ipware.*",
231-
"mixer.*",
232234
]
233235
ignore_missing_imports = true
234236

{{ cookiecutter.name }}/src/app/conf/celery.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
CELERY_BROKER_URL = env("CELERY_BROKER_URL", cast=str, default="redis://localhost:6379/0")
66
CELERY_TASK_ALWAYS_EAGER = env("CELERY_TASK_ALWAYS_EAGER", cast=bool, default=env("DEBUG"))
7+
CELERY_TASK_EAGER_PROPAGATES = True
78
CELERY_TIMEZONE = TIME_ZONE
89
CELERY_ENABLE_UTC = False
910
CELERY_TASK_ACKS_LATE = True
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
from django.core.files.uploadedfile import SimpleUploadedFile
2-
from faker import Faker
32

43
from app.testing import register
54
from app.testing.types import FactoryProtocol
65

76

8-
faker = Faker()
9-
10-
117
@register
128
def image(self: FactoryProtocol, name: str = "image.gif", content_type: str = "image/gif") -> SimpleUploadedFile:
13-
return SimpleUploadedFile(name=name, content=faker.image(), content_type=content_type)
9+
return SimpleUploadedFile(name=name, content=self.faker.image(), content_type=content_type)

{{ cookiecutter.name }}/src/app/models.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from collections.abc import Iterable
12
from typing import Any
23

3-
from behaviors.behaviors import Timestamped # type: ignore[import-untyped]
44
from django.contrib.contenttypes.models import ContentType
55
from django.db import models
6+
from django.db.models.base import ModelBase
7+
from django.utils import timezone
68

79

810
__all__ = [
@@ -42,11 +44,30 @@ def get_label(cls) -> str:
4244
return cls._meta.label_lower.split(".")[-1]
4345

4446

45-
class TimestampedModel(DefaultModel, Timestamped):
47+
class TimestampedModel(DefaultModel):
4648
"""
47-
Default app model that has `created` and `updated` attributes.
48-
Currently based on https://github.com/audiolion/django-behaviors
49+
Default app model that has `created` and `modified` attributes.
4950
"""
5051

52+
created = models.DateTimeField(auto_now_add=True)
53+
modified = models.DateTimeField(null=True, blank=True)
54+
5155
class Meta:
5256
abstract = True
57+
58+
def save(
59+
self,
60+
*,
61+
force_insert: bool | tuple[ModelBase, ...] = False,
62+
force_update: bool = False,
63+
using: str | None = None,
64+
update_fields: Iterable[str] | None = None,
65+
) -> None:
66+
if self.pk:
67+
self.modified = timezone.now()
68+
return super().save(
69+
force_insert=force_insert,
70+
force_update=force_update,
71+
using=using,
72+
update_fields=update_fields,
73+
)

{{ cookiecutter.name }}/src/app/testing/factory.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from collections.abc import Callable
22
from functools import partial
33

4-
from app.testing.mixer import mixer
4+
from faker import Faker
5+
from model_bakery import baker
56

67

78
def register(method: Callable) -> Callable:
@@ -31,7 +32,8 @@ def __getattr__(self, name: str) -> Callable:
3132

3233
class FixtureFactory:
3334
def __init__(self) -> None:
34-
self.mixer = mixer
35+
self.baker = baker # imported module
36+
self.faker = Faker()
3537
self.registry = FixtureRegistry()
3638

3739
def __getattr__(self, name: str) -> Callable:

{{ cookiecutter.name }}/src/app/testing/mixer.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

{{ cookiecutter.name }}/src/app/testing/types.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
from types import ModuleType
12
from typing import Protocol
23

3-
from mixer.backend.django import mixer
4+
from faker import Faker
45

56

67
class FactoryProtocol(Protocol):
7-
mixer: mixer
8+
baker: ModuleType
9+
faker: Faker
810

911

1012
__all__ = [

{{ cookiecutter.name }}/src/users/factory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
@register
99
def user(self: FactoryProtocol, **kwargs: dict) -> User:
10-
return self.mixer.blend("users.User", **kwargs)
10+
return self.baker.make("users.User", **kwargs)
1111

1212

1313
@register

0 commit comments

Comments
 (0)