include copy of django_extension, dont install django from git

This commit is contained in:
j 2014-11-20 16:34:55 +00:00
commit 3f7215035a
200 changed files with 14119 additions and 4 deletions

View file

@ -0,0 +1,13 @@
VERSION = (1, 2, 3, 'DEV')
# Dynamically calculate the version based on VERSION tuple
if len(VERSION) > 2 and VERSION[2] is not None:
if isinstance(VERSION[2], int):
str_version = "%s.%s.%s" % VERSION[:3]
else:
str_version = "%s.%s_%s" % VERSION[:3]
else:
str_version = "%s.%s" % VERSION[:2]
__version__ = str_version

View file

@ -0,0 +1,145 @@
#
# 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/
#
# to_string_function, Satchmo adaptation and some comments added by emes
# (Michal Salaban)
#
import six
import operator
from six.moves import reduce
from django.http import HttpResponse, HttpResponseNotFound
from django.db import models
from django.db.models.query import QuerySet
from django.utils.encoding import smart_str
from django.utils.translation import ugettext as _
from django.utils.text import get_text_list
try:
from functools import update_wrapper
assert update_wrapper
except ImportError:
from django.utils.functional import update_wrapper
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
assert ModelAdmin
else:
from django.contrib.admin import ModelAdmin
class ForeignKeyAutocompleteAdmin(ModelAdmin):
"""Admin class for models using the autocomplete feature.
There are two additional fields:
- related_search_fields: defines fields of managed model that
have to be represented by autocomplete input, together with
a list of target model fields that are searched for
input string, e.g.:
related_search_fields = {
'author': ('first_name', 'email'),
}
- related_string_functions: contains optional functions which
take target model instance as only argument and return string
representation. By default __unicode__() method of target
object is used.
"""
related_search_fields = {}
related_string_functions = {}
def get_urls(self):
try:
from django.conf.urls import patterns, url
except ImportError: # django < 1.4
from django.conf.urls.defaults import patterns, url
def wrap(view):
def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
return update_wrapper(wrapper, view)
info = self.model._meta.app_label, self.model._meta.module_name
urlpatterns = patterns('', url(r'foreignkey_autocomplete/$', wrap(self.foreignkey_autocomplete), name='%s_%s_autocomplete' % info))
urlpatterns += super(ForeignKeyAutocompleteAdmin, self).get_urls()
return urlpatterns
def foreignkey_autocomplete(self, request):
"""
Searches in the fields of the given related model and returns the
result as a simple string to be used by the jQuery Autocomplete plugin
"""
query = request.GET.get('q', None)
app_label = request.GET.get('app_label', None)
model_name = request.GET.get('model_name', None)
search_fields = request.GET.get('search_fields', None)
object_pk = request.GET.get('object_pk', None)
try:
to_string_function = self.related_string_functions[model_name]
except KeyError:
to_string_function = lambda x: x.__unicode__()
if search_fields and app_label and model_name and (query or object_pk):
def construct_search(field_name):
# use different lookup methods depending on the notation
if field_name.startswith('^'):
return "%s__istartswith" % field_name[1:]
elif field_name.startswith('='):
return "%s__iexact" % field_name[1:]
elif field_name.startswith('@'):
return "%s__search" % field_name[1:]
else:
return "%s__icontains" % field_name
model = models.get_model(app_label, model_name)
queryset = model._default_manager.all()
data = ''
if query:
for bit in query.split():
or_queries = [models.Q(**{construct_search(smart_str(field_name)): smart_str(bit)}) for field_name in search_fields.split(',')]
other_qs = QuerySet(model)
other_qs.dup_select_related(queryset)
other_qs = other_qs.filter(reduce(operator.or_, or_queries))
queryset = queryset & other_qs
data = ''.join([six.u('%s|%s\n' % (to_string_function(f), f.pk)) for f in queryset])
elif object_pk:
try:
obj = queryset.get(pk=object_pk)
except:
pass
else:
data = to_string_function(obj)
return HttpResponse(data)
return HttpResponseNotFound()
def get_help_text(self, field_name, model_name):
searchable_fields = self.related_search_fields.get(field_name, None)
if searchable_fields:
help_kwargs = {
'model_name': model_name,
'field_list': get_text_list(searchable_fields, _('and')),
}
return _('Use the left field to do %(model_name)s lookups in the fields %(field_list)s.') % help_kwargs
return ''
def formfield_for_dbfield(self, db_field, **kwargs):
"""
Overrides the default widget for Foreignkey fields if they are
specified in the related_search_fields class attribute.
"""
if (isinstance(db_field, models.ForeignKey) and db_field.name in self.related_search_fields):
model_name = db_field.rel.to._meta.object_name
help_text = self.get_help_text(db_field.name, model_name)
if kwargs.get('help_text'):
help_text = six.u('%s %s' % (kwargs['help_text'], help_text))
kwargs['widget'] = ForeignKeySearchInput(db_field.rel, self.related_search_fields[db_field.name])
kwargs['help_text'] = help_text
return super(ForeignKeyAutocompleteAdmin, self).formfield_for_dbfield(db_field, **kwargs)

View file

@ -0,0 +1,94 @@
import six
import django
from django import forms
from django.conf import settings
from django.contrib.admin.sites import site
from django.utils.safestring import mark_safe
if django.get_version() >= "1.4":
from django.utils.text import Truncator
else:
from django.utils.text import truncate_words
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
instead in a <select> box.
"""
# Set in subclass to render the widget with a different template
widget_template = None
# Set this to the patch of the search view
search_path = '../foreignkey_autocomplete/'
def _media(self):
js_files = ['django_extensions/js/jquery.bgiframe.min.js',
'django_extensions/js/jquery.ajaxQueue.js',
'django_extensions/js/jquery.autocomplete.js']
return forms.Media(css={'all': ('django_extensions/css/jquery.autocomplete.css',)},
js=js_files)
media = property(_media)
def label_for_value(self, value):
key = self.rel.get_related_field().name
obj = self.rel.to._default_manager.get(**{key: value})
if django.get_version() >= "1.4":
return Truncator(obj).words(14, truncate='...')
else:
return truncate_words(obj, 14)
def __init__(self, rel, search_fields, attrs=None):
self.search_fields = search_fields
if django.get_version() >= "1.4":
super(ForeignKeySearchInput, self).__init__(rel, site, attrs)
else:
super(ForeignKeySearchInput, self).__init__(rel, attrs)
def render(self, name, value, attrs=None):
if attrs is None:
attrs = {}
#output = [super(ForeignKeySearchInput, self).render(name, value, attrs)]
opts = self.rel.to._meta
app_label = opts.app_label
model_name = opts.object_name.lower()
related_url = '../../../%s/%s/' % (app_label, model_name)
params = self.url_parameters()
if params:
url = '?' + '&amp;'.join(['%s=%s' % (k, v) for k, v in params.items()])
else:
url = ''
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)]
if value:
label = self.label_for_value(value)
else:
label = six.u('')
try:
admin_media_prefix = settings.ADMIN_MEDIA_PREFIX
except AttributeError:
admin_media_prefix = settings.STATIC_URL + "admin/"
context = {
'url': url,
'related_url': related_url,
'admin_media_prefix': admin_media_prefix,
'search_path': self.search_path,
'search_fields': ','.join(self.search_fields),
'model_name': model_name,
'app_label': app_label,
'label': label,
'name': name,
'pre_django_14': (django.VERSION[:2] < (1, 4)),
}
output.append(render_to_string(self.widget_template or (
'django_extensions/widgets/%s/%s/foreignkey_searchinput.html' % (app_label, model_name),
'django_extensions/widgets/%s/foreignkey_searchinput.html' % app_label,
'django_extensions/widgets/foreignkey_searchinput.html',
), context))
output.reverse()
return mark_safe(six.u('').join(output))

View file

@ -0,0 +1,3 @@
from django import forms
# place form definition here

View file

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View file

@ -0,0 +1,6 @@
try:
from django.conf.urls import *
except ImportError: # django < 1.4
from django.conf.urls.defaults import *
# place app url patterns here

View file

@ -0,0 +1 @@
# Create your views here.

View file

@ -0,0 +1,7 @@
from django.core.management.base import {{ base_command }}
class Command({{ base_command }}):
help = "My shiny new management command."
def {{ handle_method }}:
raise NotImplementedError()

View file

@ -0,0 +1,8 @@
from django_extensions.management.jobs import BaseJob
class Job(BaseJob):
help = "My sample job."
def execute(self):
# executing empty sample job
pass

View file

@ -0,0 +1,287 @@
"""
Django Extensions additional model fields
"""
import re
import six
try:
import uuid
HAS_UUID = True
except ImportError:
HAS_UUID = False
from django.core.exceptions import ImproperlyConfigured
from django.template.defaultfilters import slugify
from django.db.models import DateTimeField, CharField, SlugField
try:
from django.utils.timezone import now as datetime_now
assert datetime_now
except ImportError:
import datetime
datetime_now = datetime.datetime.now
try:
from django.utils.encoding import force_unicode # NOQA
except ImportError:
from django.utils.encoding import force_text as force_unicode # NOQA
class AutoSlugField(SlugField):
""" AutoSlugField
By default, sets editable=False, blank=True.
Required arguments:
populate_from
Specifies which field or list of fields the slug is populated from.
Optional arguments:
separator
Defines the used separator (default: '-')
overwrite
If set to True, overwrites the slug on every save (default: False)
Inspired by SmileyChris' Unique Slugify snippet:
http://www.djangosnippets.org/snippets/690/
"""
def __init__(self, *args, **kwargs):
kwargs.setdefault('blank', True)
kwargs.setdefault('editable', False)
populate_from = kwargs.pop('populate_from', None)
if populate_from is None:
raise ValueError("missing 'populate_from' argument")
else:
self._populate_from = populate_from
self.separator = kwargs.pop('separator', six.u('-'))
self.overwrite = kwargs.pop('overwrite', False)
self.allow_duplicates = kwargs.pop('allow_duplicates', False)
super(AutoSlugField, self).__init__(*args, **kwargs)
def _slug_strip(self, value):
"""
Cleans up a slug by removing slug separator characters that occur at
the beginning or end of a slug.
If an alternate separator is used, it will also replace any instances
of the default '-' separator with the new separator.
"""
re_sep = '(?:-|%s)' % re.escape(self.separator)
value = re.sub('%s+' % re_sep, self.separator, value)
return re.sub(r'^%s+|%s+$' % (re_sep, re_sep), '', value)
def get_queryset(self, model_cls, slug_field):
for field, model in model_cls._meta.get_fields_with_model():
if model and field == slug_field:
return model._default_manager.all()
return model_cls._default_manager.all()
def slugify_func(self, content):
if content:
return slugify(content)
return ''
def create_slug(self, model_instance, add):
# get fields to populate from and slug field to set
if not isinstance(self._populate_from, (list, tuple)):
self._populate_from = (self._populate_from, )
slug_field = model_instance._meta.get_field(self.attname)
if add or self.overwrite:
# slugify the original field content and set next step to 2
slug_for_field = lambda field: self.slugify_func(getattr(model_instance, field))
slug = self.separator.join(map(slug_for_field, self._populate_from))
next = 2
else:
# get slug from the current model instance
slug = getattr(model_instance, self.attname)
# model_instance is being modified, and overwrite is False,
# so instead of doing anything, just return the current slug
return slug
# strip slug depending on max_length attribute of the slug field
# and clean-up
slug_len = slug_field.max_length
if slug_len:
slug = slug[:slug_len]
slug = self._slug_strip(slug)
original_slug = slug
if self.allow_duplicates:
return slug
# exclude the current model instance from the queryset used in finding
# the next valid slug
queryset = self.get_queryset(model_instance.__class__, slug_field)
if model_instance.pk:
queryset = queryset.exclude(pk=model_instance.pk)
# form a kwarg dict used to impliment any unique_together contraints
kwargs = {}
for params in model_instance._meta.unique_together:
if self.attname in params:
for param in params:
kwargs[param] = getattr(model_instance, param, None)
kwargs[self.attname] = slug
# increases the number while searching for the next valid slug
# depending on the given slug, clean-up
while not slug or queryset.filter(**kwargs):
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]
slug = self._slug_strip(slug)
slug = '%s%s' % (slug, end)
kwargs[self.attname] = slug
next += 1
return slug
def pre_save(self, model_instance, add):
value = force_unicode(self.create_slug(model_instance, add))
setattr(model_instance, self.attname, value)
return value
def get_internal_type(self):
return "SlugField"
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 = '%s.AutoSlugField' % self.__module__
args, kwargs = introspector(self)
kwargs.update({
'populate_from': repr(self._populate_from),
'separator': repr(self.separator),
'overwrite': repr(self.overwrite),
'allow_duplicates': repr(self.allow_duplicates),
})
# That's our definition!
return (field_class, args, kwargs)
class CreationDateTimeField(DateTimeField):
""" CreationDateTimeField
By default, sets editable=False, blank=True, default=datetime.now
"""
def __init__(self, *args, **kwargs):
kwargs.setdefault('editable', False)
kwargs.setdefault('blank', True)
kwargs.setdefault('default', datetime_now)
DateTimeField.__init__(self, *args, **kwargs)
def get_internal_type(self):
return "DateTimeField"
def south_field_triple(self):
"Returns a suitable description of this field for South."
# We'll just introspect ourselves, since we inherit.
from south.modelsinspector import introspector
field_class = "django.db.models.fields.DateTimeField"
args, kwargs = introspector(self)
return (field_class, args, kwargs)
class ModificationDateTimeField(CreationDateTimeField):
""" ModificationDateTimeField
By default, sets editable=False, blank=True, default=datetime.now
Sets value to datetime.now() on each save of the model.
"""
def pre_save(self, model, add):
value = datetime_now()
setattr(model, self.attname, value)
return value
def get_internal_type(self):
return "DateTimeField"
def south_field_triple(self):
"Returns a suitable description of this field for South."
# We'll just introspect ourselves, since we inherit.
from south.modelsinspector import introspector
field_class = "django.db.models.fields.DateTimeField"
args, kwargs = introspector(self)
return (field_class, args, kwargs)
class UUIDVersionError(Exception):
pass
class UUIDField(CharField):
""" UUIDField
By default uses UUID version 4 (randomly generated UUID).
The field support all uuid versions which are natively supported by the uuid python module, except version 2.
For more information see: http://docs.python.org/lib/module-uuid.html
"""
def __init__(self, verbose_name=None, name=None, auto=True, version=4, node=None, clock_seq=None, namespace=None, **kwargs):
if not HAS_UUID:
raise ImproperlyConfigured("'uuid' module is required for UUIDField. (Do you have Python 2.5 or higher installed ?)")
kwargs.setdefault('max_length', 36)
if auto:
self.empty_strings_allowed = False
kwargs['blank'] = True
kwargs.setdefault('editable', False)
self.auto = auto
self.version = version
if version == 1:
self.node, self.clock_seq = node, clock_seq
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 create_uuid(self):
if not self.version or self.version == 4:
return uuid.uuid4()
elif self.version == 1:
return uuid.uuid1(self.node, self.clock_seq)
elif self.version == 2:
raise UUIDVersionError("UUID version 2 is not supported.")
elif self.version == 3:
return uuid.uuid3(self.namespace, self.name)
elif self.version == 5:
return uuid.uuid5(self.namespace, self.name)
else:
raise UUIDVersionError("UUID version %s is not valid." % self.version)
def pre_save(self, model_instance, add):
value = super(UUIDField, self).pre_save(model_instance, add)
if self.auto and add and value is None:
value = force_unicode(self.create_uuid())
setattr(model_instance, self.attname, value)
return value
else:
if self.auto and not value:
value = force_unicode(self.create_uuid())
setattr(model_instance, self.attname, value)
return value
def formfield(self, **kwargs):
if self.auto:
return None
return super(UUIDField, self).formfield(**kwargs)
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.CharField"
args, kwargs = introspector(self)
# That's our definition!
return (field_class, args, kwargs)

View file

@ -0,0 +1,138 @@
import six
from django.db import models
from django.core.exceptions import ImproperlyConfigured
from django import forms
from django.conf import settings
import warnings
try:
from keyczar import keyczar
except ImportError:
raise ImportError('Using an encrypted field requires the Keyczar module. '
'You can obtain Keyczar from http://www.keyczar.org/.')
class EncryptionWarning(RuntimeWarning):
pass
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 the settings.ENCRYPTED_FIELD_KEYS_DIR '
'setting to your Keyczar keys directory.')
crypt_class = self.get_crypt_class()
self.crypt = crypt_class.Read(settings.ENCRYPTED_FIELD_KEYS_DIR)
# Encrypted size is larger than unencrypted
self.unencrypted_length = max_length = kwargs.get('max_length', None)
if max_length:
max_length = len(self.prefix) + len(self.crypt.Encrypt('x' * max_length))
# TODO: Re-examine if this logic will actually make a large-enough
# max-length for unicode strings that have non-ascii characters in them.
kwargs['max_length'] = max_length
super(BaseEncryptedField, self).__init__(*args, **kwargs)
def get_crypt_class(self):
"""
Get the Keyczar class to use.
The class can be customized with the ENCRYPTED_FIELD_MODE setting. By default,
this setting is DECRYPT_AND_ENCRYPT. Set this to ENCRYPT to disable decryption.
This is necessary if you are only providing public keys to Keyczar.
Returns:
keyczar.Encrypter if ENCRYPTED_FIELD_MODE is ENCRYPT.
keyczar.Crypter if ENCRYPTED_FIELD_MODE is DECRYPT_AND_ENCRYPT.
Override this method to customize the type of Keyczar class returned.
"""
crypt_type = getattr(settings, 'ENCRYPTED_FIELD_MODE', 'DECRYPT_AND_ENCRYPT')
if crypt_type == 'ENCRYPT':
crypt_class_name = 'Encrypter'
elif crypt_type == 'DECRYPT_AND_ENCRYPT':
crypt_class_name = 'Crypter'
else:
raise ImproperlyConfigured(
'ENCRYPTED_FIELD_MODE must be either DECRYPT_AND_ENCRYPT '
'or ENCRYPT, not %s.' % crypt_type)
return getattr(keyczar, crypt_class_name)
def to_python(self, value):
if isinstance(self.crypt.primary_key, keyczar.keys.RsaPublicKey):
retval = value
elif value and (value.startswith(self.prefix)):
if hasattr(self.crypt, 'Decrypt'):
retval = self.crypt.Decrypt(value[len(self.prefix):])
if retval:
retval = retval.decode('utf-8')
else:
retval = value
else:
retval = value
return retval
def get_db_prep_value(self, value, connection, prepared=False):
if value and not value.startswith(self.prefix):
# We need to encode a unicode string into a byte string, first.
# keyczar expects a bytestring, not a unicode string.
if type(value) == six.types.UnicodeType:
value = value.encode('utf-8')
# Truncated encrypted content is unreadable,
# so truncate before encryption
max_length = self.unencrypted_length
if max_length and len(value) > max_length:
warnings.warn("Truncating field %s from %d to %d bytes" % (
self.name, len(value), max_length), EncryptionWarning
)
value = value[:max_length]
value = self.prefix + self.crypt.Encrypt(value)
return value
class EncryptedTextField(six.with_metaclass(models.SubfieldBase,
BaseEncryptedField)):
def get_internal_type(self):
return 'TextField'
def formfield(self, **kwargs):
defaults = {'widget': forms.Textarea}
defaults.update(kwargs)
return super(EncryptedTextField, self).formfield(**defaults)
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)
class EncryptedCharField(six.with_metaclass(models.SubfieldBase,
BaseEncryptedField)):
def __init__(self, *args, **kwargs):
super(EncryptedCharField, self).__init__(*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)
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.CharField"
args, kwargs = introspector(self)
# That's our definition!
return (field_class, args, kwargs)

View file

@ -0,0 +1,98 @@
"""
JSONField automatically serializes most Python terms to JSON data.
Creates a TEXT field with a default value of "{}". See test_json.py for
more information.
from django.db import models
from django_extensions.db.fields import json
class LOL(models.Model):
extra = json.JSONField()
"""
import six
from decimal import Decimal
from django.db import models
from django.conf import settings
from django.core.serializers.json import DjangoJSONEncoder
try:
# Django <= 1.6 backwards compatibility
from django.utils import simplejson as json
except ImportError:
# Django >= 1.7
import json
def dumps(value):
return DjangoJSONEncoder().encode(value)
def loads(txt):
value = json.loads(
txt,
parse_float=Decimal,
encoding=settings.DEFAULT_CHARSET
)
return value
class JSONDict(dict):
"""
Hack so repr() called by dumpdata will output JSON instead of
Python formatted data. This way fixtures will work!
"""
def __repr__(self):
return dumps(self)
class JSONList(list):
"""
As above
"""
def __repr__(self):
return dumps(self)
class JSONField(six.with_metaclass(models.SubfieldBase, models.TextField)):
"""JSONField is a generic textfield that neatly serializes/unserializes
JSON objects seamlessly. Main thingy must be a dict object."""
def __init__(self, *args, **kwargs):
default = kwargs.get('default', None)
if default is None:
kwargs['default'] = '{}'
elif isinstance(default, (list, dict)):
kwargs['default'] = dumps(default)
models.TextField.__init__(self, *args, **kwargs)
def to_python(self, value):
"""Convert our string value to JSON after we load it from the DB"""
if value is None or value == '':
return {}
elif isinstance(value, six.string_types):
res = loads(value)
if isinstance(res, dict):
return JSONDict(**res)
else:
return JSONList(res)
else:
return value
def get_db_prep_save(self, value, connection):
"""Convert our JSON object to a string before we save"""
if not isinstance(value, (list, dict)):
return super(JSONField, self).get_db_prep_save("", connection=connection)
else:
return super(JSONField, self).get_db_prep_save(dumps(value),
connection=connection)
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)

View file

@ -0,0 +1,78 @@
"""
Django Extensions abstract base model classes.
"""
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django_extensions.db.fields import (ModificationDateTimeField,
CreationDateTimeField, AutoSlugField)
try:
from django.utils.timezone import now as datetime_now
assert datetime_now
except ImportError:
import datetime
datetime_now = datetime.datetime.now
class TimeStampedModel(models.Model):
""" TimeStampedModel
An abstract base class model that provides self-managed "created" and
"modified" fields.
"""
created = CreationDateTimeField(_('created'))
modified = ModificationDateTimeField(_('modified'))
class Meta:
get_latest_by = 'modified'
ordering = ('-modified', '-created',)
abstract = True
class TitleSlugDescriptionModel(models.Model):
""" TitleSlugDescriptionModel
An abstract base class model that provides title and description fields
and a self-managed "slug" field that populates from the title.
"""
title = models.CharField(_('title'), max_length=255)
slug = AutoSlugField(_('slug'), populate_from='title')
description = models.TextField(_('description'), blank=True, null=True)
class Meta:
abstract = True
class ActivatorModelManager(models.Manager):
""" ActivatorModelManager
Manager to return instances of ActivatorModel: SomeModel.objects.active() / .inactive()
"""
def active(self):
""" Returns active instances of ActivatorModel: SomeModel.objects.active() """
return self.get_query_set().filter(status=ActivatorModel.ACTIVE_STATUS)
def inactive(self):
""" Returns inactive instances of ActivatorModel: SomeModel.objects.inactive() """
return self.get_query_set().filter(status=ActivatorModel.INACTIVE_STATUS)
class ActivatorModel(models.Model):
""" ActivatorModel
An abstract base class model that provides activate and deactivate fields.
"""
INACTIVE_STATUS, ACTIVE_STATUS = range(2)
STATUS_CHOICES = (
(INACTIVE_STATUS, _('Inactive')),
(ACTIVE_STATUS, _('Active')),
)
status = models.IntegerField(_('status'), choices=STATUS_CHOICES, default=ACTIVE_STATUS)
activate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for an immediate activation'))
deactivate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for indefinite activation'))
objects = ActivatorModelManager()
class Meta:
ordering = ('status', '-activate_date',)
abstract = True
def save(self, *args, **kwargs):
if not self.activate_date:
self.activate_date = datetime_now()
super(ActivatorModel, self).save(*args, **kwargs)

View file

@ -0,0 +1,16 @@
"""
A forwards compatibility module.
Implements some features of Django 1.5 related to the 'Custom User Model' feature
when the application is run with a lower version of Django.
"""
from __future__ import unicode_literals
from django.contrib.auth.models import User
User.USERNAME_FIELD = "username"
User.get_username = lambda self: self.username
def get_user_model():
return User

View file

@ -0,0 +1,50 @@
"""
Daily cleanup job.
Can be run as a cronjob to clean out old data from the database (only expired
sessions at the moment).
"""
from django_extensions.management.jobs import DailyJob
class Job(DailyJob):
help = "Cache (db) cleanup Job"
def execute(self):
from django.conf import settings
from django.db import transaction
import os
try:
from django.utils import timezone
except ImportError:
timezone = None
if hasattr(settings, 'CACHES') and timezone:
from django.core.cache import get_cache
from django.db import router, connections
for cache_name, cache_options in settings.CACHES.iteritems():
if cache_options['BACKEND'].endswith("DatabaseCache"):
cache = get_cache(cache_name)
db = router.db_for_write(cache.cache_model_class)
cursor = connections[db].cursor()
now = timezone.now()
cache._cull(db, cursor, now)
transaction.commit_unless_managed(using=db)
return
if hasattr(settings, 'CACHE_BACKEND'):
if settings.CACHE_BACKEND.startswith('db://'):
from django.db import connection
os.environ['TZ'] = settings.TIME_ZONE
table_name = settings.CACHE_BACKEND[5:]
cursor = connection.cursor()
cursor.execute(
"DELETE FROM %s WHERE %s < current_timestamp;" % (
connection.ops.quote_name(table_name),
connection.ops.quote_name('expires')
)
)
transaction.commit_unless_managed()

View file

@ -0,0 +1,16 @@
"""
Daily cleanup job.
Can be run as a cronjob to clean out old data from the database (only expired
sessions at the moment).
"""
from django_extensions.management.jobs import DailyJob
class Job(DailyJob):
help = "Django Daily Cleanup Job"
def execute(self):
from django.core import management
management.call_command("cleanup")

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:42+0100\n"
"PO-Revision-Date: 2011-02-02 10:42+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: cs\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n"
#: admin/__init__.py:121
msgid "and"
msgstr ""
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
#: db/models.py:15
msgid "created"
msgstr ""
#: db/models.py:16
msgid "modified"
msgstr ""
#: db/models.py:26
msgid "title"
msgstr ""
#: db/models.py:27
msgid "slug"
msgstr ""
#: db/models.py:28
msgid "description"
msgstr ""
#: db/models.py:50
msgid "Inactive"
msgstr ""
#: db/models.py:51
msgid "Active"
msgstr ""
#: db/models.py:53
msgid "status"
msgstr ""
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr ""
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr ""
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr ""

View file

@ -0,0 +1,79 @@
# django_extentions in Danish.
# django_extensions på Dansk.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Michael Lind Mortensen <illio@cs.au.dk>, 2009.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:42+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "og"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Brug feltet til venstre til at lave %(model_name)s lookups i felterne %"
"(field_list)s."
#: db/models.py:15
msgid "created"
msgstr "skabt"
#: db/models.py:16
msgid "modified"
msgstr "ændret"
#: db/models.py:26
msgid "title"
msgstr "titel"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "beskrivelse"
#: db/models.py:50
msgid "Inactive"
msgstr ""
#: db/models.py:51
msgid "Active"
msgstr ""
#: db/models.py:53
msgid "status"
msgstr ""
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr ""
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr ""
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Lookup"

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:42+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "und"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Das linke Feld benutzen, um %(model_name)s Abfragen in den Feldern %"
"(field_list)s durchführen."
#: db/models.py:15
msgid "created"
msgstr "erstellt"
#: db/models.py:16
msgid "modified"
msgstr "geändert"
#: db/models.py:26
msgid "title"
msgstr "Titel"
#: db/models.py:27
msgid "slug"
msgstr "Slug"
#: db/models.py:28
msgid "description"
msgstr "Beschreibung"
#: db/models.py:50
msgid "Inactive"
msgstr "Inaktiv"
#: db/models.py:51
msgid "Active"
msgstr "Aktiv"
#: db/models.py:53
msgid "status"
msgstr "Status"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "Leer lassen für sofortige Aktivierung"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "Leer lassen für unbefristete Aktivierung"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s ist kein urlpattern Objekt"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Abfrage"

View file

@ -0,0 +1,79 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:42+0100\n"
"PO-Revision-Date: 2011-02-02 10:38+0000\n"
"Last-Translator: Jannis <jannis@leidel.info>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: el\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: admin/__init__.py:121
msgid "and"
msgstr "και"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Χρησιμοποίησε το αριστερό πεδίο για να κάνεις αναζήτηση του %(model_name)s "
"με βάσει τα πεδία %(field_list)s."
#: db/models.py:15
msgid "created"
msgstr "δημιουργήθηκε"
#: db/models.py:16
msgid "modified"
msgstr "τροποποιήθηκε"
#: db/models.py:26
msgid "title"
msgstr "τίτλος"
#: db/models.py:27
msgid "slug"
msgstr "μίνι-όνομα"
#: db/models.py:28
msgid "description"
msgstr "περιγραφή"
#: db/models.py:50
msgid "Inactive"
msgstr "ανενεργό"
#: db/models.py:51
msgid "Active"
msgstr "Ενεργό"
#: db/models.py:53
msgid "status"
msgstr "κατάσταση"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "αφήστε άδειο για άμεση ενεργοποίηση"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "αφήστε άδειο για αόριστη ενεργοποίηση"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "% s δεν φαίνεται να είναι ένα αντικείμενο urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Αναζήτηση"

View file

@ -0,0 +1,76 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:42+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr ""
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
#: db/models.py:15
msgid "created"
msgstr ""
#: db/models.py:16
msgid "modified"
msgstr ""
#: db/models.py:26
msgid "title"
msgstr ""
#: db/models.py:27
msgid "slug"
msgstr ""
#: db/models.py:28
msgid "description"
msgstr ""
#: db/models.py:50
msgid "Inactive"
msgstr ""
#: db/models.py:51
msgid "Active"
msgstr ""
#: db/models.py:53
msgid "status"
msgstr ""
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr ""
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr ""
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr ""

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "y"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Utilice el campo de la izquierda para hacer búsquedas en los campos %"
"(field_list)s de %(model_name)s."
#: db/models.py:15
msgid "created"
msgstr "creado"
#: db/models.py:16
msgid "modified"
msgstr "modificado"
#: db/models.py:26
msgid "title"
msgstr "titulo"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "descripción"
#: db/models.py:50
msgid "Inactive"
msgstr "Inactivo"
#: db/models.py:51
msgid "Active"
msgstr "Activo"
#: db/models.py:53
msgid "status"
msgstr "estado"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "mantener vacío para una activación inmediata"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "deje vacío para mantener la activación indefinida"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "% s no parece ser un objeto urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Buscar"

View file

@ -0,0 +1,75 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "ja"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
#: db/models.py:15
msgid "created"
msgstr ""
#: db/models.py:16
msgid "modified"
msgstr ""
#: db/models.py:26
msgid "title"
msgstr ""
#: db/models.py:27
msgid "slug"
msgstr ""
#: db/models.py:28
msgid "description"
msgstr ""
#: db/models.py:50
msgid "Inactive"
msgstr ""
#: db/models.py:51
msgid "Active"
msgstr ""
#: db/models.py:53
msgid "status"
msgstr ""
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr ""
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr ""
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr ""

View file

@ -0,0 +1,82 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: 2011-02-02 10:38+0000\n"
"Last-Translator: Jannis <jannis@leidel.info>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
#: admin/__init__.py:121
msgid "and"
msgstr "et"
#: admin/__init__.py:123
#, fuzzy, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Utilisez le champ de gauche pour faire des recheres de %(MODEL_NAME)s dans "
"les champs %(field_list)s."
#: db/models.py:15
msgid "created"
msgstr "créé"
#: db/models.py:16
msgid "modified"
msgstr "mise à jour"
#: db/models.py:26
msgid "title"
msgstr "titre"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "description"
#: db/models.py:50
msgid "Inactive"
msgstr "inactif"
#: db/models.py:51
msgid "Active"
msgstr "active"
#: db/models.py:53
msgid "status"
msgstr "état"
#: db/models.py:56
#, fuzzy
msgid "keep empty for an immediate activation"
msgstr "garder vide pour l'activation immédiate"
#: db/models.py:58
#, fuzzy
msgid "keep empty for indefinite activation"
msgstr "garder vide pour l'activation de durée indéterminée"
#: management/commands/show_urls.py:34
#, fuzzy, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s ne semble pas être un objet urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
#, fuzzy
msgid "Lookup"
msgstr "Recherche"

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "és"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Használd a baloldali mezőt hogy keress a %(model_name)s %(field_list)s. "
"mezőiben"
#: db/models.py:15
msgid "created"
msgstr "létrehozva"
#: db/models.py:16
msgid "modified"
msgstr "módosítva"
#: db/models.py:26
msgid "title"
msgstr "Cím"
#: db/models.py:27
msgid "slug"
msgstr "Slug"
#: db/models.py:28
msgid "description"
msgstr "Leírás"
#: db/models.py:50
msgid "Inactive"
msgstr "Inaktív"
#: db/models.py:51
msgid "Active"
msgstr "Aktív"
#: db/models.py:53
msgid "status"
msgstr "Állapot"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "Üresen hagyni azonnali aktiváláshoz"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "Üresen hagyni korlátlan aktiváláshoz"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "Úgy néz ki hogy %s nem egy urlpattern objektum"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Lekérdezés"

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "e"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Utilizzare il campo a sinistra per fare ricerche nei campi %(field_list)s "
"del modello %(model_name)s."
#: db/models.py:15
msgid "created"
msgstr "creato"
#: db/models.py:16
msgid "modified"
msgstr "modificato"
#: db/models.py:26
msgid "title"
msgstr "titolo"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "descrizione"
#: db/models.py:50
msgid "Inactive"
msgstr "Inattivo"
#: db/models.py:51
msgid "Active"
msgstr "Attivo"
#: db/models.py:53
msgid "status"
msgstr "stato"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "lasciare vuoto per attivazione immediata"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "lasciare vuoti per attivazione indefinita"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "% s non sembra essere un oggetto urlPattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Ricerca"

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "と"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"%(field_list)s フィールドの内容から %(model_name)s を検索するには左のフィール"
"ドを使用して下さい。"
#: db/models.py:15
msgid "created"
msgstr "作成日時"
#: db/models.py:16
msgid "modified"
msgstr "変更日時"
#: db/models.py:26
msgid "title"
msgstr "タイトル"
#: db/models.py:27
msgid "slug"
msgstr "スラグ"
#: db/models.py:28
msgid "description"
msgstr "説明"
#: db/models.py:50
msgid "Inactive"
msgstr "非アクティブ"
#: db/models.py:51
msgid "Active"
msgstr "アクティブ"
#: db/models.py:53
msgid "status"
msgstr "ステータス"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "すぐに有効化する場合は空白のままにして下さい"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "無期限に有効化しておく場合は空白のままにして下さい"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s は urlpattern オブジェクトではないようです"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "検索"

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Zbigniew Siciarz <antyqjon@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "i"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Użyj pola po lewej, by wyszukać pola %(field_list)s w modelu %(model_name)s."
#: db/models.py:15
msgid "created"
msgstr "utworzony"
#: db/models.py:16
msgid "modified"
msgstr "zmodyfikowany"
#: db/models.py:26
msgid "title"
msgstr "tytuł"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "opis"
#: db/models.py:50
msgid "Inactive"
msgstr "Nieaktywny"
#: db/models.py:51
msgid "Active"
msgstr "Aktywny"
#: db/models.py:53
msgid "status"
msgstr "stan"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "pozostaw puste, by aktywować od razu"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "pozostaw puste, by nie definiować daty deaktywacji"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s nie jest obiektem typu urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Szukaj"

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: 2010-11-15 22:06-0300\n"
"Last-Translator: Fernando Silva <fernand at liquuid dot net>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "e"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Use o campo esquerdo para fazer com que o modelo %(model_name)s procure nos "
"campos %(field_list)s."
#: db/models.py:15
msgid "created"
msgstr "criado"
#: db/models.py:16
msgid "modified"
msgstr "modificado"
#: db/models.py:26
msgid "title"
msgstr "título"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "descrição"
#: db/models.py:50
msgid "Inactive"
msgstr "Inativo"
#: db/models.py:51
msgid "Active"
msgstr "Ativo"
#: db/models.py:53
msgid "status"
msgstr "estado"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "deixe vazio para ativação imediata"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "deixe vazio para ativação por tempo indeterminado"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s não parece ser um objeto urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Busca"

View file

@ -0,0 +1,79 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Claudemiro Alves Feitosa Neto <dimiro1@gmail.com>, 2013.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-09-13 22:49-0300\n"
"PO-Revision-Date: 2013-09-13 22:49-0300\n"
"Last-Translator: Claudemiro Alves Feitosa <dimiro1@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: admin/__init__.py:128
msgid "and"
msgstr "e"
#: admin/__init__.py:130
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr "Use o campo da esquerda para fazer com que o modelo %(model_name)s procure nos "
"campos %(field_list)s"
#: db/models.py:22 mongodb/models.py:17
msgid "created"
msgstr "criado"
#: db/models.py:23 mongodb/models.py:18
msgid "modified"
msgstr "modificado"
#: db/models.py:36 mongodb/models.py:29
msgid "title"
msgstr "título"
#: db/models.py:37 mongodb/models.py:30
msgid "slug"
msgstr "slug"
#: db/models.py:38 mongodb/models.py:31
msgid "description"
msgstr "descrição"
#: db/models.py:63 mongodb/models.py:55
msgid "Inactive"
msgstr "Inativo"
#: db/models.py:64 mongodb/models.py:56
msgid "Active"
msgstr "Ativo"
#: db/models.py:66 mongodb/models.py:58
msgid "status"
msgstr "status"
#: db/models.py:67 mongodb/models.py:59
msgid "keep empty for an immediate activation"
msgstr "deixe vazio para uma ativação imediata"
#: db/models.py:68 mongodb/models.py:60
msgid "keep empty for indefinite activation"
msgstr "deixe vazio para ativação por tempo indeterminado"
#: mongodb/fields/__init__.py:24
#, python-format
msgid "String (up to %(max_length)s)"
msgstr "Cadeia de Caracteres (até %(max_length)s)"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Busca"

View file

@ -0,0 +1,80 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: 2011-02-02 10:38+0000\n"
"Last-Translator: Jannis <jannis@leidel.info>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ro\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
"20)) ? 1 : 2)\n"
#: admin/__init__.py:121
msgid "and"
msgstr "și"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Folosește câmpul din stânga pentru a efectua căutări de %(model_name)s în "
"câmpurile %(field_list)s."
#: db/models.py:15
msgid "created"
msgstr "creat"
#: db/models.py:16
msgid "modified"
msgstr "modificat"
#: db/models.py:26
msgid "title"
msgstr "Titlu"
#: db/models.py:27
msgid "slug"
msgstr "Slug"
#: db/models.py:28
msgid "description"
msgstr "Descriere"
#: db/models.py:50
msgid "Inactive"
msgstr "Inactiv"
#: db/models.py:51
msgid "Active"
msgstr "Activ"
#: db/models.py:53
msgid "status"
msgstr "Stare"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "A se lăsa gol pentru activare imediată"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "A se lăsa gol pentru activare nelimitată"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s nu pare să fie un obiect urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Căutare"

View file

@ -0,0 +1,78 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: 2011-02-02 10:42+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ru\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: admin/__init__.py:121
msgid "and"
msgstr ""
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
#: db/models.py:15
msgid "created"
msgstr ""
#: db/models.py:16
msgid "modified"
msgstr ""
#: db/models.py:26
msgid "title"
msgstr ""
#: db/models.py:27
msgid "slug"
msgstr ""
#: db/models.py:28
msgid "description"
msgstr ""
#: db/models.py:50
msgid "Inactive"
msgstr ""
#: db/models.py:51
msgid "Active"
msgstr ""
#: db/models.py:53
msgid "status"
msgstr ""
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr ""
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr ""
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr ""

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: 2011-02-02 10:42+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: sk\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n"
#: admin/__init__.py:121
msgid "and"
msgstr ""
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
#: db/models.py:15
msgid "created"
msgstr ""
#: db/models.py:16
msgid "modified"
msgstr ""
#: db/models.py:26
msgid "title"
msgstr ""
#: db/models.py:27
msgid "slug"
msgstr ""
#: db/models.py:28
msgid "description"
msgstr ""
#: db/models.py:50
msgid "Inactive"
msgstr ""
#: db/models.py:51
msgid "Active"
msgstr ""
#: db/models.py:53
msgid "status"
msgstr ""
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr ""
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr ""
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr ""

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: 2011-02-02 10:42+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: tr\n"
"Plural-Forms: nplurals=1; plural=0\n"
#: admin/__init__.py:121
msgid "and"
msgstr ""
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
#: db/models.py:15
msgid "created"
msgstr ""
#: db/models.py:16
msgid "modified"
msgstr ""
#: db/models.py:26
msgid "title"
msgstr ""
#: db/models.py:27
msgid "slug"
msgstr ""
#: db/models.py:28
msgid "description"
msgstr ""
#: db/models.py:50
msgid "Inactive"
msgstr ""
#: db/models.py:51
msgid "Active"
msgstr ""
#: db/models.py:53
msgid "status"
msgstr ""
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr ""
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr ""
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr ""

View file

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: 2011-02-02 10:42+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"Plural-Forms: nplurals=1; plural=0\n"
#: admin/__init__.py:121
msgid "and"
msgstr ""
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
#: db/models.py:15
msgid "created"
msgstr ""
#: db/models.py:16
msgid "modified"
msgstr ""
#: db/models.py:26
msgid "title"
msgstr ""
#: db/models.py:27
msgid "slug"
msgstr ""
#: db/models.py:28
msgid "description"
msgstr ""
#: db/models.py:50
msgid "Inactive"
msgstr ""
#: db/models.py:51
msgid "Active"
msgstr ""
#: db/models.py:53
msgid "status"
msgstr ""
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr ""
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr ""
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr ""

View file

@ -0,0 +1,53 @@
import sys
from django.core.management.base import BaseCommand
from django.utils.log import getLogger
logger = getLogger('django.commands')
class LoggingBaseCommand(BaseCommand):
"""
A subclass of BaseCommand that logs run time errors to `django.commands`.
To use this, create a management command subclassing LoggingBaseCommand:
from django_extensions.management.base import LoggingBaseCommand
class Command(LoggingBaseCommand):
help = 'Test error'
def handle(self, *args, **options):
raise Exception
And then define a logging handler in settings.py:
LOGGING = {
... # Other stuff here
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
},
},
'loggers': {
'django.commands': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
}
}
"""
def execute(self, *args, **options):
try:
super(LoggingBaseCommand, self).execute(*args, **options)
except Exception as e:
logger.error(e, exc_info=sys.exc_info(), extra={'status_code': 500})
raise

View file

@ -0,0 +1,19 @@
"""
Sets up the terminal color scheme.
"""
from django.core.management import color
from django.utils import termcolors
def color_style():
style = color.color_style()
if color.supports_color():
style.INFO = termcolors.make_style(fg='green')
style.WARN = termcolors.make_style(fg='yellow')
style.BOLD = termcolors.make_style(opts=('bold',))
style.URL = termcolors.make_style(fg='green', opts=('bold',))
style.MODULE = termcolors.make_style(fg='yellow')
style.MODULE_NAME = termcolors.make_style(opts=('bold',))
style.URL_NAME = termcolors.make_style(fg='red')
return style

View file

@ -0,0 +1,37 @@
from django.core.management.base import NoArgsCommand
from django_extensions.management.utils import get_project_root
from optparse import make_option
from os.path import join as _j
import os
class Command(NoArgsCommand):
option_list = NoArgsCommand.option_list + (
make_option('--optimize', '-o', '-O', action='store_true', dest='optimize',
help='Remove optimized python bytecode files'),
make_option('--path', '-p', action='store', dest='path',
help='Specify path to recurse into'),
)
help = "Removes all python bytecode compiled files from the project."
requires_model_validation = False
def handle_noargs(self, **options):
project_root = options.get("path", None)
if not project_root:
project_root = get_project_root()
exts = options.get("optimize", False) and [".pyc", ".pyo"] or [".pyc"]
verbose = int(options.get("verbosity", 1))
if verbose > 1:
print("Project Root: %s" % project_root)
for root, dirs, files in os.walk(project_root):
for file in files:
ext = os.path.splitext(file)[1]
if ext in exts:
full_path = _j(root, file)
if verbose > 1:
print(full_path)
os.remove(full_path)

View file

@ -0,0 +1,30 @@
from django.core.management.base import NoArgsCommand
from django_extensions.management.utils import get_project_root
from optparse import make_option
from os.path import join as _j
import py_compile
import os
class Command(NoArgsCommand):
option_list = NoArgsCommand.option_list + (
make_option('--path', '-p', action='store', dest='path', help='Specify path to recurse into'),
)
help = "Compile python bytecode files for the project."
requires_model_validation = False
def handle_noargs(self, **options):
project_root = options.get("path", None)
if not project_root:
project_root = get_project_root()
verbose = int(options.get("verbosity", 1)) > 1
for root, dirs, files in os.walk(project_root):
for file in files:
ext = os.path.splitext(file)[1]
if ext == ".py":
full_path = _j(root, file)
if verbose:
print("%sc" % full_path)
py_compile.compile(full_path)

View file

@ -0,0 +1,138 @@
import os
import re
import sys
import django_extensions
from django.conf import settings
from django.db import connection
from django.core.management.base import CommandError, LabelCommand
from django.template import Template, Context
from django_extensions.settings import REPLACEMENTS
from django_extensions.utils.dia2django import dia2django
from django_extensions.management.utils import _make_writeable
from optparse import make_option
class Command(LabelCommand):
option_list = LabelCommand.option_list + (
make_option('--template', '-t', action='store', dest='app_template',
help='The path to the app template'),
make_option('--parent_path', '-p', action='store', dest='parent_path',
help='The parent path of the application to be created'),
make_option('-d', action='store_true', dest='dia_parse',
help='Generate model.py and admin.py from [APP_NAME].dia file'),
make_option('--diagram', action='store', dest='dia_path',
help='The diagram path of the app to be created. -d is implied'),
)
help = ("Creates an application directory structure for the specified application name.")
args = "APP_NAME"
label = 'application name'
requires_model_validation = False
can_import_settings = True
def handle_label(self, label, **options):
project_dir = os.getcwd()
project_name = os.path.split(project_dir)[-1]
app_name = label
app_template = options.get('app_template') or os.path.join(django_extensions.__path__[0], 'conf', 'app_template')
app_dir = os.path.join(options.get('parent_path') or project_dir, app_name)
dia_path = options.get('dia_path') or os.path.join(project_dir, '%s.dia' % app_name)
if not os.path.exists(app_template):
raise CommandError("The template path, %r, does not exist." % app_template)
if not re.search(r'^\w+$', label):
raise CommandError("%r is not a valid application name. Please use only numbers, letters and underscores." % label)
dia_parse = options.get('dia_path') or options.get('dia_parse')
if dia_parse:
if not os.path.exists(dia_path):
raise CommandError("The diagram path, %r, does not exist." % dia_path)
if app_name in settings.INSTALLED_APPS:
raise CommandError("The application %s should not be defined in the settings file. Please remove %s now, and add it after using this command." % (app_name, app_name))
tables = [name for name in connection.introspection.table_names() if name.startswith('%s_' % app_name)]
if tables:
raise CommandError("%r application has tables in the database. Please delete them." % app_name)
try:
os.makedirs(app_dir)
except OSError as e:
raise CommandError(e)
copy_template(app_template, app_dir, project_name, app_name)
if dia_parse:
generate_models_and_admin(dia_path, app_dir, project_name, app_name)
print("Application %r created." % app_name)
print("Please add now %r and any other dependent application in settings.INSTALLED_APPS, and run 'manage syncdb'" % app_name)
def copy_template(app_template, copy_to, project_name, app_name):
"""copies the specified template directory to the copy_to location"""
import shutil
app_template = os.path.normpath(app_template)
# walks the template structure and copies it
for d, subdirs, files in os.walk(app_template):
relative_dir = d[len(app_template) + 1:]
d_new = os.path.join(copy_to, relative_dir).replace('app_name', app_name)
if relative_dir and not os.path.exists(d_new):
os.mkdir(d_new)
for i, subdir in enumerate(subdirs):
if subdir.startswith('.'):
del subdirs[i]
replacements = {'app_name': app_name, 'project_name': project_name}
replacements.update(REPLACEMENTS)
for f in files:
if f.endswith('.pyc') or f.startswith('.DS_Store'):
continue
path_old = os.path.join(d, f)
path_new = os.path.join(d_new, f.replace('app_name', app_name))
if os.path.exists(path_new):
path_new = os.path.join(d_new, f)
if os.path.exists(path_new):
continue
if path_new.endswith('.tmpl'):
path_new = path_new[:-5]
fp_old = open(path_old, 'r')
fp_new = open(path_new, 'w')
fp_new.write(Template(fp_old.read()).render(Context(replacements)))
fp_old.close()
fp_new.close()
try:
shutil.copymode(path_old, path_new)
_make_writeable(path_new)
except OSError:
sys.stderr.write("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new)
def generate_models_and_admin(dia_path, app_dir, project_name, app_name):
"""Generates the models.py and admin.py files"""
def format_text(string, indent=False):
"""format string in lines of 80 or less characters"""
retval = ''
while string:
line = string[:77]
last_space = line.rfind(' ')
if last_space != -1 and len(string) > 77:
retval += "%s \\\n" % string[:last_space]
string = string[last_space + 1:]
else:
retval += "%s\n" % string
string = ''
if string and indent:
string = ' %s' % string
return retval
model_path = os.path.join(app_dir, 'models.py')
admin_path = os.path.join(app_dir, 'admin.py')
models_txt = 'from django.db import models\n' + dia2django(dia_path)
open(model_path, 'w').write(models_txt)
classes = re.findall('class (\w+)', models_txt)
admin_txt = 'from django.contrib.admin import site, ModelAdmin\n' + format_text('from %s.%s.models import %s' % (project_name, app_name, ', '.join(classes)), indent=True)
admin_txt += format_text('\n\n%s' % '\n'.join(map((lambda t: 'site.register(%s)' % t), classes)))
open(admin_path, 'w').write(admin_txt)

View file

@ -0,0 +1,81 @@
import os
import sys
from django.core.management.base import CommandError, AppCommand
from django_extensions.management.utils import _make_writeable
from optparse import make_option
class Command(AppCommand):
option_list = AppCommand.option_list + (
make_option('--name', '-n', action='store', dest='command_name', default='sample',
help='The name to use for the management command'),
make_option('--base', '-b', action='store', dest='base_command', default='Base',
help='The base class used for implementation of this command. Should be one of Base, App, Label, or NoArgs'),
)
help = ("Creates a Django management command directory structure for the given app name"
" in the current directory.")
args = "[appname]"
label = 'application name'
requires_model_validation = False
# Can't import settings during this command, because they haven't
# necessarily been created.
can_import_settings = True
def handle_app(self, app, **options):
directory = os.getcwd()
app_name = app.__name__.split('.')[-2]
project_dir = os.path.join(directory, app_name)
if not os.path.exists(project_dir):
try:
os.mkdir(project_dir)
except OSError as e:
raise CommandError(e)
copy_template('command_template', project_dir, options.get('command_name'), '%sCommand' % options.get('base_command'))
def copy_template(template_name, copy_to, command_name, base_command):
"""copies the specified template directory to the copy_to location"""
import django_extensions
import shutil
template_dir = os.path.join(django_extensions.__path__[0], 'conf', template_name)
handle_method = "handle(self, *args, **options)"
if base_command == 'AppCommand':
handle_method = "handle_app(self, app, **options)"
elif base_command == 'LabelCommand':
handle_method = "handle_label(self, label, **options)"
elif base_command == 'NoArgsCommand':
handle_method = "handle_noargs(self, **options)"
# walks the template structure and copies it
for d, subdirs, files in os.walk(template_dir):
relative_dir = d[len(template_dir) + 1:]
if relative_dir and not os.path.exists(os.path.join(copy_to, relative_dir)):
os.mkdir(os.path.join(copy_to, relative_dir))
for i, subdir in enumerate(subdirs):
if subdir.startswith('.'):
del subdirs[i]
for f in files:
if f.endswith('.pyc') or f.startswith('.DS_Store'):
continue
path_old = os.path.join(d, f)
path_new = os.path.join(copy_to, relative_dir, f.replace('sample', command_name))
if os.path.exists(path_new):
path_new = os.path.join(copy_to, relative_dir, f)
if os.path.exists(path_new):
continue
path_new = path_new.rstrip(".tmpl")
fp_old = open(path_old, 'r')
fp_new = open(path_new, 'w')
fp_new.write(fp_old.read().replace('{{ command_name }}', command_name).replace('{{ base_command }}', base_command).replace('{{ handle_method }}', handle_method))
fp_old.close()
fp_new.close()
try:
shutil.copymode(path_old, path_new)
_make_writeable(path_new)
except OSError:
sys.stderr.write("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new)

View file

@ -0,0 +1,56 @@
import os
import sys
from django.core.management.base import AppCommand
from django_extensions.management.utils import _make_writeable
class Command(AppCommand):
help = ("Creates a Django jobs command directory structure for the given app name in the current directory.")
args = "[appname]"
label = 'application name'
requires_model_validation = False
# Can't import settings during this command, because they haven't
# necessarily been created.
can_import_settings = True
def handle_app(self, app, **options):
app_dir = os.path.dirname(app.__file__)
copy_template('jobs_template', app_dir)
def copy_template(template_name, copy_to):
"""copies the specified template directory to the copy_to location"""
import django_extensions
import shutil
template_dir = os.path.join(django_extensions.__path__[0], 'conf', template_name)
# walks the template structure and copies it
for d, subdirs, files in os.walk(template_dir):
relative_dir = d[len(template_dir) + 1:]
if relative_dir and not os.path.exists(os.path.join(copy_to, relative_dir)):
os.mkdir(os.path.join(copy_to, relative_dir))
for i, subdir in enumerate(subdirs):
if subdir.startswith('.'):
del subdirs[i]
for f in files:
if f.endswith('.pyc') or f.startswith('.DS_Store'):
continue
path_old = os.path.join(d, f)
path_new = os.path.join(copy_to, relative_dir, f)
if os.path.exists(path_new):
path_new = os.path.join(copy_to, relative_dir, f)
if os.path.exists(path_new):
continue
path_new = path_new.rstrip(".tmpl")
fp_old = open(path_old, 'r')
fp_new = open(path_new, 'w')
fp_new.write(fp_old.read())
fp_old.close()
fp_new.close()
try:
shutil.copymode(path_old, path_new)
_make_writeable(path_new)
except OSError:
sys.stderr.write("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new)

View file

@ -0,0 +1,66 @@
from django.core.management.base import LabelCommand, CommandError
from django.utils.encoding import force_unicode
class Command(LabelCommand):
help = "Outputs the specified model as a form definition to the shell."
args = "[app.model]"
label = 'application name and model name'
requires_model_validation = True
can_import_settings = True
def handle_label(self, label, **options):
return describe_form(label)
def describe_form(label, fields=None):
"""
Returns a string describing a form based on the model
"""
from django.db.models.loading import get_model
try:
app_name, model_name = label.split('.')[-2:]
except (IndexError, ValueError):
raise CommandError("Need application and model name in the form: appname.model")
model = get_model(app_name, model_name)
opts = model._meta
field_list = []
for f in opts.fields + opts.many_to_many:
if not f.editable:
continue
if fields and not f.name in fields:
continue
formfield = f.formfield()
if not '__dict__' in dir(formfield):
continue
attrs = {}
valid_fields = ['required', 'initial', 'max_length', 'min_length', 'max_value', 'min_value', 'max_digits', 'decimal_places', 'choices', 'help_text', 'label']
for k, v in formfield.__dict__.items():
if k in valid_fields and v is not None:
# ignore defaults, to minimize verbosity
if k == 'required' and v:
continue
if k == 'help_text' and not v:
continue
if k == 'widget':
attrs[k] = v.__class__
elif k in ['help_text', 'label']:
attrs[k] = force_unicode(v).strip()
else:
attrs[k] = v
params = ', '.join(['%s=%r' % (k, v) for k, v in attrs.items()])
field_list.append(' %(field_name)s = forms.%(field_type)s(%(params)s)' % {
'field_name': f.name,
'field_type': formfield.__class__.__name__,
'params': params
})
return '''
from django import forms
from %(app_name)s.models import %(object_name)s
class %(object_name)sForm(forms.Form):
%(field_list)s
''' % {'app_name': app_name, 'object_name': opts.object_name, 'field_list': '\n'.join(field_list)}

View file

@ -0,0 +1,751 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
Title: Dumpscript management command
Project: Hardytools (queryset-refactor version)
Author: Will Hardy (http://willhardy.com.au)
Date: June 2008
Usage: python manage.py dumpscript appname > scripts/scriptname.py
$Revision: 217 $
Description:
Generates a Python script that will repopulate the database using objects.
The advantage of this approach is that it is easy to understand, and more
flexible than directly populating the database, or using XML.
* It also allows for new defaults to take effect and only transfers what is
needed.
* If a new database schema has a NEW ATTRIBUTE, it is simply not
populated (using a default value will make the transition smooth :)
* If a new database schema REMOVES AN ATTRIBUTE, it is simply ignored
and the data moves across safely (I'm assuming we don't want this
attribute anymore.
* Problems may only occur if there is a new model and is now a required
ForeignKey for an existing model. But this is easy to fix by editing the
populate script. Half of the job is already done as all ForeingKey
lookups occur though the locate_object() function in the generated script.
Improvements:
See TODOs and FIXMEs scattered throughout :-)
"""
import sys
import datetime
import six
import django
from django.db.models import AutoField, BooleanField, FileField, ForeignKey
from django.core.exceptions import ObjectDoesNotExist
from django.core.management.base import BaseCommand
# conditional import, force_unicode was renamed in Django 1.5
from django.contrib.contenttypes.models import ContentType
try:
from django.utils.encoding import smart_unicode, force_unicode # NOQA
except ImportError:
from django.utils.encoding import smart_text as smart_unicode, force_text as force_unicode # NOQA
def orm_item_locator(orm_obj):
"""
This function is called every time an object that will not be exported is required.
Where orm_obj is the referred object.
We postpone the lookup to locate_object() which will be run on the generated script
"""
the_class = orm_obj._meta.object_name
original_class = the_class
pk_name = orm_obj._meta.pk.name
original_pk_name = pk_name
pk_value = getattr(orm_obj, pk_name)
while hasattr(pk_value, "_meta") and hasattr(pk_value._meta, "pk") and hasattr(pk_value._meta.pk, "name"):
the_class = pk_value._meta.object_name
pk_name = pk_value._meta.pk.name
pk_value = getattr(pk_value, pk_name)
clean_dict = make_clean_dict(orm_obj.__dict__)
for key in clean_dict:
v = clean_dict[key]
if v is not None and not isinstance(v, (six.string_types, six.integer_types, float, datetime.datetime)):
clean_dict[key] = six.u("%s" % v)
output = """ importer.locate_object(%s, "%s", %s, "%s", %s, %s ) """ % (
original_class, original_pk_name,
the_class, pk_name, pk_value, clean_dict
)
return output
class Command(BaseCommand):
help = 'Dumps the data as a customised python script.'
args = '[appname ...]'
def handle(self, *app_labels, **options):
# Get the models we want to export
models = get_models(app_labels)
# A dictionary is created to keep track of all the processed objects,
# so that foreign key references can be made using python variable names.
# This variable "context" will be passed around like the town bicycle.
context = {}
# Create a dumpscript object and let it format itself as a string
self.stdout.write(str(Script(models=models, context=context, stdout=self.stdout, stderr=self.stderr)))
self.stdout.write("\n")
def get_models(app_labels):
""" Gets a list of models for the given app labels, with some exceptions.
TODO: If a required model is referenced, it should also be included.
Or at least discovered with a get_or_create() call.
"""
from django.db.models import get_app, get_apps, get_model
from django.db.models import get_models as get_all_models
# These models are not to be output, e.g. because they can be generated automatically
# TODO: This should be "appname.modelname" string
EXCLUDED_MODELS = (ContentType, )
models = []
# If no app labels are given, return all
if not app_labels:
for app in get_apps():
models += [m for m in get_all_models(app) if m not in EXCLUDED_MODELS]
# Get all relevant apps
for app_label in app_labels:
# If a specific model is mentioned, get only that model
if "." in app_label:
app_label, model_name = app_label.split(".", 1)
models.append(get_model(app_label, model_name))
# Get all models for a given app
else:
models += [m for m in get_all_models(get_app(app_label)) if m not in EXCLUDED_MODELS]
return models
class Code(object):
""" A snippet of python script.
This keeps track of import statements and can be output to a string.
In the future, other features such as custom indentation might be included
in this class.
"""
def __init__(self, indent=-1, stdout=None, stderr=None):
if not stdout:
stdout = sys.stdout
if not stderr:
stderr = sys.stderr
self.indent = indent
self.stdout = stdout
self.stderr = stderr
def __str__(self):
""" Returns a string representation of this script.
"""
if self.imports:
self.stderr.write(repr(self.import_lines))
return flatten_blocks([""] + self.import_lines + [""] + self.lines, num_indents=self.indent)
else:
return flatten_blocks(self.lines, num_indents=self.indent)
def get_import_lines(self):
""" Takes the stored imports and converts them to lines
"""
if self.imports:
return ["from %s import %s" % (value, key) for key, value in self.imports.items()]
else:
return []
import_lines = property(get_import_lines)
class ModelCode(Code):
" Produces a python script that can recreate data for a given model class. "
def __init__(self, model, context=None, stdout=None, stderr=None):
super(ModelCode, self).__init__(indent=0, stdout=stdout, stderr=stderr)
self.model = model
if context is None:
context = {}
self.context = context
self.instances = []
def get_imports(self):
""" Returns a dictionary of import statements, with the variable being
defined as the key.
"""
return {self.model.__name__: smart_unicode(self.model.__module__)}
imports = property(get_imports)
def get_lines(self):
""" Returns a list of lists or strings, representing the code body.
Each list is a block, each string is a statement.
"""
code = []
for counter, item in enumerate(self.model._default_manager.all()):
instance = InstanceCode(instance=item, id=counter + 1, context=self.context, stdout=self.stdout, stderr=self.stderr)
self.instances.append(instance)
if instance.waiting_list:
code += instance.lines
# After each instance has been processed, try again.
# This allows self referencing fields to work.
for instance in self.instances:
if instance.waiting_list:
code += instance.lines
return code
lines = property(get_lines)
class InstanceCode(Code):
" Produces a python script that can recreate data for a given model instance. "
def __init__(self, instance, id, context=None, stdout=None, stderr=None):
""" We need the instance in question and an id """
super(InstanceCode, self).__init__(indent=0, stdout=stdout, stderr=stderr)
self.imports = {}
self.instance = instance
self.model = self.instance.__class__
if context is None:
context = {}
self.context = context
self.variable_name = "%s_%s" % (self.instance._meta.db_table, id)
self.skip_me = None
self.instantiated = False
self.waiting_list = list(self.model._meta.fields)
self.many_to_many_waiting_list = {}
for field in self.model._meta.many_to_many:
self.many_to_many_waiting_list[field] = list(getattr(self.instance, field.name).all())
def get_lines(self, force=False):
""" Returns a list of lists or strings, representing the code body.
Each list is a block, each string is a statement.
force (True or False): if an attribute object cannot be included,
it is usually skipped to be processed later. With 'force' set, there
will be no waiting: a get_or_create() call is written instead.
"""
code_lines = []
# Don't return anything if this is an instance that should be skipped
if self.skip():
return []
# Initialise our new object
# e.g. model_name_35 = Model()
code_lines += self.instantiate()
# Add each field
# e.g. model_name_35.field_one = 1034.91
# model_name_35.field_two = "text"
code_lines += self.get_waiting_list()
if force:
# TODO: Check that M2M are not affected
code_lines += self.get_waiting_list(force=force)
# Print the save command for our new object
# e.g. model_name_35.save()
if code_lines:
code_lines.append("%s = importer.save_or_locate(%s)\n" % (self.variable_name, self.variable_name))
code_lines += self.get_many_to_many_lines(force=force)
return code_lines
lines = property(get_lines)
def skip(self):
""" Determine whether or not this object should be skipped.
If this model instance is a parent of a single subclassed
instance, skip it. The subclassed instance will create this
parent instance for us.
TODO: Allow the user to force its creation?
"""
if self.skip_me is not None:
return self.skip_me
def get_skip_version():
""" Return which version of the skip code should be run
Django's deletion code was refactored in r14507 which
was just two days before 1.3 alpha 1 (r14519)
"""
if not hasattr(self, '_SKIP_VERSION'):
version = django.VERSION
# no, it isn't lisp. I swear.
self._SKIP_VERSION = (
version[0] > 1 or ( # django 2k... someday :)
version[0] == 1 and ( # 1.x
version[1] >= 4 or # 1.4+
version[1] == 3 and not ( # 1.3.x
(version[3] == 'alpha' and version[1] == 0)
)
)
)
) and 2 or 1 # NOQA
return self._SKIP_VERSION
if get_skip_version() == 1:
try:
# Django trunk since r7722 uses CollectedObjects instead of dict
from django.db.models.query import CollectedObjects
sub_objects = CollectedObjects()
except ImportError:
# previous versions don't have CollectedObjects
sub_objects = {}
self.instance._collect_sub_objects(sub_objects)
sub_objects = sub_objects.keys()
elif get_skip_version() == 2:
from django.db.models.deletion import Collector
from django.db import router
cls = self.instance.__class__
using = router.db_for_write(cls, instance=self.instance)
collector = Collector(using=using)
collector.collect([self.instance], collect_related=False)
# collector stores its instances in two places. I *think* we
# only need collector.data, but using the batches is needed
# to perfectly emulate the old behaviour
# TODO: check if batches are really needed. If not, remove them.
sub_objects = sum([list(i) for i in collector.data.values()], [])
for batch in collector.batches.values():
# batch.values can be sets, which must be converted to lists
sub_objects += sum([list(i) for i in batch.values()], [])
sub_objects_parents = [so._meta.parents for so in sub_objects]
if [self.model in p for p in sub_objects_parents].count(True) == 1:
# since this instance isn't explicitly created, it's variable name
# can't be referenced in the script, so record None in context dict
pk_name = self.instance._meta.pk.name
key = '%s_%s' % (self.model.__name__, getattr(self.instance, pk_name))
self.context[key] = None
self.skip_me = True
else:
self.skip_me = False
return self.skip_me
def instantiate(self):
" Write lines for instantiation "
# e.g. model_name_35 = Model()
code_lines = []
if not self.instantiated:
code_lines.append("%s = %s()" % (self.variable_name, self.model.__name__))
self.instantiated = True
# Store our variable name for future foreign key references
pk_name = self.instance._meta.pk.name
key = '%s_%s' % (self.model.__name__, getattr(self.instance, pk_name))
self.context[key] = self.variable_name
return code_lines
def get_waiting_list(self, force=False):
" Add lines for any waiting fields that can be completed now. "
code_lines = []
# Process normal fields
for field in list(self.waiting_list):
try:
# Find the value, add the line, remove from waiting list and move on
value = get_attribute_value(self.instance, field, self.context, force=force)
code_lines.append('%s.%s = %s' % (self.variable_name, field.name, value))
self.waiting_list.remove(field)
except SkipValue:
# Remove from the waiting list and move on
self.waiting_list.remove(field)
continue
except DoLater:
# Move on, maybe next time
continue
return code_lines
def get_many_to_many_lines(self, force=False):
""" Generates lines that define many to many relations for this instance. """
lines = []
for field, rel_items in self.many_to_many_waiting_list.items():
for rel_item in list(rel_items):
try:
pk_name = rel_item._meta.pk.name
key = '%s_%s' % (rel_item.__class__.__name__, getattr(rel_item, pk_name))
value = "%s" % self.context[key]
lines.append('%s.%s.add(%s)' % (self.variable_name, field.name, value))
self.many_to_many_waiting_list[field].remove(rel_item)
except KeyError:
if force:
item_locator = orm_item_locator(rel_item)
self.context["__extra_imports"][rel_item._meta.object_name] = rel_item.__module__
lines.append('%s.%s.add( %s )' % (self.variable_name, field.name, item_locator))
self.many_to_many_waiting_list[field].remove(rel_item)
if lines:
lines.append("")
return lines
class Script(Code):
" Produces a complete python script that can recreate data for the given apps. "
def __init__(self, models, context=None, stdout=None, stderr=None):
super(Script, self).__init__(stdout=stdout, stderr=stderr)
self.imports = {}
self.models = models
if context is None:
context = {}
self.context = context
self.context["__avaliable_models"] = set(models)
self.context["__extra_imports"] = {}
def _queue_models(self, models, context):
""" Works an an appropriate ordering for the models.
This isn't essential, but makes the script look nicer because
more instances can be defined on their first try.
"""
# Max number of cycles allowed before we call it an infinite loop.
MAX_CYCLES = 5
model_queue = []
number_remaining_models = len(models)
allowed_cycles = MAX_CYCLES
while number_remaining_models > 0:
previous_number_remaining_models = number_remaining_models
model = models.pop(0)
# If the model is ready to be processed, add it to the list
if check_dependencies(model, model_queue, context["__avaliable_models"]):
model_class = ModelCode(model=model, context=context, stdout=self.stdout, stderr=self.stderr)
model_queue.append(model_class)
# Otherwise put the model back at the end of the list
else:
models.append(model)
# Check for infinite loops.
# This means there is a cyclic foreign key structure
# That cannot be resolved by re-ordering
number_remaining_models = len(models)
if number_remaining_models == previous_number_remaining_models:
allowed_cycles -= 1
if allowed_cycles <= 0:
# Add the remaining models, but do not remove them from the model list
missing_models = [ModelCode(model=m, context=context, stdout=self.stdout, stderr=self.stderr) for m in models]
model_queue += missing_models
# Replace the models with the model class objects
# (sure, this is a little bit of hackery)
models[:] = missing_models
break
else:
allowed_cycles = MAX_CYCLES
return model_queue
def get_lines(self):
""" Returns a list of lists or strings, representing the code body.
Each list is a block, each string is a statement.
"""
code = [self.FILE_HEADER.strip()]
# Queue and process the required models
for model_class in self._queue_models(self.models, context=self.context):
msg = 'Processing model: %s\n' % model_class.model.__name__
self.stderr.write(msg)
code.append(" #" + msg)
code.append(model_class.import_lines)
code.append("")
code.append(model_class.lines)
# Process left over foreign keys from cyclic models
for model in self.models:
msg = 'Re-processing model: %s\n' % model.model.__name__
self.stderr.write(msg)
code.append(" #" + msg)
for instance in model.instances:
if instance.waiting_list or instance.many_to_many_waiting_list:
code.append(instance.get_lines(force=True))
code.insert(1, " #initial imports")
code.insert(2, "")
for key, value in self.context["__extra_imports"].items():
code.insert(2, " from %s import %s" % (value, key))
return code
lines = property(get_lines)
# A user-friendly file header
FILE_HEADER = """
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file has been automatically generated.
# Instead of changing it, create a file called import_helper.py
# and put there a class called ImportHelper(object) in it.
#
# This class will be specially casted so that instead of extending object,
# it will actually extend the class BasicImportHelper()
#
# That means you just have to overload the methods you want to
# change, leaving the other ones inteact.
#
# Something that you might want to do is use transactions, for example.
#
# Also, don't forget to add the necessary Django imports.
#
# This file was generated with the following command:
# %s
#
# to restore it, run
# manage.py runscript module_name.this_script_name
#
# example: if manage.py is at ./manage.py
# and the script is at ./some_folder/some_script.py
# you must make sure ./some_folder/__init__.py exists
# and run ./manage.py runscript some_folder.some_script
from django.db import transaction
class BasicImportHelper(object):
def pre_import(self):
pass
# You probably want to uncomment on of these two lines
# @transaction.atomic # Django 1.6
# @transaction.commit_on_success # Django <1.6
def run_import(self, import_data):
import_data()
def post_import(self):
pass
def locate_similar(self, current_object, search_data):
#you will probably want to call this method from save_or_locate()
#example:
#new_obj = self.locate_similar(the_obj, {"national_id": the_obj.national_id } )
the_obj = current_object.__class__.objects.get(**search_data)
return the_obj
def locate_object(self, original_class, original_pk_name, the_class, pk_name, pk_value, obj_content):
#You may change this function to do specific lookup for specific objects
#
#original_class class of the django orm's object that needs to be located
#original_pk_name the primary key of original_class
#the_class parent class of original_class which contains obj_content
#pk_name the primary key of original_class
#pk_value value of the primary_key
#obj_content content of the object which was not exported.
#
#you should use obj_content to locate the object on the target db
#
#and example where original_class and the_class are different is
#when original_class is Farmer and
#the_class is Person. The table may refer to a Farmer but you will actually
#need to locate Person in order to instantiate that Farmer
#
#example:
#if the_class == SurveyResultFormat or the_class == SurveyType or the_class == SurveyState:
# pk_name="name"
# pk_value=obj_content[pk_name]
#if the_class == StaffGroup:
# pk_value=8
search_data = { pk_name: pk_value }
the_obj = the_class.objects.get(**search_data)
#print(the_obj)
return the_obj
def save_or_locate(self, the_obj):
#change this if you want to locate the object in the database
try:
the_obj.save()
except:
print("---------------")
print("Error saving the following object:")
print(the_obj.__class__)
print(" ")
print(the_obj.__dict__)
print(" ")
print(the_obj)
print(" ")
print("---------------")
raise
return the_obj
importer = None
try:
import import_helper
#we need this so ImportHelper can extend BasicImportHelper, although import_helper.py
#has no knowlodge of this class
importer = type("DynamicImportHelper", (import_helper.ImportHelper, BasicImportHelper ) , {} )()
except ImportError as e:
if str(e) == "No module named import_helper":
importer = BasicImportHelper()
else:
raise
import datetime
from decimal import Decimal
from django.contrib.contenttypes.models import ContentType
def run():
importer.pre_import()
importer.run_import(import_data)
importer.post_import()
def import_data():
""" % " ".join(sys.argv)
# HELPER FUNCTIONS
#-------------------------------------------------------------------------------
def flatten_blocks(lines, num_indents=-1):
""" Takes a list (block) or string (statement) and flattens it into a string
with indentation.
"""
# The standard indent is four spaces
INDENTATION = " " * 4
if not lines:
return ""
# If this is a string, add the indentation and finish here
if isinstance(lines, six.string_types):
return INDENTATION * num_indents + lines
# If this is not a string, join the lines and recurse
return "\n".join([flatten_blocks(line, num_indents + 1) for line in lines])
def get_attribute_value(item, field, context, force=False):
""" Gets a string version of the given attribute's value, like repr() might. """
# Find the value of the field, catching any database issues
try:
value = getattr(item, field.name)
except ObjectDoesNotExist:
raise SkipValue('Could not find object for %s.%s, ignoring.\n' % (item.__class__.__name__, field.name))
# AutoField: We don't include the auto fields, they'll be automatically recreated
if isinstance(field, AutoField):
raise SkipValue()
# Some databases (eg MySQL) might store boolean values as 0/1, this needs to be cast as a bool
elif isinstance(field, BooleanField) and value is not None:
return repr(bool(value))
# Post file-storage-refactor, repr() on File/ImageFields no longer returns the path
elif isinstance(field, FileField):
return repr(force_unicode(value))
# ForeignKey fields, link directly using our stored python variable name
elif isinstance(field, ForeignKey) and value is not None:
# Special case for contenttype foreign keys: no need to output any
# content types in this script, as they can be generated again
# automatically.
# NB: Not sure if "is" will always work
if field.rel.to is ContentType:
return 'ContentType.objects.get(app_label="%s", model="%s")' % (value.app_label, value.model)
# Generate an identifier (key) for this foreign object
pk_name = value._meta.pk.name
key = '%s_%s' % (value.__class__.__name__, getattr(value, pk_name))
if key in context:
variable_name = context[key]
# If the context value is set to None, this should be skipped.
# This identifies models that have been skipped (inheritance)
if variable_name is None:
raise SkipValue()
# Return the variable name listed in the context
return "%s" % variable_name
elif value.__class__ not in context["__avaliable_models"] or force:
context["__extra_imports"][value._meta.object_name] = value.__module__
item_locator = orm_item_locator(value)
return item_locator
else:
raise DoLater('(FK) %s.%s\n' % (item.__class__.__name__, field.name))
# A normal field (e.g. a python built-in)
else:
return repr(value)
def make_clean_dict(the_dict):
if "_state" in the_dict:
clean_dict = the_dict.copy()
del clean_dict["_state"]
return clean_dict
return the_dict
def check_dependencies(model, model_queue, avaliable_models):
" Check that all the depenedencies for this model are already in the queue. "
# A list of allowed links: existing fields, itself and the special case ContentType
allowed_links = [m.model.__name__ for m in model_queue] + [model.__name__, 'ContentType']
# For each ForeignKey or ManyToMany field, check that a link is possible
for field in model._meta.fields:
if field.rel and field.rel.to.__name__ not in allowed_links:
if field.rel.to not in avaliable_models:
continue
return False
for field in model._meta.many_to_many:
if field.rel and field.rel.to.__name__ not in allowed_links:
return False
return True
# EXCEPTIONS
#-------------------------------------------------------------------------------
class SkipValue(Exception):
""" Value could not be parsed or should simply be skipped. """
class DoLater(Exception):
""" Value could not be parsed or should simply be skipped. """

View file

@ -0,0 +1,133 @@
from django.core.management.base import BaseCommand, CommandError
try:
from django.contrib.auth import get_user_model # Django 1.5
except ImportError:
from django_extensions.future_1_5 import get_user_model
from django.contrib.auth.models import Group
from optparse import make_option
from sys import stdout
from csv import writer
import six
FORMATS = [
'address',
'emails',
'google',
'outlook',
'linkedin',
'vcard',
]
def full_name(first_name, last_name, username, **extra):
name = six.u(" ").join(n for n in [first_name, last_name] if n)
if not name:
return username
return name
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--group', '-g', action='store', dest='group', default=None,
help='Limit to users which are part of the supplied group name'),
make_option('--format', '-f', action='store', dest='format', default=FORMATS[0],
help="output format. May be one of '" + "', '".join(FORMATS) + "'."),
)
help = ("Export user email address list in one of a number of formats.")
args = "[output file]"
label = 'filename to save to'
requires_model_validation = True
can_import_settings = True
encoding = 'utf-8' # RED_FLAG: add as an option -DougN
def handle(self, *args, **options):
if len(args) > 1:
raise CommandError("extra arguments supplied")
group = options['group']
if group and not Group.objects.filter(name=group).count() == 1:
names = six.u("', '").join(g['name'] for g in Group.objects.values('name')).encode('utf-8')
if names:
names = "'" + names + "'."
raise CommandError("Unknown group '" + group + "'. Valid group names are: " + names)
if len(args) and args[0] != '-':
outfile = open(args[0], 'w')
else:
outfile = stdout
User = get_user_model()
qs = User.objects.all().order_by('last_name', 'first_name', 'username', 'email')
if group:
qs = qs.filter(group__name=group).distinct()
qs = qs.values('last_name', 'first_name', 'username', 'email')
getattr(self, options['format'])(qs, outfile)
def address(self, qs, out):
"""simple single entry per line in the format of:
"full name" <my@address.com>;
"""
out.write(six.u("\n").join(six.u('"%s" <%s>;' % (full_name(**ent), ent['email']))
for ent in qs).encode(self.encoding))
out.write("\n")
def emails(self, qs, out):
"""simpler single entry with email only in the format of:
my@address.com,
"""
out.write(six.u(",\n").join(six.u('%s' % (ent['email'])) for ent in qs).encode(self.encoding))
out.write("\n")
def google(self, qs, out):
"""CSV format suitable for importing into google GMail
"""
csvf = writer(out)
csvf.writerow(['Name', 'Email'])
for ent in qs:
csvf.writerow([full_name(**ent).encode(self.encoding),
ent['email'].encode(self.encoding)])
def outlook(self, qs, out):
"""CSV format suitable for importing into outlook
"""
csvf = writer(out)
columns = ['Name', 'E-mail Address', 'Notes', 'E-mail 2 Address', 'E-mail 3 Address',
'Mobile Phone', 'Pager', 'Company', 'Job Title', 'Home Phone', 'Home Phone 2',
'Home Fax', 'Home Address', 'Business Phone', 'Business Phone 2',
'Business Fax', 'Business Address', 'Other Phone', 'Other Fax', 'Other Address']
csvf.writerow(columns)
empty = [''] * (len(columns) - 2)
for ent in qs:
csvf.writerow([full_name(**ent).encode(self.encoding),
ent['email'].encode(self.encoding)] + empty)
def linkedin(self, qs, out):
"""CSV format suitable for importing into linkedin Groups.
perfect for pre-approving members of a linkedin group.
"""
csvf = writer(out)
csvf.writerow(['First Name', 'Last Name', 'Email'])
for ent in qs:
csvf.writerow([ent['first_name'].encode(self.encoding),
ent['last_name'].encode(self.encoding),
ent['email'].encode(self.encoding)])
def vcard(self, qs, out):
try:
import vobject
except ImportError:
print(self.style.ERROR("Please install python-vobject to use the vcard export format."))
import sys
sys.exit(1)
for ent in qs:
card = vobject.vCard()
card.add('fn').value = full_name(**ent)
if not ent['last_name'] and not ent['first_name']:
# fallback to fullname, if both first and lastname are not declared
card.add('n').value = vobject.vcard.Name(full_name(**ent))
else:
card.add('n').value = vobject.vcard.Name(ent['last_name'], ent['first_name'])
emailpart = card.add('email')
emailpart.value = ent['email']
emailpart.type_param = 'INTERNET'
out.write(card.serialize().encode(self.encoding))

View file

@ -0,0 +1,35 @@
from django.core.management.base import LabelCommand
from django.template import loader
from django.template import TemplateDoesNotExist
import sys
def get_template_path(path):
try:
template = loader.find_template(path)
if template[1]:
return template[1].name
# work arround https://code.djangoproject.com/ticket/17199 issue
for template_loader in loader.template_source_loaders:
try:
source, origin = template_loader.load_template_source(path)
return origin
except TemplateDoesNotExist:
pass
raise TemplateDoesNotExist(path)
except TemplateDoesNotExist:
return None
class Command(LabelCommand):
help = "Finds the location of the given template by resolving its path"
args = "[template_path]"
label = 'template path'
def handle_label(self, template_path, **options):
path = get_template_path(template_path)
if path is None:
sys.stderr.write("No template found\n")
sys.exit(1)
else:
print(path)

View file

@ -0,0 +1,11 @@
from random import choice
from django.core.management.base import NoArgsCommand
class Command(NoArgsCommand):
help = "Generates a new SECRET_KEY that can be used in a project settings file."
requires_model_validation = False
def handle_noargs(self, **options):
return ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])

View file

@ -0,0 +1,143 @@
import sys
from optparse import make_option, NO_DEFAULT
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
from django_extensions.management.modelviz import generate_dot
try:
import pygraphviz
HAS_PYGRAPHVIZ = True
except ImportError:
HAS_PYGRAPHVIZ = False
try:
import pydot
HAS_PYDOT = True
except ImportError:
HAS_PYDOT = False
class Command(BaseCommand):
graph_models_options = (
make_option('--pygraphviz', action='store_true', dest='pygraphviz',
help='Use PyGraphViz to generate the image.'),
make_option('--pydot', action='store_true', dest='pydot',
help='Use PyDot to generate the image.'),
make_option('--disable-fields', '-d', action='store_true', dest='disable_fields',
help='Do not show the class member fields'),
make_option('--group-models', '-g', action='store_true', dest='group_models',
help='Group models together respective to their application'),
make_option('--all-applications', '-a', action='store_true', dest='all_applications',
help='Automatically include all applications from INSTALLED_APPS'),
make_option('--output', '-o', action='store', dest='outputfile',
help='Render output file. Type of output dependend on file extensions. Use png or jpg to render graph to image.'),
make_option('--layout', '-l', action='store', dest='layout', default='dot',
help='Layout to be used by GraphViz for visualization. Layouts: circo dot fdp neato nop nop1 nop2 twopi'),
make_option('--verbose-names', '-n', action='store_true', dest='verbose_names',
help='Use verbose_name of models and fields'),
make_option('--language', '-L', action='store', dest='language',
help='Specify language used for verbose_name localization'),
make_option('--exclude-columns', '-x', action='store', dest='exclude_columns',
help='Exclude specific column(s) from the graph. Can also load exclude list from file.'),
make_option('--exclude-models', '-X', action='store', dest='exclude_models',
help='Exclude specific model(s) from the graph. Can also load exclude list from file.'),
make_option('--inheritance', '-e', action='store_true', dest='inheritance', default=True,
help='Include inheritance arrows (default)'),
make_option('--no-inheritance', '-E', action='store_false', dest='inheritance',
help='Include inheritance arrows'),
make_option('--hide-relations-from-fields', '-R', action='store_false', dest="relations_as_fields",
default=True, help="Do not show relations as fields in the graph."),
make_option('--disable-sort-fields', '-S', action="store_false", dest="sort_fields",
default=True, help="Do not sort fields"),
)
option_list = BaseCommand.option_list + graph_models_options
help = "Creates a GraphViz dot file for the specified app names. You can pass multiple app names and they will all be combined into a single model. Output is usually directed to a dot file."
args = "[appname]"
label = 'application name'
requires_model_validation = True
can_import_settings = True
def handle(self, *args, **options):
self.options_from_settings(options)
if len(args) < 1 and not options['all_applications']:
raise CommandError("need one or more arguments for appname")
use_pygraphviz = options.get('pygraphviz', False)
use_pydot = options.get('pydot', False)
cli_options = ' '.join(sys.argv[2:])
dotdata = generate_dot(args, cli_options=cli_options, **options)
dotdata = dotdata.encode('utf-8')
if options['outputfile']:
if not use_pygraphviz and not use_pydot:
if HAS_PYGRAPHVIZ:
use_pygraphviz = True
elif HAS_PYDOT:
use_pydot = True
if use_pygraphviz:
self.render_output_pygraphviz(dotdata, **options)
elif use_pydot:
self.render_output_pydot(dotdata, **options)
else:
raise CommandError("Neither pygraphviz nor pydot could be found to generate the image")
else:
self.print_output(dotdata)
def options_from_settings(self, options):
defaults = getattr(settings, 'GRAPH_MODELS', None)
if defaults:
for option in self.graph_models_options:
long_opt = option._long_opts[0]
if long_opt:
long_opt = long_opt.lstrip("-").replace("-", "_")
if long_opt in defaults:
default_value = None
if not option.default == NO_DEFAULT:
default_value = option.default
if options[option.dest] == default_value:
options[option.dest] = defaults[long_opt]
def print_output(self, dotdata):
print(dotdata)
def render_output_pygraphviz(self, dotdata, **kwargs):
"""Renders the image using pygraphviz"""
if not HAS_PYGRAPHVIZ:
raise CommandError("You need to install pygraphviz python module")
version = pygraphviz.__version__.rstrip("-svn")
try:
if tuple(int(v) for v in version.split('.')) < (0, 36):
# HACK around old/broken AGraph before version 0.36 (ubuntu ships with this old version)
import tempfile
tmpfile = tempfile.NamedTemporaryFile()
tmpfile.write(dotdata)
tmpfile.seek(0)
dotdata = tmpfile.name
except ValueError:
pass
graph = pygraphviz.AGraph(dotdata)
graph.layout(prog=kwargs['layout'])
graph.draw(kwargs['outputfile'])
def render_output_pydot(self, dotdata, **kwargs):
"""Renders the image using pydot"""
if not HAS_PYDOT:
raise CommandError("You need to install pydot python module")
graph = pydot.graph_from_dot_data(dotdata)
if not graph:
raise CommandError("pydot returned an error")
output_file = kwargs['outputfile']
formats = ['bmp', 'canon', 'cmap', 'cmapx', 'cmapx_np', 'dot', 'dia', 'emf',
'em', 'fplus', 'eps', 'fig', 'gd', 'gd2', 'gif', 'gv', 'imap',
'imap_np', 'ismap', 'jpe', 'jpeg', 'jpg', 'metafile', 'pdf',
'pic', 'plain', 'plain-ext', 'png', 'pov', 'ps', 'ps2', 'svg',
'svgz', 'tif', 'tiff', 'tk', 'vml', 'vmlz', 'vrml', 'wbmp', 'xdot']
ext = output_file[output_file.rfind('.') + 1:]
format = ext if ext in formats else 'raw'
graph.write(output_file, format=format)

View file

@ -0,0 +1,80 @@
from django_extensions.management.utils import setup_logger
from django.core.management.base import BaseCommand, CommandError
from optparse import make_option
from smtpd import SMTPServer
import sys
import asyncore
from logging import getLogger
logger = getLogger(__name__)
class ExtensionDebuggingServer(SMTPServer):
"""Duplication of smtpd.DebuggingServer, but using logging instead of print."""
# Do something with the gathered message
def process_message(self, peer, mailfrom, rcpttos, data):
"""Output will be sent to the module logger at INFO level."""
inheaders = 1
lines = data.split('\n')
logger.info('---------- MESSAGE FOLLOWS ----------')
for line in lines:
# headers first
if inheaders and not line:
logger.info('X-Peer: %s' % peer[0])
inheaders = 0
logger.info(line)
logger.info('------------ END MESSAGE ------------')
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--output', dest='output_file', default=None,
help='Specifies an output file to send a copy of all messages (not flushed immediately).'),
make_option('--use-settings', dest='use_settings',
action='store_true', default=False,
help='Uses EMAIL_HOST and HOST_PORT from Django settings.'),
)
help = "Starts a test mail server for development."
args = '[optional port number or ippaddr:port]'
requires_model_validation = False
def handle(self, addrport='', *args, **options):
if args:
raise CommandError('Usage is mail_debug %s' % self.args)
if not addrport:
if options.get('use_settings', False):
from django.conf import settings
addr = getattr(settings, 'EMAIL_HOST', '')
port = str(getattr(settings, 'EMAIL_PORT', '1025'))
else:
addr = ''
port = '1025'
else:
try:
addr, port = addrport.split(':')
except ValueError:
addr, port = '', addrport
if not addr:
addr = '127.0.0.1'
if not port.isdigit():
raise CommandError("%r is not a valid port number." % port)
else:
port = int(port)
# Add console handler
setup_logger(logger, stream=self.stdout, filename=options.get('output_file', None))
def inner_run():
quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'
print("Now accepting mail at %s:%s -- use %s to quit" % (addr, port, quit_command))
ExtensionDebuggingServer((addr, port), None)
asyncore.loop()
try:
inner_run()
except KeyboardInterrupt:
pass

View file

@ -0,0 +1,48 @@
from __future__ import with_statement
from django.core.management.base import BaseCommand
from django.conf import settings
import os
import re
ANNOTATION_RE = re.compile("\{?#[\s]*?(TODO|FIXME|BUG|HACK|WARNING|NOTE|XXX)[\s:]?(.+)")
ANNOTATION_END_RE = re.compile("(.*)#\}(.*)")
class Command(BaseCommand):
help = 'Show all annotations like TODO, FIXME, BUG, HACK, WARNING, NOTE or XXX in your py and HTML files.'
args = 'tag'
label = 'annotation tag (TODO, FIXME, BUG, HACK, WARNING, NOTE, XXX)'
def handle(self, *args, **options):
# don't add django internal code
apps = filter(lambda app: not app.startswith('django.contrib'), settings.INSTALLED_APPS)
template_dirs = getattr(settings, 'TEMPLATE_DIRS', [])
if template_dirs:
apps += template_dirs
for app_dir in apps:
app_dir = app_dir.replace(".", "/")
for top, dirs, files in os.walk(app_dir):
for f in files:
if os.path.splitext(f)[1] in ('.py', '.html'):
fpath = os.path.join(top, f)
annotation_lines = []
with open(fpath, 'r') as f:
i = 0
for line in f.readlines():
i += 1
if ANNOTATION_RE.search(line):
tag, msg = ANNOTATION_RE.findall(line)[0]
if len(args) == 1:
search_for_tag = args[0].upper()
if not search_for_tag == tag:
break
if ANNOTATION_END_RE.search(msg.strip()):
msg = ANNOTATION_END_RE.findall(msg.strip())[0][0]
annotation_lines.append("[%3s] %-5s %s" % (i, tag, msg.strip()))
if annotation_lines:
print("%s:" % fpath)
for annotation in annotation_lines:
print(" * %s" % annotation)
print("")

View file

@ -0,0 +1,42 @@
from django.core.management.base import BaseCommand, CommandError
try:
from django.contrib.auth import get_user_model # Django 1.5
except ImportError:
from django_extensions.future_1_5 import get_user_model
import getpass
class Command(BaseCommand):
help = "Clone of the UNIX program ``passwd'', for django.contrib.auth."
requires_model_validation = False
def handle(self, *args, **options):
if len(args) > 1:
raise CommandError("need exactly one or zero arguments for username")
if args:
username, = args
else:
username = getpass.getuser()
User = get_user_model()
try:
u = User.objects.get(username=username)
except User.DoesNotExist:
raise CommandError("user %s does not exist" % username)
print("Changing password for user: %s" % u.username)
p1 = p2 = ""
while "" in (p1, p2) or p1 != p2:
p1 = getpass.getpass()
p2 = getpass.getpass("Password (again): ")
if p1 != p2:
print("Passwords do not match, try again")
elif "" in (p1, p2):
raise CommandError("aborted")
u.set_password(p1)
u.save()
return "Password changed successfully for user %s\n" % u.username

View file

@ -0,0 +1,256 @@
#!/usr/bin/env python
import os
import pip
import sys
import json
import urllib2
import urlparse
import xmlrpclib
from distutils.version import LooseVersion
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
from optparse import make_option
from django.core.management.base import NoArgsCommand
from django_extensions.management.color import color_style
from pip.req import parse_requirements
class Command(NoArgsCommand):
option_list = NoArgsCommand.option_list + (
make_option(
"-t", "--github-api-token", action="store", dest="github_api_token",
help="A github api authentication token."
),
make_option(
"-r", "--requirement", action="append", dest="requirements",
default=[], metavar="FILENAME",
help="Check all the packages listed in the given requirements file. "
"This option can be used multiple times."
),
make_option(
"-n", "--newer", action="store_true", dest="show_newer",
help="Also show when newer version then available is installed."
),
)
help = "Scan pip requirement files for out-of-date packages."
def handle_noargs(self, **options):
self.style = color_style()
self.options = options
if options["requirements"]:
req_files = options["requirements"]
elif os.path.exists("requirements.txt"):
req_files = ["requirements.txt"]
elif os.path.exists("requirements"):
req_files = ["requirements/{0}".format(f) for f in os.listdir("requirements")
if os.path.isfile(os.path.join("requirements", f)) and
f.lower().endswith(".txt")]
else:
sys.exit("requirements not found")
self.reqs = {}
for filename in req_files:
class Object(object):
pass
mockoptions = Object()
mockoptions.default_vcs = "git"
mockoptions.skip_requirements_regex = None
for req in parse_requirements(filename, options=mockoptions):
self.reqs[req.name] = {
"pip_req": req,
"url": req.url,
}
if options["github_api_token"]:
self.github_api_token = options["github_api_token"]
elif os.environ.get("GITHUB_API_TOKEN"):
self.github_api_token = os.environ.get("GITHUB_API_TOKEN")
else:
self.github_api_token = None # only 50 requests per hour
self.check_pypi()
if HAS_REQUESTS:
self.check_github()
else:
print(self.style.ERROR("Cannot check github urls. The requests library is not installed. ( pip install requests )"))
self.check_other()
def _urlopen_as_json(self, url, headers=None):
"""Shorcut for return contents as json"""
req = urllib2.Request(url, headers=headers)
return json.loads(urllib2.urlopen(req).read())
def check_pypi(self):
"""
If the requirement is frozen to pypi, check for a new version.
"""
for dist in pip.get_installed_distributions():
name = dist.project_name
if name in self.reqs.keys():
self.reqs[name]["dist"] = dist
pypi = xmlrpclib.ServerProxy("http://pypi.python.org/pypi")
for name, req in self.reqs.items():
if req["url"]:
continue # skipping github packages.
elif "dist" in req:
dist = req["dist"]
dist_version = LooseVersion(dist.version)
available = pypi.package_releases(req["pip_req"].url_name)
try:
available_version = LooseVersion(available[0])
except IndexError:
available_version = None
if not available_version:
msg = self.style.WARN("release is not on pypi (check capitalization and/or --extra-index-url)")
elif self.options['show_newer'] and dist_version > available_version:
msg = self.style.INFO("{0} available (newer installed)".format(available_version))
elif available_version > dist_version:
msg = self.style.INFO("{0} available".format(available_version))
else:
msg = "up to date"
del self.reqs[name]
continue
pkg_info = self.style.BOLD("{dist.project_name} {dist.version}".format(dist=dist))
else:
msg = "not installed"
pkg_info = name
print("{pkg_info:40} {msg}".format(pkg_info=pkg_info, msg=msg))
del self.reqs[name]
def check_github(self):
"""
If the requirement is frozen to a github url, check for new commits.
API Tokens
----------
For more than 50 github api calls per hour, pipchecker requires
authentication with the github api by settings the environemnt
variable ``GITHUB_API_TOKEN`` or setting the command flag
--github-api-token='mytoken'``.
To create a github api token for use at the command line::
curl -u 'rizumu' -d '{"scopes":["repo"], "note":"pipchecker"}' https://api.github.com/authorizations
For more info on github api tokens:
https://help.github.com/articles/creating-an-oauth-token-for-command-line-use
http://developer.github.com/v3/oauth/#oauth-authorizations-api
Requirement Format
------------------
Pipchecker gets the sha of frozen repo and checks if it is
found at the head of any branches. If it is not found then
the requirement is considered to be out of date.
Therefore, freezing at the commit hash will provide the expected
results, but if freezing at a branch or tag name, pipchecker will
not be able to determine with certainty if the repo is out of date.
Freeze at the commit hash (sha)::
git+git://github.com/django/django.git@393c268e725f5b229ecb554f3fac02cfc250d2df#egg=Django
Freeze with a branch name::
git+git://github.com/django/django.git@master#egg=Django
Freeze with a tag::
git+git://github.com/django/django.git@1.5b2#egg=Django
Do not freeze::
git+git://github.com/django/django.git#egg=Django
"""
for name, req in self.reqs.items():
req_url = req["url"]
if req_url.startswith("git") and "github.com/" not in req_url:
continue
headers = {
"content-type": "application/json",
}
if self.github_api_token:
headers["Authorization"] = "token {0}".format(self.github_api_token)
try:
user, repo = urlparse.urlparse(req_url).path.split("#")[0].strip("/").rstrip("/").split("/")
except (ValueError, IndexError) as e:
print(self.style.ERROR("\nFailed to parse %r: %s\n" % (req_url, e)))
continue
try:
#test_auth = self._urlopen_as_json("https://api.github.com/django/", headers=headers)
test_auth = requests.get("https://api.github.com/django/", headers=headers).json()
except urllib2.HTTPError as e:
print("\n%s\n" % str(e))
return
if "message" in test_auth and test_auth["message"] == "Bad credentials":
print(self.style.ERROR("\nGithub API: Bad credentials. Aborting!\n"))
return
elif "message" in test_auth and test_auth["message"].startswith("API Rate Limit Exceeded"):
print(self.style.ERROR("\nGithub API: Rate Limit Exceeded. Aborting!\n"))
return
frozen_commit_sha = None
if ".git" in repo:
repo_name, frozen_commit_full = repo.split(".git")
if frozen_commit_full.startswith("@"):
frozen_commit_sha = frozen_commit_full[1:]
elif "@" in repo:
repo_name, frozen_commit_sha = repo.split("@")
if frozen_commit_sha is None:
msg = self.style.ERROR("repo is not frozen")
if frozen_commit_sha:
branch_url = "https://api.github.com/repos/{0}/{1}/branches".format(user, repo_name)
#branch_data = self._urlopen_as_json(branch_url, headers=headers)
branch_data = requests.get(branch_url, headers=headers).json()
frozen_commit_url = "https://api.github.com/repos/{0}/{1}/commits/{2}".format(
user, repo_name, frozen_commit_sha
)
#frozen_commit_data = self._urlopen_as_json(frozen_commit_url, headers=headers)
frozen_commit_data = requests.get(frozen_commit_url, headers=headers).json()
if "message" in frozen_commit_data and frozen_commit_data["message"] == "Not Found":
msg = self.style.ERROR("{0} not found in {1}. Repo may be private.".format(frozen_commit_sha[:10], name))
elif frozen_commit_sha in [branch["commit"]["sha"] for branch in branch_data]:
msg = self.style.BOLD("up to date")
else:
msg = self.style.INFO("{0} is not the head of any branch".format(frozen_commit_data["sha"][:10]))
if "dist" in req:
pkg_info = "{dist.project_name} {dist.version}".format(dist=req["dist"])
elif frozen_commit_sha is None:
pkg_info = name
else:
pkg_info = "{0} {1}".format(name, frozen_commit_sha[:10])
print("{pkg_info:40} {msg}".format(pkg_info=pkg_info, msg=msg))
del self.reqs[name]
def check_other(self):
"""
If the requirement is frozen somewhere other than pypi or github, skip.
If you have a private pypi or use --extra-index-url, consider contributing
support here.
"""
if self.reqs:
print(self.style.ERROR("\nOnly pypi and github based requirements are supported:"))
for name, req in self.reqs.items():
if "dist" in req:
pkg_info = "{dist.project_name} {dist.version}".format(dist=req["dist"])
elif "url" in req:
pkg_info = "{url}".format(url=req["url"])
else:
pkg_info = "unknown package"
print(self.style.BOLD("{pkg_info:40} is not a pypi or github requirement".format(pkg_info=pkg_info)))

View file

@ -0,0 +1,72 @@
"""
print_settings
==============
Django command similar to 'diffsettings' but shows all active Django settings.
"""
from django.core.management.base import NoArgsCommand
from django.conf import settings
from optparse import make_option
class Command(NoArgsCommand):
"""print_settings command"""
help = "Print the active Django settings."
option_list = NoArgsCommand.option_list + (
make_option('--format', default='simple', dest='format',
help='Specifies output format.'),
make_option('--indent', default=4, dest='indent', type='int',
help='Specifies indent level for JSON and YAML'),
)
def handle_noargs(self, **options):
a_dict = {}
for attr in dir(settings):
if self.include_attr(attr):
value = getattr(settings, attr)
a_dict[attr] = value
output_format = options.get('format', 'json')
indent = options.get('indent', 4)
if output_format == 'json':
json = self.import_json()
print(json.dumps(a_dict, indent=indent))
elif output_format == 'yaml':
import yaml # requires PyYAML
print(yaml.dump(a_dict, indent=indent))
elif output_format == 'pprint':
from pprint import pprint
pprint(a_dict)
else:
self.print_simple(a_dict)
@staticmethod
def include_attr(attr):
"""Whether or not to include attribute in output"""
if attr.startswith('__'):
return False
else:
return True
@staticmethod
def print_simple(a_dict):
"""A very simple output format"""
for key, value in a_dict.items():
print('%-40s = %r' % (key, value))
@staticmethod
def import_json():
"""Import a module for JSON"""
try:
import json
except ImportError:
import simplejson as json # NOQA
return json

View file

@ -0,0 +1,66 @@
from importlib import import_module
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
try:
from django.contrib.auth import get_user_model # Django 1.5
except ImportError:
from django_extensions.future_1_5 import get_user_model
try:
from django.contrib.sessions.backends.base import VALID_KEY_CHARS # Django 1.5
except ImportError:
VALID_KEY_CHARS = "abcdef0123456789"
class Command(BaseCommand):
help = ("print the user information for the provided session key. "
"this is very helpful when trying to track down the person who "
"experienced a site crash.")
args = "session_key"
label = 'session key for the user'
requires_model_validation = True
can_import_settings = True
def handle(self, *args, **options):
if len(args) > 1:
raise CommandError("extra arguments supplied")
if len(args) < 1:
raise CommandError("session_key argument missing")
key = args[0].lower()
if not set(key).issubset(set(VALID_KEY_CHARS)):
raise CommandError("malformed session key")
engine = import_module(settings.SESSION_ENGINE)
if not engine.SessionStore().exists(key):
print("Session Key does not exist. Expired?")
return
session = engine.SessionStore(key)
data = session.load()
print('Session to Expire: %s' % session.get_expiry_date())
print('Raw Data: %s' % data)
uid = data.get('_auth_user_id', None)
if uid is None:
print('No user associated with session')
return
print("User id: %s" % uid)
User = get_user_model()
try:
user = User.objects.get(pk=uid)
except User.DoesNotExist:
print("No user associated with that id.")
return
for key in ['username', 'email', 'first_name', 'last_name']:
print("%s: %s" % (key, getattr(user, key)))

View file

@ -0,0 +1,177 @@
"""
originally from http://www.djangosnippets.org/snippets/828/ by dnordberg
"""
from six.moves import input
from django.conf import settings
from django.core.management.base import CommandError, BaseCommand
import django
import logging
import re
from optparse import make_option
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--noinput', action='store_false',
dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.'),
make_option('--no-utf8', action='store_true',
dest='no_utf8_support', default=False,
help='Tells Django to not create a UTF-8 charset database'),
make_option('-U', '--user', action='store',
dest='user', default=None,
help='Use another user for the database then defined in settings.py'),
make_option('-P', '--password', action='store',
dest='password', default=None,
help='Use another password for the database then defined in settings.py'),
make_option('-D', '--dbname', action='store',
dest='dbname', default=None,
help='Use another database name then defined in settings.py (For PostgreSQL this defaults to "template1")'),
make_option('-R', '--router', action='store',
dest='router', default=None,
help='Use this router-database other then defined in settings.py'),
)
help = "Resets the database for this project."
def set_db_settings(self, *args, **options):
if django.get_version() >= "1.2":
router = options.get('router')
if router is None:
return False
# retrieve this with the 'using' argument
dbinfo = settings.DATABASES.get(router)
settings.DATABASE_ENGINE = dbinfo.get('ENGINE').split('.')[-1]
settings.DATABASE_USER = dbinfo.get('USER')
settings.DATABASE_PASSWORD = dbinfo.get('PASSWORD')
settings.DATABASE_NAME = dbinfo.get('NAME')
settings.DATABASE_HOST = dbinfo.get('HOST')
settings.DATABASE_PORT = dbinfo.get('PORT')
return True
else:
# settings are set for django < 1.2 no modification needed
return True
def handle(self, *args, **options):
"""
Resets the database for this project.
Note: Transaction wrappers are in reverse as a work around for
autocommit, anybody know how to do this the right way?
"""
if django.get_version() >= "1.2":
got_db_settings = self.set_db_settings(*args, **options)
if not got_db_settings:
raise CommandError("You are using Django %s which requires to specify the db-router.\nPlease specify the router by adding --router=<routername> to this command." % django.get_version())
return
verbosity = int(options.get('verbosity', 1))
if options.get('interactive'):
confirm = input("""
You have requested a database reset.
This will IRREVERSIBLY DESTROY
ALL data in the database "%s".
Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel: """ % (settings.DATABASE_NAME,))
else:
confirm = 'yes'
if confirm != 'yes':
print("Reset cancelled.")
return
postgis = re.compile('.*postgis')
engine = settings.DATABASE_ENGINE
user = options.get('user', settings.DATABASE_USER)
if user is None:
user = settings.DATABASE_USER
password = options.get('password', settings.DATABASE_PASSWORD)
if password is None:
password = settings.DATABASE_PASSWORD
if engine in ('sqlite3', 'spatialite'):
import os
try:
logging.info("Unlinking %s database" % engine)
os.unlink(settings.DATABASE_NAME)
except OSError:
pass
elif engine == 'mysql':
import MySQLdb as Database
kwargs = {
'user': user,
'passwd': password,
}
if settings.DATABASE_HOST.startswith('/'):
kwargs['unix_socket'] = settings.DATABASE_HOST
else:
kwargs['host'] = settings.DATABASE_HOST
if settings.DATABASE_PORT:
kwargs['port'] = int(settings.DATABASE_PORT)
connection = Database.connect(**kwargs)
drop_query = 'DROP DATABASE IF EXISTS `%s`' % settings.DATABASE_NAME
utf8_support = options.get('no_utf8_support', False) and '' or 'CHARACTER SET utf8'
create_query = 'CREATE DATABASE `%s` %s' % (settings.DATABASE_NAME, utf8_support)
logging.info('Executing... "' + drop_query + '"')
connection.query(drop_query)
logging.info('Executing... "' + create_query + '"')
connection.query(create_query)
elif engine == 'postgresql' or engine == 'postgresql_psycopg2' or postgis.match(engine):
if engine == 'postgresql':
import psycopg as Database # NOQA
elif engine == 'postgresql_psycopg2' or postgis.match(engine):
import psycopg2 as Database # NOQA
if settings.DATABASE_NAME == '':
from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured("You need to specify DATABASE_NAME in your Django settings file.")
database_name = options.get('dbname', 'template1')
if options.get('dbname') is None:
database_name = 'template1'
conn_string = "dbname=%s" % database_name
if settings.DATABASE_USER:
conn_string += " user=%s" % user
if settings.DATABASE_PASSWORD:
conn_string += " password='%s'" % password
if settings.DATABASE_HOST:
conn_string += " host=%s" % settings.DATABASE_HOST
if settings.DATABASE_PORT:
conn_string += " port=%s" % settings.DATABASE_PORT
connection = Database.connect(conn_string)
connection.set_isolation_level(0) # autocommit false
cursor = connection.cursor()
drop_query = 'DROP DATABASE %s' % settings.DATABASE_NAME
logging.info('Executing... "' + drop_query + '"')
try:
cursor.execute(drop_query)
except Database.ProgrammingError as e:
logging.info("Error: %s" % str(e))
# Encoding should be SQL_ASCII (7-bit postgres default) or prefered UTF8 (8-bit)
create_query = "CREATE DATABASE %s" % settings.DATABASE_NAME
if settings.DATABASE_USER:
create_query += " WITH OWNER = %s " % settings.DATABASE_USER
create_query += " ENCODING = 'UTF8'"
if postgis.match(engine):
create_query += ' TEMPLATE = template_postgis'
if settings.DEFAULT_TABLESPACE:
create_query += ' TABLESPACE = %s;' % settings.DEFAULT_TABLESPACE
else:
create_query += ';'
logging.info('Executing... "' + create_query + '"')
cursor.execute(create_query)
else:
raise CommandError("Unknown database engine %s" % engine)
if verbosity >= 2 or options.get('interactive'):
print("Reset successful.")

View file

@ -0,0 +1,52 @@
from django.core.management.base import LabelCommand
from optparse import make_option
from django_extensions.management.jobs import get_job, print_jobs
class Command(LabelCommand):
option_list = LabelCommand.option_list + (
make_option('--list', '-l', action="store_true", dest="list_jobs",
help="List all jobs with their description"),
)
help = "Run a single maintenance job."
args = "[app_name] job_name"
label = ""
requires_model_validation = True
def runjob(self, app_name, job_name, options):
verbosity = int(options.get('verbosity', 1))
if verbosity > 1:
print("Executing job: %s (app: %s)" % (job_name, app_name))
try:
job = get_job(app_name, job_name)
except KeyError:
if app_name:
print("Error: Job %s for applabel %s not found" % (app_name, job_name))
else:
print("Error: Job %s not found" % job_name)
print("Use -l option to view all the available jobs")
return
try:
job().execute()
except Exception:
import traceback
print("ERROR OCCURED IN JOB: %s (APP: %s)" % (job_name, app_name))
print("START TRACEBACK:")
traceback.print_exc()
print("END TRACEBACK\n")
def handle(self, *args, **options):
app_name = None
job_name = None
if len(args) == 1:
job_name = args[0]
elif len(args) == 2:
app_name, job_name = args
if options.get('list_jobs'):
print_jobs(only_scheduled=False, show_when=True, show_appname=True)
else:
if not job_name:
print("Run a single maintenance job. Please specify the name of the job.")
return
self.runjob(app_name, job_name, options)

View file

@ -0,0 +1,89 @@
from django.core.management.base import LabelCommand
from optparse import make_option
from django_extensions.management.jobs import get_jobs, print_jobs
class Command(LabelCommand):
option_list = LabelCommand.option_list + (
make_option('--list', '-l', action="store_true", dest="list_jobs",
help="List all jobs with their description"),
)
help = "Runs scheduled maintenance jobs."
args = "[minutely quarter_hourly hourly daily weekly monthly yearly]"
label = ""
requires_model_validation = True
def usage_msg(self):
print("Run scheduled jobs. Please specify 'minutely', 'quarter_hourly', 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'")
def runjobs(self, when, options):
verbosity = int(options.get('verbosity', 1))
jobs = get_jobs(when, only_scheduled=True)
list = jobs.keys()
list.sort()
for app_name, job_name in list:
job = jobs[(app_name, job_name)]
if verbosity > 1:
print("Executing %s job: %s (app: %s)" % (when, job_name, app_name))
try:
job().execute()
except Exception:
import traceback
print("ERROR OCCURED IN %s JOB: %s (APP: %s)" % (when.upper(), job_name, app_name))
print("START TRACEBACK:")
traceback.print_exc()
print("END TRACEBACK\n")
def runjobs_by_signals(self, when, options):
""" Run jobs from the signals """
# Thanks for Ian Holsman for the idea and code
from django_extensions.management import signals
from django.db import models
from django.conf import settings
verbosity = int(options.get('verbosity', 1))
for app_name in settings.INSTALLED_APPS:
try:
__import__(app_name + '.management', '', '', [''])
except ImportError:
pass
for app in models.get_apps():
if verbosity > 1:
app_name = '.'.join(app.__name__.rsplit('.')[:-1])
print("Sending %s job signal for: %s" % (when, app_name))
if when == 'minutely':
signals.run_minutely_jobs.send(sender=app, app=app)
elif when == 'quarter_hourly':
signals.run_quarter_hourly_jobs.send(sender=app, app=app)
elif when == 'hourly':
signals.run_hourly_jobs.send(sender=app, app=app)
elif when == 'daily':
signals.run_daily_jobs.send(sender=app, app=app)
elif when == 'weekly':
signals.run_weekly_jobs.send(sender=app, app=app)
elif when == 'monthly':
signals.run_monthly_jobs.send(sender=app, app=app)
elif when == 'yearly':
signals.run_yearly_jobs.send(sender=app, app=app)
def handle(self, *args, **options):
when = None
if len(args) > 1:
self.usage_msg()
return
elif len(args) == 1:
if not args[0] in ['minutely', 'quarter_hourly', 'hourly', 'daily', 'weekly', 'monthly', 'yearly']:
self.usage_msg()
return
else:
when = args[0]
if options.get('list_jobs'):
print_jobs(when, only_scheduled=True, show_when=True, show_appname=True)
else:
if not when:
self.usage_msg()
return
self.runjobs(when, options)
self.runjobs_by_signals(when, options)

View file

@ -0,0 +1,291 @@
"""
runprofileserver.py
Starts a lightweight Web server with profiling enabled.
Credits for kcachegrind support taken from lsprofcalltree.py go to:
David Allouche
Jp Calderone & Itamar Shtull-Trauring
Johan Dahlin
"""
from django.core.management.base import BaseCommand, CommandError
from optparse import make_option
from datetime import datetime
from django.conf import settings
import sys
try:
from django.contrib.staticfiles.handlers import StaticFilesHandler
USE_STATICFILES = 'django.contrib.staticfiles' in settings.INSTALLED_APPS
except ImportError as e:
USE_STATICFILES = False
try:
any
except NameError:
# backwards compatibility for <2.5
def any(iterable):
for element in iterable:
if element:
return True
return False
def label(code):
if isinstance(code, str):
return ('~', 0, code) # built-in functions ('~' sorts at the end)
else:
return '%s %s:%d' % (code.co_name,
code.co_filename,
code.co_firstlineno)
class KCacheGrind(object):
def __init__(self, profiler):
self.data = profiler.getstats()
self.out_file = None
def output(self, out_file):
self.out_file = out_file
self.out_file.write('events: Ticks\n')
self._print_summary()
for entry in self.data:
self._entry(entry)
def _print_summary(self):
max_cost = 0
for entry in self.data:
totaltime = int(entry.totaltime * 1000)
max_cost = max(max_cost, totaltime)
self.out_file.write('summary: %d\n' % (max_cost,))
def _entry(self, entry):
out_file = self.out_file
code = entry.code
#print >> out_file, 'ob=%s' % (code.co_filename,)
if isinstance(code, str):
out_file.write('fi=~\n')
else:
out_file.write('fi=%s\n' % (code.co_filename,))
out_file.write('fn=%s\n' % (label(code),))
inlinetime = int(entry.inlinetime * 1000)
if isinstance(code, str):
out_file.write('0 %s\n' % inlinetime)
else:
out_file.write('%d %d\n' % (code.co_firstlineno, inlinetime))
# recursive calls are counted in entry.calls
if entry.calls:
calls = entry.calls
else:
calls = []
if isinstance(code, str):
lineno = 0
else:
lineno = code.co_firstlineno
for subentry in calls:
self._subentry(lineno, subentry)
out_file.write("\n")
def _subentry(self, lineno, subentry):
out_file = self.out_file
code = subentry.code
#out_file.write('cob=%s\n' % (code.co_filename,))
out_file.write('cfn=%s\n' % (label(code),))
if isinstance(code, str):
out_file.write('cfi=~\n')
out_file.write('calls=%d 0\n' % (subentry.callcount,))
else:
out_file.write('cfi=%s\n' % (code.co_filename,))
out_file.write('calls=%d %d\n' % (subentry.callcount, code.co_firstlineno))
totaltime = int(subentry.totaltime * 1000)
out_file.write('%d %d\n' % (lineno, totaltime))
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--noreload', action='store_false', dest='use_reloader', default=True,
help='Tells Django to NOT use the auto-reloader.'),
make_option('--adminmedia', dest='admin_media_path', default='',
help='Specifies the directory from which to serve admin media.'),
make_option('--prof-path', dest='prof_path', default='/tmp',
help='Specifies the directory which to save profile information in.'),
make_option('--prof-file', dest='prof_file', default='{path}.{duration:06d}ms.{time}',
help='Set filename format, default if "{path}.{duration:06d}ms.{time}".'),
make_option('--nomedia', action='store_true', dest='no_media', default=False,
help='Do not profile MEDIA_URL and ADMIN_MEDIA_URL'),
make_option('--use-cprofile', action='store_true', dest='use_cprofile', default=False,
help='Use cProfile if available, this is disabled per default because of incompatibilities.'),
make_option('--kcachegrind', action='store_true', dest='use_lsprof', default=False,
help='Create kcachegrind compatible lsprof files, this requires and automatically enables cProfile.'),
)
if USE_STATICFILES:
option_list += (
make_option('--nostatic', action="store_false", dest='use_static_handler', default=True,
help='Tells Django to NOT automatically serve static files at STATIC_URL.'),
make_option('--insecure', action="store_true", dest='insecure_serving', default=False,
help='Allows serving static files even if DEBUG is False.'),
)
help = "Starts a lightweight Web server with profiling enabled."
args = '[optional port number, or ipaddr:port]'
# Validation is called explicitly each time the server is reloaded.
requires_model_validation = False
def handle(self, addrport='', *args, **options):
import django
from django.core.servers.basehttp import run, WSGIServerException
try:
from django.core.servers.basehttp import get_internal_wsgi_application as WSGIHandler
except ImportError:
from django.core.handlers.wsgi import WSGIHandler # noqa
try:
from django.core.servers.basehttp import AdminMediaHandler
HAS_ADMINMEDIAHANDLER = True
except ImportError:
HAS_ADMINMEDIAHANDLER = False
if args:
raise CommandError('Usage is runserver %s' % self.args)
if not addrport:
addr = ''
port = '8000'
else:
try:
addr, port = addrport.split(':')
except ValueError:
addr, port = '', addrport
if not addr:
addr = '127.0.0.1'
if not port.isdigit():
raise CommandError("%r is not a valid port number." % port)
use_reloader = options.get('use_reloader', True)
shutdown_message = options.get('shutdown_message', '')
no_media = options.get('no_media', False)
quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'
def inner_run():
import os
import time
import hotshot
USE_CPROFILE = options.get('use_cprofile', False)
USE_LSPROF = options.get('use_lsprof', False)
if USE_LSPROF:
USE_CPROFILE = True
if USE_CPROFILE:
try:
import cProfile
USE_CPROFILE = True
except ImportError:
print("cProfile disabled, module cannot be imported!")
USE_CPROFILE = False
if USE_LSPROF and not USE_CPROFILE:
raise SystemExit("Kcachegrind compatible output format required cProfile from Python 2.5")
prof_path = options.get('prof_path', '/tmp')
prof_file = options.get('prof_file', '{path}.{duration:06d}ms.{time}')
if not prof_file.format(path='1', duration=2, time=3):
prof_file = '{path}.{duration:06d}ms.{time}'
print("Filename format is wrong. Default format used: '{path}.{duration:06d}ms.{time}'.")
def get_exclude_paths():
exclude_paths = []
media_url = getattr(settings, 'MEDIA_URL', None)
if media_url:
exclude_paths.append(media_url)
static_url = getattr(settings, 'STATIC_URL', None)
if static_url:
exclude_paths.append(static_url)
admin_media_prefix = getattr(settings, 'ADMIN_MEDIA_PREFIX', None)
if admin_media_prefix:
exclude_paths.append(admin_media_prefix)
return exclude_paths
def make_profiler_handler(inner_handler):
def handler(environ, start_response):
path_info = environ['PATH_INFO']
# when using something like a dynamic site middleware is could be necessary
# to refetch the exclude_paths every time since they could change per site.
if no_media and any(path_info.startswith(p) for p in get_exclude_paths()):
return inner_handler(environ, start_response)
path_name = path_info.strip("/").replace('/', '.') or "root"
profname = "%s.%d.prof" % (path_name, time.time())
profname = os.path.join(prof_path, profname)
if USE_CPROFILE:
prof = cProfile.Profile()
else:
prof = hotshot.Profile(profname)
start = datetime.now()
try:
return prof.runcall(inner_handler, environ, start_response)
finally:
# seeing how long the request took is important!
elap = datetime.now() - start
elapms = elap.seconds * 1000.0 + elap.microseconds / 1000.0
if USE_LSPROF:
kg = KCacheGrind(prof)
kg.output(open(profname, 'w'))
elif USE_CPROFILE:
prof.dump_stats(profname)
profname2 = prof_file.format(path=path_name, duration=int(elapms), time=int(time.time()))
profname2 = os.path.join(prof_path, "%s.prof" % profname2)
if not USE_CPROFILE:
prof.close()
os.rename(profname, profname2)
return handler
print("Validating models...")
self.validate(display_num_errors=True)
print("\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE))
print("Development server is running at http://%s:%s/" % (addr, port))
print("Quit the server with %s." % quit_command)
path = options.get('admin_media_path', '')
if not path:
admin_media_path = os.path.join(django.__path__[0], 'contrib/admin/static/admin')
if os.path.isdir(admin_media_path):
path = admin_media_path
else:
path = os.path.join(django.__path__[0], 'contrib/admin/media')
try:
handler = WSGIHandler()
if HAS_ADMINMEDIAHANDLER:
handler = AdminMediaHandler(handler, path)
if USE_STATICFILES:
use_static_handler = options.get('use_static_handler', True)
insecure_serving = options.get('insecure_serving', False)
if (use_static_handler and (settings.DEBUG or insecure_serving)):
handler = StaticFilesHandler(handler)
handler = make_profiler_handler(handler)
run(addr, int(port), handler)
except WSGIServerException as e:
# Use helpful error messages instead of ugly tracebacks.
ERRORS = {
13: "You don't have permission to access that port.",
98: "That port is already in use.",
99: "That IP address can't be assigned-to.",
}
try:
error_text = ERRORS[e.args[0].args[0]]
except (AttributeError, KeyError):
error_text = str(e)
sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n')
# Need to use an OS exit because sys.exit doesn't work in a thread
os._exit(1)
except KeyboardInterrupt:
if shutdown_message:
print(shutdown_message)
sys.exit(0)
if use_reloader:
from django.utils import autoreload
autoreload.main(inner_run)
else:
inner_run()

View file

@ -0,0 +1,147 @@
from django.core.management.base import BaseCommand
from django.conf import settings
from optparse import make_option
import imp
def vararg_callback(option, opt_str, opt_value, parser):
parser.rargs.insert(0, opt_value)
value = []
for arg in parser.rargs:
# stop on --foo like options
if arg[:2] == "--" and len(arg) > 2:
break
# stop on -a like options
if arg[:1] == "-":
break
value.append(arg)
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--fixtures', action='store_true', dest='infixtures', default=False,
help='Only look in app.fixtures subdir'),
make_option('--noscripts', action='store_true', dest='noscripts', default=False,
help='Look in app.scripts subdir'),
make_option('-s', '--silent', action='store_true', dest='silent', default=False,
help='Run silently, do not show errors and tracebacks'),
make_option('--no-traceback', action='store_true', dest='no_traceback', default=False,
help='Do not show tracebacks'),
make_option('--script-args', action='callback', callback=vararg_callback, type='string',
help='Space-separated argument list to be passed to the scripts. Note that the '
'same arguments will be passed to all named scripts.'),
)
help = 'Runs a script in django context.'
args = "script [script ...]"
def handle(self, *scripts, **options):
NOTICE = self.style.SQL_TABLE
NOTICE2 = self.style.SQL_FIELD
ERROR = self.style.ERROR
ERROR2 = self.style.NOTICE
subdirs = []
if not options.get('noscripts'):
subdirs.append('scripts')
if options.get('infixtures'):
subdirs.append('fixtures')
verbosity = int(options.get('verbosity', 1))
show_traceback = options.get('traceback', True)
if show_traceback is None:
# XXX: traceback is set to None from Django ?
show_traceback = True
no_traceback = options.get('no_traceback', False)
if no_traceback:
show_traceback = False
silent = options.get('silent', False)
if silent:
verbosity = 0
if len(subdirs) < 1:
print(NOTICE("No subdirs to run left."))
return
if len(scripts) < 1:
print(ERROR("Script name required."))
return
def run_script(mod, *script_args):
try:
mod.run(*script_args)
except Exception:
if silent:
return
if verbosity > 0:
print(ERROR("Exception while running run() in '%s'" % mod.__name__))
if show_traceback:
raise
def my_import(mod):
if verbosity > 1:
print(NOTICE("Check for %s" % mod))
# check if module exists before importing
try:
path = None
for package in mod.split('.')[:-1]:
module_tuple = imp.find_module(package, path)
path = imp.load_module(package, *module_tuple).__path__
imp.find_module(mod.split('.')[-1], path)
t = __import__(mod, [], [], [" "])
except (ImportError, AttributeError):
return False
#if verbosity > 1:
# print(NOTICE("Found script %s ..." % mod))
if hasattr(t, "run"):
if verbosity > 1:
print(NOTICE2("Found script '%s' ..." % mod))
#if verbosity > 1:
# print(NOTICE("found run() in %s. executing..." % mod))
return t
else:
if verbosity > 1:
print(ERROR2("Find script '%s' but no run() function found." % mod))
def find_modules_for_script(script):
""" find script module which contains 'run' attribute """
modules = []
# first look in apps
for app in settings.INSTALLED_APPS:
for subdir in subdirs:
mod = my_import("%s.%s.%s" % (app, subdir, script))
if mod:
modules.append(mod)
# try app.DIR.script import
sa = script.split(".")
for subdir in subdirs:
nn = ".".join(sa[:-1] + [subdir, sa[-1]])
mod = my_import(nn)
if mod:
modules.append(mod)
# try direct import
if script.find(".") != -1:
mod = my_import(script)
if mod:
modules.append(mod)
return modules
if options.get('script_args'):
script_args = options['script_args']
else:
script_args = []
for script in scripts:
modules = find_modules_for_script(script)
if not modules:
if verbosity > 0 and not silent:
print(ERROR("No module for script '%s' found" % script))
for mod in modules:
if verbosity > 1:
print(NOTICE2("Running script '%s' ..." % mod.__name__))
run_script(mod, *script_args)

View file

@ -0,0 +1,293 @@
import os
import re
import socket
import sys
import time
from optparse import make_option
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django_extensions.management.utils import setup_logger, RedirectHandler
from django_extensions.management.technical_response import null_technical_500_response
try:
if 'django.contrib.staticfiles' in settings.INSTALLED_APPS:
from django.contrib.staticfiles.handlers import StaticFilesHandler
USE_STATICFILES = True
elif 'staticfiles' in settings.INSTALLED_APPS:
from staticfiles.handlers import StaticFilesHandler # noqa
USE_STATICFILES = True
else:
USE_STATICFILES = False
except ImportError:
USE_STATICFILES = False
naiveip_re = re.compile(r"""^(?:
(?P<addr>
(?P<ipv4>\d{1,3}(?:\.\d{1,3}){3}) | # IPv4 address
(?P<ipv6>\[[a-fA-F0-9:]+\]) | # IPv6 address
(?P<fqdn>[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*) # FQDN
):)?(?P<port>\d+)$""", re.X)
DEFAULT_PORT = "8000"
import logging
logger = logging.getLogger(__name__)
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--ipv6', '-6', action='store_true', dest='use_ipv6', default=False,
help='Tells Django to use a IPv6 address.'),
make_option('--noreload', action='store_false', dest='use_reloader', default=True,
help='Tells Django to NOT use the auto-reloader.'),
make_option('--browser', action='store_true', dest='open_browser',
help='Tells Django to open a browser.'),
make_option('--adminmedia', dest='admin_media_path', default='',
help='Specifies the directory from which to serve admin media.'),
make_option('--threaded', action='store_true', dest='threaded',
help='Run in multithreaded mode.'),
make_option('--output', dest='output_file', default=None,
help='Specifies an output file to send a copy of all messages (not flushed immediately).'),
make_option('--print-sql', action='store_true', default=False,
help="Print SQL queries as they're executed"),
make_option('--cert', dest='cert_path', action="store", type="string",
help='To use SSL, specify certificate path.'),
)
if USE_STATICFILES:
option_list += (
make_option('--nostatic', action="store_false", dest='use_static_handler', default=True,
help='Tells Django to NOT automatically serve static files at STATIC_URL.'),
make_option('--insecure', action="store_true", dest='insecure_serving', default=False,
help='Allows serving static files even if DEBUG is False.'),
)
help = "Starts a lightweight Web server for development."
args = '[optional port number, or ipaddr:port]'
# Validation is called explicitly each time the server is reloaded.
requires_model_validation = False
def handle(self, addrport='', *args, **options):
import django
setup_logger(logger, self.stderr, filename=options.get('output_file', None)) # , fmt="[%(name)s] %(message)s")
logredirect = RedirectHandler(__name__)
# Redirect werkzeug log items
werklogger = logging.getLogger('werkzeug')
werklogger.setLevel(logging.INFO)
werklogger.addHandler(logredirect)
werklogger.propagate = False
if options.get("print_sql", False):
from django.db.backends import util
try:
import sqlparse
except ImportError:
sqlparse = None # noqa
class PrintQueryWrapper(util.CursorDebugWrapper):
def execute(self, sql, params=()):
starttime = time.time()
try:
return self.cursor.execute(sql, params)
finally:
raw_sql = self.db.ops.last_executed_query(self.cursor, sql, params)
execution_time = time.time() - starttime
therest = ' -- [Execution time: %.6fs] [Database: %s]' % (execution_time, self.db.alias)
if sqlparse:
logger.info(sqlparse.format(raw_sql, reindent=True) + therest)
else:
logger.info(raw_sql + therest)
util.CursorDebugWrapper = PrintQueryWrapper
try:
from django.core.servers.basehttp import AdminMediaHandler
USE_ADMINMEDIAHANDLER = True
except ImportError:
USE_ADMINMEDIAHANDLER = False
try:
from django.core.servers.basehttp import get_internal_wsgi_application as WSGIHandler
except ImportError:
from django.core.handlers.wsgi import WSGIHandler # noqa
try:
from werkzeug import run_simple, DebuggedApplication
# Set colored output
if settings.DEBUG:
try:
set_werkzeug_log_color()
except: # We are dealing with some internals, anything could go wrong
print("Wrapping internal werkzeug logger for color highlighting has failed!")
pass
except ImportError:
raise CommandError("Werkzeug is required to use runserver_plus. Please visit http://werkzeug.pocoo.org/ or install via pip. (pip install Werkzeug)")
# usurp django's handler
from django.views import debug
debug.technical_500_response = null_technical_500_response
self.use_ipv6 = options.get('use_ipv6')
if self.use_ipv6 and not socket.has_ipv6:
raise CommandError('Your Python does not support IPv6.')
self._raw_ipv6 = False
if not addrport:
try:
addrport = settings.RUNSERVERPLUS_SERVER_ADDRESS_PORT
except AttributeError:
pass
if not addrport:
self.addr = ''
self.port = DEFAULT_PORT
else:
m = re.match(naiveip_re, addrport)
if m is None:
raise CommandError('"%s" is not a valid port number '
'or address:port pair.' % addrport)
self.addr, _ipv4, _ipv6, _fqdn, self.port = m.groups()
if not self.port.isdigit():
raise CommandError("%r is not a valid port number." %
self.port)
if self.addr:
if _ipv6:
self.addr = self.addr[1:-1]
self.use_ipv6 = True
self._raw_ipv6 = True
elif self.use_ipv6 and not _fqdn:
raise CommandError('"%s" is not a valid IPv6 address.'
% self.addr)
if not self.addr:
self.addr = '::1' if self.use_ipv6 else '127.0.0.1'
threaded = options.get('threaded', False)
use_reloader = options.get('use_reloader', True)
open_browser = options.get('open_browser', False)
cert_path = options.get("cert_path")
quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'
bind_url = "http://%s:%s/" % (
self.addr if not self._raw_ipv6 else '[%s]' % self.addr, self.port)
def inner_run():
print("Validating models...")
self.validate(display_num_errors=True)
print("\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE))
print("Development server is running at %s" % (bind_url,))
print("Using the Werkzeug debugger (http://werkzeug.pocoo.org/)")
print("Quit the server with %s." % quit_command)
path = options.get('admin_media_path', '')
if not path:
admin_media_path = os.path.join(django.__path__[0], 'contrib/admin/static/admin')
if os.path.isdir(admin_media_path):
path = admin_media_path
else:
path = os.path.join(django.__path__[0], 'contrib/admin/media')
handler = WSGIHandler()
if USE_ADMINMEDIAHANDLER:
handler = AdminMediaHandler(handler, path)
if USE_STATICFILES:
use_static_handler = options.get('use_static_handler', True)
insecure_serving = options.get('insecure_serving', False)
if use_static_handler and (settings.DEBUG or insecure_serving):
handler = StaticFilesHandler(handler)
if open_browser:
import webbrowser
webbrowser.open(bind_url)
if cert_path:
"""
OpenSSL is needed for SSL support.
This will make flakes8 throw warning since OpenSSL is not used
directly, alas, this is the only way to show meaningful error
messages. See:
http://lucumr.pocoo.org/2011/9/21/python-import-blackbox/
for more information on python imports.
"""
try:
import OpenSSL # NOQA
except ImportError:
raise CommandError("Python OpenSSL Library is "
"required to use runserver_plus with ssl support. "
"Install via pip (pip install pyOpenSSL).")
dir_path, cert_file = os.path.split(cert_path)
if not dir_path:
dir_path = os.getcwd()
root, ext = os.path.splitext(cert_file)
certfile = os.path.join(dir_path, root + ".crt")
keyfile = os.path.join(dir_path, root + ".key")
try:
from werkzeug.serving import make_ssl_devcert
if os.path.exists(certfile) and \
os.path.exists(keyfile):
ssl_context = (certfile, keyfile)
else: # Create cert, key files ourselves.
ssl_context = make_ssl_devcert(
os.path.join(dir_path, root), host='localhost')
except ImportError:
print("Werkzeug version is less than 0.9, trying adhoc certificate.")
ssl_context = "adhoc"
else:
ssl_context = None
run_simple(
self.addr,
int(self.port),
DebuggedApplication(handler, True),
use_reloader=use_reloader,
use_debugger=True,
threaded=threaded,
ssl_context=ssl_context
)
inner_run()
def set_werkzeug_log_color():
"""Try to set color to the werkzeug log.
"""
from django.core.management.color import color_style
from werkzeug.serving import WSGIRequestHandler
from werkzeug._internal import _log
_style = color_style()
_orig_log = WSGIRequestHandler.log
def werk_log(self, type, message, *args):
try:
msg = '%s - - [%s] %s' % (
self.address_string(),
self.log_date_time_string(),
message % args,
)
http_code = str(args[1])
except:
return _orig_log(type, message, *args)
# Utilize terminal colors, if available
if http_code[0] == '2':
# Put 2XX first, since it should be the common case
msg = _style.HTTP_SUCCESS(msg)
elif http_code[0] == '1':
msg = _style.HTTP_INFO(msg)
elif http_code == '304':
msg = _style.HTTP_NOT_MODIFIED(msg)
elif http_code[0] == '3':
msg = _style.HTTP_REDIRECT(msg)
elif http_code == '404':
msg = _style.HTTP_NOT_FOUND(msg)
elif http_code[0] == '4':
msg = _style.HTTP_BAD_REQUEST(msg)
else:
# Any 5XX, or any other response
msg = _style.HTTP_SERVER_ERROR(msg)
_log(type, msg)
WSGIRequestHandler.log = werk_log

View file

@ -0,0 +1,81 @@
"""
set_fake_emails.py
Give all users a new email account. Useful for testing in a
development environment. As such, this command is only available when
setting.DEBUG is True.
"""
from optparse import make_option
from django.conf import settings
from django.core.management.base import NoArgsCommand, CommandError
DEFAULT_FAKE_EMAIL = '%(username)s@example.com'
class Command(NoArgsCommand):
option_list = NoArgsCommand.option_list + (
make_option('--email', dest='default_email', default=DEFAULT_FAKE_EMAIL,
help='Use this as the new email format.'),
make_option('-a', '--no-admin', action="store_true", dest='no_admin', default=False,
help='Do not change administrator accounts'),
make_option('-s', '--no-staff', action="store_true", dest='no_staff', default=False,
help='Do not change staff accounts'),
make_option('--include', dest='include_regexp', default=None,
help='Include usernames matching this regexp.'),
make_option('--exclude', dest='exclude_regexp', default=None,
help='Exclude usernames matching this regexp.'),
make_option('--include-groups', dest='include_groups', default=None,
help='Include users matching this group. (use comma seperation for multiple groups)'),
make_option('--exclude-groups', dest='exclude_groups', default=None,
help='Exclude users matching this group. (use comma seperation for multiple groups)'),
)
help = '''DEBUG only: give all users a new email based on their account data ("%s" by default). Possible parameters are: username, first_name, last_name''' % (DEFAULT_FAKE_EMAIL, )
requires_model_validation = False
def handle_noargs(self, **options):
if not settings.DEBUG:
raise CommandError('Only available in debug mode')
try:
from django.contrib.auth import get_user_model # Django 1.5
except ImportError:
from django_extensions.future_1_5 import get_user_model
from django.contrib.auth.models import Group
email = options.get('default_email', DEFAULT_FAKE_EMAIL)
include_regexp = options.get('include_regexp', None)
exclude_regexp = options.get('exclude_regexp', None)
include_groups = options.get('include_groups', None)
exclude_groups = options.get('exclude_groups', None)
no_admin = options.get('no_admin', False)
no_staff = options.get('no_staff', False)
User = get_user_model()
users = User.objects.all()
if no_admin:
users = users.exclude(is_superuser=True)
if no_staff:
users = users.exclude(is_staff=True)
if exclude_groups:
groups = Group.objects.filter(name__in=exclude_groups.split(","))
if groups:
users = users.exclude(groups__in=groups)
else:
raise CommandError("No group matches filter: %s" % exclude_groups)
if include_groups:
groups = Group.objects.filter(name__in=include_groups.split(","))
if groups:
users = users.filter(groups__in=groups)
else:
raise CommandError("No groups matches filter: %s" % include_groups)
if exclude_regexp:
users = users.exclude(username__regex=exclude_regexp)
if include_regexp:
users = users.filter(username__regex=include_regexp)
for user in users:
user.email = email % {'username': user.username,
'first_name': user.first_name,
'last_name': user.last_name}
user.save()
print('Changed %d emails' % users.count())

View file

@ -0,0 +1,49 @@
"""
set_fake_passwords.py
Reset all user passwords to a common value. Useful for testing in a
development environment. As such, this command is only available when
setting.DEBUG is True.
"""
from optparse import make_option
from django.conf import settings
from django.core.management.base import NoArgsCommand, CommandError
DEFAULT_FAKE_PASSWORD = 'password'
class Command(NoArgsCommand):
option_list = NoArgsCommand.option_list + (
make_option('--prompt', dest='prompt_passwd', default=False, action='store_true',
help='Prompts for the new password to apply to all users'),
make_option('--password', dest='default_passwd', default=DEFAULT_FAKE_PASSWORD,
help='Use this as default password.'),
)
help = 'DEBUG only: sets all user passwords to a common value ("%s" by default)' % (DEFAULT_FAKE_PASSWORD, )
requires_model_validation = False
def handle_noargs(self, **options):
if not settings.DEBUG:
raise CommandError('Only available in debug mode')
try:
from django.contrib.auth import get_user_model # Django 1.5
except ImportError:
from django_extensions.future_1_5 import get_user_model
if options.get('prompt_passwd', False):
from getpass import getpass
passwd = getpass('Password: ')
if not passwd:
raise CommandError('You must enter a valid password')
else:
passwd = options.get('default_passwd', DEFAULT_FAKE_PASSWORD)
User = get_user_model()
user = User()
user.set_password(passwd)
count = User.objects.all().update(password=user.password)
print('Reset %d passwords' % count)

Some files were not shown because too many files have changed in this diff Show more