diff --git a/{{ cookiecutter.name }}/pyproject.toml b/{{ cookiecutter.name }}/pyproject.toml index ef41d4e6..6bb43731 100644 --- a/{{ cookiecutter.name }}/pyproject.toml +++ b/{{ cookiecutter.name }}/pyproject.toml @@ -8,7 +8,6 @@ dependencies = [ "bcrypt>=4.3.0", "celery==5.4.0", "django-axes>=7.0.2", - "django-behaviors>=0.5.1", "django-environ>=0.12.0", "django-filter>=25.1", "django-healthchecks>=1.5.0", diff --git a/{{ cookiecutter.name }}/src/app/models.py b/{{ cookiecutter.name }}/src/app/models.py index 27a21491..6b8653ff 100644 --- a/{{ cookiecutter.name }}/src/app/models.py +++ b/{{ cookiecutter.name }}/src/app/models.py @@ -1,8 +1,10 @@ +from collections.abc import Iterable from typing import Any -from behaviors.behaviors import Timestamped # type: ignore[import-untyped] from django.contrib.contenttypes.models import ContentType from django.db import models +from django.db.models.base import ModelBase +from django.utils import timezone __all__ = [ @@ -42,11 +44,30 @@ def get_label(cls) -> str: return cls._meta.label_lower.split(".")[-1] -class TimestampedModel(DefaultModel, Timestamped): +class TimestampedModel(DefaultModel): """ - Default app model that has `created` and `updated` attributes. - Currently based on https://github.com/audiolion/django-behaviors + Default app model that has `created` and `modified` attributes. """ + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(null=True, blank=True) + class Meta: abstract = True + + def save( + self, + *, + force_insert: bool | tuple[ModelBase, ...] = False, + force_update: bool = False, + using: str | None = None, + update_fields: Iterable[str] | None = None, + ) -> None: + if self.pk: + self.modified = timezone.now() + return super().save( + force_insert=force_insert, + force_update=force_update, + using=using, + update_fields=update_fields, + ) diff --git a/{{ cookiecutter.name }}/uv.lock b/{{ cookiecutter.name }}/uv.lock index df40274c..65bfcb73 100644 --- a/{{ cookiecutter.name }}/uv.lock +++ b/{{ cookiecutter.name }}/uv.lock @@ -327,15 +327,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/f1/cfd83b1650a58b6c97b4c484ae8dbd489eefbf9d4385206a9e854bff37ec/django_axes-7.0.2-py3-none-any.whl", hash = "sha256:893dacce259d39e8cbcff655c61a008b3b827797c2f733f64fd9baf6bc7256e9", size = 68863, upload-time = "2025-02-19T17:54:13.581Z" }, ] -[[package]] -name = "django-behaviors" -version = "0.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e6/73/72dd3307fe51c7da27650693d09351b0474f193315ce82797dccf86de34b/django-behaviors-0.5.1.tar.gz", hash = "sha256:75e6828573c25ffa71c8ce6c568d294fc659b3b6d572507b012ce70fbb27aaff", size = 27185, upload-time = "2020-09-19T13:20:41.56Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/fc/6c99ee8f4fbd09cd7484bb146f9b9ab3bb5bd2c69cffa0b0fb21b9b98e5e/django_behaviors-0.5.1-py2.py3-none-any.whl", hash = "sha256:1ac2ec9c9e919ca4b962f9dee861a53f5af27749c8d13a21077b5a61fb879501", size = 20583, upload-time = "2020-09-19T13:20:39.4Z" }, -] - [[package]] name = "django-environ" version = "0.12.0" @@ -847,107 +838,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, ] -[[package]] -name = "{{ cookiecutter.name }}" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "bcrypt" }, - { name = "celery" }, - { name = "django" }, - { name = "django-axes" }, - { name = "django-behaviors" }, - { name = "django-environ" }, - { name = "django-filter" }, - { name = "django-healthchecks" }, - { name = "django-ipware" }, - { name = "django-split-settings" }, - { name = "django-storages" }, - { name = "djangorestframework" }, - { name = "djangorestframework-camel-case" }, - { name = "djangorestframework-simplejwt", extra = ["crypto"] }, - { name = "drf-orjson-renderer" }, - { name = "drf-spectacular", extra = ["sidecar"] }, - { name = "pillow" }, - { name = "psycopg", extra = ["binary"] }, - { name = "redis" }, - { name = "sentry-sdk" }, - { name = "whitenoise" }, -] - -[package.dev-dependencies] -dev = [ - { name = "django-stubs" }, - { name = "djangorestframework-stubs" }, - { name = "dotenv-linter" }, - { name = "freezegun" }, - { name = "ipython" }, - { name = "jedi" }, - { name = "mixer" }, - { name = "mypy" }, - { name = "pymarkdownlnt" }, - { name = "pytest-deadfixtures" }, - { name = "pytest-django" }, - { name = "pytest-env" }, - { name = "pytest-freezer" }, - { name = "pytest-mock" }, - { name = "pytest-randomly" }, - { name = "pytest-xdist" }, - { name = "ruff" }, - { name = "toml-sort" }, - { name = "types-freezegun" }, - { name = "types-pillow" }, -] - -[package.metadata] -requires-dist = [ - { name = "bcrypt", specifier = ">=4.3.0" }, - { name = "celery", specifier = "==5.4.0" }, - { name = "django", specifier = ">=5.2,<6.0" }, - { name = "django-axes", specifier = ">=7.0.2" }, - { name = "django-behaviors", specifier = ">=0.5.1" }, - { name = "django-environ", specifier = ">=0.12.0" }, - { name = "django-filter", specifier = ">=25.1" }, - { name = "django-healthchecks", specifier = ">=1.5.0" }, - { name = "django-ipware", specifier = ">=7.0.1" }, - { name = "django-split-settings", specifier = ">=1.3.2" }, - { name = "django-storages", specifier = ">=1.14.6" }, - { name = "djangorestframework", specifier = ">=3.15.2" }, - { name = "djangorestframework-camel-case", specifier = ">=1.4.2" }, - { name = "djangorestframework-simplejwt", extras = ["crypto"], specifier = ">=5.5.0" }, - { name = "drf-orjson-renderer", specifier = ">=1.7.3" }, - { name = "drf-spectacular", extras = ["sidecar"], specifier = ">=0.28.0" }, - { name = "pillow", specifier = ">=11.2.1" }, - { name = "psycopg", extras = ["binary"], specifier = ">=3.2.6" }, - { name = "redis", specifier = ">=5.2.1" }, - { name = "sentry-sdk", specifier = ">=2.27.0" }, - { name = "whitenoise", specifier = ">=6.9.0" }, -] - -[package.metadata.requires-dev] -dev = [ - { name = "django-stubs", specifier = ">=5.2.0" }, - { name = "djangorestframework-stubs", specifier = ">=3.16.0" }, - { name = "dotenv-linter", specifier = ">=0.7.0" }, - { name = "freezegun", specifier = ">=1.5.1" }, - { name = "ipython", specifier = ">=9.2.0" }, - { name = "jedi", specifier = ">=0.19.2" }, - { name = "mixer", specifier = ">=7.2.2" }, - { name = "mypy", specifier = ">=1.15.0" }, - { name = "pymarkdownlnt", specifier = ">=0.9.29" }, - { name = "pytest-deadfixtures", specifier = ">=2.2.1" }, - { name = "pytest-django", specifier = ">=4.11.1" }, - { name = "pytest-env", specifier = ">=1.1.5" }, - { name = "pytest-freezer", specifier = ">=0.4.9" }, - { name = "pytest-mock", specifier = ">=3.14.0" }, - { name = "pytest-randomly", specifier = ">=3.16.0" }, - { name = "pytest-xdist", specifier = ">=3.6.1" }, - { name = "ruff", specifier = ">=0.11.7" }, - { name = "toml-sort", specifier = ">=0.24.2" }, - { name = "types-freezegun", specifier = ">=1.1.10" }, - { name = "types-pillow", specifier = ">=10.2.0.20240822" }, -] - [[package]] name = "prompt-toolkit" version = "3.0.51" @@ -1323,6 +1213,105 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, ] +[[package]] +name = "{{ cookiecutter.name }}" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "bcrypt" }, + { name = "celery" }, + { name = "django" }, + { name = "django-axes" }, + { name = "django-environ" }, + { name = "django-filter" }, + { name = "django-healthchecks" }, + { name = "django-ipware" }, + { name = "django-split-settings" }, + { name = "django-storages" }, + { name = "djangorestframework" }, + { name = "djangorestframework-camel-case" }, + { name = "djangorestframework-simplejwt", extra = ["crypto"] }, + { name = "drf-orjson-renderer" }, + { name = "drf-spectacular", extra = ["sidecar"] }, + { name = "pillow" }, + { name = "psycopg", extra = ["binary"] }, + { name = "redis" }, + { name = "sentry-sdk" }, + { name = "whitenoise" }, +] + +[package.dev-dependencies] +dev = [ + { name = "django-stubs" }, + { name = "djangorestframework-stubs" }, + { name = "dotenv-linter" }, + { name = "freezegun" }, + { name = "ipython" }, + { name = "jedi" }, + { name = "mixer" }, + { name = "mypy" }, + { name = "pymarkdownlnt" }, + { name = "pytest-deadfixtures" }, + { name = "pytest-django" }, + { name = "pytest-env" }, + { name = "pytest-freezer" }, + { name = "pytest-mock" }, + { name = "pytest-randomly" }, + { name = "pytest-xdist" }, + { name = "ruff" }, + { name = "toml-sort" }, + { name = "types-freezegun" }, + { name = "types-pillow" }, +] + +[package.metadata] +requires-dist = [ + { name = "bcrypt", specifier = ">=4.3.0" }, + { name = "celery", specifier = "==5.4.0" }, + { name = "django", specifier = ">=5.2,<6.0" }, + { name = "django-axes", specifier = ">=7.0.2" }, + { name = "django-environ", specifier = ">=0.12.0" }, + { name = "django-filter", specifier = ">=25.1" }, + { name = "django-healthchecks", specifier = ">=1.5.0" }, + { name = "django-ipware", specifier = ">=7.0.1" }, + { name = "django-split-settings", specifier = ">=1.3.2" }, + { name = "django-storages", specifier = ">=1.14.6" }, + { name = "djangorestframework", specifier = ">=3.15.2" }, + { name = "djangorestframework-camel-case", specifier = ">=1.4.2" }, + { name = "djangorestframework-simplejwt", extras = ["crypto"], specifier = ">=5.5.0" }, + { name = "drf-orjson-renderer", specifier = ">=1.7.3" }, + { name = "drf-spectacular", extras = ["sidecar"], specifier = ">=0.28.0" }, + { name = "pillow", specifier = ">=11.2.1" }, + { name = "psycopg", extras = ["binary"], specifier = ">=3.2.6" }, + { name = "redis", specifier = ">=5.2.1" }, + { name = "sentry-sdk", specifier = ">=2.27.0" }, + { name = "whitenoise", specifier = ">=6.9.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "django-stubs", specifier = ">=5.2.0" }, + { name = "djangorestframework-stubs", specifier = ">=3.16.0" }, + { name = "dotenv-linter", specifier = ">=0.7.0" }, + { name = "freezegun", specifier = ">=1.5.1" }, + { name = "ipython", specifier = ">=9.2.0" }, + { name = "jedi", specifier = ">=0.19.2" }, + { name = "mixer", specifier = ">=7.2.2" }, + { name = "mypy", specifier = ">=1.15.0" }, + { name = "pymarkdownlnt", specifier = ">=0.9.29" }, + { name = "pytest-deadfixtures", specifier = ">=2.2.1" }, + { name = "pytest-django", specifier = ">=4.11.1" }, + { name = "pytest-env", specifier = ">=1.1.5" }, + { name = "pytest-freezer", specifier = ">=0.4.9" }, + { name = "pytest-mock", specifier = ">=3.14.0" }, + { name = "pytest-randomly", specifier = ">=3.16.0" }, + { name = "pytest-xdist", specifier = ">=3.6.1" }, + { name = "ruff", specifier = ">=0.11.7" }, + { name = "toml-sort", specifier = ">=0.24.2" }, + { name = "types-freezegun", specifier = ">=1.1.10" }, + { name = "types-pillow", specifier = ">=10.2.0.20240822" }, +] + [[package]] name = "toml-sort" version = "0.24.2"