Fixed E128 flake8 warnings in django/.

This commit is contained in:
Tim Graham 2016-03-28 18:33:29 -04:00
parent 2956e2f5e3
commit df8d8d4292
136 changed files with 1641 additions and 1212 deletions

View File

@ -297,8 +297,10 @@ class Apps(object):
available = set(available) available = set(available)
installed = set(app_config.name for app_config in self.get_app_configs()) installed = set(app_config.name for app_config in self.get_app_configs())
if not available.issubset(installed): if not available.issubset(installed):
raise ValueError("Available apps isn't a subset of installed " raise ValueError(
"apps, extra apps: %s" % ", ".join(available - installed)) "Available apps isn't a subset of installed apps, extra apps: %s"
% ", ".join(available - installed)
)
self.stored_app_configs.append(self.app_configs) self.stored_app_configs.append(self.app_configs)
self.app_configs = OrderedDict( self.app_configs = OrderedDict(

View File

@ -108,8 +108,7 @@ class Settings(BaseSettings):
if (setting in tuple_settings and if (setting in tuple_settings and
not isinstance(setting_value, (list, tuple))): not isinstance(setting_value, (list, tuple))):
raise ImproperlyConfigured("The %s setting must be a list or a tuple. " raise ImproperlyConfigured("The %s setting must be a list or a tuple. " % setting)
"Please fix your settings." % setting)
setattr(self, setting, setting_value) setattr(self, setting, setting_value)
self._explicit_settings.add(setting) self._explicit_settings.add(setting)

View File

@ -20,12 +20,12 @@ compress all jQuery-based files of the admin app. Requires the Google Closure
Compiler library and Java version 6 or later.""" Compiler library and Java version 6 or later."""
parser = argparse.ArgumentParser(description=description) parser = argparse.ArgumentParser(description=description)
parser.add_argument('file', nargs='*') parser.add_argument('file', nargs='*')
parser.add_argument("-c", dest="compiler", default="~/bin/compiler.jar", parser.add_argument(
help="path to Closure Compiler jar file") "-c", dest="compiler", default="~/bin/compiler.jar",
parser.add_argument("-v", "--verbose", help="path to Closure Compiler jar file",
action="store_true", dest="verbose") )
parser.add_argument("-q", "--quiet", parser.add_argument("-v", "--verbose", action="store_true", dest="verbose")
action="store_false", dest="verbose") parser.add_argument("-q", "--quiet", action="store_false", dest="verbose")
options = parser.parse_args() options = parser.parse_args()
compiler = closure_compiler if closure_compiler else os.path.expanduser(options.compiler) compiler = closure_compiler if closure_compiler else os.path.expanduser(options.compiler)
@ -38,8 +38,10 @@ Compiler library and Java version 6 or later."""
if not options.file: if not options.file:
if options.verbose: if options.verbose:
sys.stdout.write("No filenames given; defaulting to admin scripts\n") sys.stdout.write("No filenames given; defaulting to admin scripts\n")
files = [os.path.join(js_path, f) for f in [ files = [
"actions.js", "collapse.js", "inlines.js", "prepopulate.js"]] os.path.join(js_path, f) for f in
["actions.js", "collapse.js", "inlines.js", "prepopulate.js"]
]
else: else:
files = options.file files = options.file

View File

@ -155,8 +155,7 @@ class FieldListFilter(ListFilter):
for test, list_filter_class in cls._field_list_filters: for test, list_filter_class in cls._field_list_filters:
if not test(field): if not test(field):
continue continue
return list_filter_class(field, request, params, return list_filter_class(field, request, params, model, model_admin, field_path=field_path)
model, model_admin, field_path=field_path)
class RelatedFieldListFilter(FieldListFilter): class RelatedFieldListFilter(FieldListFilter):
@ -200,8 +199,10 @@ class RelatedFieldListFilter(FieldListFilter):
def choices(self, changelist): def choices(self, changelist):
yield { yield {
'selected': self.lookup_val is None and not self.lookup_val_isnull, 'selected': self.lookup_val is None and not self.lookup_val_isnull,
'query_string': changelist.get_query_string({}, 'query_string': changelist.get_query_string(
[self.lookup_kwarg, self.lookup_kwarg_isnull]), {},
[self.lookup_kwarg, self.lookup_kwarg_isnull]
),
'display': _('All'), 'display': _('All'),
} }
for pk_val, val in self.lookup_choices: for pk_val, val in self.lookup_choices:
@ -230,8 +231,7 @@ class BooleanFieldListFilter(FieldListFilter):
self.lookup_kwarg2 = '%s__isnull' % field_path self.lookup_kwarg2 = '%s__isnull' % field_path
self.lookup_val = request.GET.get(self.lookup_kwarg) self.lookup_val = request.GET.get(self.lookup_kwarg)
self.lookup_val2 = request.GET.get(self.lookup_kwarg2) self.lookup_val2 = request.GET.get(self.lookup_kwarg2)
super(BooleanFieldListFilter, self).__init__(field, super(BooleanFieldListFilter, self).__init__(field, request, params, model, model_admin, field_path)
request, params, model, model_admin, field_path)
def expected_parameters(self): def expected_parameters(self):
return [self.lookup_kwarg, self.lookup_kwarg2] return [self.lookup_kwarg, self.lookup_kwarg2]
@ -257,8 +257,10 @@ class BooleanFieldListFilter(FieldListFilter):
'display': _('Unknown'), 'display': _('Unknown'),
} }
FieldListFilter.register(lambda f: isinstance(f, FieldListFilter.register(
(models.BooleanField, models.NullBooleanField)), BooleanFieldListFilter) lambda f: isinstance(f, (models.BooleanField, models.NullBooleanField)),
BooleanFieldListFilter
)
class ChoicesFieldListFilter(FieldListFilter): class ChoicesFieldListFilter(FieldListFilter):
@ -290,8 +292,7 @@ FieldListFilter.register(lambda f: bool(f.choices), ChoicesFieldListFilter)
class DateFieldListFilter(FieldListFilter): class DateFieldListFilter(FieldListFilter):
def __init__(self, field, request, params, model, model_admin, field_path): def __init__(self, field, request, params, model, model_admin, field_path):
self.field_generic = '%s__' % field_path self.field_generic = '%s__' % field_path
self.date_params = {k: v for k, v in params.items() self.date_params = {k: v for k, v in params.items() if k.startswith(self.field_generic)}
if k.startswith(self.field_generic)}
now = timezone.now() now = timezone.now()
# When time zone support is enabled, convert "now" to the user's time # When time zone support is enabled, convert "now" to the user's time
@ -387,8 +388,7 @@ class AllValuesFieldListFilter(FieldListFilter):
def choices(self, changelist): def choices(self, changelist):
yield { yield {
'selected': self.lookup_val is None and self.lookup_val_isnull is None, 'selected': self.lookup_val is None and self.lookup_val_isnull is None,
'query_string': changelist.get_query_string({}, 'query_string': changelist.get_query_string({}, [self.lookup_kwarg, self.lookup_kwarg_isnull]),
[self.lookup_kwarg, self.lookup_kwarg_isnull]),
'display': _('All'), 'display': _('All'),
} }
include_none = False include_none = False

View File

@ -10,9 +10,10 @@ class AdminAuthenticationForm(AuthenticationForm):
A custom authentication form used in the admin app. A custom authentication form used in the admin app.
""" """
error_messages = { error_messages = {
'invalid_login': _("Please enter the correct %(username)s and password " 'invalid_login': _(
"for a staff account. Note that both fields may be " "Please enter the correct %(username)s and password for a staff "
"case-sensitive."), "account. Note that both fields may be case-sensitive."
),
} }
required_css_class = 'required' required_css_class = 'required'

View File

@ -25,8 +25,12 @@ ACTION_CHECKBOX_NAME = '_selected_action'
class ActionForm(forms.Form): class ActionForm(forms.Form):
action = forms.ChoiceField(label=_('Action:')) action = forms.ChoiceField(label=_('Action:'))
select_across = forms.BooleanField(label='', required=False, initial=0, select_across = forms.BooleanField(
widget=forms.HiddenInput({'class': 'select-across'})) label='',
required=False,
initial=0,
widget=forms.HiddenInput({'class': 'select-across'}),
)
checkbox = forms.CheckboxInput({'class': 'action-select'}, lambda value: False) checkbox = forms.CheckboxInput({'class': 'action-select'}, lambda value: False)
@ -73,9 +77,11 @@ class Fieldset(object):
def _media(self): def _media(self):
if 'collapse' in self.classes: if 'collapse' in self.classes:
extra = '' if settings.DEBUG else '.min' extra = '' if settings.DEBUG else '.min'
js = ['vendor/jquery/jquery%s.js' % extra, js = [
'vendor/jquery/jquery%s.js' % extra,
'jquery.init.js', 'jquery.init.js',
'collapse%s.js' % extra] 'collapse%s.js' % extra,
]
return forms.Media(js=['admin/js/%s' % url for url in js]) return forms.Media(js=['admin/js/%s' % url for url in js])
return forms.Media() return forms.Media()
media = property(_media) media = property(_media)
@ -92,9 +98,10 @@ class Fieldline(object):
self.fields = [field] self.fields = [field]
else: else:
self.fields = field self.fields = field
self.has_visible_field = not all(field in self.form.fields and self.has_visible_field = not all(
self.form.fields[field].widget.is_hidden field in self.form.fields and self.form.fields[field].widget.is_hidden
for field in self.fields) for field in self.fields
)
self.model_admin = model_admin self.model_admin = model_admin
if readonly_fields is None: if readonly_fields is None:
readonly_fields = () readonly_fields = ()
@ -103,15 +110,15 @@ class Fieldline(object):
def __iter__(self): def __iter__(self):
for i, field in enumerate(self.fields): for i, field in enumerate(self.fields):
if field in self.readonly_fields: if field in self.readonly_fields:
yield AdminReadonlyField(self.form, field, is_first=(i == 0), yield AdminReadonlyField(self.form, field, is_first=(i == 0), model_admin=self.model_admin)
model_admin=self.model_admin)
else: else:
yield AdminField(self.form, field, is_first=(i == 0)) yield AdminField(self.form, field, is_first=(i == 0))
def errors(self): def errors(self):
return mark_safe( return mark_safe(
'\n'.join(self.form[f].errors.as_ul() '\n'.join(
for f in self.fields if f not in self.readonly_fields).strip('\n') self.form[f].errors.as_ul() for f in self.fields if f not in self.readonly_fields
).strip('\n')
) )
@ -135,8 +142,10 @@ class AdminField(object):
attrs = {'class': ' '.join(classes)} if classes else {} attrs = {'class': ' '.join(classes)} if classes else {}
# checkboxes should not have a label suffix as the checkbox appears # checkboxes should not have a label suffix as the checkbox appears
# to the left of the label. # to the left of the label.
return self.field.label_tag(contents=mark_safe(contents), attrs=attrs, return self.field.label_tag(
label_suffix='' if self.is_checkbox else None) contents=mark_safe(contents), attrs=attrs,
label_suffix='' if self.is_checkbox else None,
)
def errors(self): def errors(self):
return mark_safe(self.field.errors.as_ul()) return mark_safe(self.field.errors.as_ul())
@ -241,16 +250,21 @@ class InlineAdminFormSet(object):
def __iter__(self): def __iter__(self):
for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()): for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()):
view_on_site_url = self.opts.get_view_on_site_url(original) view_on_site_url = self.opts.get_view_on_site_url(original)
yield InlineAdminForm(self.formset, form, self.fieldsets, yield InlineAdminForm(
self.prepopulated_fields, original, self.readonly_fields, self.formset, form, self.fieldsets, self.prepopulated_fields,
model_admin=self.opts, view_on_site_url=view_on_site_url) original, self.readonly_fields, model_admin=self.opts,
view_on_site_url=view_on_site_url,
)
for form in self.formset.extra_forms: for form in self.formset.extra_forms:
yield InlineAdminForm(self.formset, form, self.fieldsets, yield InlineAdminForm(
self.prepopulated_fields, None, self.readonly_fields, self.formset, form, self.fieldsets, self.prepopulated_fields,
model_admin=self.opts) None, self.readonly_fields, model_admin=self.opts,
yield InlineAdminForm(self.formset, self.formset.empty_form, )
yield InlineAdminForm(
self.formset, self.formset.empty_form,
self.fieldsets, self.prepopulated_fields, None, self.fieldsets, self.prepopulated_fields, None,
self.readonly_fields, model_admin=self.opts) self.readonly_fields, model_admin=self.opts,
)
def fields(self): def fields(self):
fk = getattr(self.formset, "fk", None) fk = getattr(self.formset, "fk", None)
@ -260,9 +274,7 @@ class InlineAdminFormSet(object):
if field_name in self.readonly_fields: if field_name in self.readonly_fields:
yield { yield {
'label': label_for_field(field_name, self.opts.model, self.opts), 'label': label_for_field(field_name, self.opts.model, self.opts),
'widget': { 'widget': {'is_hidden': False},
'is_hidden': False
},
'required': False, 'required': False,
'help_text': help_text_for_field(field_name, self.opts.model), 'help_text': help_text_for_field(field_name, self.opts.model),
} }
@ -310,13 +322,14 @@ class InlineAdminForm(AdminForm):
self.original = original self.original = original
self.show_url = original and view_on_site_url is not None self.show_url = original and view_on_site_url is not None
self.absolute_url = view_on_site_url self.absolute_url = view_on_site_url
super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields, super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields, readonly_fields, model_admin)
readonly_fields, model_admin)
def __iter__(self): def __iter__(self):
for name, options in self.fieldsets: for name, options in self.fieldsets:
yield InlineFieldset(self.formset, self.form, name, yield InlineFieldset(
self.readonly_fields, model_admin=self.model_admin, **options) self.formset, self.form, name, self.readonly_fields,
model_admin=self.model_admin, **options
)
def needs_explicit_pk_field(self): def needs_explicit_pk_field(self):
# Auto fields are editable (oddly), so need to check for auto or non-editable pk # Auto fields are editable (oddly), so need to check for auto or non-editable pk
@ -358,8 +371,7 @@ class InlineFieldset(Fieldset):
for field in self.fields: for field in self.fields:
if fk and fk.name == field: if fk and fk.name == field:
continue continue
yield Fieldline(self.form, field, self.readonly_fields, yield Fieldline(self.form, field, self.readonly_fields, model_admin=self.model_admin)
model_admin=self.model_admin)
class AdminErrorList(forms.utils.ErrorList): class AdminErrorList(forms.utils.ErrorList):

View File

@ -214,8 +214,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
""" """
db = kwargs.get('using') db = kwargs.get('using')
if db_field.name in self.raw_id_fields: if db_field.name in self.raw_id_fields:
kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.remote_field, kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.remote_field, self.admin_site, using=db)
self.admin_site, using=db)
elif db_field.name in self.radio_fields: elif db_field.name in self.radio_fields:
kwargs['widget'] = widgets.AdminRadioSelect(attrs={ kwargs['widget'] = widgets.AdminRadioSelect(attrs={
'class': get_ul_class(self.radio_fields[db_field.name]), 'class': get_ul_class(self.radio_fields[db_field.name]),
@ -240,8 +239,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
db = kwargs.get('using') db = kwargs.get('using')
if db_field.name in self.raw_id_fields: if db_field.name in self.raw_id_fields:
kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.remote_field, kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.remote_field, self.admin_site, using=db)
self.admin_site, using=db)
elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)): elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
kwargs['widget'] = widgets.FilteredSelectMultiple( kwargs['widget'] = widgets.FilteredSelectMultiple(
db_field.verbose_name, db_field.verbose_name,
@ -639,8 +637,10 @@ class ModelAdmin(BaseModelAdmin):
try: try:
return modelform_factory(self.model, **defaults) return modelform_factory(self.model, **defaults)
except FieldError as e: except FieldError as e:
raise FieldError('%s. Check fields/fieldsets/exclude attributes of class %s.' raise FieldError(
% (e, self.__class__.__name__)) '%s. Check fields/fieldsets/exclude attributes of class %s.'
% (e, self.__class__.__name__)
)
def get_changelist(self, request, **kwargs): def get_changelist(self, request, **kwargs):
""" """
@ -686,9 +686,10 @@ class ModelAdmin(BaseModelAdmin):
"formfield_callback": partial(self.formfield_for_dbfield, request=request), "formfield_callback": partial(self.formfield_for_dbfield, request=request),
} }
defaults.update(kwargs) defaults.update(kwargs)
return modelformset_factory(self.model, return modelformset_factory(
self.get_changelist_form(request), extra=0, self.model, self.get_changelist_form(request), extra=0,
fields=self.list_editable, **defaults) fields=self.list_editable, **defaults
)
def get_formsets_with_inlines(self, request, obj=None): def get_formsets_with_inlines(self, request, obj=None):
""" """
@ -974,7 +975,6 @@ class ModelAdmin(BaseModelAdmin):
compatibility. For convenience, it accepts the `level` argument as compatibility. For convenience, it accepts the `level` argument as
a string rather than the usual level number. a string rather than the usual level number.
""" """
if not isinstance(level, int): if not isinstance(level, int):
# attempt to get the level if passed a string # attempt to get the level if passed a string
try: try:
@ -982,11 +982,12 @@ class ModelAdmin(BaseModelAdmin):
except AttributeError: except AttributeError:
levels = messages.constants.DEFAULT_TAGS.values() levels = messages.constants.DEFAULT_TAGS.values()
levels_repr = ', '.join('`%s`' % l for l in levels) levels_repr = ', '.join('`%s`' % l for l in levels)
raise ValueError('Bad message level string: `%s`. ' raise ValueError(
'Possible values are: %s' % (level, levels_repr)) 'Bad message level string: `%s`. Possible values are: %s'
% (level, levels_repr)
)
messages.add_message(request, level, message, extra_tags=extra_tags, messages.add_message(request, level, message, extra_tags=extra_tags, fail_silently=fail_silently)
fail_silently=fail_silently)
def save_form(self, request, form, change): def save_form(self, request, form, change):
""" """
@ -1323,23 +1324,26 @@ class ModelAdmin(BaseModelAdmin):
'popup_response_data': popup_response_data, 'popup_response_data': popup_response_data,
}) })
self.message_user(request, self.message_user(
request,
_('The %(name)s "%(obj)s" was deleted successfully.') % { _('The %(name)s "%(obj)s" was deleted successfully.') % {
'name': force_text(opts.verbose_name), 'name': force_text(opts.verbose_name),
'obj': force_text(obj_display), 'obj': force_text(obj_display),
}, messages.SUCCESS) },
messages.SUCCESS,
)
if self.has_change_permission(request, None): if self.has_change_permission(request, None):
post_url = reverse('admin:%s_%s_changelist' % post_url = reverse(
(opts.app_label, opts.model_name), 'admin:%s_%s_changelist' % (opts.app_label, opts.model_name),
current_app=self.admin_site.name) current_app=self.admin_site.name,
)
preserved_filters = self.get_preserved_filters(request) preserved_filters = self.get_preserved_filters(request)
post_url = add_preserved_filters( post_url = add_preserved_filters(
{'preserved_filters': preserved_filters, 'opts': opts}, post_url {'preserved_filters': preserved_filters, 'opts': opts}, post_url
) )
else: else:
post_url = reverse('admin:index', post_url = reverse('admin:index', current_app=self.admin_site.name)
current_app=self.admin_site.name)
return HttpResponseRedirect(post_url) return HttpResponseRedirect(post_url)
def render_delete_form(self, request, context): def render_delete_form(self, request, context):
@ -1353,22 +1357,26 @@ class ModelAdmin(BaseModelAdmin):
media=self.media, media=self.media,
) )
return TemplateResponse(request, return TemplateResponse(
request,
self.delete_confirmation_template or [ self.delete_confirmation_template or [
"admin/{}/{}/delete_confirmation.html".format(app_label, opts.model_name), "admin/{}/{}/delete_confirmation.html".format(app_label, opts.model_name),
"admin/{}/delete_confirmation.html".format(app_label), "admin/{}/delete_confirmation.html".format(app_label),
"admin/delete_confirmation.html" "admin/delete_confirmation.html",
], context) ],
context,
)
def get_inline_formsets(self, request, formsets, inline_instances, def get_inline_formsets(self, request, formsets, inline_instances, obj=None):
obj=None):
inline_admin_formsets = [] inline_admin_formsets = []
for inline, formset in zip(inline_instances, formsets): for inline, formset in zip(inline_instances, formsets):
fieldsets = list(inline.get_fieldsets(request, obj)) fieldsets = list(inline.get_fieldsets(request, obj))
readonly = list(inline.get_readonly_fields(request, obj)) readonly = list(inline.get_readonly_fields(request, obj))
prepopulated = dict(inline.get_prepopulated_fields(request, obj)) prepopulated = dict(inline.get_prepopulated_fields(request, obj))
inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, inline_admin_formset = helpers.InlineAdminFormSet(
fieldsets, prepopulated, readonly, model_admin=self) inline, formset, fieldsets, prepopulated, readonly,
model_admin=self,
)
inline_admin_formsets.append(inline_admin_formset) inline_admin_formsets.append(inline_admin_formset)
return inline_admin_formsets return inline_admin_formsets
@ -1462,7 +1470,8 @@ class ModelAdmin(BaseModelAdmin):
for inline_formset in inline_formsets: for inline_formset in inline_formsets:
media = media + inline_formset.media media = media + inline_formset.media
context = dict(self.admin_site.each_context(request), context = dict(
self.admin_site.each_context(request),
title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name), title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name),
adminform=adminForm, adminform=adminForm,
object_id=object_id, object_id=object_id,
@ -1519,11 +1528,12 @@ class ModelAdmin(BaseModelAdmin):
ChangeList = self.get_changelist(request) ChangeList = self.get_changelist(request)
try: try:
cl = ChangeList(request, self.model, list_display, cl = ChangeList(
request, self.model, list_display,
list_display_links, list_filter, self.date_hierarchy, list_display_links, list_filter, self.date_hierarchy,
search_fields, list_select_related, self.list_per_page, search_fields, list_select_related, self.list_per_page,
self.list_max_show_all, self.list_editable, self) self.list_max_show_all, self.list_editable, self,
)
except IncorrectLookupParameters: except IncorrectLookupParameters:
# Wacky lookup parameters were given, so redirect to the main # Wacky lookup parameters were given, so redirect to the main
# changelist page, without parameters, and pass an 'invalid=1' # changelist page, without parameters, and pass an 'invalid=1'
@ -1596,11 +1606,15 @@ class ModelAdmin(BaseModelAdmin):
name = force_text(opts.verbose_name) name = force_text(opts.verbose_name)
else: else:
name = force_text(opts.verbose_name_plural) name = force_text(opts.verbose_name_plural)
msg = ungettext("%(count)s %(name)s was changed successfully.", msg = ungettext(
"%(count)s %(name)s was changed successfully.",
"%(count)s %(name)s were changed successfully.", "%(count)s %(name)s were changed successfully.",
changecount) % {'count': changecount, changecount
) % {
'count': changecount,
'name': name, 'name': name,
'obj': force_text(obj)} 'obj': force_text(obj),
}
self.message_user(request, msg, messages.SUCCESS) self.message_user(request, msg, messages.SUCCESS)
return HttpResponseRedirect(request.get_full_path()) return HttpResponseRedirect(request.get_full_path())
@ -1623,8 +1637,11 @@ class ModelAdmin(BaseModelAdmin):
else: else:
action_form = None action_form = None
selection_note_all = ungettext('%(total_count)s selected', selection_note_all = ungettext(
'All %(total_count)s selected', cl.result_count) '%(total_count)s selected',
'All %(total_count)s selected',
cl.result_count
)
context = dict( context = dict(
self.admin_site.each_context(request), self.admin_site.each_context(request),
@ -1744,7 +1761,8 @@ class ModelAdmin(BaseModelAdmin):
content_type=get_content_type_for_model(model) content_type=get_content_type_for_model(model)
).select_related().order_by('action_time') ).select_related().order_by('action_time')
context = dict(self.admin_site.each_context(request), context = dict(
self.admin_site.each_context(request),
title=_('Change history: %s') % force_text(obj), title=_('Change history: %s') % force_text(obj),
action_list=action_list, action_list=action_list,
module_name=capfirst(force_text(opts.verbose_name_plural)), module_name=capfirst(force_text(opts.verbose_name_plural)),

View File

@ -84,8 +84,9 @@ class AdminSite(object):
model_or_iterable = [model_or_iterable] model_or_iterable = [model_or_iterable]
for model in model_or_iterable: for model in model_or_iterable:
if model._meta.abstract: if model._meta.abstract:
raise ImproperlyConfigured('The model %s is abstract, so it ' raise ImproperlyConfigured(
'cannot be registered with admin.' % model.__name__) 'The model %s is abstract, so it cannot be registered with admin.' % model.__name__
)
if model in self._registry: if model in self._registry:
raise AlreadyRegistered('The model %s is already registered' % model.__name__) raise AlreadyRegistered('The model %s is already registered' % model.__name__)
@ -362,7 +363,8 @@ class AdminSite(object):
# it cannot import models from other applications at the module level, # it cannot import models from other applications at the module level,
# and django.contrib.admin.forms eventually imports User. # and django.contrib.admin.forms eventually imports User.
from django.contrib.admin.forms import AdminAuthenticationForm from django.contrib.admin.forms import AdminAuthenticationForm
context = dict(self.each_context(request), context = dict(
self.each_context(request),
title=_('Log in'), title=_('Log in'),
app_path=request.get_full_path(), app_path=request.get_full_path(),
) )
@ -479,8 +481,7 @@ class AdminSite(object):
request.current_app = self.name request.current_app = self.name
return TemplateResponse(request, self.index_template or return TemplateResponse(request, self.index_template or 'admin/index.html', context)
'admin/index.html', context)
def app_index(self, request, app_label, extra_context=None): def app_index(self, request, app_label, extra_context=None):
app_dict = self._build_app_dict(request, app_label) app_dict = self._build_app_dict(request, app_label)
@ -489,7 +490,8 @@ class AdminSite(object):
# Sort the models alphabetically within each app. # Sort the models alphabetically within each app.
app_dict['models'].sort(key=lambda x: x['name']) app_dict['models'].sort(key=lambda x: x['name'])
app_name = apps.get_app_config(app_label).verbose_name app_name = apps.get_app_config(app_label).verbose_name
context = dict(self.each_context(request), context = dict(
self.each_context(request),
title=_('%(app)s administration') % {'app': app_name}, title=_('%(app)s administration') % {'app': app_name},
app_list=[app_dict], app_list=[app_dict],
app_label=app_label, app_label=app_label,

View File

@ -111,8 +111,7 @@ class ChangeList(object):
for list_filter in self.list_filter: for list_filter in self.list_filter:
if callable(list_filter): if callable(list_filter):
# This is simply a custom list filter class. # This is simply a custom list filter class.
spec = list_filter(request, lookup_params, spec = list_filter(request, lookup_params, self.model, self.model_admin)
self.model, self.model_admin)
else: else:
field_path = None field_path = None
if isinstance(list_filter, (tuple, list)): if isinstance(list_filter, (tuple, list)):
@ -126,12 +125,12 @@ class ChangeList(object):
if not isinstance(field, models.Field): if not isinstance(field, models.Field):
field_path = field field_path = field
field = get_fields_from_path(self.model, field_path)[-1] field = get_fields_from_path(self.model, field_path)[-1]
spec = field_list_filter_class(field, request, lookup_params, spec = field_list_filter_class(
self.model, self.model_admin, field_path=field_path) field, request, lookup_params,
self.model, self.model_admin, field_path=field_path
)
# Check if we need to use distinct() # Check if we need to use distinct()
use_distinct = (use_distinct or use_distinct = use_distinct or lookup_needs_distinct(self.lookup_opts, field_path)
lookup_needs_distinct(self.lookup_opts,
field_path))
if spec and spec.has_output(): if spec and spec.has_output():
filter_specs.append(spec) filter_specs.append(spec)
@ -144,8 +143,7 @@ class ChangeList(object):
try: try:
for key, value in lookup_params.items(): for key, value in lookup_params.items():
lookup_params[key] = prepare_lookup_value(key, value) lookup_params[key] = prepare_lookup_value(key, value)
use_distinct = (use_distinct or use_distinct = use_distinct or lookup_needs_distinct(self.lookup_opts, key)
lookup_needs_distinct(self.lookup_opts, key))
return filter_specs, bool(filter_specs), lookup_params, use_distinct return filter_specs, bool(filter_specs), lookup_params, use_distinct
except FieldDoesNotExist as e: except FieldDoesNotExist as e:
six.reraise(IncorrectLookupParameters, IncorrectLookupParameters(e), sys.exc_info()[2]) six.reraise(IncorrectLookupParameters, IncorrectLookupParameters(e), sys.exc_info()[2])
@ -345,8 +343,7 @@ class ChangeList(object):
qs = qs.order_by(*ordering) qs = qs.order_by(*ordering)
# Apply search results # Apply search results
qs, search_use_distinct = self.model_admin.get_search_results( qs, search_use_distinct = self.model_admin.get_search_results(request, qs, self.query)
request, qs, self.query)
# Remove duplicates from results, if necessary # Remove duplicates from results, if necessary
if filters_use_distinct | search_use_distinct: if filters_use_distinct | search_use_distinct:

View File

@ -106,10 +106,12 @@ class AdminRadioSelect(forms.RadioSelect):
class AdminFileWidget(forms.ClearableFileInput): class AdminFileWidget(forms.ClearableFileInput):
template_with_initial = ('<p class="file-upload">%s</p>' template_with_initial = (
% forms.ClearableFileInput.template_with_initial) '<p class="file-upload">%s</p>' % forms.ClearableFileInput.template_with_initial
template_with_clear = ('<span class="clearable-file-input">%s</span>' )
% forms.ClearableFileInput.template_with_clear) template_with_clear = (
'<span class="clearable-file-input">%s</span>' % forms.ClearableFileInput.template_with_clear
)
def url_params_from_lookup_dict(lookups): def url_params_from_lookup_dict(lookups):
@ -170,8 +172,10 @@ class ForeignKeyRawIdWidget(forms.TextInput):
attrs['class'] = 'vForeignKeyRawIdAdminField' # The JavaScript code looks for this hook. attrs['class'] = 'vForeignKeyRawIdAdminField' # The JavaScript code looks for this hook.
# TODO: "lookup_id_" is hard-coded here. This should instead use # TODO: "lookup_id_" is hard-coded here. This should instead use
# the correct API to determine the ID dynamically. # the correct API to determine the ID dynamically.
extra.append('<a href="%s%s" class="related-lookup" id="lookup_id_%s" title="%s"></a>' % extra.append(
(related_url, url, name, _('Lookup'))) '<a href="%s%s" class="related-lookup" id="lookup_id_%s" title="%s"></a>'
% (related_url, url, name, _('Lookup'))
)
output = [super(ForeignKeyRawIdWidget, self).render(name, value, attrs)] + extra output = [super(ForeignKeyRawIdWidget, self).render(name, value, attrs)] + extra
if value: if value:
output.append(self.label_for_value(value)) output.append(self.label_for_value(value))

View File

@ -82,9 +82,11 @@ def parse_rst(text, default_reference_context, thing_being_parsed=None):
.. default-role:: .. default-role::
""" """
parts = docutils.core.publish_parts(source % text, parts = docutils.core.publish_parts(
source % text,
source_path=thing_being_parsed, destination_path=None, source_path=thing_being_parsed, destination_path=None,
writer_name='html', settings_overrides=overrides) writer_name='html', settings_overrides=overrides,
)
return mark_safe(parts['fragment']) return mark_safe(parts['fragment'])
# #

View File

@ -82,8 +82,7 @@ def authenticate(**credentials):
return user return user
# The credentials supplied are invalid to all backends, fire signal # The credentials supplied are invalid to all backends, fire signal
user_login_failed.send(sender=__name__, user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials))
credentials=_clean_credentials(credentials))
def login(request, user, backend=None): def login(request, user, backend=None):

View File

@ -183,10 +183,12 @@ class UserAdmin(admin.ModelAdmin):
request.current_app = self.admin_site.name request.current_app = self.admin_site.name
return TemplateResponse(request, return TemplateResponse(
request,
self.change_user_password_template or self.change_user_password_template or
'admin/auth/user/change_password.html', 'admin/auth/user/change_password.html',
context) context,
)
def response_add(self, request, obj, post_url_continue=None): def response_add(self, request, obj, post_url_continue=None):
""" """

View File

@ -12,7 +12,9 @@ class AuthConfig(AppConfig):
verbose_name = _("Authentication and Authorization") verbose_name = _("Authentication and Authorization")
def ready(self): def ready(self):
post_migrate.connect(create_permissions, post_migrate.connect(
dispatch_uid="django.contrib.auth.management.create_permissions") create_permissions,
dispatch_uid="django.contrib.auth.management.create_permissions"
)
checks.register(check_user_model, checks.Tags.models) checks.register(check_user_model, checks.Tags.models)
checks.register(check_models_permissions, checks.Tags.models) checks.register(check_models_permissions, checks.Tags.models)

View File

@ -33,12 +33,12 @@ class ReadOnlyPasswordHashWidget(forms.Widget):
hasher = identify_hasher(encoded) hasher = identify_hasher(encoded)
except ValueError: except ValueError:
summary = mark_safe("<strong>%s</strong>" % ugettext( summary = mark_safe("<strong>%s</strong>" % ugettext(
"Invalid password format or unknown hashing algorithm.")) "Invalid password format or unknown hashing algorithm."
))
else: else:
summary = format_html_join('', summary = format_html_join(
"<strong>{}</strong>: {} ", '', '<strong>{}</strong>: {} ',
((ugettext(key), value) ((ugettext(key), value) for key, value in hasher.safe_summary(encoded).items())
for key, value in hasher.safe_summary(encoded).items())
) )
return format_html("<div{}>{}</div>", flatatt(final_attrs), summary) return format_html("<div{}>{}</div>", flatatt(final_attrs), summary)
@ -68,13 +68,17 @@ class UserCreationForm(forms.ModelForm):
error_messages = { error_messages = {
'password_mismatch': _("The two password fields didn't match."), 'password_mismatch': _("The two password fields didn't match."),
} }
password1 = forms.CharField(label=_("Password"), password1 = forms.CharField(
label=_("Password"),
strip=False, strip=False,
widget=forms.PasswordInput) widget=forms.PasswordInput,
password2 = forms.CharField(label=_("Password confirmation"), )
password2 = forms.CharField(
label=_("Password confirmation"),
widget=forms.PasswordInput, widget=forms.PasswordInput,
strip=False, strip=False,
help_text=_("Enter the same password as before, for verification.")) help_text=_("Enter the same password as before, for verification."),
)
class Meta: class Meta:
model = User model = User
@ -105,10 +109,14 @@ class UserCreationForm(forms.ModelForm):
class UserChangeForm(forms.ModelForm): class UserChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField(label=_("Password"), password = ReadOnlyPasswordHashField(
help_text=_("Raw passwords are not stored, so there is no way to see " label=_("Password"),
"this user's password, but you can change the password " help_text=_(
"using <a href=\"../password/\">this form</a>.")) "Raw passwords are not stored, so there is no way to see this "
"user's password, but you can change the password using "
"<a href=\"../password/\">this form</a>."
),
)
class Meta: class Meta:
model = User model = User
@ -136,11 +144,17 @@ class AuthenticationForm(forms.Form):
max_length=254, max_length=254,
widget=forms.TextInput(attrs={'autofocus': ''}), widget=forms.TextInput(attrs={'autofocus': ''}),
) )
password = forms.CharField(label=_("Password"), strip=False, widget=forms.PasswordInput) password = forms.CharField(
label=_("Password"),
strip=False,
widget=forms.PasswordInput,
)
error_messages = { error_messages = {
'invalid_login': _("Please enter a correct %(username)s and password. " 'invalid_login': _(
"Note that both fields may be case-sensitive."), "Please enter a correct %(username)s and password. Note that both "
"fields may be case-sensitive."
),
'inactive': _("This account is inactive."), 'inactive': _("This account is inactive."),
} }
@ -164,8 +178,7 @@ class AuthenticationForm(forms.Form):
password = self.cleaned_data.get('password') password = self.cleaned_data.get('password')
if username and password: if username and password:
self.user_cache = authenticate(username=username, self.user_cache = authenticate(username=username, password=password)
password=password)
if self.user_cache is None: if self.user_cache is None:
raise forms.ValidationError( raise forms.ValidationError(
self.error_messages['invalid_login'], self.error_messages['invalid_login'],
@ -263,9 +276,10 @@ class PasswordResetForm(forms.Form):
} }
if extra_email_context is not None: if extra_email_context is not None:
context.update(extra_email_context) context.update(extra_email_context)
self.send_mail(subject_template_name, email_template_name, self.send_mail(
context, from_email, user.email, subject_template_name, email_template_name, context, from_email,
html_email_template_name=html_email_template_name) user.email, html_email_template_name=html_email_template_name,
)
class SetPasswordForm(forms.Form): class SetPasswordForm(forms.Form):
@ -276,13 +290,17 @@ class SetPasswordForm(forms.Form):
error_messages = { error_messages = {
'password_mismatch': _("The two password fields didn't match."), 'password_mismatch': _("The two password fields didn't match."),
} }
new_password1 = forms.CharField(label=_("New password"), new_password1 = forms.CharField(
label=_("New password"),
widget=forms.PasswordInput, widget=forms.PasswordInput,
strip=False, strip=False,
help_text=password_validation.password_validators_help_text_html()) help_text=password_validation.password_validators_help_text_html(),
new_password2 = forms.CharField(label=_("New password confirmation"), )
new_password2 = forms.CharField(
label=_("New password confirmation"),
strip=False, strip=False,
widget=forms.PasswordInput) widget=forms.PasswordInput,
)
def __init__(self, user, *args, **kwargs): def __init__(self, user, *args, **kwargs):
self.user = user self.user = user
@ -314,8 +332,7 @@ class PasswordChangeForm(SetPasswordForm):
password. password.
""" """
error_messages = dict(SetPasswordForm.error_messages, **{ error_messages = dict(SetPasswordForm.error_messages, **{
'password_incorrect': _("Your old password was entered incorrectly. " 'password_incorrect': _("Your old password was entered incorrectly. Please enter it again."),
"Please enter it again."),
}) })
old_password = forms.CharField( old_password = forms.CharField(
label=_("Old password"), label=_("Old password"),

View File

@ -30,8 +30,10 @@ def _get_builtin_permissions(opts):
""" """
perms = [] perms = []
for action in opts.default_permissions: for action in opts.default_permissions:
perms.append((get_permission_codename(action, opts), perms.append((
'Can %s %s' % (action, opts.verbose_name_raw))) get_permission_codename(action, opts),
'Can %s %s' % (action, opts.verbose_name_raw)
))
return perms return perms
@ -125,9 +127,11 @@ def get_default_username(check_db=True):
default_username = get_system_username() default_username = get_system_username()
try: try:
default_username = (unicodedata.normalize('NFKD', default_username) default_username = (
unicodedata.normalize('NFKD', default_username)
.encode('ascii', 'ignore').decode('ascii') .encode('ascii', 'ignore').decode('ascii')
.replace(' ', '').lower()) .replace(' ', '').lower()
)
except UnicodeDecodeError: except UnicodeDecodeError:
return '' return ''

View File

@ -22,11 +22,15 @@ class Command(BaseCommand):
return p return p
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('username', nargs='?', parser.add_argument(
help='Username to change password for; by default, it\'s the current username.') 'username', nargs='?',
parser.add_argument('--database', action='store', dest='database', help='Username to change password for; by default, it\'s the current username.',
)
parser.add_argument(
'--database', action='store', dest='database',
default=DEFAULT_DB_ALIAS, default=DEFAULT_DB_ALIAS,
help='Specifies the database to use. Default is "default".') help='Specifies the database to use. Default is "default".',
)
def handle(self, *args, **options): def handle(self, *args, **options):
if options['username']: if options['username']:

View File

@ -31,22 +31,32 @@ class Command(BaseCommand):
self.username_field = self.UserModel._meta.get_field(self.UserModel.USERNAME_FIELD) self.username_field = self.UserModel._meta.get_field(self.UserModel.USERNAME_FIELD)
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('--%s' % self.UserModel.USERNAME_FIELD, parser.add_argument(
'--%s' % self.UserModel.USERNAME_FIELD,
dest=self.UserModel.USERNAME_FIELD, default=None, dest=self.UserModel.USERNAME_FIELD, default=None,
help='Specifies the login for the superuser.') help='Specifies the login for the superuser.',
parser.add_argument('--noinput', '--no-input', )
parser.add_argument(
'--noinput', '--no-input',
action='store_false', dest='interactive', default=True, action='store_false', dest='interactive', default=True,
help=('Tells Django to NOT prompt the user for input of any kind. ' help=(
'Tells Django to NOT prompt the user for input of any kind. '
'You must use --%s with --noinput, along with an option for ' 'You must use --%s with --noinput, along with an option for '
'any other required field. Superusers created with --noinput will ' 'any other required field. Superusers created with --noinput will '
' not be able to log in until they\'re given a valid password.' % 'not be able to log in until they\'re given a valid password.' %
self.UserModel.USERNAME_FIELD)) self.UserModel.USERNAME_FIELD
parser.add_argument('--database', action='store', dest='database', ),
)
parser.add_argument(
'--database', action='store', dest='database',
default=DEFAULT_DB_ALIAS, default=DEFAULT_DB_ALIAS,
help='Specifies the database to use. Default is "default".') help='Specifies the database to use. Default is "default".',
)
for field in self.UserModel.REQUIRED_FIELDS: for field in self.UserModel.REQUIRED_FIELDS:
parser.add_argument('--%s' % field, dest=field, default=None, parser.add_argument(
help='Specifies the %s for the superuser.' % field) '--%s' % field, dest=field, default=None,
help='Specifies the %s for the superuser.' % field,
)
def execute(self, *args, **options): def execute(self, *args, **options):
self.stdin = options.get('stdin', sys.stdin) # Used for testing self.stdin = options.get('stdin', sys.stdin) # Used for testing
@ -67,8 +77,7 @@ class Command(BaseCommand):
if not options['interactive']: if not options['interactive']:
try: try:
if not username: if not username:
raise CommandError("You must use --%s with --noinput." % raise CommandError("You must use --%s with --noinput." % self.UserModel.USERNAME_FIELD)
self.UserModel.USERNAME_FIELD)
username = self.username_field.clean(username, None) username = self.username_field.clean(username, None)
for field_name in self.UserModel.REQUIRED_FIELDS: for field_name in self.UserModel.REQUIRED_FIELDS:

View File

@ -15,10 +15,10 @@ def check_generic_foreign_keys(app_configs=None, **kwargs):
else: else:
models = chain.from_iterable(app_config.get_models() for app_config in app_configs) models = chain.from_iterable(app_config.get_models() for app_config in app_configs)
errors = [] errors = []
fields = (obj fields = (
for model in models obj for model in models for obj in six.itervalues(vars(model))
for obj in six.itervalues(vars(model)) if isinstance(obj, GenericForeignKey)
if isinstance(obj, GenericForeignKey)) )
for field in fields: for field in fields:
errors.extend(field.check()) errors.extend(field.check())
return errors return errors

View File

@ -38,16 +38,11 @@ class BaseGenericInlineFormSet(BaseModelFormSet):
@classmethod @classmethod
def get_default_prefix(cls): def get_default_prefix(cls):
opts = cls.model._meta opts = cls.model._meta
return '-'.join( return '-'.join((opts.app_label, opts.model_name, cls.ct_field.name, cls.ct_fk_field.name))
(opts.app_label, opts.model_name,
cls.ct_field.name, cls.ct_fk_field.name)
)
def save_new(self, form, commit=True): def save_new(self, form, commit=True):
setattr(form.instance, self.ct_field.get_attname(), setattr(form.instance, self.ct_field.get_attname(), ContentType.objects.get_for_model(self.instance).pk)
ContentType.objects.get_for_model(self.instance).pk) setattr(form.instance, self.ct_fk_field.get_attname(), self.instance.pk)
setattr(form.instance, self.ct_fk_field.get_attname(),
self.instance.pk)
return form.save(commit=commit) return form.save(commit=commit)
@ -76,13 +71,12 @@ def generic_inlineformset_factory(model, form=ModelForm,
exclude.extend([ct_field.name, fk_field.name]) exclude.extend([ct_field.name, fk_field.name])
else: else:
exclude = [ct_field.name, fk_field.name] exclude = [ct_field.name, fk_field.name]
FormSet = modelformset_factory(model, form=form, FormSet = modelformset_factory(
formfield_callback=formfield_callback, model, form=form, formfield_callback=formfield_callback,
formset=formset, formset=formset, extra=extra, can_delete=can_delete,
extra=extra, can_delete=can_delete, can_order=can_order, can_order=can_order, fields=fields, exclude=exclude, max_num=max_num,
fields=fields, exclude=exclude, max_num=max_num, validate_max=validate_max, min_num=min_num, validate_min=validate_min,
validate_max=validate_max, min_num=min_num, )
validate_min=validate_min)
FormSet.ct_field = ct_field FormSet.ct_field = ct_field
FormSet.ct_fk_field = fk_field FormSet.ct_fk_field = fk_field
FormSet.for_concrete_model = for_concrete_model FormSet.for_concrete_model = for_concrete_model

View File

@ -22,9 +22,11 @@ class FlatPage(models.Model):
"the system will use 'flatpages/default.html'." "the system will use 'flatpages/default.html'."
), ),
) )
registration_required = models.BooleanField(_('registration required'), registration_required = models.BooleanField(
_('registration required'),
help_text=_("If this is checked, only logged-in users will be able to view the page."), help_text=_("If this is checked, only logged-in users will be able to view the page."),
default=False) default=False,
)
sites = models.ManyToManyField(Site, verbose_name=_('sites')) sites = models.ManyToManyField(Site, verbose_name=_('sites'))
class Meta: class Meta:

View File

@ -34,13 +34,11 @@ def flatpage(request, url):
url = '/' + url url = '/' + url
site_id = get_current_site(request).id site_id = get_current_site(request).id
try: try:
f = get_object_or_404(FlatPage, f = get_object_or_404(FlatPage, url=url, sites=site_id)
url=url, sites=site_id)
except Http404: except Http404:
if not url.endswith('/') and settings.APPEND_SLASH: if not url.endswith('/') and settings.APPEND_SLASH:
url += '/' url += '/'
f = get_object_or_404(FlatPage, f = get_object_or_404(FlatPage, url=url, sites=site_id)
url=url, sites=site_id)
return HttpResponsePermanentRedirect('%s/' % request.path) return HttpResponsePermanentRedirect('%s/' % request.path)
else: else:
raise raise

View File

@ -26,8 +26,7 @@ elif os.name == 'nt':
lib_names = ['gdal111', 'gdal110', 'gdal19', 'gdal18', 'gdal17'] lib_names = ['gdal111', 'gdal110', 'gdal19', 'gdal18', 'gdal17']
elif os.name == 'posix': elif os.name == 'posix':
# *NIX library names. # *NIX library names.
lib_names = ['gdal', 'GDAL', 'gdal1.11.0', 'gdal1.10.0', 'gdal1.9.0', lib_names = ['gdal', 'GDAL', 'gdal1.11.0', 'gdal1.10.0', 'gdal1.9.0', 'gdal1.8.0', 'gdal1.7.0']
'gdal1.8.0', 'gdal1.7.0']
else: else:
raise GDALException('Unsupported OS "%s"' % os.name) raise GDALException('Unsupported OS "%s"' % os.name)
@ -40,9 +39,10 @@ if lib_names:
break break
if lib_path is None: if lib_path is None:
raise GDALException('Could not find the GDAL library (tried "%s"). ' raise GDALException(
'Try setting GDAL_LIBRARY_PATH in your settings.' % 'Could not find the GDAL library (tried "%s"). Try setting '
'", "'.join(lib_names)) 'GDAL_LIBRARY_PATH in your settings.' % '", "'.join(lib_names)
)
# This loads the GDAL/OGR C library # This loads the GDAL/OGR C library
lgdal = CDLL(lib_path) lgdal = CDLL(lib_path)

View File

@ -42,7 +42,8 @@ reset_reading = void_output(lgdal.OGR_L_ResetReading, [c_void_p], errcheck=False
test_capability = int_output(lgdal.OGR_L_TestCapability, [c_void_p, c_char_p]) test_capability = int_output(lgdal.OGR_L_TestCapability, [c_void_p, c_char_p])
get_spatial_filter = geom_output(lgdal.OGR_L_GetSpatialFilter, [c_void_p]) get_spatial_filter = geom_output(lgdal.OGR_L_GetSpatialFilter, [c_void_p])
set_spatial_filter = void_output(lgdal.OGR_L_SetSpatialFilter, [c_void_p, c_void_p], errcheck=False) set_spatial_filter = void_output(lgdal.OGR_L_SetSpatialFilter, [c_void_p, c_void_p], errcheck=False)
set_spatial_filter_rect = void_output(lgdal.OGR_L_SetSpatialFilterRect, set_spatial_filter_rect = void_output(
lgdal.OGR_L_SetSpatialFilterRect,
[c_void_p, c_double, c_double, c_double, c_double], errcheck=False [c_void_p, c_double, c_double, c_double, c_double], errcheck=False
) )
@ -61,7 +62,8 @@ get_feat_geom_ref = geom_output(lgdal.OGR_F_GetGeometryRef, [c_void_p])
get_feat_field_count = int_output(lgdal.OGR_F_GetFieldCount, [c_void_p]) get_feat_field_count = int_output(lgdal.OGR_F_GetFieldCount, [c_void_p])
get_feat_field_defn = voidptr_output(lgdal.OGR_F_GetFieldDefnRef, [c_void_p, c_int]) get_feat_field_defn = voidptr_output(lgdal.OGR_F_GetFieldDefnRef, [c_void_p, c_int])
get_fid = int_output(lgdal.OGR_F_GetFID, [c_void_p]) get_fid = int_output(lgdal.OGR_F_GetFID, [c_void_p])
get_field_as_datetime = int_output(lgdal.OGR_F_GetFieldAsDateTime, get_field_as_datetime = int_output(
lgdal.OGR_F_GetFieldAsDateTime,
[c_void_p, c_int, c_int_p, c_int_p, c_int_p, c_int_p, c_int_p, c_int_p] [c_void_p, c_int, c_int_p, c_int_p, c_int_p, c_int_p, c_int_p, c_int_p]
) )
get_field_as_double = double_output(lgdal.OGR_F_GetFieldAsDouble, [c_void_p, c_int]) get_field_as_double = double_output(lgdal.OGR_F_GetFieldAsDouble, [c_void_p, c_int])

View File

@ -112,8 +112,7 @@ def string_output(func, argtypes, offset=-1, str_result=False, decoding=None):
# Dynamically defining our error-checking function with the # Dynamically defining our error-checking function with the
# given offset. # given offset.
def _check_str(result, func, cargs): def _check_str(result, func, cargs):
res = check_string(result, func, cargs, res = check_string(result, func, cargs, offset=offset, str_result=str_result)
offset=offset, str_result=str_result)
if res and decoding: if res and decoding:
res = res.decode(decoding) res = res.decode(decoding)
return res return res

View File

@ -82,7 +82,8 @@ get_geom_count = int_output(lgdal.OGR_G_GetGeometryCount, [c_void_p])
get_geom_name = const_string_output(lgdal.OGR_G_GetGeometryName, [c_void_p], decoding='ascii') get_geom_name = const_string_output(lgdal.OGR_G_GetGeometryName, [c_void_p], decoding='ascii')
get_geom_type = int_output(lgdal.OGR_G_GetGeometryType, [c_void_p]) get_geom_type = int_output(lgdal.OGR_G_GetGeometryType, [c_void_p])
get_point_count = int_output(lgdal.OGR_G_GetPointCount, [c_void_p]) get_point_count = int_output(lgdal.OGR_G_GetPointCount, [c_void_p])
get_point = void_output(lgdal.OGR_G_GetPoint, get_point = void_output(
lgdal.OGR_G_GetPoint,
[c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)], errcheck=False [c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)], errcheck=False
) )
geom_close_rings = void_output(lgdal.OGR_G_CloseRings, [c_void_p], errcheck=False) geom_close_rings = void_output(lgdal.OGR_G_CloseRings, [c_void_p], errcheck=False)

View File

@ -35,7 +35,8 @@ if GDAL_VERSION >= (2, 0):
else: else:
close_ds = void_output(std_call('GDALClose'), [c_void_p]) close_ds = void_output(std_call('GDALClose'), [c_void_p])
flush_ds = int_output(std_call('GDALFlushCache'), [c_void_p]) flush_ds = int_output(std_call('GDALFlushCache'), [c_void_p])
copy_ds = voidptr_output(std_call('GDALCreateCopy'), copy_ds = voidptr_output(
std_call('GDALCreateCopy'),
[c_void_p, c_char_p, c_void_p, c_int, POINTER(c_char_p), c_void_p, c_void_p] [c_void_p, c_char_p, c_void_p, c_int, POINTER(c_char_p), c_void_p, c_void_p]
) )
add_band_ds = void_output(std_call('GDALAddBand'), [c_void_p, c_int]) add_band_ds = void_output(std_call('GDALAddBand'), [c_void_p, c_int])
@ -51,7 +52,8 @@ get_ds_geotransform = void_output(std_call('GDALGetGeoTransform'), [c_void_p, PO
set_ds_geotransform = void_output(std_call('GDALSetGeoTransform'), [c_void_p, POINTER(c_double * 6)]) set_ds_geotransform = void_output(std_call('GDALSetGeoTransform'), [c_void_p, POINTER(c_double * 6)])
# Raster Band Routines # Raster Band Routines
band_io = void_output(std_call('GDALRasterIO'), band_io = void_output(
std_call('GDALRasterIO'),
[c_void_p, c_int, c_int, c_int, c_int, c_int, c_void_p, c_int, c_int, c_int, c_int, c_int] [c_void_p, c_int, c_int, c_int, c_int, c_int, c_void_p, c_int, c_int, c_int, c_int, c_int]
) )
get_band_xsize = int_output(std_call('GDALGetRasterBandXSize'), [c_void_p]) get_band_xsize = int_output(std_call('GDALGetRasterBandXSize'), [c_void_p])
@ -74,15 +76,18 @@ get_band_statistics = void_output(
], ],
errcheck=False errcheck=False
) )
compute_band_statistics = void_output(std_call('GDALComputeRasterStatistics'), compute_band_statistics = void_output(
std_call('GDALComputeRasterStatistics'),
[c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double), POINTER(c_double), c_void_p, c_void_p], [c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double), POINTER(c_double), c_void_p, c_void_p],
errcheck=False errcheck=False
) )
# Reprojection routine # Reprojection routine
reproject_image = void_output(std_call('GDALReprojectImage'), reproject_image = void_output(
std_call('GDALReprojectImage'),
[c_void_p, c_char_p, c_void_p, c_char_p, c_int, c_double, c_double, c_void_p, c_void_p, c_void_p] [c_void_p, c_char_p, c_void_p, c_char_p, c_int, c_double, c_double, c_void_p, c_void_p, c_void_p]
) )
auto_create_warped_vrt = voidptr_output(std_call('GDALAutoCreateWarpedVRT'), auto_create_warped_vrt = voidptr_output(
std_call('GDALAutoCreateWarpedVRT'),
[c_void_p, c_char_p, c_char_p, c_int, c_double, c_void_p] [c_void_p, c_char_p, c_char_p, c_int, c_double, c_void_p]
) )

View File

@ -56,7 +56,8 @@ angular_units = units_func(lgdal.OSRGetAngularUnits)
# For exporting to WKT, PROJ.4, "Pretty" WKT, and XML. # For exporting to WKT, PROJ.4, "Pretty" WKT, and XML.
to_wkt = string_output(std_call('OSRExportToWkt'), [c_void_p, POINTER(c_char_p)], decoding='ascii') to_wkt = string_output(std_call('OSRExportToWkt'), [c_void_p, POINTER(c_char_p)], decoding='ascii')
to_proj = string_output(std_call('OSRExportToProj4'), [c_void_p, POINTER(c_char_p)], decoding='ascii') to_proj = string_output(std_call('OSRExportToProj4'), [c_void_p, POINTER(c_char_p)], decoding='ascii')
to_pretty_wkt = string_output(std_call('OSRExportToPrettyWkt'), to_pretty_wkt = string_output(
std_call('OSRExportToPrettyWkt'),
[c_void_p, POINTER(c_char_p), c_int], offset=-2, decoding='ascii' [c_void_p, POINTER(c_char_p), c_int], offset=-2, decoding='ascii'
) )

View File

@ -176,6 +176,8 @@ class Polygon(GEOSGeometry):
@property @property
def kml(self): def kml(self):
"Returns the KML representation of this Polygon." "Returns the KML representation of this Polygon."
inner_kml = ''.join("<innerBoundaryIs>%s</innerBoundaryIs>" % self[i + 1].kml inner_kml = ''.join(
for i in range(self.num_interior_rings)) "<innerBoundaryIs>%s</innerBoundaryIs>" % self[i + 1].kml
for i in range(self.num_interior_rings)
)
return "<Polygon><outerBoundaryIs>%s</outerBoundaryIs>%s</Polygon>" % (self[0].kml, inner_kml) return "<Polygon><outerBoundaryIs>%s</outerBoundaryIs>%s</Polygon>" % (self[0].kml, inner_kml)

View File

@ -31,49 +31,70 @@ class ListOptionAction(argparse.Action):
class Command(BaseCommand): class Command(BaseCommand):
help = ('Inspects the given OGR-compatible data source (e.g., a shapefile) and outputs\n' help = (
'Inspects the given OGR-compatible data source (e.g., a shapefile) and outputs\n'
'a GeoDjango model with the given model name. For example:\n' 'a GeoDjango model with the given model name. For example:\n'
' ./manage.py ogrinspect zipcode.shp Zipcode') ' ./manage.py ogrinspect zipcode.shp Zipcode'
)
requires_system_checks = False requires_system_checks = False
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('data_source', help='Path to the data source.') parser.add_argument('data_source', help='Path to the data source.')
parser.add_argument('model_name', help='Name of the model to create.') parser.add_argument('model_name', help='Name of the model to create.')
parser.add_argument('--blank', dest='blank', parser.add_argument(
'--blank', dest='blank',
action=ListOptionAction, default=False, action=ListOptionAction, default=False,
help='Use a comma separated list of OGR field names to add ' help='Use a comma separated list of OGR field names to add '
'the `blank=True` option to the field definition. Set to `true` ' 'the `blank=True` option to the field definition. Set to `true` '
'to apply to all applicable fields.') 'to apply to all applicable fields.',
parser.add_argument('--decimal', dest='decimal', )
parser.add_argument(
'--decimal', dest='decimal',
action=ListOptionAction, default=False, action=ListOptionAction, default=False,
help='Use a comma separated list of OGR float fields to ' help='Use a comma separated list of OGR float fields to '
'generate `DecimalField` instead of the default ' 'generate `DecimalField` instead of the default '
'`FloatField`. Set to `true` to apply to all OGR float fields.') '`FloatField`. Set to `true` to apply to all OGR float fields.',
parser.add_argument('--geom-name', dest='geom_name', default='geom', )
help='Specifies the model name for the Geometry Field ' parser.add_argument(
'(defaults to `geom`)') '--geom-name', dest='geom_name', default='geom',
parser.add_argument('--layer', dest='layer_key', help='Specifies the model name for the Geometry Field (defaults to `geom`)'
)
parser.add_argument(
'--layer', dest='layer_key',
action=LayerOptionAction, default=0, action=LayerOptionAction, default=0,
help='The key for specifying which layer in the OGR data ' help='The key for specifying which layer in the OGR data '
'source to use. Defaults to 0 (the first layer). May be ' 'source to use. Defaults to 0 (the first layer). May be '
'an integer or a string identifier for the layer.') 'an integer or a string identifier for the layer.',
parser.add_argument('--multi-geom', action='store_true', )
parser.add_argument(
'--multi-geom', action='store_true',
dest='multi_geom', default=False, dest='multi_geom', default=False,
help='Treat the geometry in the data source as a geometry collection.') help='Treat the geometry in the data source as a geometry collection.',
parser.add_argument('--name-field', dest='name_field', )
help='Specifies a field name to return for the `__unicode__`/`__str__` function.') parser.add_argument(
parser.add_argument('--no-imports', action='store_false', dest='imports', default=True, '--name-field', dest='name_field',
help='Do not include `from django.contrib.gis.db import models` statement.') help='Specifies a field name to return for the `__unicode__`/`__str__` function.',
parser.add_argument('--null', dest='null', action=ListOptionAction, default=False, )
parser.add_argument(
'--no-imports', action='store_false', dest='imports', default=True,
help='Do not include `from django.contrib.gis.db import models` statement.',
)
parser.add_argument(
'--null', dest='null', action=ListOptionAction, default=False,
help='Use a comma separated list of OGR field names to add ' help='Use a comma separated list of OGR field names to add '
'the `null=True` option to the field definition. Set to `true` ' 'the `null=True` option to the field definition. Set to `true` '
'to apply to all applicable fields.') 'to apply to all applicable fields.',
parser.add_argument('--srid', dest='srid', )
parser.add_argument(
'--srid', dest='srid',
help='The SRID to use for the Geometry Field. If it can be ' help='The SRID to use for the Geometry Field. If it can be '
'determined, the SRID of the data source is used.') 'determined, the SRID of the data source is used.',
parser.add_argument('--mapping', action='store_true', dest='mapping', )
help='Generate mapping dictionary for use with `LayerMapping`.') parser.add_argument(
'--mapping', action='store_true', dest='mapping',
help='Generate mapping dictionary for use with `LayerMapping`.',
)
def handle(self, *args, **options): def handle(self, *args, **options):
data_source, model_name = options.pop('data_source'), options.pop('model_name') data_source, model_name = options.pop('data_source'), options.pop('model_name')
@ -97,7 +118,8 @@ class Command(BaseCommand):
if options['mapping']: if options['mapping']:
# Constructing the keyword arguments for `mapping`, and # Constructing the keyword arguments for `mapping`, and
# calling it on the data source. # calling it on the data source.
kwargs = {'geom_name': options['geom_name'], kwargs = {
'geom_name': options['geom_name'],
'layer_key': options['layer_key'], 'layer_key': options['layer_key'],
'multi_geom': options['multi_geom'], 'multi_geom': options['multi_geom'],
} }

View File

@ -78,8 +78,7 @@ class MeasureBase(object):
raise AttributeError('Unknown unit type: %s' % name) raise AttributeError('Unknown unit type: %s' % name)
def __repr__(self): def __repr__(self):
return '%s(%s=%s)' % (pretty_name(self), self._default_unit, return '%s(%s=%s)' % (pretty_name(self), self._default_unit, getattr(self, self._default_unit))
getattr(self, self._default_unit))
def __str__(self): def __str__(self):
return '%s %s' % (getattr(self, self._default_unit), self._default_unit) return '%s %s' % (getattr(self, self._default_unit), self._default_unit)
@ -102,8 +101,10 @@ class MeasureBase(object):
def __add__(self, other): def __add__(self, other):
if isinstance(other, self.__class__): if isinstance(other, self.__class__):
return self.__class__(default_unit=self._default_unit, return self.__class__(
**{self.STANDARD_UNIT: (self.standard + other.standard)}) default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard + other.standard)}
)
else: else:
raise TypeError('%(class)s must be added with %(class)s' % {"class": pretty_name(self)}) raise TypeError('%(class)s must be added with %(class)s' % {"class": pretty_name(self)})
@ -116,8 +117,10 @@ class MeasureBase(object):
def __sub__(self, other): def __sub__(self, other):
if isinstance(other, self.__class__): if isinstance(other, self.__class__):
return self.__class__(default_unit=self._default_unit, return self.__class__(
**{self.STANDARD_UNIT: (self.standard - other.standard)}) default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard - other.standard)}
)
else: else:
raise TypeError('%(class)s must be subtracted from %(class)s' % {"class": pretty_name(self)}) raise TypeError('%(class)s must be subtracted from %(class)s' % {"class": pretty_name(self)})
@ -130,8 +133,10 @@ class MeasureBase(object):
def __mul__(self, other): def __mul__(self, other):
if isinstance(other, NUMERIC_TYPES): if isinstance(other, NUMERIC_TYPES):
return self.__class__(default_unit=self._default_unit, return self.__class__(
**{self.STANDARD_UNIT: (self.standard * other)}) default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard * other)}
)
else: else:
raise TypeError('%(class)s must be multiplied with number' % {"class": pretty_name(self)}) raise TypeError('%(class)s must be multiplied with number' % {"class": pretty_name(self)})
@ -149,8 +154,10 @@ class MeasureBase(object):
if isinstance(other, self.__class__): if isinstance(other, self.__class__):
return self.standard / other.standard return self.standard / other.standard
if isinstance(other, NUMERIC_TYPES): if isinstance(other, NUMERIC_TYPES):
return self.__class__(default_unit=self._default_unit, return self.__class__(
**{self.STANDARD_UNIT: (self.standard / other)}) default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard / other)}
)
else: else:
raise TypeError('%(class)s must be divided with number or %(class)s' % {"class": pretty_name(self)}) raise TypeError('%(class)s must be divided with number or %(class)s' % {"class": pretty_name(self)})
@ -300,11 +307,15 @@ class Distance(MeasureBase):
def __mul__(self, other): def __mul__(self, other):
if isinstance(other, self.__class__): if isinstance(other, self.__class__):
return Area(default_unit=AREA_PREFIX + self._default_unit, return Area(
**{AREA_PREFIX + self.STANDARD_UNIT: (self.standard * other.standard)}) default_unit=AREA_PREFIX + self._default_unit,
**{AREA_PREFIX + self.STANDARD_UNIT: (self.standard * other.standard)}
)
elif isinstance(other, NUMERIC_TYPES): elif isinstance(other, NUMERIC_TYPES):
return self.__class__(default_unit=self._default_unit, return self.__class__(
**{self.STANDARD_UNIT: (self.standard * other)}) default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard * other)}
)
else: else:
raise TypeError('%(distance)s must be multiplied with number or %(distance)s' % { raise TypeError('%(distance)s must be multiplied with number or %(distance)s' % {
"distance": pretty_name(self.__class__), "distance": pretty_name(self.__class__),
@ -320,8 +331,10 @@ class Area(MeasureBase):
def __truediv__(self, other): def __truediv__(self, other):
if isinstance(other, NUMERIC_TYPES): if isinstance(other, NUMERIC_TYPES):
return self.__class__(default_unit=self._default_unit, return self.__class__(
**{self.STANDARD_UNIT: (self.standard / other)}) default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard / other)}
)
else: else:
raise TypeError('%(class)s must be divided by a number' % {"class": pretty_name(self)}) raise TypeError('%(class)s must be divided by a number' % {"class": pretty_name(self)})

View File

@ -24,8 +24,10 @@ def compress_kml(kml):
def render_to_kml(*args, **kwargs): def render_to_kml(*args, **kwargs):
"Renders the response as KML (using the correct MIME type)." "Renders the response as KML (using the correct MIME type)."
return HttpResponse(loader.render_to_string(*args, **kwargs), return HttpResponse(
content_type='application/vnd.google-earth.kml+xml') loader.render_to_string(*args, **kwargs),
content_type='application/vnd.google-earth.kml+xml',
)
def render_to_kmz(*args, **kwargs): def render_to_kmz(*args, **kwargs):
@ -33,11 +35,12 @@ def render_to_kmz(*args, **kwargs):
Compresses the KML content and returns as KMZ (using the correct Compresses the KML content and returns as KMZ (using the correct
MIME type). MIME type).
""" """
return HttpResponse(compress_kml(loader.render_to_string(*args, **kwargs)), return HttpResponse(
content_type='application/vnd.google-earth.kmz') compress_kml(loader.render_to_string(*args, **kwargs)),
content_type='application/vnd.google-earth.kmz',
)
def render_to_text(*args, **kwargs): def render_to_text(*args, **kwargs):
"Renders the response using the MIME type for plain text." "Renders the response using the MIME type for plain text."
return HttpResponse(loader.render_to_string(*args, **kwargs), return HttpResponse(loader.render_to_string(*args, **kwargs), content_type='text/plain')
content_type='text/plain')

View File

@ -24,8 +24,10 @@ def add_message(request, level, message, extra_tags='', fail_silently=False):
if hasattr(request, '_messages'): if hasattr(request, '_messages'):
return request._messages.add(level, message, extra_tags) return request._messages.add(level, message, extra_tags)
if not fail_silently: if not fail_silently:
raise MessageFailure('You cannot add messages without installing ' raise MessageFailure(
'django.contrib.messages.middleware.MessageMiddleware') 'You cannot add messages without installing '
'django.contrib.messages.middleware.MessageMiddleware'
)
def get_messages(request): def get_messages(request):

View File

@ -82,13 +82,14 @@ class CookieStorage(BaseStorage):
store, or deletes the cookie. store, or deletes the cookie.
""" """
if encoded_data: if encoded_data:
response.set_cookie(self.cookie_name, encoded_data, response.set_cookie(
self.cookie_name, encoded_data,
domain=settings.SESSION_COOKIE_DOMAIN, domain=settings.SESSION_COOKIE_DOMAIN,
secure=settings.SESSION_COOKIE_SECURE or None, secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None) httponly=settings.SESSION_COOKIE_HTTPONLY or None,
)
else: else:
response.delete_cookie(self.cookie_name, response.delete_cookie(self.cookie_name, domain=settings.SESSION_COOKIE_DOMAIN)
domain=settings.SESSION_COOKIE_DOMAIN)
def _store(self, messages, response, remove_oldest=True, *args, **kwargs): def _store(self, messages, response, remove_oldest=True, *args, **kwargs):
""" """

View File

@ -44,14 +44,16 @@ class KeysValidator(object):
keys = set(value.keys()) keys = set(value.keys())
missing_keys = self.keys - keys missing_keys = self.keys - keys
if missing_keys: if missing_keys:
raise ValidationError(self.messages['missing_keys'], raise ValidationError(
self.messages['missing_keys'],
code='missing_keys', code='missing_keys',
params={'keys': ', '.join(missing_keys)}, params={'keys': ', '.join(missing_keys)},
) )
if self.strict: if self.strict:
extra_keys = keys - self.keys extra_keys = keys - self.keys
if extra_keys: if extra_keys:
raise ValidationError(self.messages['extra_keys'], raise ValidationError(
self.messages['extra_keys'],
code='extra_keys', code='extra_keys',
params={'keys': ', '.join(extra_keys)}, params={'keys': ', '.join(extra_keys)},
) )

View File

@ -7,10 +7,18 @@ from django.utils.translation import ugettext_lazy as _
@python_2_unicode_compatible @python_2_unicode_compatible
class Redirect(models.Model): class Redirect(models.Model):
site = models.ForeignKey(Site, models.CASCADE, verbose_name=_('site')) site = models.ForeignKey(Site, models.CASCADE, verbose_name=_('site'))
old_path = models.CharField(_('redirect from'), max_length=200, db_index=True, old_path = models.CharField(
help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'.")) _('redirect from'),
new_path = models.CharField(_('redirect to'), max_length=200, blank=True, max_length=200,
help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'.")) db_index=True,
help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'."),
)
new_path = models.CharField(
_('redirect to'),
max_length=200,
blank=True,
help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'."),
)
class Meta: class Meta:
verbose_name = _('redirect') verbose_name = _('redirect')

View File

@ -110,8 +110,7 @@ class SessionBase(object):
# ValueError, SuspiciousOperation, unpickling exceptions. If any of # ValueError, SuspiciousOperation, unpickling exceptions. If any of
# these happen, just return an empty dictionary (an empty session). # these happen, just return an empty dictionary (an empty session).
if isinstance(e, SuspiciousOperation): if isinstance(e, SuspiciousOperation):
logger = logging.getLogger('django.security.%s' % logger = logging.getLogger('django.security.%s' % e.__class__.__name__)
e.__class__.__name__)
logger.warning(force_text(e)) logger.warning(force_text(e))
return {} return {}

View File

@ -45,12 +45,10 @@ class SessionStore(DBStore):
expire_date__gt=timezone.now() expire_date__gt=timezone.now()
) )
data = self.decode(s.session_data) data = self.decode(s.session_data)
self._cache.set(self.cache_key, data, self._cache.set(self.cache_key, data, self.get_expiry_age(expiry=s.expire_date))
self.get_expiry_age(expiry=s.expire_date))
except (self.model.DoesNotExist, SuspiciousOperation) as e: except (self.model.DoesNotExist, SuspiciousOperation) as e:
if isinstance(e, SuspiciousOperation): if isinstance(e, SuspiciousOperation):
logger = logging.getLogger('django.security.%s' % logger = logging.getLogger('django.security.%s' % e.__class__.__name__)
e.__class__.__name__)
logger.warning(force_text(e)) logger.warning(force_text(e))
self._session_key = None self._session_key = None
data = {} data = {}

View File

@ -37,8 +37,7 @@ class SessionStore(SessionBase):
return self.decode(s.session_data) return self.decode(s.session_data)
except (self.model.DoesNotExist, SuspiciousOperation) as e: except (self.model.DoesNotExist, SuspiciousOperation) as e:
if isinstance(e, SuspiciousOperation): if isinstance(e, SuspiciousOperation):
logger = logging.getLogger('django.security.%s' % logger = logging.getLogger('django.security.%s' % e.__class__.__name__)
e.__class__.__name__)
logger.warning(force_text(e)) logger.warning(force_text(e))
self._session_key = None self._session_key = None
return {} return {}

View File

@ -92,8 +92,7 @@ class SessionStore(SessionBase):
session_data = self.decode(file_data) session_data = self.decode(file_data)
except (EOFError, SuspiciousOperation) as e: except (EOFError, SuspiciousOperation) as e:
if isinstance(e, SuspiciousOperation): if isinstance(e, SuspiciousOperation):
logger = logging.getLogger('django.security.%s' % logger = logging.getLogger('django.security.%s' % e.__class__.__name__)
e.__class__.__name__)
logger.warning(force_text(e)) logger.warning(force_text(e))
self.create() self.create()
@ -160,8 +159,7 @@ class SessionStore(SessionBase):
dir, prefix = os.path.split(session_file_name) dir, prefix = os.path.split(session_file_name)
try: try:
output_file_fd, output_file_name = tempfile.mkstemp(dir=dir, output_file_fd, output_file_name = tempfile.mkstemp(dir=dir, prefix=prefix + '_out_')
prefix=prefix + '_out_')
renamed = False renamed = False
try: try:
try: try:

View File

@ -12,11 +12,13 @@ class SessionStore(SessionBase):
raises BadSignature if signature fails. raises BadSignature if signature fails.
""" """
try: try:
return signing.loads(self.session_key, return signing.loads(
self.session_key,
serializer=self.serializer, serializer=self.serializer,
# This doesn't handle non-default expiry dates, see #19201 # This doesn't handle non-default expiry dates, see #19201
max_age=settings.SESSION_COOKIE_AGE, max_age=settings.SESSION_COOKIE_AGE,
salt='django.contrib.sessions.backends.signed_cookies') salt='django.contrib.sessions.backends.signed_cookies',
)
except Exception: except Exception:
# BadSignature, ValueError, or unpickling exceptions. If any of # BadSignature, ValueError, or unpickling exceptions. If any of
# these happen, reset the session. # these happen, reset the session.
@ -73,9 +75,11 @@ class SessionStore(SessionBase):
session key. session key.
""" """
session_cache = getattr(self, '_session_cache', {}) session_cache = getattr(self, '_session_cache', {})
return signing.dumps(session_cache, compress=True, return signing.dumps(
session_cache, compress=True,
salt='django.contrib.sessions.backends.signed_cookies', salt='django.contrib.sessions.backends.signed_cookies',
serializer=self.serializer) serializer=self.serializer,
)
@classmethod @classmethod
def clear_expired(cls): def clear_expired(cls):

View File

@ -33,8 +33,7 @@ class SessionMiddleware(object):
# First check if we need to delete this cookie. # First check if we need to delete this cookie.
# The session should be deleted only if the session is entirely empty # The session should be deleted only if the session is entirely empty
if settings.SESSION_COOKIE_NAME in request.COOKIES and empty: if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
response.delete_cookie(settings.SESSION_COOKIE_NAME, response.delete_cookie(settings.SESSION_COOKIE_NAME, domain=settings.SESSION_COOKIE_DOMAIN)
domain=settings.SESSION_COOKIE_DOMAIN)
else: else:
if accessed: if accessed:
patch_vary_headers(response, ('Cookie',)) patch_vary_headers(response, ('Cookie',))
@ -56,10 +55,12 @@ class SessionMiddleware(object):
# page will result in a redirect to the login page # page will result in a redirect to the login page
# if required. # if required.
return redirect(request.path) return redirect(request.path)
response.set_cookie(settings.SESSION_COOKIE_NAME, response.set_cookie(
settings.SESSION_COOKIE_NAME,
request.session.session_key, max_age=max_age, request.session.session_key, max_age=max_age,
expires=expires, domain=settings.SESSION_COOKIE_DOMAIN, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
path=settings.SESSION_COOKIE_PATH, path=settings.SESSION_COOKIE_PATH,
secure=settings.SESSION_COOKIE_SECURE or None, secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None) httponly=settings.SESSION_COOKIE_HTTPONLY or None,
)
return response return response

View File

@ -85,8 +85,12 @@ class SiteManager(models.Manager):
@python_2_unicode_compatible @python_2_unicode_compatible
class Site(models.Model): class Site(models.Model):
domain = models.CharField(_('domain name'), max_length=100, domain = models.CharField(
validators=[_simple_domain_name_validator], unique=True) _('domain name'),
max_length=100,
validators=[_simple_domain_name_validator],
unique=True,
)
name = models.CharField(_('display name'), max_length=50) name = models.CharField(_('display name'), max_length=50)
objects = SiteManager() objects = SiteManager()

View File

@ -39,30 +39,43 @@ class Command(BaseCommand):
return True return True
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('--noinput', '--no-input', parser.add_argument(
'--noinput', '--no-input',
action='store_false', dest='interactive', default=True, action='store_false', dest='interactive', default=True,
help="Do NOT prompt the user for input of any kind.") help="Do NOT prompt the user for input of any kind.",
parser.add_argument('--no-post-process', )
parser.add_argument(
'--no-post-process',
action='store_false', dest='post_process', default=True, action='store_false', dest='post_process', default=True,
help="Do NOT post process collected files.") help="Do NOT post process collected files.",
parser.add_argument('-i', '--ignore', action='append', default=[], )
parser.add_argument(
'-i', '--ignore', action='append', default=[],
dest='ignore_patterns', metavar='PATTERN', dest='ignore_patterns', metavar='PATTERN',
help="Ignore files or directories matching this glob-style " help="Ignore files or directories matching this glob-style "
"pattern. Use multiple times to ignore more.") "pattern. Use multiple times to ignore more.",
parser.add_argument('-n', '--dry-run', )
parser.add_argument(
'-n', '--dry-run',
action='store_true', dest='dry_run', default=False, action='store_true', dest='dry_run', default=False,
help="Do everything except modify the filesystem.") help="Do everything except modify the filesystem.",
parser.add_argument('-c', '--clear', )
parser.add_argument(
'-c', '--clear',
action='store_true', dest='clear', default=False, action='store_true', dest='clear', default=False,
help="Clear the existing files using the storage " help="Clear the existing files using the storage "
"before trying to copy or link the original file.") "before trying to copy or link the original file.",
parser.add_argument('-l', '--link', )
parser.add_argument(
'-l', '--link',
action='store_true', dest='link', default=False, action='store_true', dest='link', default=False,
help="Create a symbolic link to each file instead of copying.") help="Create a symbolic link to each file instead of copying.",
parser.add_argument('--no-default-ignore', action='store_false', )
parser.add_argument(
'--no-default-ignore', action='store_false',
dest='use_default_ignore_patterns', default=True, dest='use_default_ignore_patterns', default=True,
help="Don't ignore the common private glob-style patterns 'CVS', " help="Don't ignore the common private glob-style patterns 'CVS', '.*' and '*~'.",
"'.*' and '*~'.") )
def set_options(self, **options): def set_options(self, **options):
""" """

View File

@ -13,18 +13,21 @@ class Command(LabelCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
super(Command, self).add_arguments(parser) super(Command, self).add_arguments(parser)
parser.add_argument('--first', action='store_false', dest='all', parser.add_argument(
'--first', action='store_false', dest='all',
default=True, default=True,
help="Only return the first match for each static file.") help="Only return the first match for each static file.",
)
def handle_label(self, path, **options): def handle_label(self, path, **options):
verbosity = options['verbosity'] verbosity = options['verbosity']
result = finders.find(path, all=options['all']) result = finders.find(path, all=options['all'])
path = force_text(path) path = force_text(path)
if verbosity >= 2: if verbosity >= 2:
searched_locations = ("\nLooking in the following locations:\n %s" % searched_locations = (
"\n ".join(force_text(location) "\nLooking in the following locations:\n %s" %
for location in finders.searched_locations)) "\n ".join(force_text(location) for location in finders.searched_locations)
)
else: else:
searched_locations = '' searched_locations = ''
if result: if result:

View File

@ -9,10 +9,14 @@ class Command(RunserverCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
super(Command, self).add_arguments(parser) super(Command, self).add_arguments(parser)
parser.add_argument('--nostatic', action="store_false", dest='use_static_handler', default=True, parser.add_argument(
help='Tells Django to NOT automatically serve static files at STATIC_URL.') '--nostatic', action="store_false", dest='use_static_handler', default=True,
parser.add_argument('--insecure', action="store_true", dest='insecure_serving', default=False, help='Tells Django to NOT automatically serve static files at STATIC_URL.',
help='Allows serving static files even if DEBUG is False.') )
parser.add_argument(
'--insecure', action="store_true", dest='insecure_serving', default=False,
help='Allows serving static files even if DEBUG is False.',
)
def get_handler(self, *args, **options): def get_handler(self, *args, **options):
""" """

View File

@ -234,14 +234,16 @@ class BaseCache(object):
cache code. cache code.
""" """
if len(key) > MEMCACHE_MAX_KEY_LENGTH: if len(key) > MEMCACHE_MAX_KEY_LENGTH:
warnings.warn('Cache key will cause errors if used with memcached: ' warnings.warn(
'%r (longer than %s)' % (key, MEMCACHE_MAX_KEY_LENGTH), 'Cache key will cause errors if used with memcached: %r '
CacheKeyWarning) '(longer than %s)' % (key, MEMCACHE_MAX_KEY_LENGTH), CacheKeyWarning
)
for char in key: for char in key:
if ord(char) < 33 or ord(char) == 127: if ord(char) < 33 or ord(char) == 127:
warnings.warn('Cache key contains characters that will cause ' warnings.warn(
'errors if used with memcached: %r' % key, 'Cache key contains characters that will cause errors if '
CacheKeyWarning) 'used with memcached: %r' % key, CacheKeyWarning
)
break break
def incr_version(self, key, delta=1, version=None): def incr_version(self, key, delta=1, version=None):

View File

@ -35,8 +35,7 @@ if os.name == 'nt':
Python 2.6+, or the 'delete', 'buffering', 'encoding', or 'newline' Python 2.6+, or the 'delete', 'buffering', 'encoding', or 'newline'
keyword arguments in Python 3.0+. keyword arguments in Python 3.0+.
""" """
def __init__(self, mode='w+b', bufsize=-1, suffix='', prefix='', def __init__(self, mode='w+b', bufsize=-1, suffix='', prefix='', dir=None):
dir=None):
fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir) fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)
self.name = name self.name = name
self.file = os.fdopen(fd, mode, bufsize) self.file = os.fdopen(fd, mode, bufsize)

View File

@ -62,8 +62,7 @@ class TemporaryUploadedFile(UploadedFile):
""" """
def __init__(self, name, content_type, size, charset, content_type_extra=None): def __init__(self, name, content_type, size, charset, content_type_extra=None):
if settings.FILE_UPLOAD_TEMP_DIR: if settings.FILE_UPLOAD_TEMP_DIR:
file = tempfile.NamedTemporaryFile(suffix='.upload', file = tempfile.NamedTemporaryFile(suffix='.upload', dir=settings.FILE_UPLOAD_TEMP_DIR)
dir=settings.FILE_UPLOAD_TEMP_DIR)
else: else:
file = tempfile.NamedTemporaryFile(suffix='.upload') file = tempfile.NamedTemporaryFile(suffix='.upload')
super(TemporaryUploadedFile, self).__init__(file, name, content_type, size, charset, content_type_extra) super(TemporaryUploadedFile, self).__init__(file, name, content_type, size, charset, content_type_extra)

View File

@ -154,8 +154,10 @@ class BaseHandler(object):
view_name = callback.__name__ view_name = callback.__name__
else: # CBV else: # CBV
view_name = callback.__class__.__name__ + '.__call__' view_name = callback.__class__.__name__ + '.__call__'
raise ValueError("The view %s.%s didn't return an HttpResponse object. It returned None instead." raise ValueError(
% (callback.__module__, view_name)) "The view %s.%s didn't return an HttpResponse object. It "
"returned None instead." % (callback.__module__, view_name)
)
# If the response supports deferred rendering, apply template # If the response supports deferred rendering, apply template
# response middleware and then render the response # response middleware and then render the response
@ -167,7 +169,8 @@ class BaseHandler(object):
raise ValueError( raise ValueError(
"%s.process_template_response didn't return an " "%s.process_template_response didn't return an "
"HttpResponse object. It returned None instead." "HttpResponse object. It returned None instead."
% (middleware_method.__self__.__class__.__name__)) % (middleware_method.__self__.__class__.__name__)
)
try: try:
response = response.render() response = response.render()
except Exception as e: except Exception as e:
@ -176,11 +179,10 @@ class BaseHandler(object):
response_is_rendered = True response_is_rendered = True
except http.Http404 as exc: except http.Http404 as exc:
logger.warning('Not Found: %s', request.path, logger.warning(
extra={ 'Not Found: %s', request.path,
'status_code': 404, extra={'status_code': 404, 'request': request},
'request': request )
})
if settings.DEBUG: if settings.DEBUG:
response = debug.technical_404_response(request, exc) response = debug.technical_404_response(request, exc)
else: else:
@ -189,32 +191,25 @@ class BaseHandler(object):
except PermissionDenied as exc: except PermissionDenied as exc:
logger.warning( logger.warning(
'Forbidden (Permission denied): %s', request.path, 'Forbidden (Permission denied): %s', request.path,
extra={ extra={'status_code': 403, 'request': request},
'status_code': 403, )
'request': request
})
response = self.get_exception_response(request, resolver, 403, exc) response = self.get_exception_response(request, resolver, 403, exc)
except MultiPartParserError as exc: except MultiPartParserError as exc:
logger.warning( logger.warning(
'Bad request (Unable to parse request body): %s', request.path, 'Bad request (Unable to parse request body): %s', request.path,
extra={ extra={'status_code': 400, 'request': request},
'status_code': 400, )
'request': request
})
response = self.get_exception_response(request, resolver, 400, exc) response = self.get_exception_response(request, resolver, 400, exc)
except SuspiciousOperation as exc: except SuspiciousOperation as exc:
# The request logger receives events for any problematic request # The request logger receives events for any problematic request
# The security logger receives events for all SuspiciousOperations # The security logger receives events for all SuspiciousOperations
security_logger = logging.getLogger('django.security.%s' % security_logger = logging.getLogger('django.security.%s' % exc.__class__.__name__)
exc.__class__.__name__)
security_logger.error( security_logger.error(
force_text(exc), force_text(exc),
extra={ extra={'status_code': 400, 'request': request},
'status_code': 400, )
'request': request
})
if settings.DEBUG: if settings.DEBUG:
return debug.technical_500_response(request, *sys.exc_info(), status_code=400) return debug.technical_500_response(request, *sys.exc_info(), status_code=400)
@ -277,12 +272,10 @@ class BaseHandler(object):
if settings.DEBUG_PROPAGATE_EXCEPTIONS: if settings.DEBUG_PROPAGATE_EXCEPTIONS:
raise raise
logger.error('Internal Server Error: %s', request.path, logger.error(
'Internal Server Error: %s', request.path,
exc_info=exc_info, exc_info=exc_info,
extra={ extra={'status_code': 500, 'request': request},
'status_code': 500,
'request': request
}
) )
if settings.DEBUG: if settings.DEBUG:

View File

@ -158,7 +158,8 @@ class WSGIHandler(base.BaseHandler):
try: try:
request = self.request_class(environ) request = self.request_class(environ)
except UnicodeDecodeError: except UnicodeDecodeError:
logger.warning('Bad Request (UnicodeDecodeError)', logger.warning(
'Bad Request (UnicodeDecodeError)',
exc_info=sys.exc_info(), exc_info=sys.exc_info(),
extra={ extra={
'status_code': 400, 'status_code': 400,

View File

@ -50,11 +50,12 @@ def send_mail(subject, message, from_email, recipient_list,
Note: The API for this method is frozen. New code wanting to extend the Note: The API for this method is frozen. New code wanting to extend the
functionality should use the EmailMessage class directly. functionality should use the EmailMessage class directly.
""" """
connection = connection or get_connection(username=auth_user, connection = connection or get_connection(
username=auth_user,
password=auth_password, password=auth_password,
fail_silently=fail_silently) fail_silently=fail_silently,
mail = EmailMultiAlternatives(subject, message, from_email, recipient_list, )
connection=connection) mail = EmailMultiAlternatives(subject, message, from_email, recipient_list, connection=connection)
if html_message: if html_message:
mail.attach_alternative(html_message, 'text/html') mail.attach_alternative(html_message, 'text/html')
@ -75,12 +76,15 @@ def send_mass_mail(datatuple, fail_silently=False, auth_user=None,
Note: The API for this method is frozen. New code wanting to extend the Note: The API for this method is frozen. New code wanting to extend the
functionality should use the EmailMessage class directly. functionality should use the EmailMessage class directly.
""" """
connection = connection or get_connection(username=auth_user, connection = connection or get_connection(
username=auth_user,
password=auth_password, password=auth_password,
fail_silently=fail_silently) fail_silently=fail_silently,
messages = [EmailMessage(subject, message, sender, recipient, )
connection=connection) messages = [
for subject, message, sender, recipient in datatuple] EmailMessage(subject, message, sender, recipient, connection=connection)
for subject, message, sender, recipient in datatuple
]
return connection.send_messages(messages) return connection.send_messages(messages)
@ -89,9 +93,11 @@ def mail_admins(subject, message, fail_silently=False, connection=None,
"""Sends a message to the admins, as defined by the ADMINS setting.""" """Sends a message to the admins, as defined by the ADMINS setting."""
if not settings.ADMINS: if not settings.ADMINS:
return return
mail = EmailMultiAlternatives('%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject), mail = EmailMultiAlternatives(
message, settings.SERVER_EMAIL, [a[1] for a in settings.ADMINS], '%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject), message,
connection=connection) settings.SERVER_EMAIL, [a[1] for a in settings.ADMINS],
connection=connection,
)
if html_message: if html_message:
mail.attach_alternative(html_message, 'text/html') mail.attach_alternative(html_message, 'text/html')
mail.send(fail_silently=fail_silently) mail.send(fail_silently=fail_silently)
@ -102,9 +108,11 @@ def mail_managers(subject, message, fail_silently=False, connection=None,
"""Sends a message to the managers, as defined by the MANAGERS setting.""" """Sends a message to the managers, as defined by the MANAGERS setting."""
if not settings.MANAGERS: if not settings.MANAGERS:
return return
mail = EmailMultiAlternatives('%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject), mail = EmailMultiAlternatives(
message, settings.SERVER_EMAIL, [a[1] for a in settings.MANAGERS], '%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject), message,
connection=connection) settings.SERVER_EMAIL, [a[1] for a in settings.MANAGERS],
connection=connection,
)
if html_message: if html_message:
mail.attach_alternative(html_message, 'text/html') mail.attach_alternative(html_message, 'text/html')
mail.send(fail_silently=fail_silently) mail.send(fail_silently=fail_silently)

View File

@ -90,8 +90,7 @@ def forbid_multi_line_headers(name, val, encoding):
val.encode('ascii') val.encode('ascii')
except UnicodeEncodeError: except UnicodeEncodeError:
if name.lower() in ADDRESS_HEADERS: if name.lower() in ADDRESS_HEADERS:
val = ', '.join(sanitize_address(addr, encoding) val = ', '.join(sanitize_address(addr, encoding) for addr in getaddresses((val,)))
for addr in getaddresses((val,)))
else: else:
val = Header(val, encoding).encode() val = Header(val, encoding).encode()
else: else:

View File

@ -196,8 +196,10 @@ class ManagementUtility(object):
settings.INSTALLED_APPS settings.INSTALLED_APPS
else: else:
sys.stderr.write("No Django settings specified.\n") sys.stderr.write("No Django settings specified.\n")
sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % sys.stderr.write(
(subcommand, self.prog_name)) "Unknown command: %r\nType '%s help' for usage.\n"
% (subcommand, self.prog_name)
)
sys.exit(1) sys.exit(1)
if isinstance(app_name, BaseCommand): if isinstance(app_name, BaseCommand):
# If the command is already loaded, use it directly. # If the command is already loaded, use it directly.

View File

@ -241,25 +241,33 @@ class BaseCommand(object):
Create and return the ``ArgumentParser`` which will be used to Create and return the ``ArgumentParser`` which will be used to
parse the arguments to this command. parse the arguments to this command.
""" """
parser = CommandParser(self, prog="%s %s" % (os.path.basename(prog_name), subcommand), parser = CommandParser(
description=self.help or None) self, prog="%s %s" % (os.path.basename(prog_name), subcommand),
description=self.help or None,
)
parser.add_argument('--version', action='version', version=self.get_version()) parser.add_argument('--version', action='version', version=self.get_version())
parser.add_argument('-v', '--verbosity', action='store', dest='verbosity', default=1, parser.add_argument(
'-v', '--verbosity', action='store', dest='verbosity', default=1,
type=int, choices=[0, 1, 2, 3], type=int, choices=[0, 1, 2, 3],
help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output') help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output',
parser.add_argument('--settings', )
parser.add_argument(
'--settings',
help=( help=(
'The Python path to a settings module, e.g. ' 'The Python path to a settings module, e.g. '
'"myproject.settings.main". If this isn\'t provided, the ' '"myproject.settings.main". If this isn\'t provided, the '
'DJANGO_SETTINGS_MODULE environment variable will be used.' 'DJANGO_SETTINGS_MODULE environment variable will be used.'
), ),
) )
parser.add_argument('--pythonpath', parser.add_argument(
help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".') '--pythonpath',
parser.add_argument('--traceback', action='store_true', help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".',
help='Raise on CommandError exceptions') )
parser.add_argument('--no-color', action='store_true', dest='no_color', default=False, parser.add_argument('--traceback', action='store_true', help='Raise on CommandError exceptions')
help="Don't colorize the command output.") parser.add_argument(
'--no-color', action='store_true', dest='no_color', default=False,
help="Don't colorize the command output.",
)
self.add_arguments(parser) self.add_arguments(parser)
return parser return parser
@ -478,8 +486,7 @@ class AppCommand(BaseCommand):
missing_args_message = "Enter at least one application label." missing_args_message = "Enter at least one application label."
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('args', metavar='app_label', nargs='+', parser.add_argument('args', metavar='app_label', nargs='+', help='One or more application label.')
help='One or more application label.')
def handle(self, *app_labels, **options): def handle(self, *app_labels, **options):
from django.apps import apps from django.apps import apps

View File

@ -14,12 +14,18 @@ class Command(BaseCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('args', metavar='app_label', nargs='*') parser.add_argument('args', metavar='app_label', nargs='*')
parser.add_argument('--tag', '-t', action='append', dest='tags', parser.add_argument(
help='Run only checks labeled with given tag.') '--tag', '-t', action='append', dest='tags',
parser.add_argument('--list-tags', action='store_true', dest='list_tags', help='Run only checks labeled with given tag.',
help='List available tags.') )
parser.add_argument('--deploy', action='store_true', dest='deploy', parser.add_argument(
help='Check deployment settings.') '--list-tags', action='store_true', dest='list_tags',
help='List available tags.',
)
parser.add_argument(
'--deploy', action='store_true', dest='deploy',
help='Check deployment settings.',
)
parser.add_argument( parser.add_argument(
'--fail-level', '--fail-level',
default='ERROR', default='ERROR',

View File

@ -36,13 +36,19 @@ class Command(BaseCommand):
program_options = ['--check-format'] program_options = ['--check-format']
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('--locale', '-l', dest='locale', action='append', default=[], parser.add_argument(
'--locale', '-l', dest='locale', action='append', default=[],
help='Locale(s) to process (e.g. de_AT). Default is to process all. ' help='Locale(s) to process (e.g. de_AT). Default is to process all. '
'Can be used multiple times.') 'Can be used multiple times.',
parser.add_argument('--exclude', '-x', dest='exclude', action='append', default=[], )
help='Locales to exclude. Default is none. Can be used multiple times.') parser.add_argument(
parser.add_argument('--use-fuzzy', '-f', dest='fuzzy', action='store_true', default=False, '--exclude', '-x', dest='exclude', action='append', default=[],
help='Use fuzzy translations.') help='Locales to exclude. Default is none. Can be used multiple times.',
)
parser.add_argument(
'--use-fuzzy', '-f', dest='fuzzy', action='store_true', default=False,
help='Use fuzzy translations.',
)
def handle(self, **options): def handle(self, **options):
locale = options['locale'] locale = options['locale']
@ -116,8 +122,9 @@ class Command(BaseCommand):
"mo files will not be updated/created." % dirpath) "mo files will not be updated/created." % dirpath)
return return
args = [self.program] + self.program_options + ['-o', args = [self.program] + self.program_options + [
npath(base_path + '.mo'), npath(base_path + '.po')] '-o', npath(base_path + '.mo'), npath(base_path + '.po')
]
output, errors, status = popen_wrapper(args) output, errors, status = popen_wrapper(args)
if status: if status:
if errors: if errors:

View File

@ -15,16 +15,20 @@ class Command(BaseCommand):
requires_system_checks = False requires_system_checks = False
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('args', metavar='table_name', nargs='*', parser.add_argument(
help='Optional table names. Otherwise, settings.CACHES is used to ' 'args', metavar='table_name', nargs='*',
'find cache tables.') help='Optional table names. Otherwise, settings.CACHES is used to find cache tables.',
parser.add_argument('--database', action='store', dest='database', )
parser.add_argument(
'--database', action='store', dest='database',
default=DEFAULT_DB_ALIAS, default=DEFAULT_DB_ALIAS,
help='Nominates a database onto which the cache tables will be ' help='Nominates a database onto which the cache tables will be '
'installed. Defaults to the "default" database.') 'installed. Defaults to the "default" database.',
parser.add_argument('--dry-run', action='store_true', dest='dry_run', )
help='Does not create the table, just prints the SQL that would ' parser.add_argument(
'be run.') '--dry-run', action='store_true', dest='dry_run',
help='Does not create the table, just prints the SQL that would be run.',
)
def handle(self, *tablenames, **options): def handle(self, *tablenames, **options):
db = options['database'] db = options['database']
@ -72,9 +76,10 @@ class Command(BaseCommand):
field_output.append("UNIQUE") field_output.append("UNIQUE")
if f.db_index: if f.db_index:
unique = "UNIQUE " if f.unique else "" unique = "UNIQUE " if f.unique else ""
index_output.append("CREATE %sINDEX %s ON %s (%s);" % index_output.append(
(unique, qn('%s_%s' % (tablename, f.name)), qn(tablename), "CREATE %sINDEX %s ON %s (%s);" %
qn(f.name))) (unique, qn('%s_%s' % (tablename, f.name)), qn(tablename), qn(f.name))
)
table_output.append(" ".join(field_output)) table_output.append(" ".join(field_output))
full_statement = ["CREATE TABLE %s (" % qn(tablename)] full_statement = ["CREATE TABLE %s (" % qn(tablename)]
for i, line in enumerate(table_output): for i, line in enumerate(table_output):
@ -89,8 +94,7 @@ class Command(BaseCommand):
self.stdout.write(statement) self.stdout.write(statement)
return return
with transaction.atomic(using=database, with transaction.atomic(using=database, savepoint=connection.features.can_rollback_ddl):
savepoint=connection.features.can_rollback_ddl):
with connection.cursor() as curs: with connection.cursor() as curs:
try: try:
curs.execute(full_statement) curs.execute(full_statement)

View File

@ -3,15 +3,18 @@ from django.db import DEFAULT_DB_ALIAS, connections
class Command(BaseCommand): class Command(BaseCommand):
help = ("Runs the command-line client for specified database, or the " help = (
"default database if none is provided.") "Runs the command-line client for specified database, or the "
"default database if none is provided."
)
requires_system_checks = False requires_system_checks = False
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('--database', action='store', dest='database', parser.add_argument(
default=DEFAULT_DB_ALIAS, help='Nominates a database onto which to ' '--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
'open a shell. Defaults to the "default" database.') help='Nominates a database onto which to open a shell. Defaults to the "default" database.',
)
def handle(self, **options): def handle(self, **options):
connection = connections[options['database']] connection = connections[options['database']]
@ -22,5 +25,7 @@ class Command(BaseCommand):
# isn't installed. There's a possibility OSError would be raised # isn't installed. There's a possibility OSError would be raised
# for some other reason, in which case this error message would be # for some other reason, in which case this error message would be
# inaccurate. Still, this message catches the common case. # inaccurate. Still, this message catches the common case.
raise CommandError('You appear not to have the %r program installed or on your path.' % raise CommandError(
connection.client.executable_name) 'You appear not to have the %r program installed or on your path.' %
connection.client.executable_name
)

View File

@ -14,9 +14,10 @@ class Command(BaseCommand):
requires_system_checks = False requires_system_checks = False
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('--all', action='store_true', dest='all', default=False, parser.add_argument(
help='Display all settings, regardless of their value. ' '--all', action='store_true', dest='all', default=False,
'Default values are prefixed by "###".') help='Display all settings, regardless of their value. Default values are prefixed by "###".',
)
def handle(self, **options): def handle(self, **options):
# Inspired by Postfix's "postconf -n". # Inspired by Postfix's "postconf -n".

View File

@ -12,37 +12,57 @@ class ProxyModelWarning(Warning):
class Command(BaseCommand): class Command(BaseCommand):
help = ("Output the contents of the database as a fixture of the given " help = (
"format (using each model's default manager unless --all is " "Output the contents of the database as a fixture of the given format "
"specified).") "(using each model's default manager unless --all is specified)."
)
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('args', metavar='app_label[.ModelName]', nargs='*', parser.add_argument(
help='Restricts dumped data to the specified app_label or app_label.ModelName.') 'args', metavar='app_label[.ModelName]', nargs='*',
parser.add_argument('--format', default='json', dest='format', help='Restricts dumped data to the specified app_label or app_label.ModelName.',
help='Specifies the output serialization format for fixtures.') )
parser.add_argument('--indent', default=None, dest='indent', type=int, parser.add_argument(
help='Specifies the indent level to use when pretty-printing output.') '--format', default='json', dest='format',
parser.add_argument('--database', action='store', dest='database', help='Specifies the output serialization format for fixtures.',
)
parser.add_argument(
'--indent', default=None, dest='indent', type=int,
help='Specifies the indent level to use when pretty-printing output.',
)
parser.add_argument(
'--database', action='store', dest='database',
default=DEFAULT_DB_ALIAS, default=DEFAULT_DB_ALIAS,
help='Nominates a specific database to dump fixtures from. ' help='Nominates a specific database to dump fixtures from. '
'Defaults to the "default" database.') 'Defaults to the "default" database.',
parser.add_argument('-e', '--exclude', dest='exclude', action='append', default=[], )
parser.add_argument(
'-e', '--exclude', dest='exclude', action='append', default=[],
help='An app_label or app_label.ModelName to exclude ' help='An app_label or app_label.ModelName to exclude '
'(use multiple --exclude to exclude multiple apps/models).') '(use multiple --exclude to exclude multiple apps/models).',
parser.add_argument('--natural-foreign', action='store_true', dest='use_natural_foreign_keys', default=False, )
help='Use natural foreign keys if they are available.') parser.add_argument(
parser.add_argument('--natural-primary', action='store_true', dest='use_natural_primary_keys', default=False, '--natural-foreign', action='store_true', dest='use_natural_foreign_keys', default=False,
help='Use natural primary keys if they are available.') help='Use natural foreign keys if they are available.',
parser.add_argument('-a', '--all', action='store_true', dest='use_base_manager', default=False, )
parser.add_argument(
'--natural-primary', action='store_true', dest='use_natural_primary_keys', default=False,
help='Use natural primary keys if they are available.',
)
parser.add_argument(
'-a', '--all', action='store_true', dest='use_base_manager', default=False,
help="Use Django's base manager to dump all models stored in the database, " help="Use Django's base manager to dump all models stored in the database, "
"including those that would otherwise be filtered or modified by a custom manager.") "including those that would otherwise be filtered or modified by a custom manager.",
parser.add_argument('--pks', dest='primary_keys', )
help="Only dump objects with given primary keys. " parser.add_argument(
"Accepts a comma separated list of keys. " '--pks', dest='primary_keys',
"This option will only work when you specify one model.") help="Only dump objects with given primary keys. Accepts a comma-separated "
parser.add_argument('-o', '--output', default=None, dest='output', "list of keys. This option only works when you specify one model.",
help='Specifies file to which the output is written.') )
parser.add_argument(
'-o', '--output', default=None, dest='output',
help='Specifies file to which the output is written.'
)
def handle(self, *app_labels, **options): def handle(self, *app_labels, **options):
format = options['format'] format = options['format']
@ -80,9 +100,10 @@ class Command(BaseCommand):
if len(app_labels) == 0: if len(app_labels) == 0:
if primary_keys: if primary_keys:
raise CommandError("You can only use --pks option with one model") raise CommandError("You can only use --pks option with one model")
app_list = OrderedDict((app_config, None) app_list = OrderedDict(
for app_config in apps.get_app_configs() (app_config, None) for app_config in apps.get_app_configs()
if app_config.models_module is not None and app_config not in excluded_apps) if app_config.models_module is not None and app_config not in excluded_apps
)
else: else:
if len(app_labels) > 1 and primary_keys: if len(app_labels) > 1 and primary_keys:
raise CommandError("You can only use --pks option with one model") raise CommandError("You can only use --pks option with one model")
@ -171,11 +192,13 @@ class Command(BaseCommand):
object_count = sum(get_objects(count_only=True)) object_count = sum(get_objects(count_only=True))
stream = open(output, 'w') if output else None stream = open(output, 'w') if output else None
try: try:
serializers.serialize(format, get_objects(), indent=indent, serializers.serialize(
format, get_objects(), indent=indent,
use_natural_foreign_keys=use_natural_foreign_keys, use_natural_foreign_keys=use_natural_foreign_keys,
use_natural_primary_keys=use_natural_primary_keys, use_natural_primary_keys=use_natural_primary_keys,
stream=stream or self.stdout, progress_output=progress_output, stream=stream or self.stdout, progress_output=progress_output,
object_count=object_count) object_count=object_count,
)
finally: finally:
if stream: if stream:
stream.close() stream.close()

View File

@ -13,16 +13,21 @@ from django.utils.six.moves import input
class Command(BaseCommand): class Command(BaseCommand):
help = ('Removes ALL DATA from the database, including data added during ' help = (
'migrations. Does not achieve a "fresh install" state.') 'Removes ALL DATA from the database, including data added during '
'migrations. Does not achieve a "fresh install" state.'
)
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('--noinput', '--no-input', parser.add_argument(
'--noinput', '--no-input',
action='store_false', dest='interactive', default=True, action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.') help='Tells Django to NOT prompt the user for input of any kind.',
parser.add_argument('--database', action='store', dest='database', )
default=DEFAULT_DB_ALIAS, parser.add_argument(
help='Nominates a database to flush. Defaults to the "default" database.') '--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
help='Nominates a database to flush. Defaults to the "default" database.',
)
def handle(self, **options): def handle(self, **options):
database = options['database'] database = options['database']

View File

@ -17,11 +17,14 @@ class Command(BaseCommand):
db_module = 'django.db' db_module = 'django.db'
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('table', action='store', nargs='*', type=str, parser.add_argument(
help='Selects what tables or views should be introspected.') 'table', action='store', nargs='*', type=str,
parser.add_argument('--database', action='store', dest='database', help='Selects what tables or views should be introspected.',
default=DEFAULT_DB_ALIAS, help='Nominates a database to ' )
'introspect. Defaults to using the "default" database.') parser.add_argument(
'--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
help='Nominates a database to introspect. Defaults to using the "default" database.',
)
def handle(self, **options): def handle(self, **options):
try: try:

View File

@ -32,21 +32,26 @@ except ImportError:
class Command(BaseCommand): class Command(BaseCommand):
help = 'Installs the named fixture(s) in the database.' help = 'Installs the named fixture(s) in the database.'
missing_args_message = ("No database fixture specified. Please provide the " missing_args_message = (
"path of at least one fixture in the command line.") "No database fixture specified. Please provide the path of at least "
"one fixture in the command line."
)
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('args', metavar='fixture', nargs='+', parser.add_argument('args', metavar='fixture', nargs='+', help='Fixture labels.')
help='Fixture labels.') parser.add_argument(
parser.add_argument('--database', action='store', dest='database', '--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
default=DEFAULT_DB_ALIAS, help='Nominates a specific database to load ' help='Nominates a specific database to load fixtures into. Defaults to the "default" database.',
'fixtures into. Defaults to the "default" database.') )
parser.add_argument('--app', action='store', dest='app_label', parser.add_argument(
default=None, help='Only look for fixtures in the specified app.') '--app', action='store', dest='app_label', default=None,
parser.add_argument('--ignorenonexistent', '-i', action='store_true', help='Only look for fixtures in the specified app.',
dest='ignore', default=False, )
parser.add_argument(
'--ignorenonexistent', '-i', action='store_true', dest='ignore', default=False,
help='Ignores entries in the serialized data for fields that do not ' help='Ignores entries in the serialized data for fields that do not '
'currently exist on the model.') 'currently exist on the model.',
)
def handle(self, *fixture_labels, **options): def handle(self, *fixture_labels, **options):
@ -120,11 +125,15 @@ class Command(BaseCommand):
if self.verbosity >= 1: if self.verbosity >= 1:
if self.fixture_object_count == self.loaded_object_count: if self.fixture_object_count == self.loaded_object_count:
self.stdout.write("Installed %d object(s) from %d fixture(s)" % self.stdout.write(
(self.loaded_object_count, self.fixture_count)) "Installed %d object(s) from %d fixture(s)"
% (self.loaded_object_count, self.fixture_count)
)
else: else:
self.stdout.write("Installed %d object(s) (of %d) from %d fixture(s)" % self.stdout.write(
(self.loaded_object_count, self.fixture_object_count, self.fixture_count)) "Installed %d object(s) (of %d) from %d fixture(s)"
% (self.loaded_object_count, self.fixture_object_count, self.fixture_count)
)
def load_label(self, fixture_label): def load_label(self, fixture_label):
""" """
@ -140,11 +149,14 @@ class Command(BaseCommand):
objects_in_fixture = 0 objects_in_fixture = 0
loaded_objects_in_fixture = 0 loaded_objects_in_fixture = 0
if self.verbosity >= 2: if self.verbosity >= 2:
self.stdout.write("Installing %s fixture '%s' from %s." % self.stdout.write(
(ser_fmt, fixture_name, humanize(fixture_dir))) "Installing %s fixture '%s' from %s."
% (ser_fmt, fixture_name, humanize(fixture_dir))
)
objects = serializers.deserialize(ser_fmt, fixture, objects = serializers.deserialize(
using=self.using, ignorenonexistent=self.ignore) ser_fmt, fixture, using=self.using, ignorenonexistent=self.ignore,
)
for obj in objects: for obj in objects:
objects_in_fixture += 1 objects_in_fixture += 1
@ -208,8 +220,10 @@ class Command(BaseCommand):
for dir_ in fixture_dirs] for dir_ in fixture_dirs]
fixture_name = os.path.basename(fixture_name) fixture_name = os.path.basename(fixture_name)
suffixes = ('.'.join(ext for ext in combo if ext) suffixes = (
for combo in product(databases, ser_fmts, cmp_fmts)) '.'.join(ext for ext in combo if ext)
for combo in product(databases, ser_fmts, cmp_fmts)
)
targets = set('.'.join((fixture_name, suffix)) for suffix in suffixes) targets = set('.'.join((fixture_name, suffix)) for suffix in suffixes)
fixture_files = [] fixture_files = []

View File

@ -30,8 +30,10 @@ NO_LOCALE_DIR = object()
def check_programs(*programs): def check_programs(*programs):
for program in programs: for program in programs:
if find_command(program) is None: if find_command(program) is None:
raise CommandError("Can't find %s. Make sure you have GNU " raise CommandError(
"gettext tools 0.15 or newer installed." % program) "Can't find %s. Make sure you have GNU gettext tools 0.15 or "
"newer installed." % program
)
@total_ordering @total_ordering
@ -161,11 +163,13 @@ def write_pot_file(potfile, msgs):
class Command(BaseCommand): class Command(BaseCommand):
help = ("Runs over the entire source tree of the current directory and " help = (
"pulls out all strings marked for translation. It creates (or updates) a message " "Runs over the entire source tree of the current directory and "
"file in the conf/locale (in the django tree) or locale (for projects and " "pulls out all strings marked for translation. It creates (or updates) a message "
"applications) directory.\n\nYou must run this command with one of either the " "file in the conf/locale (in the django tree) or locale (for projects and "
"--locale, --exclude or --all options.") "applications) directory.\n\nYou must run this command with one of either the "
"--locale, --exclude, or --all options."
)
translatable_file_class = TranslatableFile translatable_file_class = TranslatableFile
build_file_class = BuildFile build_file_class = BuildFile
@ -179,37 +183,60 @@ class Command(BaseCommand):
xgettext_options = ['--from-code=UTF-8', '--add-comments=Translators'] xgettext_options = ['--from-code=UTF-8', '--add-comments=Translators']
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('--locale', '-l', default=[], dest='locale', action='append', parser.add_argument(
'--locale', '-l', default=[], dest='locale', action='append',
help='Creates or updates the message files for the given locale(s) (e.g. pt_BR). ' help='Creates or updates the message files for the given locale(s) (e.g. pt_BR). '
'Can be used multiple times.') 'Can be used multiple times.',
parser.add_argument('--exclude', '-x', default=[], dest='exclude', action='append', )
help='Locales to exclude. Default is none. Can be used multiple times.') parser.add_argument(
parser.add_argument('--domain', '-d', default='django', dest='domain', '--exclude', '-x', default=[], dest='exclude', action='append',
help='The domain of the message files (default: "django").') help='Locales to exclude. Default is none. Can be used multiple times.',
parser.add_argument('--all', '-a', action='store_true', dest='all', )
default=False, help='Updates the message files for all existing locales.') parser.add_argument(
parser.add_argument('--extension', '-e', dest='extensions', '--domain', '-d', default='django', dest='domain',
help='The domain of the message files (default: "django").',
)
parser.add_argument(
'--all', '-a', action='store_true', dest='all', default=False,
help='Updates the message files for all existing locales.',
)
parser.add_argument(
'--extension', '-e', dest='extensions', action='append',
help='The file extension(s) to examine (default: "html,txt,py", or "js" ' help='The file extension(s) to examine (default: "html,txt,py", or "js" '
'if the domain is "djangojs"). Separate multiple extensions with ' 'if the domain is "djangojs"). Separate multiple extensions with '
'commas, or use -e multiple times.', 'commas, or use -e multiple times.',
action='append') )
parser.add_argument('--symlinks', '-s', action='store_true', dest='symlinks', parser.add_argument(
default=False, help='Follows symlinks to directories when examining ' '--symlinks', '-s', action='store_true', dest='symlinks', default=False,
'source code and templates for translation strings.') help='Follows symlinks to directories when examining source code '
parser.add_argument('--ignore', '-i', action='append', dest='ignore_patterns', 'and templates for translation strings.',
)
parser.add_argument(
'--ignore', '-i', action='append', dest='ignore_patterns',
default=[], metavar='PATTERN', default=[], metavar='PATTERN',
help='Ignore files or directories matching this glob-style pattern. ' help='Ignore files or directories matching this glob-style pattern. '
'Use multiple times to ignore more.') 'Use multiple times to ignore more.',
parser.add_argument('--no-default-ignore', action='store_false', dest='use_default_ignore_patterns', )
default=True, help="Don't ignore the common glob-style patterns 'CVS', '.*', '*~' and '*.pyc'.") parser.add_argument(
parser.add_argument('--no-wrap', action='store_true', dest='no_wrap', '--no-default-ignore', action='store_false', dest='use_default_ignore_patterns',
default=False, help="Don't break long message lines into several lines.") default=True, help="Don't ignore the common glob-style patterns 'CVS', '.*', '*~' and '*.pyc'.",
parser.add_argument('--no-location', action='store_true', dest='no_location', )
default=False, help="Don't write '#: filename:line' lines.") parser.add_argument(
parser.add_argument('--no-obsolete', action='store_true', dest='no_obsolete', '--no-wrap', action='store_true', dest='no_wrap',
default=False, help="Remove obsolete message strings.") default=False, help="Don't break long message lines into several lines.",
parser.add_argument('--keep-pot', action='store_true', dest='keep_pot', )
default=False, help="Keep .pot file after making messages. Useful when debugging.") parser.add_argument(
'--no-location', action='store_true', dest='no_location',
default=False, help="Don't write '#: filename:line' lines.",
)
parser.add_argument(
'--no-obsolete', action='store_true', dest='no_obsolete',
default=False, help="Remove obsolete message strings.",
)
parser.add_argument(
'--keep-pot', action='store_true', dest='keep_pot',
default=False, help="Keep .pot file after making messages. Useful when debugging.",
)
def handle(self, *args, **options): def handle(self, *args, **options):
locale = options['locale'] locale = options['locale']
@ -256,12 +283,16 @@ class Command(BaseCommand):
self.extensions = handle_extensions(exts) self.extensions = handle_extensions(exts)
if (locale is None and not exclude and not process_all) or self.domain is None: if (locale is None and not exclude and not process_all) or self.domain is None:
raise CommandError("Type '%s help %s' for usage information." % ( raise CommandError(
os.path.basename(sys.argv[0]), sys.argv[1])) "Type '%s help %s' for usage information."
% (os.path.basename(sys.argv[0]), sys.argv[1])
)
if self.verbosity > 1: if self.verbosity > 1:
self.stdout.write('examining files with the extensions: %s\n' self.stdout.write(
% get_text_list(list(self.extensions), 'and')) 'examining files with the extensions: %s\n'
% get_text_list(list(self.extensions), 'and')
)
self.invoked_for_django = False self.invoked_for_django = False
self.locale_paths = [] self.locale_paths = []

View File

@ -24,24 +24,40 @@ class Command(BaseCommand):
help = "Creates new migration(s) for apps." help = "Creates new migration(s) for apps."
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('args', metavar='app_label', nargs='*', parser.add_argument(
help='Specify the app label(s) to create migrations for.') 'args', metavar='app_label', nargs='*',
parser.add_argument('--dry-run', action='store_true', dest='dry_run', default=False, help='Specify the app label(s) to create migrations for.',
help="Just show what migrations would be made; don't actually write them.") )
parser.add_argument('--merge', action='store_true', dest='merge', default=False, parser.add_argument(
help="Enable fixing of migration conflicts.") '--dry-run', action='store_true', dest='dry_run', default=False,
parser.add_argument('--empty', action='store_true', dest='empty', default=False, help="Just show what migrations would be made; don't actually write them.",
help="Create an empty migration.") )
parser.add_argument('--noinput', '--no-input', parser.add_argument(
'--merge', action='store_true', dest='merge', default=False,
help="Enable fixing of migration conflicts.",
)
parser.add_argument(
'--empty', action='store_true', dest='empty', default=False,
help="Create an empty migration.",
)
parser.add_argument(
'--noinput', '--no-input',
action='store_false', dest='interactive', default=True, action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.') help='Tells Django to NOT prompt the user for input of any kind.',
parser.add_argument('-n', '--name', action='store', dest='name', default=None, )
help="Use this name for migration file(s).") parser.add_argument(
parser.add_argument('-e', '--exit', action='store_true', dest='exit_code', default=False, '-n', '--name', action='store', dest='name', default=None,
help="Use this name for migration file(s).",
)
parser.add_argument(
'-e', '--exit', action='store_true', dest='exit_code', default=False,
help='Exit with error code 1 if no changes needing migrations are found. ' help='Exit with error code 1 if no changes needing migrations are found. '
'Deprecated, use the --check option instead.') 'Deprecated, use the --check option instead.',
parser.add_argument('--check', action='store_true', dest='check_changes', )
help='Exit with a non-zero status if model changes are missing migrations.') parser.add_argument(
'--check', action='store_true', dest='check_changes',
help='Exit with a non-zero status if model changes are missing migrations.',
)
def handle(self, *app_labels, **options): def handle(self, *app_labels, **options):
self.verbosity = options['verbosity'] self.verbosity = options['verbosity']

View File

@ -22,28 +22,39 @@ class Command(BaseCommand):
help = "Updates database schema. Manages both apps with migrations and those without." help = "Updates database schema. Manages both apps with migrations and those without."
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('app_label', nargs='?', parser.add_argument(
help='App label of an application to synchronize the state.') 'app_label', nargs='?',
parser.add_argument('migration_name', nargs='?', help='App label of an application to synchronize the state.',
help=(
'Database state will be brought to the state after that '
'migration. Use the name "zero" to unapply all migrations.'
),
) )
parser.add_argument('--noinput', '--no-input', parser.add_argument(
'migration_name', nargs='?',
help='Database state will be brought to the state after that '
'migration. Use the name "zero" to unapply all migrations.',
)
parser.add_argument(
'--noinput', '--no-input',
action='store_false', dest='interactive', default=True, action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.') help='Tells Django to NOT prompt the user for input of any kind.',
parser.add_argument('--database', action='store', dest='database', )
default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. ' parser.add_argument(
'Defaults to the "default" database.') '--database', action='store', dest='database',
parser.add_argument('--fake', action='store_true', dest='fake', default=False, default=DEFAULT_DB_ALIAS,
help='Mark migrations as run without actually running them.') help='Nominates a database to synchronize. Defaults to the "default" database.',
parser.add_argument('--fake-initial', action='store_true', dest='fake_initial', default=False, )
parser.add_argument(
'--fake', action='store_true', dest='fake', default=False,
help='Mark migrations as run without actually running them.',
)
parser.add_argument(
'--fake-initial', action='store_true', dest='fake_initial', default=False,
help='Detect if tables already exist and fake-apply initial migrations if so. Make sure ' help='Detect if tables already exist and fake-apply initial migrations if so. Make sure '
'that the current database schema matches your initial migration before using this ' 'that the current database schema matches your initial migration before using this '
'flag. Django will only check for an existing table name.') 'flag. Django will only check for an existing table name.',
parser.add_argument('--run-syncdb', action='store_true', dest='run_syncdb', )
help='Creates tables for apps without migrations.') parser.add_argument(
'--run-syncdb', action='store_true', dest='run_syncdb',
help='Creates tables for apps without migrations.',
)
def handle(self, *args, **options): def handle(self, *args, **options):
@ -238,8 +249,10 @@ class Command(BaseCommand):
opts = model._meta opts = model._meta
converter = connection.introspection.table_name_converter converter = connection.introspection.table_name_converter
# Note that if a model is unmanaged we short-circuit and never try to install it # Note that if a model is unmanaged we short-circuit and never try to install it
return not ((converter(opts.db_table) in tables) or return not (
(opts.auto_created and converter(opts.auto_created._meta.db_table) in tables)) (converter(opts.db_table) in tables) or
(opts.auto_created and converter(opts.auto_created._meta.db_table) in tables)
)
manifest = OrderedDict( manifest = OrderedDict(
(app_name, list(filter(model_installed, model_list))) (app_name, list(filter(model_installed, model_list)))

View File

@ -32,14 +32,22 @@ class Command(BaseCommand):
default_port = '8000' default_port = '8000'
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('addrport', nargs='?', parser.add_argument(
help='Optional port number, or ipaddr:port') 'addrport', nargs='?',
parser.add_argument('--ipv6', '-6', action='store_true', dest='use_ipv6', default=False, help='Optional port number, or ipaddr:port'
help='Tells Django to use an IPv6 address.') )
parser.add_argument('--nothreading', action='store_false', dest='use_threading', default=True, parser.add_argument(
help='Tells Django to NOT use threading.') '--ipv6', '-6', action='store_true', dest='use_ipv6', default=False,
parser.add_argument('--noreload', action='store_false', dest='use_reloader', default=True, help='Tells Django to use an IPv6 address.',
help='Tells Django to NOT use the auto-reloader.') )
parser.add_argument(
'--nothreading', action='store_false', dest='use_threading', default=True,
help='Tells Django to NOT use threading.',
)
parser.add_argument(
'--noreload', action='store_false', dest='use_reloader', default=True,
help='Tells Django to NOT use the auto-reloader.',
)
def execute(self, *args, **options): def execute(self, *args, **options):
if options['no_color']: if options['no_color']:

View File

@ -10,12 +10,18 @@ class Command(BaseCommand):
missing_args_message = "You must specify some email recipients, or pass the --managers or --admin options." missing_args_message = "You must specify some email recipients, or pass the --managers or --admin options."
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('email', nargs='*', parser.add_argument(
help='One or more email addresses to send a test email to.') 'email', nargs='*',
parser.add_argument('--managers', action='store_true', dest='managers', default=False, help='One or more email addresses to send a test email to.',
help='Send a test email to the addresses specified in settings.MANAGERS.') )
parser.add_argument('--admins', action='store_true', dest='admins', default=False, parser.add_argument(
help='Send a test email to the addresses specified in settings.ADMINS.') '--managers', action='store_true', dest='managers', default=False,
help='Send a test email to the addresses specified in settings.MANAGERS.',
)
parser.add_argument(
'--admins', action='store_true', dest='admins', default=False,
help='Send a test email to the addresses specified in settings.ADMINS.',
)
def handle(self, *args, **kwargs): def handle(self, *args, **kwargs):
subject = 'Test email from %s on %s' % (socket.gethostname(), timezone.now()) subject = 'Test email from %s on %s' % (socket.gethostname(), timezone.now())

View File

@ -11,15 +11,23 @@ class Command(BaseCommand):
shells = ['ipython', 'bpython', 'python'] shells = ['ipython', 'bpython', 'python']
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('--plain', action='store_true', dest='plain', parser.add_argument(
'--plain', action='store_true', dest='plain',
help='Tells Django to use plain Python, not IPython or bpython. ' help='Tells Django to use plain Python, not IPython or bpython. '
'Deprecated, use the `-i python` or `--interface python` option instead.') 'Deprecated, use the `-i python` or `--interface python` option instead.',
parser.add_argument('--no-startup', action='store_true', dest='no_startup', )
help='When using plain Python, ignore the PYTHONSTARTUP environment variable and ~/.pythonrc.py script.') parser.add_argument(
parser.add_argument('-i', '--interface', choices=self.shells, dest='interface', '--no-startup', action='store_true', dest='no_startup',
help='Specify an interactive interpreter interface. Available options: "ipython", "bpython", and "python"') help='When using plain Python, ignore the PYTHONSTARTUP environment variable and ~/.pythonrc.py script.',
parser.add_argument('-c', '--command', dest='command', )
help='Instead of opening an interactive shell, run a command as Django and exit.') parser.add_argument(
'-i', '--interface', choices=self.shells, dest='interface',
help='Specify an interactive interpreter interface. Available options: "ipython", "bpython", and "python"',
)
parser.add_argument(
'-c', '--command', dest='command',
help='Instead of opening an interactive shell, run a command as Django and exit.',
)
def _ipython_pre_011(self): def _ipython_pre_011(self):
"""Start IPython pre-0.11""" """Start IPython pre-0.11"""

View File

@ -10,16 +10,24 @@ class Command(BaseCommand):
help = "Shows all available migrations for the current project" help = "Shows all available migrations for the current project"
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('app_label', nargs='*', parser.add_argument(
help='App labels of applications to limit the output to.') 'app_label', nargs='*',
parser.add_argument('--database', action='store', dest='database', default=DEFAULT_DB_ALIAS, help='App labels of applications to limit the output to.',
help='Nominates a database to synchronize. Defaults to the "default" database.') )
parser.add_argument(
'--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
help='Nominates a database to synchronize. Defaults to the "default" database.',
)
formats = parser.add_mutually_exclusive_group() formats = parser.add_mutually_exclusive_group()
formats.add_argument('--list', '-l', action='store_const', dest='format', const='list', formats.add_argument(
help='Shows a list of all migrations and which are applied.') '--list', '-l', action='store_const', dest='format', const='list',
formats.add_argument('--plan', '-p', action='store_const', dest='format', const='plan', help='Shows a list of all migrations and which are applied.',
help='Shows all migrations in the order they will be applied.') )
formats.add_argument(
'--plan', '-p', action='store_const', dest='format', const='plan',
help='Shows all migrations in the order they will be applied.',
)
parser.set_defaults(format='list') parser.set_defaults(format='list')

View File

@ -15,9 +15,10 @@ class Command(BaseCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
super(Command, self).add_arguments(parser) super(Command, self).add_arguments(parser)
parser.add_argument('--database', default=DEFAULT_DB_ALIAS, parser.add_argument(
help='Nominates a database to print the SQL for. Defaults to the ' '--database', default=DEFAULT_DB_ALIAS,
'"default" database.') help='Nominates a database to print the SQL for. Defaults to the "default" database.',
)
def handle(self, **options): def handle(self, **options):
return '\n'.join(sql_flush(self.style, connections[options['database']], only_django=True)) return '\n'.join(sql_flush(self.style, connections[options['database']], only_django=True))

View File

@ -13,15 +13,17 @@ class Command(BaseCommand):
output_transaction = True output_transaction = True
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('app_label', parser.add_argument('app_label', help='App label of the application containing the migration.')
help='App label of the application containing the migration.') parser.add_argument('migration_name', help='Migration name to print the SQL for.')
parser.add_argument('migration_name', parser.add_argument(
help='Migration name to print the SQL for.') '--database', default=DEFAULT_DB_ALIAS,
parser.add_argument('--database', default=DEFAULT_DB_ALIAS, help='Nominates a database to create SQL for. Defaults to the "default" database.',
help='Nominates a database to create SQL for. Defaults to the ' )
'"default" database.') parser.add_argument(
parser.add_argument('--backwards', action='store_true', dest='backwards', '--backwards', action='store_true', dest='backwards',
default=False, help='Creates SQL to unapply the migration, rather than to apply it') default=False,
help='Creates SQL to unapply the migration, rather than to apply it',
)
def execute(self, *args, **options): def execute(self, *args, **options):
# sqlmigrate doesn't support coloring its output but we need to force # sqlmigrate doesn't support coloring its output but we need to force

View File

@ -11,9 +11,10 @@ class Command(AppCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
super(Command, self).add_arguments(parser) super(Command, self).add_arguments(parser)
parser.add_argument('--database', default=DEFAULT_DB_ALIAS, parser.add_argument(
help='Nominates a database to print the SQL for. Defaults to the ' '--database', default=DEFAULT_DB_ALIAS,
'"default" database.') help='Nominates a database to print the SQL for. Defaults to the "default" database.',
)
def handle_app_config(self, app_config, **options): def handle_app_config(self, app_config, **options):
if app_config.models_module is None: if app_config.models_module is None:

View File

@ -13,17 +13,26 @@ class Command(BaseCommand):
help = "Squashes an existing set of migrations (from first until specified) into a single new one." help = "Squashes an existing set of migrations (from first until specified) into a single new one."
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('app_label', parser.add_argument(
help='App label of the application to squash migrations for.') 'app_label',
parser.add_argument('start_migration_name', default=None, nargs='?', help='App label of the application to squash migrations for.',
help='Migrations will be squashed starting from and including this migration.') )
parser.add_argument('migration_name', parser.add_argument(
help='Migrations will be squashed until and including this migration.') 'start_migration_name', default=None, nargs='?',
parser.add_argument('--no-optimize', action='store_true', dest='no_optimize', default=False, help='Migrations will be squashed starting from and including this migration.',
help='Do not try to optimize the squashed operations.') )
parser.add_argument('--noinput', '--no-input', parser.add_argument(
action='store_false', dest='interactive', default=True, 'migration_name',
help='Tells Django to NOT prompt the user for input of any kind.') help='Migrations will be squashed until and including this migration.',
)
parser.add_argument(
'--no-optimize', action='store_true', dest='no_optimize', default=False,
help='Do not try to optimize the squashed operations.',
)
parser.add_argument(
'--noinput', '--no-input', action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.',
)
def handle(self, **options): def handle(self, **options):

View File

@ -5,9 +5,10 @@ from django.core.management.templates import TemplateCommand
class Command(TemplateCommand): class Command(TemplateCommand):
help = ("Creates a Django app directory structure for the given app " help = (
"name in the current directory or optionally in the given " "Creates a Django app directory structure for the given app name in "
"directory.") "the current directory or optionally in the given directory."
)
missing_args_message = "You must provide an application name." missing_args_message = "You must provide an application name."
def handle(self, **options): def handle(self, **options):
@ -20,8 +21,9 @@ class Command(TemplateCommand):
except ImportError: except ImportError:
pass pass
else: else:
raise CommandError("%r conflicts with the name of an existing " raise CommandError(
"Python module and cannot be used as an app " "%r conflicts with the name of an existing Python module and "
"name. Please try another name." % app_name) "cannot be used as an app name. Please try another name." % app_name
)
super(Command, self).handle('app', app_name, target, **options) super(Command, self).handle('app', app_name, target, **options)

View File

@ -7,9 +7,10 @@ from ..utils import get_random_secret_key
class Command(TemplateCommand): class Command(TemplateCommand):
help = ("Creates a Django project directory structure for the given " help = (
"project name in the current directory or optionally in the " "Creates a Django project directory structure for the given project "
"given directory.") "name in the current directory or optionally in the given directory."
)
missing_args_message = "You must provide a project name." missing_args_message = "You must provide a project name."
def handle(self, **options): def handle(self, **options):
@ -22,10 +23,10 @@ class Command(TemplateCommand):
except ImportError: except ImportError:
pass pass
else: else:
raise CommandError("%r conflicts with the name of an existing " raise CommandError(
"Python module and cannot be used as a " "%r conflicts with the name of an existing Python module and "
"project name. Please try another name." % "cannot be used as a project name. Please try another name." % project_name
project_name) )
# Create a random SECRET_KEY to put it in the main settings. # Create a random SECRET_KEY to put it in the main settings.
options['secret_key'] = get_random_secret_key() options['secret_key'] = get_random_secret_key()

View File

@ -29,24 +29,29 @@ class Command(BaseCommand):
super(Command, self).run_from_argv(argv) super(Command, self).run_from_argv(argv)
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('args', metavar='test_label', nargs='*', parser.add_argument(
help='Module paths to test; can be modulename, modulename.TestCase or modulename.TestCase.test_method') 'args', metavar='test_label', nargs='*',
parser.add_argument('--noinput', '--no-input', help='Module paths to test; can be modulename, modulename.TestCase or modulename.TestCase.test_method'
action='store_false', dest='interactive', default=True, )
help='Tells Django to NOT prompt the user for input of any kind.') parser.add_argument(
parser.add_argument('--failfast', '--noinput', '--no-input', action='store_false', dest='interactive', default=True,
action='store_true', dest='failfast', default=False, help='Tells Django to NOT prompt the user for input of any kind.',
help='Tells Django to stop running the test suite after first ' )
'failed test.') parser.add_argument(
parser.add_argument('--testrunner', '--failfast', action='store_true', dest='failfast', default=False,
action='store', dest='testrunner', help='Tells Django to stop running the test suite after first failed test.',
)
parser.add_argument(
'--testrunner', action='store', dest='testrunner',
help='Tells Django to use specified test runner class instead of ' help='Tells Django to use specified test runner class instead of '
'the one specified by the TEST_RUNNER setting.') 'the one specified by the TEST_RUNNER setting.',
parser.add_argument('--liveserver', )
action='store', dest='liveserver', default=None, parser.add_argument(
'--liveserver', action='store', dest='liveserver', default=None,
help='Overrides the default address where the live server (used ' help='Overrides the default address where the live server (used '
'with LiveServerTestCase) is expected to run from. The ' 'with LiveServerTestCase) is expected to run from. The '
'default value is localhost:8081-8179.') 'default value is localhost:8081-8179.',
)
test_runner_class = get_runner(settings, self.test_runner) test_runner_class = get_runner(settings, self.test_runner)

View File

@ -9,15 +9,22 @@ class Command(BaseCommand):
requires_system_checks = False requires_system_checks = False
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('args', metavar='fixture', nargs='*', parser.add_argument(
help='Path(s) to fixtures to load before running the server.') 'args', metavar='fixture', nargs='*',
parser.add_argument('--noinput', '--no-input', help='Path(s) to fixtures to load before running the server.',
action='store_false', dest='interactive', default=True, )
help='Tells Django to NOT prompt the user for input of any kind.') parser.add_argument(
parser.add_argument('--addrport', default='', '--noinput', '--no-input', action='store_false', dest='interactive', default=True,
help='Port number or ipaddr:port to run the server on.') help='Tells Django to NOT prompt the user for input of any kind.',
parser.add_argument('--ipv6', '-6', action='store_true', dest='use_ipv6', default=False, )
help='Tells Django to use an IPv6 address.') parser.add_argument(
'--addrport', default='',
help='Port number or ipaddr:port to run the server on.',
)
parser.add_argument(
'--ipv6', '-6', action='store_true', dest='use_ipv6', default=False,
help='Tells Django to use an IPv6 address.',
)
def handle(self, *fixture_labels, **options): def handle(self, *fixture_labels, **options):
verbosity = options['verbosity'] verbosity = options['verbosity']

View File

@ -51,18 +51,20 @@ class TemplateCommand(BaseCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('name', help='Name of the application or project.') parser.add_argument('name', help='Name of the application or project.')
parser.add_argument('directory', nargs='?', help='Optional destination directory') parser.add_argument('directory', nargs='?', help='Optional destination directory')
parser.add_argument('--template', parser.add_argument('--template', help='The path or URL to load the template from.')
help='The path or URL to load the template from.') parser.add_argument(
parser.add_argument('--extension', '-e', dest='extensions', '--extension', '-e', dest='extensions',
action='append', default=['py'], action='append', default=['py'],
help='The file extension(s) to render (default: "py"). ' help='The file extension(s) to render (default: "py"). '
'Separate multiple extensions with commas, or use ' 'Separate multiple extensions with commas, or use '
'-e multiple times.') '-e multiple times.'
parser.add_argument('--name', '-n', dest='files', )
parser.add_argument(
'--name', '-n', dest='files',
action='append', default=[], action='append', default=[],
help='The file name(s) to render. ' help='The file name(s) to render. Separate multiple extensions '
'Separate multiple extensions with commas, or use ' 'with commas, or use -n multiple times.'
'-n multiple times.') )
def handle(self, app_or_project, name, target=None, **options): def handle(self, app_or_project, name, target=None, **options):
self.app_or_project = app_or_project self.app_or_project = app_or_project

View File

@ -227,9 +227,12 @@ def sort_dependencies(app_list):
else: else:
skipped.append((model, deps)) skipped.append((model, deps))
if not changed: if not changed:
raise RuntimeError("Can't resolve dependencies for %s in serialized app list." % raise RuntimeError(
', '.join('%s.%s' % (model._meta.app_label, model._meta.object_name) "Can't resolve dependencies for %s in serialized app list." %
for model, deps in sorted(skipped, key=lambda obj: obj[0].__name__)) ', '.join(
'%s.%s' % (model._meta.app_label, model._meta.object_name)
for model, deps in sorted(skipped, key=lambda obj: obj[0].__name__)
)
) )
model_dependencies = skipped model_dependencies = skipped

View File

@ -75,8 +75,9 @@ class Serializer(base.Serializer):
else: else:
def m2m_value(value): def m2m_value(value):
return force_text(value._get_pk_val(), strings_only=True) return force_text(value._get_pk_val(), strings_only=True)
self._current[field.name] = [m2m_value(related) self._current[field.name] = [
for related in getattr(obj, field.name).iterator()] m2m_value(related) for related in getattr(obj, field.name).iterator()
]
def getvalue(self): def getvalue(self):
return self.objects return self.objects

View File

@ -160,8 +160,7 @@ class Signer(object):
'Unsafe Signer separator: %r (cannot be empty or consist of ' 'Unsafe Signer separator: %r (cannot be empty or consist of '
'only A-z0-9-_=)' % sep, 'only A-z0-9-_=)' % sep,
) )
self.salt = force_str(salt or self.salt = force_str(salt or '%s.%s' % (self.__class__.__module__, self.__class__.__name__))
'%s.%s' % (self.__class__.__module__, self.__class__.__name__))
def signature(self, value): def signature(self, value):
signature = base64_hmac(self.salt + 'signer', value, self.key) signature = base64_hmac(self.salt + 'signer', value, self.key)

View File

@ -6,8 +6,7 @@ from django.utils import six
TableInfo = namedtuple('TableInfo', ['name', 'type']) TableInfo = namedtuple('TableInfo', ['name', 'type'])
# Structure returned by the DB-API cursor.description interface (PEP 249) # Structure returned by the DB-API cursor.description interface (PEP 249)
FieldInfo = namedtuple('FieldInfo', FieldInfo = namedtuple('FieldInfo', 'name type_code display_size internal_size precision scale null_ok')
'name type_code display_size internal_size precision scale null_ok')
class BaseDatabaseIntrospection(object): class BaseDatabaseIntrospection(object):

View File

@ -43,8 +43,8 @@ from .validation import DatabaseValidation # isort:skip
# lexicographic ordering in this check because then (1, 2, 1, 'gamma') # lexicographic ordering in this check because then (1, 2, 1, 'gamma')
# inadvertently passes the version test. # inadvertently passes the version test.
version = Database.version_info version = Database.version_info
if (version < (1, 2, 1) or (version[:3] == (1, 2, 1) and if (version < (1, 2, 1) or (
(len(version) < 5 or version[3] != 'final' or version[4] < 2))): version[:3] == (1, 2, 1) and (len(version) < 5 or version[3] != 'final' or version[4] < 2))):
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured("MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__) raise ImproperlyConfigured("MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__)
@ -334,19 +334,27 @@ class DatabaseWrapper(BaseDatabaseWrapper):
continue continue
key_columns = self.introspection.get_key_columns(cursor, table_name) key_columns = self.introspection.get_key_columns(cursor, table_name)
for column_name, referenced_table_name, referenced_column_name in key_columns: for column_name, referenced_table_name, referenced_column_name in key_columns:
cursor.execute(""" cursor.execute(
"""
SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING
LEFT JOIN `%s` as REFERRED LEFT JOIN `%s` as REFERRED
ON (REFERRING.`%s` = REFERRED.`%s`) ON (REFERRING.`%s` = REFERRED.`%s`)
WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL""" WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL
% (primary_key_column_name, column_name, table_name, referenced_table_name, """ % (
column_name, referenced_column_name, column_name, referenced_column_name)) primary_key_column_name, column_name, table_name,
referenced_table_name, column_name, referenced_column_name,
column_name, referenced_column_name,
)
)
for bad_row in cursor.fetchall(): for bad_row in cursor.fetchall():
raise utils.IntegrityError("The row in table '%s' with primary key '%s' has an invalid " raise utils.IntegrityError(
"The row in table '%s' with primary key '%s' has an invalid "
"foreign key: %s.%s contains a value '%s' that does not have a corresponding value in %s.%s." "foreign key: %s.%s contains a value '%s' that does not have a corresponding value in %s.%s."
% (table_name, bad_row[0], % (
table_name, column_name, bad_row[1], table_name, bad_row[0], table_name, column_name,
referenced_table_name, referenced_column_name)) bad_row[1], referenced_table_name, referenced_column_name,
)
)
def is_usable(self): def is_usable(self):
try: try:

View File

@ -12,7 +12,8 @@ class DatabaseOperations(BaseDatabaseOperations):
compiler_module = "django.db.backends.mysql.compiler" compiler_module = "django.db.backends.mysql.compiler"
# MySQL stores positive fields as UNSIGNED ints. # MySQL stores positive fields as UNSIGNED ints.
integer_field_ranges = dict(BaseDatabaseOperations.integer_field_ranges, integer_field_ranges = dict(
BaseDatabaseOperations.integer_field_ranges,
PositiveSmallIntegerField=(0, 65535), PositiveSmallIntegerField=(0, 65535),
PositiveIntegerField=(0, 4294967295), PositiveIntegerField=(0, 4294967295),
) )

View File

@ -367,8 +367,7 @@ class OracleParam(object):
else: else:
# To transmit to the database, we need Unicode if supported # To transmit to the database, we need Unicode if supported
# To get size right, we must consider bytes. # To get size right, we must consider bytes.
self.force_bytes = convert_unicode(param, cursor.charset, self.force_bytes = convert_unicode(param, cursor.charset, strings_only)
strings_only)
if isinstance(self.force_bytes, six.string_types): if isinstance(self.force_bytes, six.string_types):
# We could optimize by only converting up to 4000 bytes here # We could optimize by only converting up to 4000 bytes here
string_size = len(force_bytes(param, cursor.charset, strings_only)) string_size = len(force_bytes(param, cursor.charset, strings_only))
@ -498,8 +497,7 @@ class FormatStylePlaceholderCursor(object):
formatted = [firstparams] + [self._format_params(p) for p in params_iter] formatted = [firstparams] + [self._format_params(p) for p in params_iter]
self._guess_input_sizes(formatted) self._guess_input_sizes(formatted)
try: try:
return self.cursor.executemany(query, return self.cursor.executemany(query, [self._param_generator(p) for p in formatted])
[self._param_generator(p) for p in formatted])
except Database.DatabaseError as e: except Database.DatabaseError as e:
# cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400. # cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400.
if hasattr(e.args[0], 'code') and e.args[0].code == 1400 and not isinstance(e, IntegrityError): if hasattr(e.args[0], 'code') and e.args[0].code == 1400 and not isinstance(e, IntegrityError):

View File

@ -99,8 +99,7 @@ WHEN (new.%(col_name)s IS NULL)
days = str(timedelta.days) days = str(timedelta.days)
day_precision = len(days) day_precision = len(days)
fmt = "INTERVAL '%s %02d:%02d:%02d.%06d' DAY(%d) TO SECOND(6)" fmt = "INTERVAL '%s %02d:%02d:%02d.%06d' DAY(%d) TO SECOND(6)"
return fmt % (days, hours, minutes, seconds, timedelta.microseconds, return fmt % (days, hours, minutes, seconds, timedelta.microseconds, day_precision), []
day_precision), []
def date_trunc_sql(self, lookup_type, field_name): def date_trunc_sql(self, lookup_type, field_name):
# http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions230.htm#i1002084 # http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions230.htm#i1002084

View File

@ -139,11 +139,11 @@ class DatabaseOperations(BaseDatabaseOperations):
# This will be the case if it's an m2m using an autogenerated # This will be the case if it's an m2m using an autogenerated
# intermediate table (see BaseDatabaseIntrospection.sequence_list) # intermediate table (see BaseDatabaseIntrospection.sequence_list)
column_name = 'id' column_name = 'id'
sql.append("%s setval(pg_get_serial_sequence('%s','%s'), 1, false);" % sql.append("%s setval(pg_get_serial_sequence('%s','%s'), 1, false);" % (
(style.SQL_KEYWORD('SELECT'), style.SQL_KEYWORD('SELECT'),
style.SQL_TABLE(self.quote_name(table_name)), style.SQL_TABLE(self.quote_name(table_name)),
style.SQL_FIELD(column_name)) style.SQL_FIELD(column_name),
) ))
return sql return sql
def tablespace_sql(self, tablespace, inline=False): def tablespace_sql(self, tablespace, inline=False):

View File

@ -282,18 +282,28 @@ class DatabaseWrapper(BaseDatabaseWrapper):
continue continue
key_columns = self.introspection.get_key_columns(cursor, table_name) key_columns = self.introspection.get_key_columns(cursor, table_name)
for column_name, referenced_table_name, referenced_column_name in key_columns: for column_name, referenced_table_name, referenced_column_name in key_columns:
cursor.execute(""" cursor.execute(
"""
SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING
LEFT JOIN `%s` as REFERRED LEFT JOIN `%s` as REFERRED
ON (REFERRING.`%s` = REFERRED.`%s`) ON (REFERRING.`%s` = REFERRED.`%s`)
WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL""" WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL
% (primary_key_column_name, column_name, table_name, referenced_table_name, """
column_name, referenced_column_name, column_name, referenced_column_name)) % (
primary_key_column_name, column_name, table_name,
referenced_table_name, column_name, referenced_column_name,
column_name, referenced_column_name,
)
)
for bad_row in cursor.fetchall(): for bad_row in cursor.fetchall():
raise utils.IntegrityError("The row in table '%s' with primary key '%s' has an invalid " raise utils.IntegrityError(
"foreign key: %s.%s contains a value '%s' that does not have a corresponding value in %s.%s." "The row in table '%s' with primary key '%s' has an "
% (table_name, bad_row[0], table_name, column_name, bad_row[1], "invalid foreign key: %s.%s contains a value '%s' that "
referenced_table_name, referenced_column_name)) "does not have a corresponding value in %s.%s." % (
table_name, bad_row[0], table_name, column_name,
bad_row[1], referenced_table_name, referenced_column_name,
)
)
def is_usable(self): def is_usable(self):
return True return True

View File

@ -85,7 +85,8 @@ class CursorDebugWrapper(CursorWrapper):
'sql': sql, 'sql': sql,
'time': "%.3f" % duration, 'time': "%.3f" % duration,
}) })
logger.debug('(%.3f) %s; args=%s', duration, sql, params, logger.debug(
'(%.3f) %s; args=%s', duration, sql, params,
extra={'duration': duration, 'sql': sql, 'params': params} extra={'duration': duration, 'sql': sql, 'params': params}
) )
@ -104,7 +105,8 @@ class CursorDebugWrapper(CursorWrapper):
'sql': '%s times: %s' % (times, sql), 'sql': '%s times: %s' % (times, sql),
'time': "%.3f" % duration, 'time': "%.3f" % duration,
}) })
logger.debug('(%.3f) %s; args=%s', duration, sql, param_list, logger.debug(
'(%.3f) %s; args=%s', duration, sql, param_list,
extra={'duration': duration, 'sql': sql, 'params': param_list} extra={'duration': duration, 'sql': sql, 'params': param_list}
) )
@ -154,9 +156,11 @@ def typecast_timestamp(s): # does NOT store time zone information
else: else:
microseconds = '0' microseconds = '0'
tzinfo = utc if settings.USE_TZ else None tzinfo = utc if settings.USE_TZ else None
return datetime.datetime(int(dates[0]), int(dates[1]), int(dates[2]), return datetime.datetime(
int(dates[0]), int(dates[1]), int(dates[2]),
int(times[0]), int(times[1]), int(seconds), int(times[0]), int(times[1]), int(seconds),
int((microseconds + '000000')[:6]), tzinfo) int((microseconds + '000000')[:6]), tzinfo
)
def typecast_decimal(s): def typecast_decimal(s):

View File

@ -519,9 +519,10 @@ class Model(six.with_metaclass(ModelBase)):
if pickled_version: if pickled_version:
current_version = get_version() current_version = get_version()
if current_version != pickled_version: if current_version != pickled_version:
msg = ("Pickled model instance's Django version %s does" msg = (
" not match the current version %s." "Pickled model instance's Django version %s does not match "
% (pickled_version, current_version)) "the current version %s." % (pickled_version, current_version)
)
else: else:
msg = "Pickled model instance's Django version is not specified." msg = "Pickled model instance's Django version is not specified."
@ -1285,9 +1286,7 @@ class Model(six.with_metaclass(ModelBase)):
@classmethod @classmethod
def _check_id_field(cls): def _check_id_field(cls):
""" Check if `id` field is a primary key. """ """ Check if `id` field is a primary key. """
fields = list(f for f in cls._meta.local_fields if f.name == 'id' and f != cls._meta.pk)
fields = list(f for f in cls._meta.local_fields
if f.name == 'id' and f != cls._meta.pk)
# fields is empty or consists of the invalid "id" field # fields is empty or consists of the invalid "id" field
if fields and not fields[0].primary_key and cls._meta.pk.name == 'id': if fields and not fields[0].primary_key and cls._meta.pk.name == 'id':
return [ return [
@ -1342,8 +1341,7 @@ class Model(six.with_metaclass(ModelBase)):
# field "id" and automatically added unique field "id", both # field "id" and automatically added unique field "id", both
# defined at the same model. This special case is considered in # defined at the same model. This special case is considered in
# _check_id_field and here we ignore it. # _check_id_field and here we ignore it.
id_conflict = (f.name == "id" and id_conflict = f.name == "id" and clash and clash.name == "id" and clash.model == cls
clash and clash.name == "id" and clash.model == cls)
if clash and not id_conflict: if clash and not id_conflict:
errors.append( errors.append(
checks.Error( checks.Error(
@ -1397,8 +1395,7 @@ class Model(six.with_metaclass(ModelBase)):
) )
] ]
elif any(not isinstance(fields, (tuple, list)) elif any(not isinstance(fields, (tuple, list)) for fields in cls._meta.index_together):
for fields in cls._meta.index_together):
return [ return [
checks.Error( checks.Error(
"All 'index_together' elements must be lists or tuples.", "All 'index_together' elements must be lists or tuples.",
@ -1425,8 +1422,7 @@ class Model(six.with_metaclass(ModelBase)):
) )
] ]
elif any(not isinstance(fields, (tuple, list)) elif any(not isinstance(fields, (tuple, list)) for fields in cls._meta.unique_together):
for fields in cls._meta.unique_together):
return [ return [
checks.Error( checks.Error(
"All 'unique_together' elements must be lists or tuples.", "All 'unique_together' elements must be lists or tuples.",

View File

@ -20,8 +20,9 @@ def CASCADE(collector, field, sub_objs, using):
def PROTECT(collector, field, sub_objs, using): def PROTECT(collector, field, sub_objs, using):
raise ProtectedError("Cannot delete some instances of model '%s' because " raise ProtectedError(
"they are referenced through a protected foreign key: '%s.%s'" % ( "Cannot delete some instances of model '%s' because they are "
"referenced through a protected foreign key: '%s.%s'" % (
field.remote_field.model.__name__, sub_objs[0].__class__.__name__, field.name field.remote_field.model.__name__, sub_objs[0].__class__.__name__, field.name
), ),
sub_objs sub_objs

View File

@ -806,8 +806,7 @@ class Field(RegisterLookupMixin):
if callable(self.default): if callable(self.default):
return self.default() return self.default()
return self.default return self.default
if (not self.empty_strings_allowed or (self.null and if not self.empty_strings_allowed or self.null and not connection.features.interprets_empty_strings_as_nulls:
not connection.features.interprets_empty_strings_as_nulls)):
return None return None
return "" return ""
@ -1177,10 +1176,8 @@ class DateTimeCheckMixin(object):
# auto_now, auto_now_add, and default are mutually exclusive # auto_now, auto_now_add, and default are mutually exclusive
# options. The use of more than one of these options together # options. The use of more than one of these options together
# will trigger an Error # will trigger an Error
mutually_exclusive_options = [self.auto_now_add, self.auto_now, mutually_exclusive_options = [self.auto_now_add, self.auto_now, self.has_default()]
self.has_default()] enabled_options = [option not in (None, False) for option in mutually_exclusive_options].count(True)
enabled_options = [option not in (None, False)
for option in mutually_exclusive_options].count(True)
if enabled_options > 1: if enabled_options > 1:
return [ return [
checks.Error( checks.Error(
@ -1314,12 +1311,14 @@ class DateField(DateTimeCheckMixin, Field):
def contribute_to_class(self, cls, name, **kwargs): def contribute_to_class(self, cls, name, **kwargs):
super(DateField, self).contribute_to_class(cls, name, **kwargs) super(DateField, self).contribute_to_class(cls, name, **kwargs)
if not self.null: if not self.null:
setattr(cls, 'get_next_by_%s' % self.name, setattr(
curry(cls._get_next_or_previous_by_FIELD, field=self, cls, 'get_next_by_%s' % self.name,
is_next=True)) curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=True)
setattr(cls, 'get_previous_by_%s' % self.name, )
curry(cls._get_next_or_previous_by_FIELD, field=self, setattr(
is_next=False)) cls, 'get_previous_by_%s' % self.name,
curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=False)
)
def get_prep_value(self, value): def get_prep_value(self, value):
value = super(DateField, self).get_prep_value(value) value = super(DateField, self).get_prep_value(value)
@ -1633,8 +1632,7 @@ class DecimalField(Field):
return utils.format_number(value, self.max_digits, self.decimal_places) return utils.format_number(value, self.max_digits, self.decimal_places)
def get_db_prep_save(self, value, connection): def get_db_prep_save(self, value, connection):
return connection.ops.adapt_decimalfield_value(self.to_python(value), return connection.ops.adapt_decimalfield_value(self.to_python(value), self.max_digits, self.decimal_places)
self.max_digits, self.decimal_places)
def get_prep_value(self, value): def get_prep_value(self, value):
value = super(DecimalField, self).get_prep_value(value) value = super(DecimalField, self).get_prep_value(value)
@ -2002,8 +2000,7 @@ class GenericIPAddressField(Field):
value = force_text(value) value = force_text(value)
value = value.strip() value = value.strip()
if ':' in value: if ':' in value:
return clean_ipv6_address(value, return clean_ipv6_address(value, self.unpack_ipv4, self.error_messages['invalid'])
self.unpack_ipv4, self.error_messages['invalid'])
return value return value
def get_db_prep_value(self, value, connection, prepared=False): def get_db_prep_value(self, value, connection, prepared=False):

View File

@ -369,8 +369,7 @@ class ImageField(FileField):
descriptor_class = ImageFileDescriptor descriptor_class = ImageFileDescriptor
description = _("Image") description = _("Image")
def __init__(self, verbose_name=None, name=None, width_field=None, def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):
height_field=None, **kwargs):
self.width_field, self.height_field = width_field, height_field self.width_field, self.height_field = width_field, height_field
super(ImageField, self).__init__(verbose_name, name, **kwargs) super(ImageField, self).__init__(verbose_name, name, **kwargs)

View File

@ -221,8 +221,7 @@ class RelatedField(Field):
# model_set and it clashes with Target.model_set. # model_set and it clashes with Target.model_set.
potential_clashes = rel_opts.fields + rel_opts.many_to_many potential_clashes = rel_opts.fields + rel_opts.many_to_many
for clash_field in potential_clashes: for clash_field in potential_clashes:
clash_name = "%s.%s" % (rel_opts.object_name, clash_name = "%s.%s" % (rel_opts.object_name, clash_field.name) # i.e. "Target.model_set"
clash_field.name) # i. e. "Target.model_set"
if not rel_is_hidden and clash_field.name == rel_name: if not rel_is_hidden and clash_field.name == rel_name:
errors.append( errors.append(
checks.Error( checks.Error(
@ -491,8 +490,9 @@ class ForeignObject(RelatedField):
has_unique_constraint = any(u <= foreign_fields for u in unique_foreign_fields) has_unique_constraint = any(u <= foreign_fields for u in unique_foreign_fields)
if not has_unique_constraint and len(self.foreign_related_fields) > 1: if not has_unique_constraint and len(self.foreign_related_fields) > 1:
field_combination = ', '.join("'%s'" % rel_field.name field_combination = ', '.join(
for rel_field in self.foreign_related_fields) "'%s'" % rel_field.name for rel_field in self.foreign_related_fields
)
model_name = self.remote_field.model.__name__ model_name = self.remote_field.model.__name__
return [ return [
checks.Error( checks.Error(
@ -1241,8 +1241,10 @@ class ManyToManyField(RelatedField):
# Count foreign keys in intermediate model # Count foreign keys in intermediate model
if self_referential: if self_referential:
seen_self = sum(from_model == getattr(field.remote_field, 'model', None) seen_self = sum(
for field in self.remote_field.through._meta.fields) from_model == getattr(field.remote_field, 'model', None)
for field in self.remote_field.through._meta.fields
)
if seen_self > 2 and not self.remote_field.through_fields: if seen_self > 2 and not self.remote_field.through_fields:
errors.append( errors.append(
@ -1260,10 +1262,14 @@ class ManyToManyField(RelatedField):
else: else:
# Count foreign keys in relationship model # Count foreign keys in relationship model
seen_from = sum(from_model == getattr(field.remote_field, 'model', None) seen_from = sum(
for field in self.remote_field.through._meta.fields) from_model == getattr(field.remote_field, 'model', None)
seen_to = sum(to_model == getattr(field.remote_field, 'model', None) for field in self.remote_field.through._meta.fields
for field in self.remote_field.through._meta.fields) )
seen_to = sum(
to_model == getattr(field.remote_field, 'model', None)
for field in self.remote_field.through._meta.fields
)
if seen_from > 1 and not self.remote_field.through_fields: if seen_from > 1 and not self.remote_field.through_fields:
errors.append( errors.append(
@ -1469,8 +1475,7 @@ class ManyToManyField(RelatedField):
elif self.db_table: elif self.db_table:
return self.db_table return self.db_table
else: else:
return utils.truncate_name('%s_%s' % (opts.db_table, self.name), return utils.truncate_name('%s_%s' % (opts.db_table, self.name), connection.ops.max_name_length())
connection.ops.max_name_length())
def _get_m2m_attr(self, related, attr): def _get_m2m_attr(self, related, attr):
""" """

View File

@ -868,16 +868,19 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
def clear(self): def clear(self):
db = router.db_for_write(self.through, instance=self.instance) db = router.db_for_write(self.through, instance=self.instance)
with transaction.atomic(using=db, savepoint=False): with transaction.atomic(using=db, savepoint=False):
signals.m2m_changed.send(sender=self.through, action="pre_clear", signals.m2m_changed.send(
sender=self.through, action="pre_clear",
instance=self.instance, reverse=self.reverse, instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=None, using=db) model=self.model, pk_set=None, using=db,
)
filters = self._build_remove_filters(super(ManyRelatedManager, self).get_queryset().using(db)) filters = self._build_remove_filters(super(ManyRelatedManager, self).get_queryset().using(db))
self.through._default_manager.using(db).filter(filters).delete() self.through._default_manager.using(db).filter(filters).delete()
signals.m2m_changed.send(sender=self.through, action="post_clear", signals.m2m_changed.send(
sender=self.through, action="post_clear",
instance=self.instance, reverse=self.reverse, instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=None, using=db) model=self.model, pk_set=None, using=db,
)
clear.alters_data = True clear.alters_data = True
def set(self, objs, **kwargs): def set(self, objs, **kwargs):
@ -905,9 +908,10 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
new_objs = [] new_objs = []
for obj in objs: for obj in objs:
fk_val = (self.target_field.get_foreign_related_value(obj)[0] fk_val = (
if isinstance(obj, self.model) else obj) self.target_field.get_foreign_related_value(obj)[0]
if isinstance(obj, self.model) else obj
)
if fk_val in old_ids: if fk_val in old_ids:
old_ids.remove(fk_val) old_ids.remove(fk_val)
else: else:
@ -998,9 +1002,11 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
if self.reverse or source_field_name == self.source_field_name: if self.reverse or source_field_name == self.source_field_name:
# Don't send the signal when we are inserting the # Don't send the signal when we are inserting the
# duplicate data row for symmetrical reverse entries. # duplicate data row for symmetrical reverse entries.
signals.m2m_changed.send(sender=self.through, action='pre_add', signals.m2m_changed.send(
sender=self.through, action='pre_add',
instance=self.instance, reverse=self.reverse, instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=new_ids, using=db) model=self.model, pk_set=new_ids, using=db,
)
# Add the ones that aren't there already # Add the ones that aren't there already
self.through._default_manager.using(db).bulk_create([ self.through._default_manager.using(db).bulk_create([
@ -1014,9 +1020,11 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
if self.reverse or source_field_name == self.source_field_name: if self.reverse or source_field_name == self.source_field_name:
# Don't send the signal when we are inserting the # Don't send the signal when we are inserting the
# duplicate data row for symmetrical reverse entries. # duplicate data row for symmetrical reverse entries.
signals.m2m_changed.send(sender=self.through, action='post_add', signals.m2m_changed.send(
sender=self.through, action='post_add',
instance=self.instance, reverse=self.reverse, instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=new_ids, using=db) model=self.model, pk_set=new_ids, using=db,
)
def _remove_items(self, source_field_name, target_field_name, *objs): def _remove_items(self, source_field_name, target_field_name, *objs):
# source_field_name: the PK colname in join table for the source object # source_field_name: the PK colname in join table for the source object
@ -1037,9 +1045,11 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
db = router.db_for_write(self.through, instance=self.instance) db = router.db_for_write(self.through, instance=self.instance)
with transaction.atomic(using=db, savepoint=False): with transaction.atomic(using=db, savepoint=False):
# Send a signal to the other end if need be. # Send a signal to the other end if need be.
signals.m2m_changed.send(sender=self.through, action="pre_remove", signals.m2m_changed.send(
sender=self.through, action="pre_remove",
instance=self.instance, reverse=self.reverse, instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=old_ids, using=db) model=self.model, pk_set=old_ids, using=db,
)
target_model_qs = super(ManyRelatedManager, self).get_queryset() target_model_qs = super(ManyRelatedManager, self).get_queryset()
if target_model_qs._has_filters(): if target_model_qs._has_filters():
old_vals = target_model_qs.using(db).filter(**{ old_vals = target_model_qs.using(db).filter(**{
@ -1049,8 +1059,10 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
filters = self._build_remove_filters(old_vals) filters = self._build_remove_filters(old_vals)
self.through._default_manager.using(db).filter(filters).delete() self.through._default_manager.using(db).filter(filters).delete()
signals.m2m_changed.send(sender=self.through, action="post_remove", signals.m2m_changed.send(
sender=self.through, action="post_remove",
instance=self.instance, reverse=self.reverse, instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=old_ids, using=db) model=self.model, pk_set=old_ids, using=db,
)
return ManyRelatedManager return ManyRelatedManager

View File

@ -235,8 +235,7 @@ class ManyToOneRel(ForeignObjectRel):
""" """
field = self.model._meta.get_field(self.field_name) field = self.model._meta.get_field(self.field_name)
if not field.concrete: if not field.concrete:
raise exceptions.FieldDoesNotExist("No related field named '%s'" % raise exceptions.FieldDoesNotExist("No related field named '%s'" % self.field_name)
self.field_name)
return field return field
def set_field_name(self): def set_field_name(self):
@ -274,8 +273,8 @@ class ManyToManyRel(ForeignObjectRel):
""" """
def __init__(self, field, to, related_name=None, related_query_name=None, def __init__(self, field, to, related_name=None, related_query_name=None,
limit_choices_to=None, symmetrical=True, through=None, through_fields=None, limit_choices_to=None, symmetrical=True, through=None,
db_constraint=True): through_fields=None, db_constraint=True):
super(ManyToManyRel, self).__init__( super(ManyToManyRel, self).__init__(
field, to, field, to,
related_name=related_name, related_name=related_name,

View File

@ -28,13 +28,14 @@ IMMUTABLE_WARNING = (
"for your own use, make a copy first." "for your own use, make a copy first."
) )
DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering', DEFAULT_NAMES = (
'unique_together', 'permissions', 'get_latest_by', 'verbose_name', 'verbose_name_plural', 'db_table', 'ordering',
'order_with_respect_to', 'app_label', 'db_tablespace', 'unique_together', 'permissions', 'get_latest_by', 'order_with_respect_to',
'abstract', 'managed', 'proxy', 'swappable', 'auto_created', 'app_label', 'db_tablespace', 'abstract', 'managed', 'proxy', 'swappable',
'index_together', 'apps', 'default_permissions', 'auto_created', 'index_together', 'apps', 'default_permissions',
'select_on_save', 'default_related_name', 'select_on_save', 'default_related_name', 'required_db_features',
'required_db_features', 'required_db_vendor') 'required_db_vendor',
)
def normalize_together(option_together): def normalize_together(option_together):
@ -249,8 +250,7 @@ class Options(object):
field.primary_key = True field.primary_key = True
self.setup_pk(field) self.setup_pk(field)
else: else:
auto = AutoField(verbose_name='ID', primary_key=True, auto = AutoField(verbose_name='ID', primary_key=True, auto_created=True)
auto_created=True)
model.add_to_class('id', auto) model.add_to_class('id', auto)
def add_field(self, field, virtual=False): def add_field(self, field, virtual=False):
@ -385,8 +385,7 @@ class Options(object):
return make_immutable_fields_list( return make_immutable_fields_list(
"fields", "fields",
(f for f in self._get_fields(reverse=False) (f for f in self._get_fields(reverse=False)
if is_not_an_m2m_field(f) and is_not_a_generic_relation(f) and if is_not_an_m2m_field(f) and is_not_a_generic_relation(f) and is_not_a_generic_foreign_key(f))
is_not_a_generic_foreign_key(f))
) )
@cached_property @cached_property
@ -426,8 +425,7 @@ class Options(object):
""" """
return make_immutable_fields_list( return make_immutable_fields_list(
"many_to_many", "many_to_many",
(f for f in self._get_fields(reverse=False) (f for f in self._get_fields(reverse=False) if f.is_relation and f.many_to_many)
if f.is_relation and f.many_to_many)
) )
@cached_property @cached_property
@ -444,8 +442,7 @@ class Options(object):
all_related_fields = self._get_fields(forward=False, reverse=True, include_hidden=True) all_related_fields = self._get_fields(forward=False, reverse=True, include_hidden=True)
return make_immutable_fields_list( return make_immutable_fields_list(
"related_objects", "related_objects",
(obj for obj in all_related_fields (obj for obj in all_related_fields if not obj.hidden or obj.field.many_to_many)
if not obj.hidden or obj.field.many_to_many)
) )
@cached_property @cached_property

View File

@ -220,9 +220,10 @@ class QuerySet(object):
if pickled_version: if pickled_version:
current_version = get_version() current_version = get_version()
if current_version != pickled_version: if current_version != pickled_version:
msg = ("Pickled queryset instance's Django version %s does" msg = (
" not match the current version %s." "Pickled queryset instance's Django version %s does not "
% (pickled_version, current_version)) "match the current version %s." % (pickled_version, current_version)
)
else: else:
msg = "Pickled queryset instance's Django version is not specified." msg = "Pickled queryset instance's Django version is not specified."
@ -673,9 +674,7 @@ class QuerySet(object):
def raw(self, raw_query, params=None, translations=None, using=None): def raw(self, raw_query, params=None, translations=None, using=None):
if using is None: if using is None:
using = self.db using = self.db
return RawQuerySet(raw_query, model=self.model, return RawQuerySet(raw_query, model=self.model, params=params, translations=translations, using=using)
params=params, translations=translations,
using=using)
def _values(self, *fields): def _values(self, *fields):
clone = self._clone() clone = self._clone()
@ -726,8 +725,7 @@ class QuerySet(object):
def values_list(self, *fields, **kwargs): def values_list(self, *fields, **kwargs):
flat = kwargs.pop('flat', False) flat = kwargs.pop('flat', False)
if kwargs: if kwargs:
raise TypeError('Unexpected keyword arguments to values_list: %s' raise TypeError('Unexpected keyword arguments to values_list: %s' % (list(kwargs),))
% (list(kwargs),))
if flat and len(fields) > 1: if flat and len(fields) > 1:
raise TypeError("'flat' is not valid when values_list is called with more than one field.") raise TypeError("'flat' is not valid when values_list is called with more than one field.")
@ -1116,8 +1114,10 @@ class QuerySet(object):
set(self.query.values_select) != set(other.query.values_select) or set(self.query.values_select) != set(other.query.values_select) or
set(self.query.extra_select) != set(other.query.extra_select) or set(self.query.extra_select) != set(other.query.extra_select) or
set(self.query.annotation_select) != set(other.query.annotation_select)): set(self.query.annotation_select) != set(other.query.annotation_select)):
raise TypeError("Merging '%s' classes must involve the same values in each case." raise TypeError(
% self.__class__.__name__) "Merging '%s' classes must involve the same values in each case."
% self.__class__.__name__
)
def _merge_known_related_objects(self, other): def _merge_known_related_objects(self, other):
""" """
@ -1291,10 +1291,12 @@ class RawQuerySet(object):
""" """
Selects which database this Raw QuerySet should execute its query against. Selects which database this Raw QuerySet should execute its query against.
""" """
return RawQuerySet(self.raw_query, model=self.model, return RawQuerySet(
self.raw_query, model=self.model,
query=self.query.clone(using=alias), query=self.query.clone(using=alias),
params=self.params, translations=self.translations, params=self.params, translations=self.translations,
using=alias) using=alias,
)
@property @property
def columns(self): def columns(self):

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