Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/django-extensions/django-ex…
Browse files Browse the repository at this point in the history
…tensions

Conflicts:
	django_extensions/db/models.py
  • Loading branch information
tehfink committed Apr 22, 2011
2 parents 7fa216b + 8d36f71 commit 5632a00
Show file tree
Hide file tree
Showing 100 changed files with 2,627 additions and 718 deletions.
8 changes: 8 additions & 0 deletions .tx/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[django-extensions.master]
file_filter = django_extensions/locale/<lang>/LC_MESSAGES/django.po
source_file = django_extensions/locale/en/LC_MESSAGES/django.po
source_lang = en

[main]
host = https://www.transifex.net

38 changes: 38 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
===================
Django Extensions
===================

Django Extensions is a collection of custom extensions for the Django Framework.

Getting Started
===============

The easiest way to figure out what Django Extensions are all about is to watch the `excellent screencast by Eric Holscher`__. In a couple minutes Eric walks you through a half a dozen command extensions.

Getting It
==========

You can get Django Extentions by using pip or easy_install::

$ pip install django-extensions
or
$ easy_install django-extensions

If you want to install it from source, grab the git repository from github and run setup.py::

$ git clone git://github.com/django-extensions/django-extensions.git
$ cd django-extensions
$ python setup.py install

For more information look

Documentation
=============

You can view documentation online at::
http://packages.python.org/django-extensions/

Or you can look at the docs/ directory in the repository.

__ http://ericholscher.com/blog/2008/sep/12/screencast-django-command-extensions/

4 changes: 2 additions & 2 deletions django_extensions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

VERSION = (0, "4.2", "pre")
VERSION = (0, 7, 'pre')

# Dynamically calculate the version based on VERSION tuple
if len(VERSION)>2 and VERSION[2] is not None:
if len(VERSION) > 2 and VERSION[2] is not None:
str_version = "%s.%s_%s" % VERSION[:3]
else:
str_version = "%s.%s" % VERSION[:2]
Expand Down
16 changes: 9 additions & 7 deletions django_extensions/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#
# Autocomplete feature for admin panel
# Autocomplete feature for admin panel
#
# Most of the code has been written by Jannis Leidel and was updated a bit
# for django_extensions.
# http://jannisleidel.com/2008/11/autocomplete-form-widget-foreignkey-model-fields/
# Most of the code has been written by Jannis Leidel and was updated a bit
# for django_extensions.
# http://jannisleidel.com/2008/11/autocomplete-form-widget-foreignkey-model-fields/
#
# to_string_function, Satchmo adaptation and some comments added by emes
# (Michal Salaban)
# to_string_function, Satchmo adaptation and some comments added by emes
# (Michal Salaban)
#

import operator
from django.http import HttpResponse, HttpResponseNotFound
from django.db import models
Expand All @@ -20,11 +21,13 @@
from django_extensions.admin.widgets import ForeignKeySearchInput

from django.conf import settings

if 'reversion' in settings.INSTALLED_APPS:
from reversion.admin import VersionAdmin as ModelAdmin
else:
from django.contrib.admin import ModelAdmin


class ForeignKeyAutocompleteAdmin(ModelAdmin):
"""Admin class for models using the autocomplete feature.
Expand Down Expand Up @@ -139,4 +142,3 @@ def formfield_for_dbfield(self, db_field, **kwargs):
kwargs['help_text'] = help_text
return super(ForeignKeyAutocompleteAdmin,
self).formfield_for_dbfield(db_field, **kwargs)

5 changes: 3 additions & 2 deletions django_extensions/admin/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from django.template.loader import render_to_string
from django.contrib.admin.widgets import ForeignKeyRawIdWidget


class ForeignKeySearchInput(ForeignKeyRawIdWidget):
"""
A Widget for displaying ForeignKeys in an autocomplete search input
A Widget for displaying ForeignKeys in an autocomplete search input
instead in a <select> box.
"""
# Set in subclass to render the widget with a different template
Expand Down Expand Up @@ -48,7 +49,7 @@ def render(self, name, value, attrs=None):
url = '?' + '&amp;'.join(['%s=%s' % (k, v) for k, v in params.items()])
else:
url = ''
if not attrs.has_key('class'):
if not 'class' in attrs:
attrs['class'] = 'vForeignKeyRawIdAdminField'
# Call the TextInput render method directly to have more control
output = [forms.TextInput.render(self, name, value, attrs)]
Expand Down
38 changes: 27 additions & 11 deletions django_extensions/db/fields/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
except ImportError:
from django_extensions.utils import uuid


class AutoSlugField(SlugField):
""" AutoSlugField
Expand Down Expand Up @@ -42,7 +43,7 @@ def __init__(self, *args, **kwargs):
raise ValueError("missing 'populate_from' argument")
else:
self._populate_from = populate_from
self.separator = kwargs.pop('separator', u'-')
self.separator = kwargs.pop('separator', u'-')
self.overwrite = kwargs.pop('overwrite', False)
super(AutoSlugField, self).__init__(*args, **kwargs)

Expand Down Expand Up @@ -111,8 +112,8 @@ def create_slug(self, model_instance, add):
slug = original_slug
end = '%s%s' % (self.separator, next)
end_len = len(end)
if slug_len and len(slug)+end_len > slug_len:
slug = slug[:slug_len-end_len]
if slug_len and len(slug) + end_len > slug_len:
slug = slug[:slug_len - end_len]
slug = self._slug_strip(slug)
slug = '%s%s' % (slug, end)
kwargs[self.attname] = slug
Expand All @@ -136,6 +137,7 @@ def south_field_triple(self):
# That's our definition!
return (field_class, args, kwargs)


class CreationDateTimeField(DateTimeField):
""" CreationDateTimeField
Expand All @@ -159,6 +161,7 @@ def south_field_triple(self):
args, kwargs = introspector(self)
return (field_class, args, kwargs)


class ModificationDateTimeField(CreationDateTimeField):
""" ModificationDateTimeField
Expand All @@ -183,9 +186,11 @@ def south_field_triple(self):
args, kwargs = introspector(self)
return (field_class, args, kwargs)


class UUIDVersionError(Exception):
pass


class UUIDField(CharField):
""" UUIDField
Expand All @@ -202,25 +207,36 @@ def __init__(self, verbose_name=None, name=None, auto=True, version=1, node=None
kwargs.setdefault('editable', False)
self.auto = auto
self.version = version
if version==1:
if version == 1:
self.node, self.clock_seq = node, clock_seq
elif version==3 or version==5:
elif version == 3 or version == 5:
self.namespace, self.name = namespace, name
CharField.__init__(self, verbose_name, name, **kwargs)

def get_internal_type(self):
return CharField.__name__

def contribute_to_class(self, cls, name):
if self.primary_key:
assert not cls._meta.has_auto_field, \
"A model can't have more than one AutoField: %s %s %s; have %s" % \
(self, cls, name, cls._meta.auto_field)
super(UUIDField, self).contribute_to_class(cls, name)
cls._meta.has_auto_field = True
cls._meta.auto_field = self
else:
super(UUIDField, self).contribute_to_class(cls, name)

def create_uuid(self):
if not self.version or self.version==4:
if not self.version or self.version == 4:
return uuid.uuid4()
elif self.version==1:
elif self.version == 1:
return uuid.uuid1(self.node, self.clock_seq)
elif self.version==2:
elif self.version == 2:
raise UUIDVersionError("UUID version 2 is not supported.")
elif self.version==3:
elif self.version == 3:
return uuid.uuid3(self.namespace, self.name)
elif self.version==5:
elif self.version == 5:
return uuid.uuid5(self.namespace, self.name)
else:
raise UUIDVersionError("UUID version %s is not valid." % self.version)
Expand All @@ -244,4 +260,4 @@ def south_field_triple(self):
field_class = "django.db.models.fields.CharField"
args, kwargs = introspector(self)
# That's our definition!
return (field_class, args, kwargs)
return (field_class, args, kwargs)
23 changes: 13 additions & 10 deletions django_extensions/db/fields/encrypted.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,54 @@
except ImportError:
raise ImportError('Using an encrypted field requires the Keyczar module. You can obtain Keyczar from http://www.keyczar.org/.')


class BaseEncryptedField(models.Field):
prefix = 'enc_str:::'
def __init__(self, *args, **kwargs):
if not hasattr(settings, 'ENCRYPTED_FIELD_KEYS_DIR'):
raise ImproperlyConfigured('You must set settings.ENCRYPTED_FIELD_KEYS_DIR to your Keyczar keys directory.')
self.crypt = keyczar.Crypter.Read(settings.ENCRYPTED_FIELD_KEYS_DIR)
super(BaseEncryptedField, self).__init__(*args, **kwargs)

def to_python(self, value):
if (value.startswith(self.prefix)):
retval = self.crypt.Decrypt(value[len(self.prefix):])
else:
retval = value

return retval

def get_db_prep_value(self, value):
if not value.startswith(self.prefix):
value = self.prefix + self.crypt.Encrypt(value)
return value


class EncryptedTextField(BaseEncryptedField):
__metaclass__ = models.SubfieldBase

def get_internal_type(self):
def get_internal_type(self):
return 'TextField'

def formfield(self, **kwargs):
defaults = {'widget': forms.Textarea}
defaults.update(kwargs)
return super(EncryptedTextField, self).formfield(**defaults)


class EncryptedCharField(BaseEncryptedField):
__metaclass__ = models.SubfieldBase

def __init__(self, max_length=None, *args, **kwargs):
if max_length:
max_length += len(self.prefix)

super(EncryptedCharField, self).__init__(max_length=max_length, *args, **kwargs)

def get_internal_type(self):
return "CharField"

def formfield(self, **kwargs):
defaults = {'max_length': self.max_length}
defaults.update(kwargs)
return super(EncryptedCharField, self).formfield(**defaults)
return super(EncryptedCharField, self).formfield(**defaults)
19 changes: 17 additions & 2 deletions django_extensions/db/fields/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class LOL(models.Model):
from django.utils import simplejson
from django.utils.encoding import smart_unicode


class JSONEncoder(simplejson.JSONEncoder):
def default(self, obj):
if isinstance(obj, Decimal):
Expand All @@ -26,18 +27,22 @@ def default(self, obj):
return obj.strftime('%Y-%m-%dT%H:%M:%SZ')
return simplejson.JSONEncoder.default(self, obj)


def dumps(value):
assert isinstance(value, dict)
return JSONEncoder().encode(value)


def loads(txt):
value = simplejson.loads(
txt,
parse_float = Decimal,
encoding = settings.DEFAULT_CHARSET)
parse_float=Decimal,
encoding=settings.DEFAULT_CHARSET
)
assert isinstance(value, dict)
return value


class JSONDict(dict):
"""
Hack so repr() called by dumpdata will output JSON instead of
Expand All @@ -46,6 +51,7 @@ class JSONDict(dict):
def __repr__(self):
return dumps(self)


class JSONField(models.TextField):
"""JSONField is a generic textfield that neatly serializes/unserializes
JSON objects seamlessly. Main thingy must be a dict object."""
Expand Down Expand Up @@ -75,3 +81,12 @@ def get_db_prep_save(self, value):
return super(JSONField, self).get_db_prep_save("")
else:
return super(JSONField, self).get_db_prep_save(dumps(value))

def south_field_triple(self):
"Returns a suitable description of this field for South."
# We'll just introspect the _actual_ field.
from south.modelsinspector import introspector
field_class = "django.db.models.fields.TextField"
args, kwargs = introspector(self)
# That's our definition!
return (field_class, args, kwargs)
4 changes: 4 additions & 0 deletions django_extensions/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django_extensions.db.fields import (ModificationDateTimeField,
CreationDateTimeField, AutoSlugField)


class TimeStampedModel(models.Model):
""" TimeStampedModel
An abstract base class model that provides self-managed "created" and
Expand All @@ -18,6 +19,7 @@ class TimeStampedModel(models.Model):
class Meta:
abstract = True


class TitleSlugDescriptionModel(models.Model):
""" TitleSlugDescriptionModel
An abstract base class model that provides title and description fields
Expand All @@ -30,6 +32,7 @@ class TitleSlugDescriptionModel(models.Model):
class Meta:
abstract = True


class ActivatorModelManager(models.Manager):
""" ActivatorModelManager
Manager to return instances of ActivatorModel: SomeModel.objects.active() / .inactive()
Expand All @@ -42,6 +45,7 @@ def inactive(self):
""" Returns inactive instances of ActivatorModel: SomeModel.objects.inactive() """
return super(ActivatorModelManager, self).get_query_set().filter(status=0)


class ActivatorModel(models.Model):
""" ActivatorModel
An abstract base class model that provides activate and deactivate fields.
Expand Down
Loading

0 comments on commit 5632a00

Please sign in to comment.