#27996 closed New feature (fixed)
Add pgcrypto extension and GEN_RANDOM_UUID function to contrib.postgres
Reported by: | Paolo Melchiorre | Owned by: | Paolo Melchiorre |
---|---|---|---|
Component: | contrib.postgres | Version: | dev |
Severity: | Normal | Keywords: | uuid extension function random postgresql cryptography |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
After the introduction of the UUID Field in Django 1.8, I believe that django.contrib.postgres could benefit from some custom functions based on the pgcrypto extension of PostgreSQL (see https://www.postgresql.org/docs/9.6/static/pgcrypto.html). That kind of functions would be very helpful for apply a migration that adds a unique non-nullable field to a table with existing rows.
Starting from "Migrations that add unique fields" (see https://docs.djangoproject.com/en/dev/howto/writing-migrations/#migrations-that-add-unique-fields) I speed up the gen_uuid
using GEN_RANDOM_UUID
function changing it from:
import uuid def gen_uuid(apps, schema_editor): MyModel = apps.get_model('myapp', 'MyModel') for row in MyModel.objects.all(): row.uuid = uuid.uuid4() row.save(update_fields=['uuid'])
to
from django.contrib.postgres.functions import RandomUUID def gen_uuid(apps, schema_editor): MyModel = apps.get_model('myapp', 'MyModel') MyModel.objects.update(uuid=RandomUUID())
Using this function on my system the time to migrate more than 10000 objects decreased from
real 0m15.988s user 0m10.680s sys 0m0.508s
to
real 0m2.957s user 0m1.736s sys 0m0.072s
I already implemented a solution for thi feature and I've created a PR
Change History (15)
comment:1 by , 8 years ago
comment:2 by , 8 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:3 by , 8 years ago
Description: | modified (diff) |
---|
comment:4 by , 8 years ago
Has patch: | unset |
---|
comment:5 by , 8 years ago
Description: | modified (diff) |
---|---|
Has patch: | set |
comment:6 by , 8 years ago
Patch needs improvement: | set |
---|
comment:7 by , 8 years ago
Patch needs improvement: | unset |
---|
comment:8 by , 8 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
comment:12 by , 4 years ago
Hi! Today I updated my master and test migrations failed because of https://github.com/django/django/pull/13241 . You checked for is_postgresql_13
even if the connection is not postgresql. It fails with psycopg2 installed but using another db (sqlite in my case).
comment:13 by , 4 years ago
For completeness, here is the stacktrace.
Traceback (most recent call last): File "runtests.py", line 571, in <module> failures = django_tests( File "runtests.py", line 313, in django_tests failures = test_runner.run_tests( File "django/django/test/runner.py", line 707, in run_tests old_config = self.setup_databases(aliases=databases) File "django/django/test/runner.py", line 626, in setup_databases return _setup_databases( File "django/django/test/utils.py", line 170, in setup_databases connection.creation.create_test_db( File "django/django/db/backends/base/creation.py", line 65, in create_test_db call_command( File "django/django/core/management/__init__.py", line 168, in call_command return command.execute(*args, **defaults) File "django/django/core/management/base.py", line 394, in execute output = self.handle(*args, **options) File "django/django/core/management/base.py", line 89, in wrapped res = handle_func(*args, **kwargs) File "django/django/core/management/commands/migrate.py", line 92, in handle executor = MigrationExecutor(connection, self.migration_progress_callback) File "django/django/db/migrations/executor.py", line 18, in __init__ self.loader = MigrationLoader(self.connection) File "django/django/db/migrations/loader.py", line 53, in __init__ self.build_graph() File "django/django/db/migrations/loader.py", line 210, in build_graph self.load_disk() File "django/django/db/migrations/loader.py", line 112, in load_disk migration_module = import_module(migration_path) File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1014, in _gcd_import File "<frozen importlib._bootstrap>", line 991, in _find_and_load File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 671, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 783, in exec_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "django/tests/postgres_tests/migrations/0001_setup_extensions.py", line 22, in <module> needs_crypto_extension = not connection.features.is_postgresql_13 AttributeError: 'DatabaseFeatures' object has no attribute 'is_postgresql_13'
I just submitted a full featured pull request on ghithub https://github.com/django/django/pull/8265