From 726fea8fc4ad6146ed711d580323e8c9b47d7341 Mon Sep 17 00:00:00 2001 From: Derrick Petzold Date: Sat, 30 May 2015 12:33:20 -0700 Subject: [PATCH 1/2] RandomCharField - set db_index default to False This is a saner setting as fields with a short length have higher chance of exhausting the avalible permutations. --- django_extensions/db/fields/__init__.py | 15 +++++++++++---- docs/field_extensions.rst | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/django_extensions/db/fields/__init__.py b/django_extensions/db/fields/__init__.py index a644d40a2..3cb03b795 100644 --- a/django_extensions/db/fields/__init__.py +++ b/django_extensions/db/fields/__init__.py @@ -214,7 +214,7 @@ def deconstruct(self): class RandomCharField(UniqueFieldMixin, CharField): """ RandomCharField - By default, sets editable=False, blank=True. + By default, sets editable=False, blank=True, db_index=False. Required arguments: @@ -223,6 +223,9 @@ class RandomCharField(UniqueFieldMixin, CharField): Optional arguments: + db_index + If set to True, duplicate entries are not allowed (default: False) + lowercase If set to True, lowercase the alpha characters (default: False) @@ -253,9 +256,9 @@ def __init__(self, *args, **kwargs): self.include_punctuation = kwargs.pop('include_punctuation', False) self.check_is_bool('include_punctuation') - # Set db_index=True unless it's been set manually. + # Set db_index=False unless it's been set manually. if 'db_index' not in kwargs: - kwargs['db_index'] = True + kwargs['db_index'] = False super(RandomCharField, self).__init__(*args, **kwargs) @@ -282,10 +285,14 @@ def pre_save(self, model_instance, add): if self.include_punctuation: population += string.punctuation + random_chars = self.random_char_generator(population) + if not self.db_index: + return random_chars + return super(RandomCharField, self).find_unique( model_instance, model_instance._meta.get_field(self.attname), - self.random_char_generator(population), + random_chars, ) def internal_type(self): diff --git a/docs/field_extensions.rst b/docs/field_extensions.rst index 224a1f438..6b4795523 100644 --- a/docs/field_extensions.rst +++ b/docs/field_extensions.rst @@ -17,7 +17,7 @@ Current Database Model Field Extensions a length of 8 thats yields 3.4 million possible combinations. A 12 character field would yield about 2 billion. Below are some examples:: - >>> RandomCharField(length=8) + >>> RandomCharField(length=8, db_index=True) BVm9GEaE >>> RandomCharField(length=4, include_alpha=False) From d4db4ba6d9138932aed366f9232ba328f62b369c Mon Sep 17 00:00:00 2001 From: Derrick Petzold Date: Sat, 30 May 2015 13:55:01 -0700 Subject: [PATCH 2/2] RandomCharField - Updated to use django.utils.crypto.get_random_string. --- django_extensions/db/fields/__init__.py | 7 +++---- tests/test_randomchar_field.py | 2 +- tests/testapp/models.py | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/django_extensions/db/fields/__init__.py b/django_extensions/db/fields/__init__.py index 3cb03b795..610ca3e54 100644 --- a/django_extensions/db/fields/__init__.py +++ b/django_extensions/db/fields/__init__.py @@ -1,7 +1,6 @@ """ Django Extensions additional model fields """ -import random import re import six import string @@ -20,8 +19,9 @@ HAS_SHORT_UUID = False from django.core.exceptions import ImproperlyConfigured -from django.template.defaultfilters import slugify from django.db.models import DateTimeField, CharField, SlugField +from django.utils.crypto import get_random_string +from django.template.defaultfilters import slugify try: from django.utils.timezone import now as datetime_now @@ -37,7 +37,6 @@ MAX_UNIQUE_QUERY_ATTEMPTS = 100 -random_sample = random.SystemRandom().sample class UniqueFieldMixin(object): @@ -264,7 +263,7 @@ def __init__(self, *args, **kwargs): def random_char_generator(self, chars): for i in range(100): - yield ''.join(random_sample(chars, self.length)) + yield ''.join(get_random_string(self.length, chars)) raise RuntimeError('max random character attempts exceeded (%s)' % MAX_UNIQUE_QUERY_ATTEMPTS) diff --git a/tests/test_randomchar_field.py b/tests/test_randomchar_field.py index d5c74d132..dbdac4a21 100644 --- a/tests/test_randomchar_field.py +++ b/tests/test_randomchar_field.py @@ -68,7 +68,7 @@ def testRandomCharTestModelDuplicate(self): assert m.random_char_field == 'aaa' def testRandomCharTestModelAsserts(self): - with mock.patch('django_extensions.db.fields.random_sample') as mock_sample: + with mock.patch('django_extensions.db.fields.get_random_string') as mock_sample: mock_sample.return_value = 'aaa' m = RandomCharTestModel() m.save() diff --git a/tests/testapp/models.py b/tests/testapp/models.py index fdfc071cf..281bada93 100644 --- a/tests/testapp/models.py +++ b/tests/testapp/models.py @@ -129,7 +129,7 @@ class Meta: class RandomCharTestModel(models.Model): - random_char_field = RandomCharField(length=8) + random_char_field = RandomCharField(length=8, db_index=True) class Meta: app_label = 'django_extensions'