Kaydet (Commit) fcb5dbfe authored tarafından Paolo Melchiorre's avatar Paolo Melchiorre Kaydeden (comit) Tim Graham

Fixed #27996 -- Added RandomUUID function and CryptoExtension to contrib.postgres.

üst 98ee57e3
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): ...@@ -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 ...@@ -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;``. ...@@ -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 ...@@ -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 ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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)
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): ...@@ -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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment