include copy of django_extension, dont install django from git

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

11
contrib/django_extensions/.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
*.pyc
*.pyo
*.egg-info
MANIFEST
build
dist
docs/_build
docs/_static
*.egg-info
.tox
*.bak

View file

@ -0,0 +1,29 @@
language: python
python:
- 2.6
- 2.7
- 3.3
env:
- DJANGO=Django==1.3 --use-mirrors
- DJANGO=Django==1.4 --use-mirrors
- DJANGO=Django==1.5 --use-mirrors
install:
- pip install -q $DJANGO
- pip install flake8 --use-mirrors
- if [[ $TRAVIS_PYTHON_VERSION < '3.0' ]]; then pip install -q python-keyczar --use-mirrors; fi
- pip install -q PyYAML --use-mirrors
- pip install -e . --use-mirrors
script:
- flake8 --ignore=E501,W391 .
- python setup.py test
matrix:
exclude:
- python: 3.3
env: DJANGO=Django==1.3 --use-mirrors
- python: 3.3
env: DJANGO=Django==1.4 --use-mirrors

View file

@ -0,0 +1,8 @@
[django-extensions.master]
file_filter = django_extensions/locale/<lang>/LC_MESSAGES/django.po
source_file = django_extensions/locale/en/LC_MESSAGES/django.po
source_lang = en
[main]
host = https://www.transifex.net

View file

@ -0,0 +1,19 @@
Copyright (c) 2007 Michael Trier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,5 @@
recursive-include django_extensions/conf *.tmpl
recursive-include django_extensions/templates *.html
recursive-include django_extensions/static *
recursive-include docs *
include LICENSE

View file

@ -0,0 +1,73 @@
===================
Django Extensions
===================
.. image:: https://secure.travis-ci.org/django-extensions/django-extensions.png?branch=master
:alt: Build Status
:target: http://travis-ci.org/django-extensions/django-extensions
Django Extensions is a collection of custom extensions for the Django Framework.
Getting Started
===============
The easiest way to figure out what Django Extensions are all about is to watch the `excellent screencast by Eric Holscher`__. In a couple minutes Eric walks you through a half a dozen command extensions.
Getting It
==========
You can get Django Extensions by using pip or easy_install::
$ pip install django-extensions
or
$ easy_install django-extensions
If you want to install it from source, grab the git repository from GitHub and run setup.py::
$ git clone git://github.com/django-extensions/django-extensions.git
$ cd django-extensions
$ python setup.py install
Installing It
=============
To enable `django_extensions` in your project you need to add it to `INSTALLED_APPS` in your projects `settings.py` file::
INSTALLED_APPS = (
...
'django_extensions',
...
)
Using It
========
Generate (and view) a graphviz graph of app models::
$ python manage.py graph_models -a -o myapp_models.png
Produce a tab-separated list of `(url_pattern, view_function, name)` tuples for a project::
$ python manage.py show_urls
Getting Involved
================
Open Source projects can always use more help. Fixing a problem, documenting a feature, adding translation in your language. If you have some time to spare and like to help us, here are the places to do so:
- GitHub: https://github.com/django-extensions/django-extensions
- Mailing list: http://groups.google.com/group/django-extensions
- Translations: https://www.transifex.net/projects/p/django-extensions/
Documentation
=============
You can view documentation online at:
- http://packages.python.org/django-extensions/
Or you can look at the docs/ directory in the repository.
__ http://ericholscher.com/blog/2008/sep/12/screencast-django-command-extensions/

View file

@ -0,0 +1,22 @@
Metadata-Version: 1.1
Name: django-extensions
Version: 1.2.3
Summary: Extensions for Django
Home-page: http://github.com/django-extensions/django-extensions
Author: Bas van Oostveen
Author-email: v.oostveen@gmail.com
License: New BSD License
Description: django-extensions bundles several useful
additions for Django projects. See the project page for more information:
http://github.com/django-extensions/django-extensions
Platform: any
Classifier: Development Status :: 4 - Beta
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Utilities

View file

@ -0,0 +1,152 @@
LICENSE
MANIFEST.in
README.rst
django_extensions/__init__.py
django_extensions/future_1_5.py
django_extensions/models.py
django_extensions/settings.py
django_extensions.egg-info/PKG-INFO
django_extensions.egg-info/SOURCES.txt
django_extensions.egg-info/dependency_links.txt
django_extensions.egg-info/requires.txt
django_extensions.egg-info/top_level.txt
django_extensions/admin/__init__.py
django_extensions/admin/widgets.py
django_extensions/conf/app_template/__init__.py.tmpl
django_extensions/conf/app_template/forms.py.tmpl
django_extensions/conf/app_template/models.py.tmpl
django_extensions/conf/app_template/urls.py.tmpl
django_extensions/conf/app_template/views.py.tmpl
django_extensions/conf/command_template/management/__init__.py.tmpl
django_extensions/conf/command_template/management/commands/__init__.py.tmpl
django_extensions/conf/command_template/management/commands/sample.py.tmpl
django_extensions/conf/jobs_template/jobs/__init__.py.tmpl
django_extensions/conf/jobs_template/jobs/sample.py.tmpl
django_extensions/conf/jobs_template/jobs/daily/__init__.py.tmpl
django_extensions/conf/jobs_template/jobs/hourly/__init__.py.tmpl
django_extensions/conf/jobs_template/jobs/monthly/__init__.py.tmpl
django_extensions/conf/jobs_template/jobs/weekly/__init__.py.tmpl
django_extensions/conf/jobs_template/jobs/yearly/__init__.py.tmpl
django_extensions/db/__init__.py
django_extensions/db/models.py
django_extensions/db/fields/__init__.py
django_extensions/db/fields/encrypted.py
django_extensions/db/fields/json.py
django_extensions/jobs/__init__.py
django_extensions/jobs/daily/__init__.py
django_extensions/jobs/daily/cache_cleanup.py
django_extensions/jobs/daily/daily_cleanup.py
django_extensions/jobs/hourly/__init__.py
django_extensions/jobs/minutely/__init__.py
django_extensions/jobs/monthly/__init__.py
django_extensions/jobs/weekly/__init__.py
django_extensions/jobs/yearly/__init__.py
django_extensions/management/__init__.py
django_extensions/management/base.py
django_extensions/management/color.py
django_extensions/management/jobs.py
django_extensions/management/modelviz.py
django_extensions/management/notebook_extension.py
django_extensions/management/shells.py
django_extensions/management/signals.py
django_extensions/management/technical_response.py
django_extensions/management/utils.py
django_extensions/management/commands/__init__.py
django_extensions/management/commands/clean_pyc.py
django_extensions/management/commands/compile_pyc.py
django_extensions/management/commands/create_app.py
django_extensions/management/commands/create_command.py
django_extensions/management/commands/create_jobs.py
django_extensions/management/commands/describe_form.py
django_extensions/management/commands/dumpscript.py
django_extensions/management/commands/export_emails.py
django_extensions/management/commands/find_template.py
django_extensions/management/commands/generate_secret_key.py
django_extensions/management/commands/graph_models.py
django_extensions/management/commands/mail_debug.py
django_extensions/management/commands/notes.py
django_extensions/management/commands/passwd.py
django_extensions/management/commands/pipchecker.py
django_extensions/management/commands/print_settings.py
django_extensions/management/commands/print_user_for_session.py
django_extensions/management/commands/reset_db.py
django_extensions/management/commands/runjob.py
django_extensions/management/commands/runjobs.py
django_extensions/management/commands/runprofileserver.py
django_extensions/management/commands/runscript.py
django_extensions/management/commands/runserver_plus.py
django_extensions/management/commands/set_fake_emails.py
django_extensions/management/commands/set_fake_passwords.py
django_extensions/management/commands/shell_plus.py
django_extensions/management/commands/show_templatetags.py
django_extensions/management/commands/show_urls.py
django_extensions/management/commands/sqlcreate.py
django_extensions/management/commands/sqldiff.py
django_extensions/management/commands/sync_media_s3.py
django_extensions/management/commands/sync_s3.py
django_extensions/management/commands/syncdata.py
django_extensions/management/commands/unreferenced_files.py
django_extensions/management/commands/update_permissions.py
django_extensions/management/commands/validate_templates.py
django_extensions/migrations/0001_empty.py
django_extensions/migrations/__init__.py
django_extensions/mongodb/__init__.py
django_extensions/mongodb/models.py
django_extensions/mongodb/fields/__init__.py
django_extensions/mongodb/fields/encrypted.py
django_extensions/mongodb/fields/json.py
django_extensions/static/django_extensions/css/jquery.autocomplete.css
django_extensions/static/django_extensions/img/indicator.gif
django_extensions/static/django_extensions/js/jquery.ajaxQueue.js
django_extensions/static/django_extensions/js/jquery.autocomplete.js
django_extensions/static/django_extensions/js/jquery.bgiframe.min.js
django_extensions/templates/django_extensions/widgets/foreignkey_searchinput.html
django_extensions/templatetags/__init__.py
django_extensions/templatetags/highlighting.py
django_extensions/templatetags/indent_text.py
django_extensions/templatetags/syntax_color.py
django_extensions/templatetags/truncate_letters.py
django_extensions/templatetags/widont.py
django_extensions/tests/__init__.py
django_extensions/tests/encrypted_fields.py
django_extensions/tests/fields.py
django_extensions/tests/json_field.py
django_extensions/tests/management_command.py
django_extensions/tests/models.py
django_extensions/tests/test_dumpscript.py
django_extensions/tests/urls.py
django_extensions/tests/utils.py
django_extensions/tests/uuid_field.py
django_extensions/tests/management/__init__.py
django_extensions/tests/management/commands/__init__.py
django_extensions/tests/management/commands/error_raising_command.py
django_extensions/utils/__init__.py
django_extensions/utils/dia2django.py
django_extensions/utils/text.py
django_extensions/utils/validatingtemplatetags.py
docs/AUTHORS
docs/Makefile
docs/admin_extensions.rst
docs/command_extension_ideas.rst
docs/command_extensions.rst
docs/conf.py
docs/create_app.rst
docs/creating_release.txt
docs/dumpscript.rst
docs/export_emails.rst
docs/field_extensions.rst
docs/graph_models.rst
docs/index.rst
docs/installation_instructions.rst
docs/jobs_scheduling.rst
docs/model_extensions.rst
docs/namespace_proposal.rst
docs/print_settings.rst
docs/runprofileserver.rst
docs/runscript.rst
docs/runserver_plus.rst
docs/shell_plus.rst
docs/sqlcreate.rst
docs/sqldiff.rst
docs/sync_s3.rst
docs/validate_templates.rst

View file

@ -0,0 +1 @@
six

View file

@ -0,0 +1 @@
django_extensions

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

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