Fixed #27996 -- Added RandomUUID function and CryptoExtension to contrib.postgres.
This commit is contained in:
parent
98ee57e343
commit
fcb5dbfec0
|
@ -1,4 +1,13 @@
|
||||||
from django.db.models import DateTimeField, Func
|
from django.db.models import DateTimeField, Func, UUIDField
|
||||||
|
|
||||||
|
|
||||||
|
class RandomUUID(Func):
|
||||||
|
template = 'GEN_RANDOM_UUID()'
|
||||||
|
|
||||||
|
def __init__(self, output_field=None, **extra):
|
||||||
|
if output_field is None:
|
||||||
|
output_field = UUIDField()
|
||||||
|
super().__init__(output_field=output_field, **extra)
|
||||||
|
|
||||||
|
|
||||||
class TransactionNow(Func):
|
class TransactionNow(Func):
|
||||||
|
|
|
@ -35,6 +35,12 @@ class CITextExtension(CreateExtension):
|
||||||
self.name = 'citext'
|
self.name = 'citext'
|
||||||
|
|
||||||
|
|
||||||
|
class CryptoExtension(CreateExtension):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.name = 'pgcrypto'
|
||||||
|
|
||||||
|
|
||||||
class HStoreExtension(CreateExtension):
|
class HStoreExtension(CreateExtension):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
@ -7,6 +7,26 @@ All of these functions are available from the
|
||||||
|
|
||||||
.. currentmodule:: django.contrib.postgres.functions
|
.. currentmodule:: django.contrib.postgres.functions
|
||||||
|
|
||||||
|
``RandomUUID``
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. class:: RandomUUID()
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
Returns a version 4 UUID.
|
||||||
|
|
||||||
|
The `pgcrypto extension`_ must be installed. You can use the
|
||||||
|
:class:`~django.contrib.postgres.operations.CryptoExtension` migration
|
||||||
|
operation to install it.
|
||||||
|
|
||||||
|
.. _pgcrypto extension: https://www.postgresql.org/docs/current/static/pgcrypto.html
|
||||||
|
|
||||||
|
Usage example::
|
||||||
|
|
||||||
|
>>> from django.contrib.postgres.functions import RandomUUID
|
||||||
|
>>> Article.objects.update(uuid=RandomUUID())
|
||||||
|
|
||||||
``TransactionNow``
|
``TransactionNow``
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,15 @@ run the query ``CREATE EXTENSION IF NOT EXISTS hstore;``.
|
||||||
|
|
||||||
Installs the ``citext`` extension.
|
Installs the ``citext`` extension.
|
||||||
|
|
||||||
|
``CryptoExtension``
|
||||||
|
===================
|
||||||
|
|
||||||
|
.. class:: CryptoExtension()
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
Installs the ``pgcrypto`` extension.
|
||||||
|
|
||||||
``HStoreExtension``
|
``HStoreExtension``
|
||||||
===================
|
===================
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,12 @@ Minor features
|
||||||
:class:`~django.contrib.postgres.aggregates.ArrayAgg` determines if
|
:class:`~django.contrib.postgres.aggregates.ArrayAgg` determines if
|
||||||
concatenated values will be distinct.
|
concatenated values will be distinct.
|
||||||
|
|
||||||
|
* The new :class:`~django.contrib.postgres.functions.RandomUUID` database
|
||||||
|
function returns a version 4 UUID. It requires use of PostgreSQL's
|
||||||
|
``pgcrypto`` extension which can be activated using the new
|
||||||
|
:class:`~django.contrib.postgres.operations.CryptoExtension` migration
|
||||||
|
operation.
|
||||||
|
|
||||||
:mod:`django.contrib.redirects`
|
:mod:`django.contrib.redirects`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,14 @@ from django.db import migrations
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from django.contrib.postgres.operations import (
|
from django.contrib.postgres.operations import (
|
||||||
BtreeGinExtension, CITextExtension, CreateExtension, HStoreExtension,
|
BtreeGinExtension, CITextExtension, CreateExtension, CryptoExtension,
|
||||||
TrigramExtension, UnaccentExtension,
|
HStoreExtension, TrigramExtension, UnaccentExtension,
|
||||||
)
|
)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
BtreeGinExtension = mock.Mock()
|
BtreeGinExtension = mock.Mock()
|
||||||
CITextExtension = mock.Mock()
|
CITextExtension = mock.Mock()
|
||||||
CreateExtension = mock.Mock()
|
CreateExtension = mock.Mock()
|
||||||
|
CryptoExtension = mock.Mock()
|
||||||
HStoreExtension = mock.Mock()
|
HStoreExtension = mock.Mock()
|
||||||
TrigramExtension = mock.Mock()
|
TrigramExtension = mock.Mock()
|
||||||
UnaccentExtension = mock.Mock()
|
UnaccentExtension = mock.Mock()
|
||||||
|
@ -24,6 +25,7 @@ class Migration(migrations.Migration):
|
||||||
# Ensure CreateExtension quotes extension names by creating one with a
|
# Ensure CreateExtension quotes extension names by creating one with a
|
||||||
# dash in its name.
|
# dash in its name.
|
||||||
CreateExtension('uuid-ossp'),
|
CreateExtension('uuid-ossp'),
|
||||||
|
CryptoExtension(),
|
||||||
HStoreExtension(),
|
HStoreExtension(),
|
||||||
TrigramExtension(),
|
TrigramExtension(),
|
||||||
UnaccentExtension(),
|
UnaccentExtension(),
|
||||||
|
|
|
@ -191,6 +191,13 @@ class Migration(migrations.Migration):
|
||||||
('when', models.DateTimeField(null=True, default=None)),
|
('when', models.DateTimeField(null=True, default=None)),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UUIDTestModel',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('uuid', models.UUIDField(default=None, null=True)),
|
||||||
|
]
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='RangesModel',
|
name='RangesModel',
|
||||||
fields=[
|
fields=[
|
||||||
|
|
|
@ -171,3 +171,7 @@ class StatTestModel(models.Model):
|
||||||
|
|
||||||
class NowTestModel(models.Model):
|
class NowTestModel(models.Model):
|
||||||
when = models.DateTimeField(null=True, default=None)
|
when = models.DateTimeField(null=True, default=None)
|
||||||
|
|
||||||
|
|
||||||
|
class UUIDTestModel(models.Model):
|
||||||
|
uuid = models.UUIDField(default=None, null=True)
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
import uuid
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from django.contrib.postgres.functions import TransactionNow
|
from django.contrib.postgres.functions import RandomUUID, TransactionNow
|
||||||
|
|
||||||
from . import PostgreSQLTestCase
|
from . import PostgreSQLTestCase
|
||||||
from .models import NowTestModel
|
from .models import NowTestModel, UUIDTestModel
|
||||||
|
|
||||||
|
|
||||||
class TestTransactionNow(PostgreSQLTestCase):
|
class TestTransactionNow(PostgreSQLTestCase):
|
||||||
|
@ -26,3 +27,15 @@ class TestTransactionNow(PostgreSQLTestCase):
|
||||||
|
|
||||||
self.assertIsInstance(m1.when, datetime)
|
self.assertIsInstance(m1.when, datetime)
|
||||||
self.assertEqual(m1.when, m2.when)
|
self.assertEqual(m1.when, m2.when)
|
||||||
|
|
||||||
|
|
||||||
|
class TestRandomUUID(PostgreSQLTestCase):
|
||||||
|
|
||||||
|
def test_random_uuid(self):
|
||||||
|
m1 = UUIDTestModel.objects.create()
|
||||||
|
m2 = UUIDTestModel.objects.create()
|
||||||
|
UUIDTestModel.objects.update(uuid=RandomUUID())
|
||||||
|
m1.refresh_from_db()
|
||||||
|
m2.refresh_from_db()
|
||||||
|
self.assertIsInstance(m1.uuid, uuid.UUID)
|
||||||
|
self.assertNotEqual(m1.uuid, m2.uuid)
|
||||||
|
|
Loading…
Reference in New Issue