diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 81345e8c..ec7c2d82 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -66,7 +66,7 @@ jobs: TOXENV: py-django${{ matrix.django }} rest: - name: Integration/Coverage/Docs/Codestyle + name: ${{ matrix.toxenv }} runs-on: blacksmith-4vcpu-ubuntu-2204 strategy: matrix: diff --git a/django_celery_results/apps.py b/django_celery_results/apps.py index f24b0fa6..41083198 100644 --- a/django_celery_results/apps.py +++ b/django_celery_results/apps.py @@ -5,6 +5,8 @@ __all__ = ['CeleryResultConfig'] +from django_celery_results.conf import app_settings + class CeleryResultConfig(AppConfig): """Default configuration for the django_celery_results app.""" @@ -12,4 +14,4 @@ class CeleryResultConfig(AppConfig): name = 'django_celery_results' label = 'django_celery_results' verbose_name = _('Celery Results') - default_auto_field = 'django.db.models.AutoField' + default_auto_field = app_settings.DJANGO_CELERY_RESULTS_DEFAULT_AUTO_FIELD diff --git a/django_celery_results/conf.py b/django_celery_results/conf.py new file mode 100644 index 00000000..e44d905e --- /dev/null +++ b/django_celery_results/conf.py @@ -0,0 +1,43 @@ +"""Application settings.""" +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any + +from django.conf import settings as django_settings + +# All attributes accessed with this prefix are possible +# to overwrite through django.conf.settings. +SETTINGS_PREFIX = "DJANGO_CELERY_RESULTS_" + + +@dataclass(frozen=True) +class AppSettings: + """Proxy class to encapsulate all the app settings. + + This instance should be accessed via the singleton + ``django_celery_results.conf.app_settings``. + + You shouldn't have to set any of these yourself, the class checks a Django + settings with the same name and use these if defined, defaulting to the + values documented here. + """ + + DJANGO_CELERY_RESULTS_DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + + def __getattribute__(self, __name: str) -> Any: + """Check if a Django project settings should override the app default. + + In order to avoid returning any random properties of the Django + settings, we first inspect the prefix. + """ + if ( + __name.startswith(SETTINGS_PREFIX) + and hasattr(django_settings, __name) + ): + return getattr(django_settings, __name) + + return super().__getattribute__(__name) + + +app_settings = AppSettings() diff --git a/django_celery_results/migrations/0001_initial.py b/django_celery_results/migrations/0001_initial.py index 91599f96..4d927a79 100644 --- a/django_celery_results/migrations/0001_initial.py +++ b/django_celery_results/migrations/0001_initial.py @@ -1,5 +1,11 @@ from django.conf import settings from django.db import migrations, models +from django.utils.module_loading import import_string + +from django_celery_results.conf import app_settings + +auto_field_class = import_string( + app_settings.DJANGO_CELERY_RESULTS_DEFAULT_AUTO_FIELD) class Migration(migrations.Migration): @@ -13,7 +19,7 @@ class Migration(migrations.Migration): migrations.CreateModel( name='TaskResult', fields=[ - ('id', models.AutoField(auto_created=True, + ('id', auto_field_class(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), diff --git a/django_celery_results/migrations/0008_chordcounter.py b/django_celery_results/migrations/0008_chordcounter.py index 0e64adfe..596dfa5b 100644 --- a/django_celery_results/migrations/0008_chordcounter.py +++ b/django_celery_results/migrations/0008_chordcounter.py @@ -2,6 +2,12 @@ from django.conf import settings from django.db import migrations, models +from django.utils.module_loading import import_string + +from django_celery_results.conf import app_settings + +auto_field_class = import_string( + app_settings.DJANGO_CELERY_RESULTS_DEFAULT_AUTO_FIELD) class Migration(migrations.Migration): @@ -14,7 +20,7 @@ class Migration(migrations.Migration): migrations.CreateModel( name='ChordCounter', fields=[ - ('id', models.AutoField( + ('id', auto_field_class( auto_created=True, primary_key=True, serialize=False, diff --git a/django_celery_results/migrations/0009_groupresult.py b/django_celery_results/migrations/0009_groupresult.py index 7c14608c..e149a576 100644 --- a/django_celery_results/migrations/0009_groupresult.py +++ b/django_celery_results/migrations/0009_groupresult.py @@ -1,6 +1,12 @@ # Generated by Django 3.2 on 2021-04-19 14:55 from django.conf import settings from django.db import migrations, models +from django.utils.module_loading import import_string + +from django_celery_results.conf import app_settings + +auto_field_class = import_string( + app_settings.DJANGO_CELERY_RESULTS_DEFAULT_AUTO_FIELD) class FakeAddIndex(migrations.AddIndex): @@ -28,7 +34,7 @@ class Migration(migrations.Migration): migrations.CreateModel( name='GroupResult', fields=[ - ('id', models.AutoField( + ('id', auto_field_class( auto_created=True, primary_key=True, serialize=False, diff --git a/docs/configuration.rst b/docs/configuration.rst new file mode 100644 index 00000000..8e642525 --- /dev/null +++ b/docs/configuration.rst @@ -0,0 +1,19 @@ +Configuration +============= + +These are the available settings that can be configured in your Django +project's settings module by defining a setting with the same name. + +* ``DJANGO_CELERY_RESULTS_DEFAULT_AUTO_FIELD``: The ``default_auto_field`` used + when first deploying the app, defaults to ``django.db.models.BigAutoField`` + if unspecified. + + This is only used for the first deployment and + and has no effect if changed after this point. If you want to change its + value after the initial deployment, you should migrate back to zero and + re-apply migrations again:: + + $ python manage.py migrate django_celery_results zero + $ python manage.py migrate django_celery_results + + This will drop and recreate all tables used by django-celery-results. diff --git a/docs/index.rst b/docs/index.rst index ad00baf2..e203fac2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,6 +12,7 @@ Contents getting_started injecting_metadata + configuration copyright .. toctree:: diff --git a/setup.cfg b/setup.cfg index 26f1ac65..bef5e063 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,7 +9,7 @@ markers = [flake8] # classes can be lowercase, arguments and variables can be uppercase # whenever it makes the code more readable. -ignore = N806, N802, N801, N803 +ignore = N806, N802, N801, N803, W503 [pep257] convention=google diff --git a/t/proj/settings.py b/t/proj/settings.py index 227d5976..d0758c31 100644 --- a/t/proj/settings.py +++ b/t/proj/settings.py @@ -172,6 +172,7 @@ USE_TZ = True DJANGO_CELERY_RESULTS_TASK_ID_MAX_LENGTH = 191 +DJANGO_CELERY_RESULTS_DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # Static files (CSS, JavaScript, Images) diff --git a/t/unit/test_models.py b/t/unit/test_models.py index e655f4ce..3f0c1476 100644 --- a/t/unit/test_models.py +++ b/t/unit/test_models.py @@ -64,6 +64,11 @@ def test_taskmeta(self, ctype='application/json', cenc='utf-8'): ) assert m1 not in TaskResult.objects.all() + def test_task_result_pk_use_big_auto_field(self): + task_result = TaskResult.objects.create( + pk=5_000_000_000, task_id=uuid()) + assert task_result.pk is not None + def test_store_result(self, ctype='application/json', cenc='utf-8'): """ Test the `using` argument.