Fixed #28909 -- Simplified code using tuple/list/set/dict unpacking.
This commit is contained in:
parent
a9e5ac823d
commit
d13a9e44de
|
@ -59,19 +59,19 @@ def delete_selected(modeladmin, request, queryset):
|
||||||
else:
|
else:
|
||||||
title = _("Are you sure?")
|
title = _("Are you sure?")
|
||||||
|
|
||||||
context = dict(
|
context = {
|
||||||
modeladmin.admin_site.each_context(request),
|
**modeladmin.admin_site.each_context(request),
|
||||||
title=title,
|
'title': title,
|
||||||
objects_name=str(objects_name),
|
'objects_name': str(objects_name),
|
||||||
deletable_objects=[deletable_objects],
|
'deletable_objects': [deletable_objects],
|
||||||
model_count=dict(model_count).items(),
|
'model_count': dict(model_count).items(),
|
||||||
queryset=queryset,
|
'queryset': queryset,
|
||||||
perms_lacking=perms_needed,
|
'perms_lacking': perms_needed,
|
||||||
protected=protected,
|
'protected': protected,
|
||||||
opts=opts,
|
'opts': opts,
|
||||||
action_checkbox_name=helpers.ACTION_CHECKBOX_NAME,
|
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
|
||||||
media=modeladmin.media,
|
'media': modeladmin.media,
|
||||||
)
|
}
|
||||||
|
|
||||||
request.current_app = modeladmin.admin_site.name
|
request.current_app = modeladmin.admin_site.name
|
||||||
|
|
||||||
|
|
|
@ -65,21 +65,21 @@ def check_dependencies(**kwargs):
|
||||||
class BaseModelAdminChecks:
|
class BaseModelAdminChecks:
|
||||||
|
|
||||||
def check(self, admin_obj, **kwargs):
|
def check(self, admin_obj, **kwargs):
|
||||||
errors = []
|
return [
|
||||||
errors.extend(self._check_autocomplete_fields(admin_obj))
|
*self._check_autocomplete_fields(admin_obj),
|
||||||
errors.extend(self._check_raw_id_fields(admin_obj))
|
*self._check_raw_id_fields(admin_obj),
|
||||||
errors.extend(self._check_fields(admin_obj))
|
*self._check_fields(admin_obj),
|
||||||
errors.extend(self._check_fieldsets(admin_obj))
|
*self._check_fieldsets(admin_obj),
|
||||||
errors.extend(self._check_exclude(admin_obj))
|
*self._check_exclude(admin_obj),
|
||||||
errors.extend(self._check_form(admin_obj))
|
*self._check_form(admin_obj),
|
||||||
errors.extend(self._check_filter_vertical(admin_obj))
|
*self._check_filter_vertical(admin_obj),
|
||||||
errors.extend(self._check_filter_horizontal(admin_obj))
|
*self._check_filter_horizontal(admin_obj),
|
||||||
errors.extend(self._check_radio_fields(admin_obj))
|
*self._check_radio_fields(admin_obj),
|
||||||
errors.extend(self._check_prepopulated_fields(admin_obj))
|
*self._check_prepopulated_fields(admin_obj),
|
||||||
errors.extend(self._check_view_on_site_url(admin_obj))
|
*self._check_view_on_site_url(admin_obj),
|
||||||
errors.extend(self._check_ordering(admin_obj))
|
*self._check_ordering(admin_obj),
|
||||||
errors.extend(self._check_readonly_fields(admin_obj))
|
*self._check_readonly_fields(admin_obj),
|
||||||
return errors
|
]
|
||||||
|
|
||||||
def _check_autocomplete_fields(self, obj):
|
def _check_autocomplete_fields(self, obj):
|
||||||
"""
|
"""
|
||||||
|
@ -554,20 +554,21 @@ class BaseModelAdminChecks:
|
||||||
class ModelAdminChecks(BaseModelAdminChecks):
|
class ModelAdminChecks(BaseModelAdminChecks):
|
||||||
|
|
||||||
def check(self, admin_obj, **kwargs):
|
def check(self, admin_obj, **kwargs):
|
||||||
errors = super().check(admin_obj)
|
return [
|
||||||
errors.extend(self._check_save_as(admin_obj))
|
*super().check(admin_obj),
|
||||||
errors.extend(self._check_save_on_top(admin_obj))
|
*self._check_save_as(admin_obj),
|
||||||
errors.extend(self._check_inlines(admin_obj))
|
*self._check_save_on_top(admin_obj),
|
||||||
errors.extend(self._check_list_display(admin_obj))
|
*self._check_inlines(admin_obj),
|
||||||
errors.extend(self._check_list_display_links(admin_obj))
|
*self._check_list_display(admin_obj),
|
||||||
errors.extend(self._check_list_filter(admin_obj))
|
*self._check_list_display_links(admin_obj),
|
||||||
errors.extend(self._check_list_select_related(admin_obj))
|
*self._check_list_filter(admin_obj),
|
||||||
errors.extend(self._check_list_per_page(admin_obj))
|
*self._check_list_select_related(admin_obj),
|
||||||
errors.extend(self._check_list_max_show_all(admin_obj))
|
*self._check_list_per_page(admin_obj),
|
||||||
errors.extend(self._check_list_editable(admin_obj))
|
*self._check_list_max_show_all(admin_obj),
|
||||||
errors.extend(self._check_search_fields(admin_obj))
|
*self._check_list_editable(admin_obj),
|
||||||
errors.extend(self._check_date_hierarchy(admin_obj))
|
*self._check_search_fields(admin_obj),
|
||||||
return errors
|
*self._check_date_hierarchy(admin_obj),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_save_as(self, obj):
|
def _check_save_as(self, obj):
|
||||||
""" Check save_as is a boolean. """
|
""" Check save_as is a boolean. """
|
||||||
|
@ -883,15 +884,16 @@ class ModelAdminChecks(BaseModelAdminChecks):
|
||||||
class InlineModelAdminChecks(BaseModelAdminChecks):
|
class InlineModelAdminChecks(BaseModelAdminChecks):
|
||||||
|
|
||||||
def check(self, inline_obj, **kwargs):
|
def check(self, inline_obj, **kwargs):
|
||||||
errors = super().check(inline_obj)
|
|
||||||
parent_model = inline_obj.parent_model
|
parent_model = inline_obj.parent_model
|
||||||
errors.extend(self._check_relation(inline_obj, parent_model))
|
return [
|
||||||
errors.extend(self._check_exclude_of_parent_model(inline_obj, parent_model))
|
*super().check(inline_obj),
|
||||||
errors.extend(self._check_extra(inline_obj))
|
*self._check_relation(inline_obj, parent_model),
|
||||||
errors.extend(self._check_max_num(inline_obj))
|
*self._check_exclude_of_parent_model(inline_obj, parent_model),
|
||||||
errors.extend(self._check_min_num(inline_obj))
|
*self._check_extra(inline_obj),
|
||||||
errors.extend(self._check_formset(inline_obj))
|
*self._check_max_num(inline_obj),
|
||||||
return errors
|
*self._check_min_num(inline_obj),
|
||||||
|
*self._check_formset(inline_obj),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_exclude_of_parent_model(self, obj, parent_model):
|
def _check_exclude_of_parent_model(self, obj, parent_model):
|
||||||
# Do not perform more specific checks if the base checks result in an
|
# Do not perform more specific checks if the base checks result in an
|
||||||
|
|
|
@ -7,13 +7,13 @@ class AdminAuthenticationForm(AuthenticationForm):
|
||||||
"""
|
"""
|
||||||
A custom authentication form used in the admin app.
|
A custom authentication form used in the admin app.
|
||||||
"""
|
"""
|
||||||
error_messages = dict(AuthenticationForm.error_messages)
|
error_messages = {
|
||||||
error_messages.update({
|
**AuthenticationForm.error_messages,
|
||||||
'invalid_login': _(
|
'invalid_login': _(
|
||||||
"Please enter the correct %(username)s and password for a staff "
|
"Please enter the correct %(username)s and password for a staff "
|
||||||
"account. Note that both fields may be case-sensitive."
|
"account. Note that both fields may be case-sensitive."
|
||||||
),
|
),
|
||||||
})
|
}
|
||||||
required_css_class = 'required'
|
required_css_class = 'required'
|
||||||
|
|
||||||
def confirm_login_allowed(self, user):
|
def confirm_login_allowed(self, user):
|
||||||
|
|
|
@ -145,7 +145,7 @@ class BaseModelAdmin(metaclass=forms.MediaDefiningClass):
|
||||||
# formfield_overrides because **kwargs is more specific, and should
|
# formfield_overrides because **kwargs is more specific, and should
|
||||||
# always win.
|
# always win.
|
||||||
if db_field.__class__ in self.formfield_overrides:
|
if db_field.__class__ in self.formfield_overrides:
|
||||||
kwargs = dict(self.formfield_overrides[db_field.__class__], **kwargs)
|
kwargs = {**self.formfield_overrides[db_field.__class__], **kwargs}
|
||||||
|
|
||||||
# Get the correct formfield.
|
# Get the correct formfield.
|
||||||
if isinstance(db_field, models.ForeignKey):
|
if isinstance(db_field, models.ForeignKey):
|
||||||
|
@ -176,7 +176,7 @@ class BaseModelAdmin(metaclass=forms.MediaDefiningClass):
|
||||||
# passed to formfield_for_dbfield override the defaults.
|
# passed to formfield_for_dbfield override the defaults.
|
||||||
for klass in db_field.__class__.mro():
|
for klass in db_field.__class__.mro():
|
||||||
if klass in self.formfield_overrides:
|
if klass in self.formfield_overrides:
|
||||||
kwargs = dict(copy.deepcopy(self.formfield_overrides[klass]), **kwargs)
|
kwargs = {**copy.deepcopy(self.formfield_overrides[klass]), **kwargs}
|
||||||
return db_field.formfield(**kwargs)
|
return db_field.formfield(**kwargs)
|
||||||
|
|
||||||
# For any other type of field, just call its formfield() method.
|
# For any other type of field, just call its formfield() method.
|
||||||
|
@ -653,12 +653,12 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
form = type(self.form.__name__, (self.form,), new_attrs)
|
form = type(self.form.__name__, (self.form,), new_attrs)
|
||||||
|
|
||||||
defaults = {
|
defaults = {
|
||||||
"form": form,
|
'form': form,
|
||||||
"fields": fields,
|
'fields': fields,
|
||||||
"exclude": exclude,
|
'exclude': exclude,
|
||||||
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
|
'formfield_callback': partial(self.formfield_for_dbfield, request=request),
|
||||||
|
**kwargs,
|
||||||
}
|
}
|
||||||
defaults.update(kwargs)
|
|
||||||
|
|
||||||
if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
|
if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
|
||||||
defaults['fields'] = forms.ALL_FIELDS
|
defaults['fields'] = forms.ALL_FIELDS
|
||||||
|
@ -724,9 +724,9 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
Return a Form class for use in the Formset on the changelist page.
|
Return a Form class for use in the Formset on the changelist page.
|
||||||
"""
|
"""
|
||||||
defaults = {
|
defaults = {
|
||||||
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
|
'formfield_callback': partial(self.formfield_for_dbfield, request=request),
|
||||||
|
**kwargs,
|
||||||
}
|
}
|
||||||
defaults.update(kwargs)
|
|
||||||
if defaults.get('fields') is None and not modelform_defines_fields(defaults.get('form')):
|
if defaults.get('fields') is None and not modelform_defines_fields(defaults.get('form')):
|
||||||
defaults['fields'] = forms.ALL_FIELDS
|
defaults['fields'] = forms.ALL_FIELDS
|
||||||
|
|
||||||
|
@ -738,9 +738,9 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
is used.
|
is used.
|
||||||
"""
|
"""
|
||||||
defaults = {
|
defaults = {
|
||||||
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
|
'formfield_callback': partial(self.formfield_for_dbfield, request=request),
|
||||||
|
**kwargs,
|
||||||
}
|
}
|
||||||
defaults.update(kwargs)
|
|
||||||
return modelformset_factory(
|
return modelformset_factory(
|
||||||
self.model, 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
|
||||||
|
@ -1540,20 +1540,19 @@ 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(
|
context = {
|
||||||
self.admin_site.each_context(request),
|
**self.admin_site.each_context(request),
|
||||||
title=(_('Add %s') if add else _('Change %s')) % opts.verbose_name,
|
'title': (_('Add %s') if add else _('Change %s')) % opts.verbose_name,
|
||||||
adminform=adminForm,
|
'adminform': adminForm,
|
||||||
object_id=object_id,
|
'object_id': object_id,
|
||||||
original=obj,
|
'original': obj,
|
||||||
is_popup=(IS_POPUP_VAR in request.POST or
|
'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET,
|
||||||
IS_POPUP_VAR in request.GET),
|
'to_field': to_field,
|
||||||
to_field=to_field,
|
'media': media,
|
||||||
media=media,
|
'inline_admin_formsets': inline_formsets,
|
||||||
inline_admin_formsets=inline_formsets,
|
'errors': helpers.AdminErrorList(form, formsets),
|
||||||
errors=helpers.AdminErrorList(form, formsets),
|
'preserved_filters': self.get_preserved_filters(request),
|
||||||
preserved_filters=self.get_preserved_filters(request),
|
}
|
||||||
)
|
|
||||||
|
|
||||||
# Hide the "Save" and "Save and continue" buttons if "Save as New" was
|
# Hide the "Save" and "Save and continue" buttons if "Save as New" was
|
||||||
# previously chosen to prevent the interface from getting confusing.
|
# previously chosen to prevent the interface from getting confusing.
|
||||||
|
@ -1700,25 +1699,25 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
cl.result_count
|
cl.result_count
|
||||||
)
|
)
|
||||||
|
|
||||||
context = dict(
|
context = {
|
||||||
self.admin_site.each_context(request),
|
**self.admin_site.each_context(request),
|
||||||
module_name=str(opts.verbose_name_plural),
|
'module_name': str(opts.verbose_name_plural),
|
||||||
selection_note=_('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)},
|
'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)},
|
||||||
selection_note_all=selection_note_all % {'total_count': cl.result_count},
|
'selection_note_all': selection_note_all % {'total_count': cl.result_count},
|
||||||
title=cl.title,
|
'title': cl.title,
|
||||||
is_popup=cl.is_popup,
|
'is_popup': cl.is_popup,
|
||||||
to_field=cl.to_field,
|
'to_field': cl.to_field,
|
||||||
cl=cl,
|
'cl': cl,
|
||||||
media=media,
|
'media': media,
|
||||||
has_add_permission=self.has_add_permission(request),
|
'has_add_permission': self.has_add_permission(request),
|
||||||
opts=cl.opts,
|
'opts': cl.opts,
|
||||||
action_form=action_form,
|
'action_form': action_form,
|
||||||
actions_on_top=self.actions_on_top,
|
'actions_on_top': self.actions_on_top,
|
||||||
actions_on_bottom=self.actions_on_bottom,
|
'actions_on_bottom': self.actions_on_bottom,
|
||||||
actions_selection_counter=self.actions_selection_counter,
|
'actions_selection_counter': self.actions_selection_counter,
|
||||||
preserved_filters=self.get_preserved_filters(request),
|
'preserved_filters': self.get_preserved_filters(request),
|
||||||
)
|
**(extra_context or {}),
|
||||||
context.update(extra_context or {})
|
}
|
||||||
|
|
||||||
request.current_app = self.admin_site.name
|
request.current_app = self.admin_site.name
|
||||||
|
|
||||||
|
@ -1775,23 +1774,22 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
else:
|
else:
|
||||||
title = _("Are you sure?")
|
title = _("Are you sure?")
|
||||||
|
|
||||||
context = dict(
|
context = {
|
||||||
self.admin_site.each_context(request),
|
**self.admin_site.each_context(request),
|
||||||
title=title,
|
'title': title,
|
||||||
object_name=object_name,
|
'object_name': object_name,
|
||||||
object=obj,
|
'object': obj,
|
||||||
deleted_objects=deleted_objects,
|
'deleted_objects': deleted_objects,
|
||||||
model_count=dict(model_count).items(),
|
'model_count': dict(model_count).items(),
|
||||||
perms_lacking=perms_needed,
|
'perms_lacking': perms_needed,
|
||||||
protected=protected,
|
'protected': protected,
|
||||||
opts=opts,
|
'opts': opts,
|
||||||
app_label=app_label,
|
'app_label': app_label,
|
||||||
preserved_filters=self.get_preserved_filters(request),
|
'preserved_filters': self.get_preserved_filters(request),
|
||||||
is_popup=(IS_POPUP_VAR in request.POST or
|
'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET,
|
||||||
IS_POPUP_VAR in request.GET),
|
'to_field': to_field,
|
||||||
to_field=to_field,
|
**(extra_context or {}),
|
||||||
)
|
}
|
||||||
context.update(extra_context or {})
|
|
||||||
|
|
||||||
return self.render_delete_form(request, context)
|
return self.render_delete_form(request, context)
|
||||||
|
|
||||||
|
@ -1815,16 +1813,16 @@ 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(
|
context = {
|
||||||
self.admin_site.each_context(request),
|
**self.admin_site.each_context(request),
|
||||||
title=_('Change history: %s') % obj,
|
'title': _('Change history: %s') % obj,
|
||||||
action_list=action_list,
|
'action_list': action_list,
|
||||||
module_name=str(capfirst(opts.verbose_name_plural)),
|
'module_name': str(capfirst(opts.verbose_name_plural)),
|
||||||
object=obj,
|
'object': obj,
|
||||||
opts=opts,
|
'opts': opts,
|
||||||
preserved_filters=self.get_preserved_filters(request),
|
'preserved_filters': self.get_preserved_filters(request),
|
||||||
)
|
**(extra_context or {}),
|
||||||
context.update(extra_context or {})
|
}
|
||||||
|
|
||||||
request.current_app = self.admin_site.name
|
request.current_app = self.admin_site.name
|
||||||
|
|
||||||
|
@ -1937,19 +1935,19 @@ class InlineModelAdmin(BaseModelAdmin):
|
||||||
exclude = exclude or None
|
exclude = exclude or None
|
||||||
can_delete = self.can_delete and self.has_delete_permission(request, obj)
|
can_delete = self.can_delete and self.has_delete_permission(request, obj)
|
||||||
defaults = {
|
defaults = {
|
||||||
"form": self.form,
|
'form': self.form,
|
||||||
"formset": self.formset,
|
'formset': self.formset,
|
||||||
"fk_name": self.fk_name,
|
'fk_name': self.fk_name,
|
||||||
"fields": fields,
|
'fields': fields,
|
||||||
"exclude": exclude,
|
'exclude': exclude,
|
||||||
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
|
'formfield_callback': partial(self.formfield_for_dbfield, request=request),
|
||||||
"extra": self.get_extra(request, obj, **kwargs),
|
'extra': self.get_extra(request, obj, **kwargs),
|
||||||
"min_num": self.get_min_num(request, obj, **kwargs),
|
'min_num': self.get_min_num(request, obj, **kwargs),
|
||||||
"max_num": self.get_max_num(request, obj, **kwargs),
|
'max_num': self.get_max_num(request, obj, **kwargs),
|
||||||
"can_delete": can_delete,
|
'can_delete': can_delete,
|
||||||
|
**kwargs,
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults.update(kwargs)
|
|
||||||
base_model_form = defaults['form']
|
base_model_form = defaults['form']
|
||||||
|
|
||||||
class DeleteProtectedModelForm(base_model_form):
|
class DeleteProtectedModelForm(base_model_form):
|
||||||
|
|
|
@ -312,7 +312,7 @@ class AdminSite:
|
||||||
defaults = {
|
defaults = {
|
||||||
'form_class': AdminPasswordChangeForm,
|
'form_class': AdminPasswordChangeForm,
|
||||||
'success_url': url,
|
'success_url': url,
|
||||||
'extra_context': dict(self.each_context(request), **(extra_context or {})),
|
'extra_context': {**self.each_context(request), **(extra_context or {})},
|
||||||
}
|
}
|
||||||
if self.password_change_template is not None:
|
if self.password_change_template is not None:
|
||||||
defaults['template_name'] = self.password_change_template
|
defaults['template_name'] = self.password_change_template
|
||||||
|
@ -325,7 +325,7 @@ class AdminSite:
|
||||||
"""
|
"""
|
||||||
from django.contrib.auth.views import PasswordChangeDoneView
|
from django.contrib.auth.views import PasswordChangeDoneView
|
||||||
defaults = {
|
defaults = {
|
||||||
'extra_context': dict(self.each_context(request), **(extra_context or {})),
|
'extra_context': {**self.each_context(request), **(extra_context or {})},
|
||||||
}
|
}
|
||||||
if self.password_change_done_template is not None:
|
if self.password_change_done_template is not None:
|
||||||
defaults['template_name'] = self.password_change_done_template
|
defaults['template_name'] = self.password_change_done_template
|
||||||
|
@ -350,13 +350,13 @@ class AdminSite:
|
||||||
"""
|
"""
|
||||||
from django.contrib.auth.views import LogoutView
|
from django.contrib.auth.views import LogoutView
|
||||||
defaults = {
|
defaults = {
|
||||||
'extra_context': dict(
|
'extra_context': {
|
||||||
self.each_context(request),
|
**self.each_context(request),
|
||||||
# Since the user isn't logged out at this point, the value of
|
# Since the user isn't logged out at this point, the value of
|
||||||
# has_permission must be overridden.
|
# has_permission must be overridden.
|
||||||
has_permission=False,
|
'has_permission': False,
|
||||||
**(extra_context or {})
|
**(extra_context or {})
|
||||||
),
|
},
|
||||||
}
|
}
|
||||||
if self.logout_template is not None:
|
if self.logout_template is not None:
|
||||||
defaults['template_name'] = self.logout_template
|
defaults['template_name'] = self.logout_template
|
||||||
|
@ -378,12 +378,12 @@ class AdminSite:
|
||||||
# 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(
|
context = {
|
||||||
self.each_context(request),
|
**self.each_context(request),
|
||||||
title=_('Log in'),
|
'title': _('Log in'),
|
||||||
app_path=request.get_full_path(),
|
'app_path': request.get_full_path(),
|
||||||
username=request.user.get_username(),
|
'username': request.user.get_username(),
|
||||||
)
|
}
|
||||||
if (REDIRECT_FIELD_NAME not in request.GET and
|
if (REDIRECT_FIELD_NAME not in request.GET and
|
||||||
REDIRECT_FIELD_NAME not in request.POST):
|
REDIRECT_FIELD_NAME not in request.POST):
|
||||||
context[REDIRECT_FIELD_NAME] = reverse('admin:index', current_app=self.name)
|
context[REDIRECT_FIELD_NAME] = reverse('admin:index', current_app=self.name)
|
||||||
|
@ -486,12 +486,12 @@ class AdminSite:
|
||||||
"""
|
"""
|
||||||
app_list = self.get_app_list(request)
|
app_list = self.get_app_list(request)
|
||||||
|
|
||||||
context = dict(
|
context = {
|
||||||
self.each_context(request),
|
**self.each_context(request),
|
||||||
title=self.index_title,
|
'title': self.index_title,
|
||||||
app_list=app_list,
|
'app_list': app_list,
|
||||||
)
|
**(extra_context or {}),
|
||||||
context.update(extra_context or {})
|
}
|
||||||
|
|
||||||
request.current_app = self.name
|
request.current_app = self.name
|
||||||
|
|
||||||
|
@ -504,13 +504,13 @@ class AdminSite:
|
||||||
# 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(
|
context = {
|
||||||
self.each_context(request),
|
**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,
|
||||||
)
|
**(extra_context or {}),
|
||||||
context.update(extra_context or {})
|
}
|
||||||
|
|
||||||
request.current_app = self.name
|
request.current_app = self.name
|
||||||
|
|
||||||
|
|
|
@ -64,15 +64,17 @@ def pagination(cl):
|
||||||
# ON_EACH_SIDE links at either end of the "current page" link.
|
# ON_EACH_SIDE links at either end of the "current page" link.
|
||||||
page_range = []
|
page_range = []
|
||||||
if page_num > (ON_EACH_SIDE + ON_ENDS):
|
if page_num > (ON_EACH_SIDE + ON_ENDS):
|
||||||
page_range.extend(range(0, ON_ENDS))
|
page_range += [
|
||||||
page_range.append(DOT)
|
*range(0, ON_ENDS), DOT,
|
||||||
page_range.extend(range(page_num - ON_EACH_SIDE, page_num + 1))
|
*range(page_num - ON_EACH_SIDE, page_num + 1),
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
page_range.extend(range(0, page_num + 1))
|
page_range.extend(range(0, page_num + 1))
|
||||||
if page_num < (paginator.num_pages - ON_EACH_SIDE - ON_ENDS - 1):
|
if page_num < (paginator.num_pages - ON_EACH_SIDE - ON_ENDS - 1):
|
||||||
page_range.extend(range(page_num + 1, page_num + ON_EACH_SIDE + 1))
|
page_range += [
|
||||||
page_range.append(DOT)
|
*range(page_num + 1, page_num + ON_EACH_SIDE + 1), DOT,
|
||||||
page_range.extend(range(paginator.num_pages - ON_ENDS, paginator.num_pages))
|
*range(paginator.num_pages - ON_ENDS, paginator.num_pages)
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
page_range.extend(range(page_num + 1, paginator.num_pages))
|
page_range.extend(range(page_num + 1, paginator.num_pages))
|
||||||
|
|
||||||
|
|
|
@ -62,10 +62,8 @@ class AdminDateWidget(forms.DateInput):
|
||||||
return forms.Media(js=["admin/js/%s" % path for path in js])
|
return forms.Media(js=["admin/js/%s" % path for path in js])
|
||||||
|
|
||||||
def __init__(self, attrs=None, format=None):
|
def __init__(self, attrs=None, format=None):
|
||||||
final_attrs = {'class': 'vDateField', 'size': '10'}
|
attrs = {'class': 'vDateField', 'size': '10', **(attrs or {})}
|
||||||
if attrs is not None:
|
super().__init__(attrs=attrs, format=format)
|
||||||
final_attrs.update(attrs)
|
|
||||||
super().__init__(attrs=final_attrs, format=format)
|
|
||||||
|
|
||||||
|
|
||||||
class AdminTimeWidget(forms.TimeInput):
|
class AdminTimeWidget(forms.TimeInput):
|
||||||
|
@ -81,10 +79,8 @@ class AdminTimeWidget(forms.TimeInput):
|
||||||
return forms.Media(js=["admin/js/%s" % path for path in js])
|
return forms.Media(js=["admin/js/%s" % path for path in js])
|
||||||
|
|
||||||
def __init__(self, attrs=None, format=None):
|
def __init__(self, attrs=None, format=None):
|
||||||
final_attrs = {'class': 'vTimeField', 'size': '8'}
|
attrs = {'class': 'vTimeField', 'size': '8', **(attrs or {})}
|
||||||
if attrs is not None:
|
super().__init__(attrs=attrs, format=format)
|
||||||
final_attrs.update(attrs)
|
|
||||||
super().__init__(attrs=final_attrs, format=format)
|
|
||||||
|
|
||||||
|
|
||||||
class AdminSplitDateTime(forms.SplitDateTimeWidget):
|
class AdminSplitDateTime(forms.SplitDateTimeWidget):
|
||||||
|
@ -328,36 +324,24 @@ class RelatedFieldWidgetWrapper(forms.Widget):
|
||||||
|
|
||||||
class AdminTextareaWidget(forms.Textarea):
|
class AdminTextareaWidget(forms.Textarea):
|
||||||
def __init__(self, attrs=None):
|
def __init__(self, attrs=None):
|
||||||
final_attrs = {'class': 'vLargeTextField'}
|
super().__init__(attrs={'class': 'vLargeTextField', **(attrs or {})})
|
||||||
if attrs is not None:
|
|
||||||
final_attrs.update(attrs)
|
|
||||||
super().__init__(attrs=final_attrs)
|
|
||||||
|
|
||||||
|
|
||||||
class AdminTextInputWidget(forms.TextInput):
|
class AdminTextInputWidget(forms.TextInput):
|
||||||
def __init__(self, attrs=None):
|
def __init__(self, attrs=None):
|
||||||
final_attrs = {'class': 'vTextField'}
|
super().__init__(attrs={'class': 'vTextField', **(attrs or {})})
|
||||||
if attrs is not None:
|
|
||||||
final_attrs.update(attrs)
|
|
||||||
super().__init__(attrs=final_attrs)
|
|
||||||
|
|
||||||
|
|
||||||
class AdminEmailInputWidget(forms.EmailInput):
|
class AdminEmailInputWidget(forms.EmailInput):
|
||||||
def __init__(self, attrs=None):
|
def __init__(self, attrs=None):
|
||||||
final_attrs = {'class': 'vTextField'}
|
super().__init__(attrs={'class': 'vTextField', **(attrs or {})})
|
||||||
if attrs is not None:
|
|
||||||
final_attrs.update(attrs)
|
|
||||||
super().__init__(attrs=final_attrs)
|
|
||||||
|
|
||||||
|
|
||||||
class AdminURLFieldWidget(forms.URLInput):
|
class AdminURLFieldWidget(forms.URLInput):
|
||||||
template_name = 'admin/widgets/url.html'
|
template_name = 'admin/widgets/url.html'
|
||||||
|
|
||||||
def __init__(self, attrs=None):
|
def __init__(self, attrs=None):
|
||||||
final_attrs = {'class': 'vURLField'}
|
super().__init__(attrs={'class': 'vURLField', **(attrs or {})})
|
||||||
if attrs is not None:
|
|
||||||
final_attrs.update(attrs)
|
|
||||||
super().__init__(attrs=final_attrs)
|
|
||||||
|
|
||||||
def get_context(self, name, value, attrs):
|
def get_context(self, name, value, attrs):
|
||||||
context = super().get_context(name, value, attrs)
|
context = super().get_context(name, value, attrs)
|
||||||
|
@ -371,10 +355,7 @@ class AdminIntegerFieldWidget(forms.NumberInput):
|
||||||
class_name = 'vIntegerField'
|
class_name = 'vIntegerField'
|
||||||
|
|
||||||
def __init__(self, attrs=None):
|
def __init__(self, attrs=None):
|
||||||
final_attrs = {'class': self.class_name}
|
super().__init__(attrs={'class': self.class_name, **(attrs or {})})
|
||||||
if attrs is not None:
|
|
||||||
final_attrs.update(attrs)
|
|
||||||
super().__init__(attrs=final_attrs)
|
|
||||||
|
|
||||||
|
|
||||||
class AdminBigIntegerFieldWidget(AdminIntegerFieldWidget):
|
class AdminBigIntegerFieldWidget(AdminIntegerFieldWidget):
|
||||||
|
|
|
@ -40,9 +40,11 @@ class BaseAdminDocsView(TemplateView):
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs.update({'root_path': reverse('admin:index')})
|
return super().get_context_data(**{
|
||||||
kwargs.update(admin.site.each_context(self.request))
|
**kwargs,
|
||||||
return super().get_context_data(**kwargs)
|
'root_path': reverse('admin:index'),
|
||||||
|
**admin.site.each_context(self.request),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class BookmarkletsView(BaseAdminDocsView):
|
class BookmarkletsView(BaseAdminDocsView):
|
||||||
|
@ -87,8 +89,7 @@ class TemplateTagIndexView(BaseAdminDocsView):
|
||||||
'meta': metadata,
|
'meta': metadata,
|
||||||
'library': tag_library,
|
'library': tag_library,
|
||||||
})
|
})
|
||||||
kwargs.update({'tags': tags})
|
return super().get_context_data(**{**kwargs, 'tags': tags})
|
||||||
return super().get_context_data(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateFilterIndexView(BaseAdminDocsView):
|
class TemplateFilterIndexView(BaseAdminDocsView):
|
||||||
|
@ -121,8 +122,7 @@ class TemplateFilterIndexView(BaseAdminDocsView):
|
||||||
'meta': metadata,
|
'meta': metadata,
|
||||||
'library': tag_library,
|
'library': tag_library,
|
||||||
})
|
})
|
||||||
kwargs.update({'filters': filters})
|
return super().get_context_data(**{**kwargs, 'filters': filters})
|
||||||
return super().get_context_data(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ViewIndexView(BaseAdminDocsView):
|
class ViewIndexView(BaseAdminDocsView):
|
||||||
|
@ -145,8 +145,7 @@ class ViewIndexView(BaseAdminDocsView):
|
||||||
'namespace': ':'.join((namespace or [])),
|
'namespace': ':'.join((namespace or [])),
|
||||||
'name': name,
|
'name': name,
|
||||||
})
|
})
|
||||||
kwargs.update({'views': views})
|
return super().get_context_data(**{**kwargs, 'views': views})
|
||||||
return super().get_context_data(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ViewDetailView(BaseAdminDocsView):
|
class ViewDetailView(BaseAdminDocsView):
|
||||||
|
@ -181,13 +180,13 @@ class ViewDetailView(BaseAdminDocsView):
|
||||||
body = utils.parse_rst(body, 'view', _('view:') + view)
|
body = utils.parse_rst(body, 'view', _('view:') + view)
|
||||||
for key in metadata:
|
for key in metadata:
|
||||||
metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view)
|
metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view)
|
||||||
kwargs.update({
|
return super().get_context_data(**{
|
||||||
|
**kwargs,
|
||||||
'name': view,
|
'name': view,
|
||||||
'summary': title,
|
'summary': title,
|
||||||
'body': body,
|
'body': body,
|
||||||
'meta': metadata,
|
'meta': metadata,
|
||||||
})
|
})
|
||||||
return super().get_context_data(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ModelIndexView(BaseAdminDocsView):
|
class ModelIndexView(BaseAdminDocsView):
|
||||||
|
@ -195,8 +194,7 @@ class ModelIndexView(BaseAdminDocsView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
m_list = [m._meta for m in apps.get_models()]
|
m_list = [m._meta for m in apps.get_models()]
|
||||||
kwargs.update({'models': m_list})
|
return super().get_context_data(**{**kwargs, 'models': m_list})
|
||||||
return super().get_context_data(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ModelDetailView(BaseAdminDocsView):
|
class ModelDetailView(BaseAdminDocsView):
|
||||||
|
@ -319,14 +317,14 @@ class ModelDetailView(BaseAdminDocsView):
|
||||||
'data_type': 'Integer',
|
'data_type': 'Integer',
|
||||||
'verbose': utils.parse_rst(_("number of %s") % verbose, 'model', _('model:') + opts.model_name),
|
'verbose': utils.parse_rst(_("number of %s") % verbose, 'model', _('model:') + opts.model_name),
|
||||||
})
|
})
|
||||||
kwargs.update({
|
return super().get_context_data(**{
|
||||||
|
**kwargs,
|
||||||
'name': '%s.%s' % (opts.app_label, opts.object_name),
|
'name': '%s.%s' % (opts.app_label, opts.object_name),
|
||||||
'summary': title,
|
'summary': title,
|
||||||
'description': body,
|
'description': body,
|
||||||
'fields': fields,
|
'fields': fields,
|
||||||
'methods': methods,
|
'methods': methods,
|
||||||
})
|
})
|
||||||
return super().get_context_data(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateDetailView(BaseAdminDocsView):
|
class TemplateDetailView(BaseAdminDocsView):
|
||||||
|
@ -355,11 +353,11 @@ class TemplateDetailView(BaseAdminDocsView):
|
||||||
'contents': template_contents,
|
'contents': template_contents,
|
||||||
'order': index,
|
'order': index,
|
||||||
})
|
})
|
||||||
kwargs.update({
|
return super().get_context_data(**{
|
||||||
|
**kwargs,
|
||||||
'name': template,
|
'name': template,
|
||||||
'templates': templates,
|
'templates': templates,
|
||||||
})
|
})
|
||||||
return super().get_context_data(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -177,8 +177,8 @@ class UserAdmin(admin.ModelAdmin):
|
||||||
'original': user,
|
'original': user,
|
||||||
'save_as': False,
|
'save_as': False,
|
||||||
'show_save': True,
|
'show_save': True,
|
||||||
|
**self.admin_site.each_context(request),
|
||||||
}
|
}
|
||||||
context.update(self.admin_site.each_context(request))
|
|
||||||
|
|
||||||
request.current_app = self.admin_site.name
|
request.current_app = self.admin_site.name
|
||||||
|
|
||||||
|
|
|
@ -75,9 +75,10 @@ class ModelBackend:
|
||||||
if not user_obj.is_active or user_obj.is_anonymous or obj is not None:
|
if not user_obj.is_active or user_obj.is_anonymous or obj is not None:
|
||||||
return set()
|
return set()
|
||||||
if not hasattr(user_obj, '_perm_cache'):
|
if not hasattr(user_obj, '_perm_cache'):
|
||||||
user_obj._perm_cache = set()
|
user_obj._perm_cache = {
|
||||||
user_obj._perm_cache.update(self.get_user_permissions(user_obj))
|
*self.get_user_permissions(user_obj),
|
||||||
user_obj._perm_cache.update(self.get_group_permissions(user_obj))
|
*self.get_group_permissions(user_obj),
|
||||||
|
}
|
||||||
return user_obj._perm_cache
|
return user_obj._perm_cache
|
||||||
|
|
||||||
def has_perm(self, user_obj, perm, obj=None):
|
def has_perm(self, user_obj, perm, obj=None):
|
||||||
|
|
|
@ -299,9 +299,8 @@ class PasswordResetForm(forms.Form):
|
||||||
'user': user,
|
'user': user,
|
||||||
'token': token_generator.make_token(user),
|
'token': token_generator.make_token(user),
|
||||||
'protocol': 'https' if use_https else 'http',
|
'protocol': 'https' if use_https else 'http',
|
||||||
|
**(extra_email_context or {}),
|
||||||
}
|
}
|
||||||
if extra_email_context is not None:
|
|
||||||
context.update(extra_email_context)
|
|
||||||
self.send_mail(
|
self.send_mail(
|
||||||
subject_template_name, email_template_name, context, from_email,
|
subject_template_name, email_template_name, context, from_email,
|
||||||
email, html_email_template_name=html_email_template_name,
|
email, html_email_template_name=html_email_template_name,
|
||||||
|
@ -357,9 +356,10 @@ class PasswordChangeForm(SetPasswordForm):
|
||||||
A form that lets a user change their password by entering their old
|
A form that lets a user change their password by entering their old
|
||||||
password.
|
password.
|
||||||
"""
|
"""
|
||||||
error_messages = dict(SetPasswordForm.error_messages, **{
|
error_messages = {
|
||||||
|
**SetPasswordForm.error_messages,
|
||||||
'password_incorrect': _("Your old password was entered incorrectly. Please enter it again."),
|
'password_incorrect': _("Your old password was entered incorrectly. Please enter it again."),
|
||||||
})
|
}
|
||||||
old_password = forms.CharField(
|
old_password = forms.CharField(
|
||||||
label=_("Old password"),
|
label=_("Old password"),
|
||||||
strip=False,
|
strip=False,
|
||||||
|
|
|
@ -31,9 +31,7 @@ class SuccessURLAllowedHostsMixin:
|
||||||
success_url_allowed_hosts = set()
|
success_url_allowed_hosts = set()
|
||||||
|
|
||||||
def get_success_url_allowed_hosts(self):
|
def get_success_url_allowed_hosts(self):
|
||||||
allowed_hosts = {self.request.get_host()}
|
return {self.request.get_host(), *self.success_url_allowed_hosts}
|
||||||
allowed_hosts.update(self.success_url_allowed_hosts)
|
|
||||||
return allowed_hosts
|
|
||||||
|
|
||||||
|
|
||||||
class LoginView(SuccessURLAllowedHostsMixin, FormView):
|
class LoginView(SuccessURLAllowedHostsMixin, FormView):
|
||||||
|
@ -98,9 +96,8 @@ class LoginView(SuccessURLAllowedHostsMixin, FormView):
|
||||||
self.redirect_field_name: self.get_redirect_url(),
|
self.redirect_field_name: self.get_redirect_url(),
|
||||||
'site': current_site,
|
'site': current_site,
|
||||||
'site_name': current_site.name,
|
'site_name': current_site.name,
|
||||||
|
**(self.extra_context or {})
|
||||||
})
|
})
|
||||||
if self.extra_context is not None:
|
|
||||||
context.update(self.extra_context)
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,9 +155,8 @@ class LogoutView(SuccessURLAllowedHostsMixin, TemplateView):
|
||||||
'site': current_site,
|
'site': current_site,
|
||||||
'site_name': current_site.name,
|
'site_name': current_site.name,
|
||||||
'title': _('Logged out'),
|
'title': _('Logged out'),
|
||||||
|
**(self.extra_context or {})
|
||||||
})
|
})
|
||||||
if self.extra_context is not None:
|
|
||||||
context.update(self.extra_context)
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -201,9 +197,10 @@ class PasswordContextMixin:
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['title'] = self.title
|
context.update({
|
||||||
if self.extra_context is not None:
|
'title': self.title,
|
||||||
context.update(self.extra_context)
|
**(self.extra_context or {})
|
||||||
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -92,11 +92,7 @@ class GenericInlineModelAdmin(InlineModelAdmin):
|
||||||
fields = kwargs.pop('fields')
|
fields = kwargs.pop('fields')
|
||||||
else:
|
else:
|
||||||
fields = flatten_fieldsets(self.get_fieldsets(request, obj))
|
fields = flatten_fieldsets(self.get_fieldsets(request, obj))
|
||||||
if self.exclude is None:
|
exclude = [*(self.exclude or []), *self.get_readonly_fields(request, obj)]
|
||||||
exclude = []
|
|
||||||
else:
|
|
||||||
exclude = list(self.exclude)
|
|
||||||
exclude.extend(self.get_readonly_fields(request, obj))
|
|
||||||
if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
|
if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
|
||||||
# Take the custom ModelForm's Meta.exclude into account only if the
|
# Take the custom ModelForm's Meta.exclude into account only if the
|
||||||
# GenericInlineModelAdmin doesn't define its own.
|
# GenericInlineModelAdmin doesn't define its own.
|
||||||
|
@ -104,20 +100,20 @@ class GenericInlineModelAdmin(InlineModelAdmin):
|
||||||
exclude = exclude or None
|
exclude = exclude or None
|
||||||
can_delete = self.can_delete and self.has_delete_permission(request, obj)
|
can_delete = self.can_delete and self.has_delete_permission(request, obj)
|
||||||
defaults = {
|
defaults = {
|
||||||
"ct_field": self.ct_field,
|
'ct_field': self.ct_field,
|
||||||
"fk_field": self.ct_fk_field,
|
'fk_field': self.ct_fk_field,
|
||||||
"form": self.form,
|
'form': self.form,
|
||||||
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
|
'formfield_callback': partial(self.formfield_for_dbfield, request=request),
|
||||||
"formset": self.formset,
|
'formset': self.formset,
|
||||||
"extra": self.get_extra(request, obj),
|
'extra': self.get_extra(request, obj),
|
||||||
"can_delete": can_delete,
|
'can_delete': can_delete,
|
||||||
"can_order": False,
|
'can_order': False,
|
||||||
"fields": fields,
|
'fields': fields,
|
||||||
"min_num": self.get_min_num(request, obj),
|
'min_num': self.get_min_num(request, obj),
|
||||||
"max_num": self.get_max_num(request, obj),
|
'max_num': self.get_max_num(request, obj),
|
||||||
"exclude": exclude
|
'exclude': exclude,
|
||||||
|
**kwargs,
|
||||||
}
|
}
|
||||||
defaults.update(kwargs)
|
|
||||||
|
|
||||||
if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
|
if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
|
||||||
defaults['fields'] = ALL_FIELDS
|
defaults['fields'] = ALL_FIELDS
|
||||||
|
|
|
@ -72,11 +72,11 @@ class GenericForeignKey(FieldCacheMixin):
|
||||||
return '%s.%s.%s' % (app, model._meta.object_name, self.name)
|
return '%s.%s.%s' % (app, model._meta.object_name, self.name)
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = []
|
return [
|
||||||
errors.extend(self._check_field_name())
|
*self._check_field_name(),
|
||||||
errors.extend(self._check_object_id_field())
|
*self._check_object_id_field(),
|
||||||
errors.extend(self._check_content_type_field())
|
*self._check_content_type_field(),
|
||||||
return errors
|
]
|
||||||
|
|
||||||
def _check_field_name(self):
|
def _check_field_name(self):
|
||||||
if self.name.endswith("_"):
|
if self.name.endswith("_"):
|
||||||
|
@ -308,9 +308,10 @@ class GenericRelation(ForeignObject):
|
||||||
self.for_concrete_model = for_concrete_model
|
self.for_concrete_model = for_concrete_model
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_generic_foreign_key_existence())
|
*super().check(**kwargs),
|
||||||
return errors
|
*self._check_generic_foreign_key_existence(),
|
||||||
|
]
|
||||||
|
|
||||||
def _is_matching_generic_foreign_key(self, field):
|
def _is_matching_generic_foreign_key(self, field):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -63,11 +63,7 @@ def generic_inlineformset_factory(model, form=ModelForm,
|
||||||
if not isinstance(ct_field, models.ForeignKey) or ct_field.remote_field.model != ContentType:
|
if not isinstance(ct_field, models.ForeignKey) or ct_field.remote_field.model != ContentType:
|
||||||
raise Exception("fk_name '%s' is not a ForeignKey to ContentType" % ct_field)
|
raise Exception("fk_name '%s' is not a ForeignKey to ContentType" % ct_field)
|
||||||
fk_field = opts.get_field(fk_field) # let the exception propagate
|
fk_field = opts.get_field(fk_field) # let the exception propagate
|
||||||
if exclude is not None:
|
exclude = [*(exclude or []), ct_field.name, fk_field.name]
|
||||||
exclude = list(exclude)
|
|
||||||
exclude.extend([ct_field.name, fk_field.name])
|
|
||||||
else:
|
|
||||||
exclude = [ct_field.name, fk_field.name]
|
|
||||||
FormSet = modelformset_factory(
|
FormSet = modelformset_factory(
|
||||||
model, form=form, formfield_callback=formfield_callback,
|
model, form=form, formfield_callback=formfield_callback,
|
||||||
formset=formset, extra=extra, can_delete=can_delete,
|
formset=formset, extra=extra, can_delete=can_delete,
|
||||||
|
|
|
@ -9,16 +9,16 @@ class GeoFlexibleFieldLookupDict(FlexibleFieldLookupDict):
|
||||||
Sublcass that includes updates the `base_data_types_reverse` dict
|
Sublcass that includes updates the `base_data_types_reverse` dict
|
||||||
for geometry field types.
|
for geometry field types.
|
||||||
"""
|
"""
|
||||||
base_data_types_reverse = FlexibleFieldLookupDict.base_data_types_reverse.copy()
|
base_data_types_reverse = {
|
||||||
base_data_types_reverse.update(
|
**FlexibleFieldLookupDict.base_data_types_reverse,
|
||||||
{'point': 'GeometryField',
|
'point': 'GeometryField',
|
||||||
'linestring': 'GeometryField',
|
'linestring': 'GeometryField',
|
||||||
'polygon': 'GeometryField',
|
'polygon': 'GeometryField',
|
||||||
'multipoint': 'GeometryField',
|
'multipoint': 'GeometryField',
|
||||||
'multilinestring': 'GeometryField',
|
'multilinestring': 'GeometryField',
|
||||||
'multipolygon': 'GeometryField',
|
'multipolygon': 'GeometryField',
|
||||||
'geometrycollection': 'GeometryField',
|
'geometrycollection': 'GeometryField',
|
||||||
})
|
}
|
||||||
|
|
||||||
|
|
||||||
class SpatiaLiteIntrospection(DatabaseIntrospection):
|
class SpatiaLiteIntrospection(DatabaseIntrospection):
|
||||||
|
|
|
@ -250,11 +250,12 @@ class GeometryField(BaseSpatialField):
|
||||||
setattr(cls, self.attname, SpatialProxy(self.geom_class or GEOSGeometry, self, load_func=GEOSGeometry))
|
setattr(cls, self.attname, SpatialProxy(self.geom_class or GEOSGeometry, self, load_func=GEOSGeometry))
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': self.form_class,
|
defaults = {
|
||||||
'geom_type': self.geom_type,
|
'form_class': self.form_class,
|
||||||
'srid': self.srid,
|
'geom_type': self.geom_type,
|
||||||
}
|
'srid': self.srid,
|
||||||
defaults.update(kwargs)
|
**kwargs,
|
||||||
|
}
|
||||||
if self.dim > 2 and not getattr(defaults['form_class'].widget, 'supports_3d', False):
|
if self.dim > 2 and not getattr(defaults['form_class'].widget, 'supports_3d', False):
|
||||||
defaults.setdefault('widget', forms.Textarea)
|
defaults.setdefault('widget', forms.Textarea)
|
||||||
return super().formfield(**defaults)
|
return super().formfield(**defaults)
|
||||||
|
|
|
@ -415,12 +415,10 @@ class SnapToGrid(SQLiteDecimalToFloatMixin, GeomOutputGeoFunc):
|
||||||
)
|
)
|
||||||
elif nargs == 4:
|
elif nargs == 4:
|
||||||
# Reverse origin and size param ordering
|
# Reverse origin and size param ordering
|
||||||
expressions.extend(
|
expressions += [
|
||||||
[self._handle_param(arg, '', NUMERIC_TYPES) for arg in args[2:]]
|
*(self._handle_param(arg, '', NUMERIC_TYPES) for arg in args[2:]),
|
||||||
)
|
*(self._handle_param(arg, '', NUMERIC_TYPES) for arg in args[0:2]),
|
||||||
expressions.extend(
|
]
|
||||||
[self._handle_param(arg, '', NUMERIC_TYPES) for arg in args[0:2]]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise ValueError('Must provide 1, 2, or 4 arguments to `SnapToGrid`.')
|
raise ValueError('Must provide 1, 2, or 4 arguments to `SnapToGrid`.')
|
||||||
super().__init__(*expressions, **extra)
|
super().__init__(*expressions, **extra)
|
||||||
|
|
|
@ -78,8 +78,7 @@ class GISLookup(Lookup):
|
||||||
rhs_sql, rhs_params = self.process_rhs(compiler, connection)
|
rhs_sql, rhs_params = self.process_rhs(compiler, connection)
|
||||||
sql_params.extend(rhs_params)
|
sql_params.extend(rhs_params)
|
||||||
|
|
||||||
template_params = {'lhs': lhs_sql, 'rhs': rhs_sql, 'value': '%s'}
|
template_params = {'lhs': lhs_sql, 'rhs': rhs_sql, 'value': '%s', **self.template_params}
|
||||||
template_params.update(self.template_params)
|
|
||||||
rhs_op = self.get_rhs_op(connection, rhs_sql)
|
rhs_op = self.get_rhs_op(connection, rhs_sql)
|
||||||
return rhs_op.as_sql(connection, self, template_params, sql_params)
|
return rhs_op.as_sql(connection, self, template_params, sql_params)
|
||||||
|
|
||||||
|
|
|
@ -60,19 +60,15 @@ class BaseGeometryWidget(Widget):
|
||||||
value.srid, self.map_srid, err
|
value.srid, self.map_srid, err
|
||||||
)
|
)
|
||||||
|
|
||||||
if attrs is None:
|
context.update(self.build_attrs(self.attrs, {
|
||||||
attrs = {}
|
|
||||||
|
|
||||||
build_attrs_kwargs = {
|
|
||||||
'name': name,
|
'name': name,
|
||||||
'module': 'geodjango_%s' % name.replace('-', '_'), # JS-safe
|
'module': 'geodjango_%s' % name.replace('-', '_'), # JS-safe
|
||||||
'serialized': self.serialize(value),
|
'serialized': self.serialize(value),
|
||||||
'geom_type': gdal.OGRGeomType(self.attrs['geom_type']),
|
'geom_type': gdal.OGRGeomType(self.attrs['geom_type']),
|
||||||
'STATIC_URL': settings.STATIC_URL,
|
'STATIC_URL': settings.STATIC_URL,
|
||||||
'LANGUAGE_BIDI': translation.get_language_bidi(),
|
'LANGUAGE_BIDI': translation.get_language_bidi(),
|
||||||
}
|
**(attrs or {}),
|
||||||
build_attrs_kwargs.update(attrs)
|
}))
|
||||||
context.update(self.build_attrs(self.attrs, build_attrs_kwargs))
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ class CsOperation(GEOSFuncFactory):
|
||||||
else:
|
else:
|
||||||
argtypes = [CS_PTR, c_uint, dbl_param]
|
argtypes = [CS_PTR, c_uint, dbl_param]
|
||||||
|
|
||||||
super().__init__(*args, **dict(kwargs, errcheck=errcheck, argtypes=argtypes))
|
super().__init__(*args, **{**kwargs, 'errcheck': errcheck, 'argtypes': argtypes})
|
||||||
|
|
||||||
|
|
||||||
class CsOutput(GEOSFuncFactory):
|
class CsOutput(GEOSFuncFactory):
|
||||||
|
|
|
@ -55,9 +55,7 @@ class GEOSFunc:
|
||||||
return self.cfunc.argtypes
|
return self.cfunc.argtypes
|
||||||
|
|
||||||
def _set_argtypes(self, argtypes):
|
def _set_argtypes(self, argtypes):
|
||||||
new_argtypes = [CONTEXT_PTR]
|
self.cfunc.argtypes = [CONTEXT_PTR, *argtypes]
|
||||||
new_argtypes.extend(argtypes)
|
|
||||||
self.cfunc.argtypes = new_argtypes
|
|
||||||
|
|
||||||
argtypes = property(_get_argtypes, _set_argtypes)
|
argtypes = property(_get_argtypes, _set_argtypes)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ def get_level_tags():
|
||||||
"""
|
"""
|
||||||
Return the message level tags.
|
Return the message level tags.
|
||||||
"""
|
"""
|
||||||
level_tags = constants.DEFAULT_TAGS.copy()
|
return {
|
||||||
level_tags.update(getattr(settings, 'MESSAGE_TAGS', {}))
|
**constants.DEFAULT_TAGS,
|
||||||
return level_tags
|
**getattr(settings, 'MESSAGE_TAGS', {}),
|
||||||
|
}
|
||||||
|
|
|
@ -183,13 +183,12 @@ class ArrayField(CheckFieldDefaultMixin, Field):
|
||||||
)
|
)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'form_class': SimpleArrayField,
|
'form_class': SimpleArrayField,
|
||||||
'base_field': self.base_field.formfield(),
|
'base_field': self.base_field.formfield(),
|
||||||
'max_length': self.size,
|
'max_length': self.size,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
||||||
|
|
||||||
@ArrayField.register_lookup
|
@ArrayField.register_lookup
|
||||||
|
|
|
@ -44,11 +44,10 @@ class HStoreField(Field):
|
||||||
return json.dumps(self.value_from_object(obj))
|
return json.dumps(self.value_from_object(obj))
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'form_class': forms.HStoreField,
|
'form_class': forms.HStoreField,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
||||||
def get_prep_value(self, value):
|
def get_prep_value(self, value):
|
||||||
value = super().get_prep_value(value)
|
value = super().get_prep_value(value)
|
||||||
|
|
|
@ -77,9 +77,10 @@ class JSONField(CheckFieldDefaultMixin, Field):
|
||||||
return self.value_from_object(obj)
|
return self.value_from_object(obj)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.JSONField}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.JSONField,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
JSONField.register_lookup(lookups.DataContains)
|
JSONField.register_lookup(lookups.DataContains)
|
||||||
|
|
|
@ -135,7 +135,7 @@ class SplitArrayWidget(forms.Widget):
|
||||||
except IndexError:
|
except IndexError:
|
||||||
widget_value = None
|
widget_value = None
|
||||||
if id_:
|
if id_:
|
||||||
final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
|
final_attrs = {**final_attrs, 'id': '%s_%s' % (id_, i)}
|
||||||
context['widget']['subwidgets'].append(
|
context['widget']['subwidgets'].append(
|
||||||
self.widget.get_context(name + '_%s' % i, widget_value, final_attrs)['widget']
|
self.widget.get_context(name + '_%s' % i, widget_value, final_attrs)['widget']
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,7 +22,7 @@ def prefix_validation_error(error, prefix, code, params):
|
||||||
SimpleLazyObject(lambda: error.message % error_params),
|
SimpleLazyObject(lambda: error.message % error_params),
|
||||||
),
|
),
|
||||||
code=code,
|
code=code,
|
||||||
params=dict(error_params, **params),
|
params={**error_params, **params},
|
||||||
)
|
)
|
||||||
return ValidationError([
|
return ValidationError([
|
||||||
prefix_validation_error(e, prefix, code, params) for e in error.error_list
|
prefix_validation_error(e, prefix, code, params) for e in error.error_list
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import copy
|
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import (
|
from django.core.validators import (
|
||||||
MaxLengthValidator, MaxValueValidator, MinLengthValidator,
|
MaxLengthValidator, MaxValueValidator, MinLengthValidator,
|
||||||
|
@ -37,8 +35,7 @@ class KeysValidator:
|
||||||
self.keys = set(keys)
|
self.keys = set(keys)
|
||||||
self.strict = strict
|
self.strict = strict
|
||||||
if messages is not None:
|
if messages is not None:
|
||||||
self.messages = copy.copy(self.messages)
|
self.messages = {**self.messages, **messages}
|
||||||
self.messages.update(messages)
|
|
||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
keys = set(value)
|
keys = set(value)
|
||||||
|
|
|
@ -44,8 +44,7 @@ def _create_cache(backend, **kwargs):
|
||||||
location = kwargs.pop('LOCATION', '')
|
location = kwargs.pop('LOCATION', '')
|
||||||
params = kwargs
|
params = kwargs
|
||||||
else:
|
else:
|
||||||
params = conf.copy()
|
params = {**conf, **kwargs}
|
||||||
params.update(kwargs)
|
|
||||||
backend = params.pop('BACKEND')
|
backend = params.pop('BACKEND')
|
||||||
location = params.pop('LOCATION', '')
|
location = params.pop('LOCATION', '')
|
||||||
backend_cls = import_string(backend)
|
backend_cls = import_string(backend)
|
||||||
|
|
|
@ -96,7 +96,7 @@ def response_for_exception(request, exc):
|
||||||
def get_exception_response(request, resolver, status_code, exception, sender=None):
|
def get_exception_response(request, resolver, status_code, exception, sender=None):
|
||||||
try:
|
try:
|
||||||
callback, param_dict = resolver.resolve_error_handler(status_code)
|
callback, param_dict = resolver.resolve_error_handler(status_code)
|
||||||
response = callback(request, **dict(param_dict, exception=exception))
|
response = callback(request, **{**param_dict, 'exception': exception})
|
||||||
except Exception:
|
except Exception:
|
||||||
signals.got_request_exception.send(sender=sender, request=request)
|
signals.got_request_exception.send(sender=sender, request=request)
|
||||||
response = handle_uncaught_exception(request, resolver, sys.exc_info())
|
response = handle_uncaught_exception(request, resolver, sys.exc_info())
|
||||||
|
|
|
@ -104,13 +104,14 @@ class TemplateCommand(BaseCommand):
|
||||||
camel_case_name = 'camel_case_%s_name' % app_or_project
|
camel_case_name = 'camel_case_%s_name' % app_or_project
|
||||||
camel_case_value = ''.join(x for x in name.title() if x != '_')
|
camel_case_value = ''.join(x for x in name.title() if x != '_')
|
||||||
|
|
||||||
context = Context(dict(options, **{
|
context = Context({
|
||||||
|
**options,
|
||||||
base_name: name,
|
base_name: name,
|
||||||
base_directory: top_dir,
|
base_directory: top_dir,
|
||||||
camel_case_name: camel_case_value,
|
camel_case_name: camel_case_value,
|
||||||
'docs_version': get_docs_version(),
|
'docs_version': get_docs_version(),
|
||||||
'django_version': django.__version__,
|
'django_version': django.__version__,
|
||||||
}), autoescape=False)
|
}, autoescape=False)
|
||||||
|
|
||||||
# Setup a stub settings environment for template rendering
|
# Setup a stub settings environment for template rendering
|
||||||
if not settings.configured:
|
if not settings.configured:
|
||||||
|
|
|
@ -39,10 +39,10 @@ if version < (1, 3, 3):
|
||||||
# MySQLdb returns TIME columns as timedelta -- they are more like timedelta in
|
# MySQLdb returns TIME columns as timedelta -- they are more like timedelta in
|
||||||
# terms of actual behavior as they are signed and include days -- and Django
|
# terms of actual behavior as they are signed and include days -- and Django
|
||||||
# expects time.
|
# expects time.
|
||||||
django_conversions = conversions.copy()
|
django_conversions = {
|
||||||
django_conversions.update({
|
**conversions,
|
||||||
FIELD_TYPE.TIME: backend_utils.typecast_time,
|
**{FIELD_TYPE.TIME: backend_utils.typecast_time},
|
||||||
})
|
}
|
||||||
|
|
||||||
# This should match the numerical portion of the version numbers (we can treat
|
# This should match the numerical portion of the version numbers (we can treat
|
||||||
# versions like 5.0.24 and 5.0.24a as the same).
|
# versions like 5.0.24 and 5.0.24a as the same).
|
||||||
|
|
|
@ -10,11 +10,11 @@ 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(
|
integer_field_ranges = {
|
||||||
BaseDatabaseOperations.integer_field_ranges,
|
**BaseDatabaseOperations.integer_field_ranges,
|
||||||
PositiveSmallIntegerField=(0, 65535),
|
'PositiveSmallIntegerField': (0, 65535),
|
||||||
PositiveIntegerField=(0, 4294967295),
|
'PositiveIntegerField': (0, 4294967295),
|
||||||
)
|
}
|
||||||
cast_data_types = {
|
cast_data_types = {
|
||||||
'CharField': 'char(%(max_length)s)',
|
'CharField': 'char(%(max_length)s)',
|
||||||
'IntegerField': 'signed integer',
|
'IntegerField': 'signed integer',
|
||||||
|
|
|
@ -136,15 +136,15 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||||
'iendswith': "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
|
'iendswith': "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
|
||||||
}
|
}
|
||||||
|
|
||||||
_likec_operators = _standard_operators.copy()
|
_likec_operators = {
|
||||||
_likec_operators.update({
|
**_standard_operators,
|
||||||
'contains': "LIKEC %s ESCAPE '\\'",
|
'contains': "LIKEC %s ESCAPE '\\'",
|
||||||
'icontains': "LIKEC UPPER(%s) ESCAPE '\\'",
|
'icontains': "LIKEC UPPER(%s) ESCAPE '\\'",
|
||||||
'startswith': "LIKEC %s ESCAPE '\\'",
|
'startswith': "LIKEC %s ESCAPE '\\'",
|
||||||
'endswith': "LIKEC %s ESCAPE '\\'",
|
'endswith': "LIKEC %s ESCAPE '\\'",
|
||||||
'istartswith': "LIKEC UPPER(%s) ESCAPE '\\'",
|
'istartswith': "LIKEC UPPER(%s) ESCAPE '\\'",
|
||||||
'iendswith': "LIKEC UPPER(%s) ESCAPE '\\'",
|
'iendswith': "LIKEC UPPER(%s) ESCAPE '\\'",
|
||||||
})
|
}
|
||||||
|
|
||||||
# The patterns below are used to generate SQL pattern lookup clauses when
|
# The patterns below are used to generate SQL pattern lookup clauses when
|
||||||
# the right-hand side of the lookup isn't a raw string (it might be an expression
|
# the right-hand side of the lookup isn't a raw string (it might be an expression
|
||||||
|
|
|
@ -23,8 +23,7 @@ class DatabaseCreation(BaseDatabaseCreation):
|
||||||
settings_dict = settings.DATABASES[self.connection.alias]
|
settings_dict = settings.DATABASES[self.connection.alias]
|
||||||
user = settings_dict.get('SAVED_USER') or settings_dict['USER']
|
user = settings_dict.get('SAVED_USER') or settings_dict['USER']
|
||||||
password = settings_dict.get('SAVED_PASSWORD') or settings_dict['PASSWORD']
|
password = settings_dict.get('SAVED_PASSWORD') or settings_dict['PASSWORD']
|
||||||
settings_dict = settings_dict.copy()
|
settings_dict = {**settings_dict, 'USER': user, 'PASSWORD': password}
|
||||||
settings_dict.update(USER=user, PASSWORD=password)
|
|
||||||
DatabaseWrapper = type(self.connection)
|
DatabaseWrapper = type(self.connection)
|
||||||
return DatabaseWrapper(settings_dict, alias=self.connection.alias)
|
return DatabaseWrapper(settings_dict, alias=self.connection.alias)
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
'PositiveSmallIntegerField': (0, 99999999999),
|
'PositiveSmallIntegerField': (0, 99999999999),
|
||||||
'PositiveIntegerField': (0, 99999999999),
|
'PositiveIntegerField': (0, 99999999999),
|
||||||
}
|
}
|
||||||
set_operators = dict(BaseDatabaseOperations.set_operators, difference='MINUS')
|
set_operators = {**BaseDatabaseOperations.set_operators, 'difference': 'MINUS'}
|
||||||
|
|
||||||
# TODO: colorize this SQL code with style.SQL_KEYWORD(), etc.
|
# TODO: colorize this SQL code with style.SQL_KEYWORD(), etc.
|
||||||
_sequence_reset_sql = """
|
_sequence_reset_sql = """
|
||||||
|
|
|
@ -151,8 +151,8 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||||
"Please supply the NAME value.")
|
"Please supply the NAME value.")
|
||||||
conn_params = {
|
conn_params = {
|
||||||
'database': settings_dict['NAME'] or 'postgres',
|
'database': settings_dict['NAME'] or 'postgres',
|
||||||
|
**settings_dict['OPTIONS'],
|
||||||
}
|
}
|
||||||
conn_params.update(settings_dict['OPTIONS'])
|
|
||||||
conn_params.pop('isolation_level', None)
|
conn_params.pop('isolation_level', None)
|
||||||
if settings_dict['USER']:
|
if settings_dict['USER']:
|
||||||
conn_params['user'] = settings_dict['USER']
|
conn_params['user'] = settings_dict['USER']
|
||||||
|
|
|
@ -137,8 +137,8 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'database': settings_dict['NAME'],
|
'database': settings_dict['NAME'],
|
||||||
'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
|
'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
|
||||||
|
**settings_dict['OPTIONS'],
|
||||||
}
|
}
|
||||||
kwargs.update(settings_dict['OPTIONS'])
|
|
||||||
# Always allow the underlying SQLite connection to be shareable
|
# Always allow the underlying SQLite connection to be shareable
|
||||||
# between multiple threads. The safe-guarding will be handled at a
|
# between multiple threads. The safe-guarding will be handled at a
|
||||||
# higher level by the `BaseDatabaseWrapper.allow_thread_sharing`
|
# higher level by the `BaseDatabaseWrapper.allow_thread_sharing`
|
||||||
|
|
|
@ -147,13 +147,11 @@ class CreateModel(ModelOperation):
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
elif isinstance(operation, AlterModelOptions) and self.name_lower == operation.name_lower:
|
elif isinstance(operation, AlterModelOptions) and self.name_lower == operation.name_lower:
|
||||||
new_options = self.options.copy()
|
|
||||||
new_options.update(operation.options)
|
|
||||||
return [
|
return [
|
||||||
CreateModel(
|
CreateModel(
|
||||||
self.name,
|
self.name,
|
||||||
fields=self.fields,
|
fields=self.fields,
|
||||||
options=new_options,
|
options={**self.options, **operation.options},
|
||||||
bases=self.bases,
|
bases=self.bases,
|
||||||
managers=self.managers,
|
managers=self.managers,
|
||||||
),
|
),
|
||||||
|
@ -690,8 +688,7 @@ class AlterModelOptions(ModelOptionOperation):
|
||||||
|
|
||||||
def state_forwards(self, app_label, state):
|
def state_forwards(self, app_label, state):
|
||||||
model_state = state.models[app_label, self.name_lower]
|
model_state = state.models[app_label, self.name_lower]
|
||||||
model_state.options = dict(model_state.options)
|
model_state.options = {**model_state.options, **self.options}
|
||||||
model_state.options.update(self.options)
|
|
||||||
for key in self.ALTER_OPTION_KEYS:
|
for key in self.ALTER_OPTION_KEYS:
|
||||||
if key not in self.options:
|
if key not in self.options:
|
||||||
model_state.options.pop(key, False)
|
model_state.options.pop(key, False)
|
||||||
|
|
|
@ -119,9 +119,8 @@ class EnumSerializer(BaseSerializer):
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
enum_class = self.value.__class__
|
enum_class = self.value.__class__
|
||||||
module = enum_class.__module__
|
module = enum_class.__module__
|
||||||
imports = {"import %s" % module}
|
|
||||||
v_string, v_imports = serializer_factory(self.value.value).serialize()
|
v_string, v_imports = serializer_factory(self.value.value).serialize()
|
||||||
imports.update(v_imports)
|
imports = {'import %s' % module, *v_imports}
|
||||||
return "%s.%s(%s)" % (module, enum_class.__name__, v_string), imports
|
return "%s.%s(%s)" % (module, enum_class.__name__, v_string), imports
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,15 +160,12 @@ class FunctionTypeSerializer(BaseSerializer):
|
||||||
|
|
||||||
class FunctoolsPartialSerializer(BaseSerializer):
|
class FunctoolsPartialSerializer(BaseSerializer):
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
imports = {'import functools'}
|
|
||||||
# Serialize functools.partial() arguments
|
# Serialize functools.partial() arguments
|
||||||
func_string, func_imports = serializer_factory(self.value.func).serialize()
|
func_string, func_imports = serializer_factory(self.value.func).serialize()
|
||||||
args_string, args_imports = serializer_factory(self.value.args).serialize()
|
args_string, args_imports = serializer_factory(self.value.args).serialize()
|
||||||
keywords_string, keywords_imports = serializer_factory(self.value.keywords).serialize()
|
keywords_string, keywords_imports = serializer_factory(self.value.keywords).serialize()
|
||||||
# Add any imports needed by arguments
|
# Add any imports needed by arguments
|
||||||
imports.update(func_imports)
|
imports = {'import functools', *func_imports, *args_imports, *keywords_imports}
|
||||||
imports.update(args_imports)
|
|
||||||
imports.update(keywords_imports)
|
|
||||||
return (
|
return (
|
||||||
'functools.%s(%s, *%s, **%s)' % (
|
'functools.%s(%s, *%s, **%s)' % (
|
||||||
self.value.__class__.__name__,
|
self.value.__class__.__name__,
|
||||||
|
@ -221,14 +217,12 @@ class OperationSerializer(BaseSerializer):
|
||||||
|
|
||||||
class RegexSerializer(BaseSerializer):
|
class RegexSerializer(BaseSerializer):
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
imports = {"import re"}
|
|
||||||
regex_pattern, pattern_imports = serializer_factory(self.value.pattern).serialize()
|
regex_pattern, pattern_imports = serializer_factory(self.value.pattern).serialize()
|
||||||
# Turn off default implicit flags (e.g. re.U) because regexes with the
|
# Turn off default implicit flags (e.g. re.U) because regexes with the
|
||||||
# same implicit and explicit flags aren't equal.
|
# same implicit and explicit flags aren't equal.
|
||||||
flags = self.value.flags ^ re.compile('').flags
|
flags = self.value.flags ^ re.compile('').flags
|
||||||
regex_flags, flag_imports = serializer_factory(flags).serialize()
|
regex_flags, flag_imports = serializer_factory(flags).serialize()
|
||||||
imports.update(pattern_imports)
|
imports = {'import re', *pattern_imports, *flag_imports}
|
||||||
imports.update(flag_imports)
|
|
||||||
args = [regex_pattern]
|
args = [regex_pattern]
|
||||||
if flags:
|
if flags:
|
||||||
args.append(regex_flags)
|
args.append(regex_flags)
|
||||||
|
|
|
@ -553,8 +553,7 @@ class ModelState:
|
||||||
def render(self, apps):
|
def render(self, apps):
|
||||||
"""Create a Model object from our current state into the given apps."""
|
"""Create a Model object from our current state into the given apps."""
|
||||||
# First, make a Meta object
|
# First, make a Meta object
|
||||||
meta_contents = {'app_label': self.app_label, "apps": apps}
|
meta_contents = {'app_label': self.app_label, 'apps': apps, **self.options}
|
||||||
meta_contents.update(self.options)
|
|
||||||
meta = type("Meta", (), meta_contents)
|
meta = type("Meta", (), meta_contents)
|
||||||
# Then, work out our bases
|
# Then, work out our bases
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -121,8 +121,7 @@ class Count(Aggregate):
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_repr_options(self):
|
def _get_repr_options(self):
|
||||||
options = super()._get_repr_options()
|
return {**super()._get_repr_options(), 'distinct': self.extra['distinct'] != ''}
|
||||||
return dict(options, distinct=self.extra['distinct'] != '')
|
|
||||||
|
|
||||||
def convert_value(self, value, expression, connection):
|
def convert_value(self, value, expression, connection):
|
||||||
return 0 if value is None else value
|
return 0 if value is None else value
|
||||||
|
@ -147,8 +146,7 @@ class StdDev(Aggregate):
|
||||||
super().__init__(expression, **extra)
|
super().__init__(expression, **extra)
|
||||||
|
|
||||||
def _get_repr_options(self):
|
def _get_repr_options(self):
|
||||||
options = super()._get_repr_options()
|
return {**super()._get_repr_options(), 'sample': self.function == 'STDDEV_SAMP'}
|
||||||
return dict(options, sample=self.function == 'STDDEV_SAMP')
|
|
||||||
|
|
||||||
|
|
||||||
class Sum(Aggregate):
|
class Sum(Aggregate):
|
||||||
|
@ -174,5 +172,4 @@ class Variance(Aggregate):
|
||||||
super().__init__(expression, **extra)
|
super().__init__(expression, **extra)
|
||||||
|
|
||||||
def _get_repr_options(self):
|
def _get_repr_options(self):
|
||||||
options = super()._get_repr_options()
|
return {**super()._get_repr_options(), 'sample': self.function == 'VAR_SAMP'}
|
||||||
return dict(options, sample=self.function == 'VAR_SAMP')
|
|
||||||
|
|
|
@ -1186,14 +1186,13 @@ class Model(metaclass=ModelBase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def check(cls, **kwargs):
|
def check(cls, **kwargs):
|
||||||
errors = []
|
errors = [*cls._check_swappable(), *cls._check_model(), *cls._check_managers(**kwargs)]
|
||||||
errors.extend(cls._check_swappable())
|
|
||||||
errors.extend(cls._check_model())
|
|
||||||
errors.extend(cls._check_managers(**kwargs))
|
|
||||||
if not cls._meta.swapped:
|
if not cls._meta.swapped:
|
||||||
errors.extend(cls._check_fields(**kwargs))
|
errors += [
|
||||||
errors.extend(cls._check_m2m_through_same_relationship())
|
*cls._check_fields(**kwargs),
|
||||||
errors.extend(cls._check_long_column_names())
|
*cls._check_m2m_through_same_relationship(),
|
||||||
|
*cls._check_long_column_names(),
|
||||||
|
]
|
||||||
clash_errors = (
|
clash_errors = (
|
||||||
cls._check_id_field() +
|
cls._check_id_field() +
|
||||||
cls._check_field_name_clashes() +
|
cls._check_field_name_clashes() +
|
||||||
|
@ -1204,9 +1203,11 @@ class Model(metaclass=ModelBase):
|
||||||
# clashes.
|
# clashes.
|
||||||
if not clash_errors:
|
if not clash_errors:
|
||||||
errors.extend(cls._check_column_name_clashes())
|
errors.extend(cls._check_column_name_clashes())
|
||||||
errors.extend(cls._check_index_together())
|
errors += [
|
||||||
errors.extend(cls._check_unique_together())
|
*cls._check_index_together(),
|
||||||
errors.extend(cls._check_ordering())
|
*cls._check_unique_together(),
|
||||||
|
*cls._check_ordering(),
|
||||||
|
]
|
||||||
|
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
|
@ -565,7 +565,7 @@ class Func(SQLiteNumericMixin, Expression):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
args = self.arg_joiner.join(str(arg) for arg in self.source_expressions)
|
args = self.arg_joiner.join(str(arg) for arg in self.source_expressions)
|
||||||
extra = dict(self.extra, **self._get_repr_options())
|
extra = {**self.extra, **self._get_repr_options()}
|
||||||
if extra:
|
if extra:
|
||||||
extra = ', '.join(str(key) + '=' + str(val) for key, val in sorted(extra.items()))
|
extra = ', '.join(str(key) + '=' + str(val) for key, val in sorted(extra.items()))
|
||||||
return "{}({}, {})".format(self.__class__.__name__, args, extra)
|
return "{}({}, {})".format(self.__class__.__name__, args, extra)
|
||||||
|
@ -596,8 +596,7 @@ class Func(SQLiteNumericMixin, Expression):
|
||||||
arg_sql, arg_params = compiler.compile(arg)
|
arg_sql, arg_params = compiler.compile(arg)
|
||||||
sql_parts.append(arg_sql)
|
sql_parts.append(arg_sql)
|
||||||
params.extend(arg_params)
|
params.extend(arg_params)
|
||||||
data = self.extra.copy()
|
data = {**self.extra, **extra_context}
|
||||||
data.update(**extra_context)
|
|
||||||
# Use the first supplied value in this order: the parameter to this
|
# Use the first supplied value in this order: the parameter to this
|
||||||
# method, a value supplied in __init__()'s **extra (the value in
|
# method, a value supplied in __init__()'s **extra (the value in
|
||||||
# `data`), or the value defined on the class.
|
# `data`), or the value defined on the class.
|
||||||
|
@ -921,8 +920,7 @@ class Case(Expression):
|
||||||
connection.ops.check_expression_support(self)
|
connection.ops.check_expression_support(self)
|
||||||
if not self.cases:
|
if not self.cases:
|
||||||
return compiler.compile(self.default)
|
return compiler.compile(self.default)
|
||||||
template_params = self.extra.copy()
|
template_params = {**self.extra, **extra_context}
|
||||||
template_params.update(extra_context)
|
|
||||||
case_parts = []
|
case_parts = []
|
||||||
sql_params = []
|
sql_params = []
|
||||||
for case in self.cases:
|
for case in self.cases:
|
||||||
|
@ -1017,8 +1015,7 @@ class Subquery(Expression):
|
||||||
|
|
||||||
def as_sql(self, compiler, connection, template=None, **extra_context):
|
def as_sql(self, compiler, connection, template=None, **extra_context):
|
||||||
connection.ops.check_expression_support(self)
|
connection.ops.check_expression_support(self)
|
||||||
template_params = self.extra.copy()
|
template_params = {**self.extra, **extra_context}
|
||||||
template_params.update(extra_context)
|
|
||||||
template_params['subquery'], sql_params = self.queryset.query.get_compiler(connection=connection).as_sql()
|
template_params['subquery'], sql_params = self.queryset.query.get_compiler(connection=connection).as_sql()
|
||||||
|
|
||||||
template = template or template_params.get('template', self.template)
|
template = template or template_params.get('template', self.template)
|
||||||
|
@ -1103,8 +1100,8 @@ class OrderBy(BaseExpression):
|
||||||
placeholders = {
|
placeholders = {
|
||||||
'expression': expression_sql,
|
'expression': expression_sql,
|
||||||
'ordering': 'DESC' if self.descending else 'ASC',
|
'ordering': 'DESC' if self.descending else 'ASC',
|
||||||
|
**extra_context,
|
||||||
}
|
}
|
||||||
placeholders.update(extra_context)
|
|
||||||
template = template or self.template
|
template = template or self.template
|
||||||
params *= template.count('%(expression)s')
|
params *= template.count('%(expression)s')
|
||||||
return (template % placeholders).rstrip(), params
|
return (template % placeholders).rstrip(), params
|
||||||
|
|
|
@ -2,7 +2,6 @@ import collections
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import decimal
|
import decimal
|
||||||
import itertools
|
|
||||||
import operator
|
import operator
|
||||||
import uuid
|
import uuid
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -199,15 +198,15 @@ class Field(RegisterLookupMixin):
|
||||||
return '<%s>' % path
|
return '<%s>' % path
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = []
|
return [
|
||||||
errors.extend(self._check_field_name())
|
*self._check_field_name(),
|
||||||
errors.extend(self._check_choices())
|
*self._check_choices(),
|
||||||
errors.extend(self._check_db_index())
|
*self._check_db_index(),
|
||||||
errors.extend(self._check_null_allowed_for_primary_keys())
|
*self._check_null_allowed_for_primary_keys(),
|
||||||
errors.extend(self._check_backend_specific_checks(**kwargs))
|
*self._check_backend_specific_checks(**kwargs),
|
||||||
errors.extend(self._check_validators())
|
*self._check_validators(),
|
||||||
errors.extend(self._check_deprecation_details())
|
*self._check_deprecation_details(),
|
||||||
return errors
|
]
|
||||||
|
|
||||||
def _check_field_name(self):
|
def _check_field_name(self):
|
||||||
"""
|
"""
|
||||||
|
@ -549,7 +548,7 @@ class Field(RegisterLookupMixin):
|
||||||
Some validators can't be created at field initialization time.
|
Some validators can't be created at field initialization time.
|
||||||
This method provides a way to delay their creation until required.
|
This method provides a way to delay their creation until required.
|
||||||
"""
|
"""
|
||||||
return list(itertools.chain(self.default_validators, self._validators))
|
return [*self.default_validators, *self._validators]
|
||||||
|
|
||||||
def run_validators(self, value):
|
def run_validators(self, value):
|
||||||
if value in self.empty_values:
|
if value in self.empty_values:
|
||||||
|
@ -886,9 +885,10 @@ class AutoField(Field):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_primary_key())
|
*super().check(**kwargs),
|
||||||
return errors
|
*self._check_primary_key(),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_primary_key(self):
|
def _check_primary_key(self):
|
||||||
if not self.primary_key:
|
if not self.primary_key:
|
||||||
|
@ -972,9 +972,10 @@ class BooleanField(Field):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_null(**kwargs))
|
*super().check(**kwargs),
|
||||||
return errors
|
*self._check_null(**kwargs),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_null(self, **kwargs):
|
def _check_null(self, **kwargs):
|
||||||
if getattr(self, 'null', False):
|
if getattr(self, 'null', False):
|
||||||
|
@ -1038,9 +1039,10 @@ class CharField(Field):
|
||||||
self.validators.append(validators.MaxLengthValidator(self.max_length))
|
self.validators.append(validators.MaxLengthValidator(self.max_length))
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_max_length_attribute(**kwargs))
|
*super().check(**kwargs),
|
||||||
return errors
|
*self._check_max_length_attribute(**kwargs),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_max_length_attribute(self, **kwargs):
|
def _check_max_length_attribute(self, **kwargs):
|
||||||
if self.max_length is None:
|
if self.max_length is None:
|
||||||
|
@ -1111,10 +1113,11 @@ class CommaSeparatedIntegerField(CharField):
|
||||||
class DateTimeCheckMixin:
|
class DateTimeCheckMixin:
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_mutually_exclusive_options())
|
*super().check(**kwargs),
|
||||||
errors.extend(self._check_fix_default_value())
|
*self._check_mutually_exclusive_options(),
|
||||||
return errors
|
*self._check_fix_default_value(),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_mutually_exclusive_options(self):
|
def _check_mutually_exclusive_options(self):
|
||||||
# auto_now, auto_now_add, and default are mutually exclusive
|
# auto_now, auto_now_add, and default are mutually exclusive
|
||||||
|
@ -1276,9 +1279,10 @@ class DateField(DateTimeCheckMixin, Field):
|
||||||
return '' if val is None else val.isoformat()
|
return '' if val is None else val.isoformat()
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.DateField}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.DateField,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class DateTimeField(DateField):
|
class DateTimeField(DateField):
|
||||||
|
@ -1431,9 +1435,10 @@ class DateTimeField(DateField):
|
||||||
return '' if val is None else val.isoformat()
|
return '' if val is None else val.isoformat()
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.DateTimeField}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.DateTimeField,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class DecimalField(Field):
|
class DecimalField(Field):
|
||||||
|
@ -1451,8 +1456,10 @@ class DecimalField(Field):
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
errors = super().check(**kwargs)
|
||||||
|
|
||||||
digits_errors = self._check_decimal_places()
|
digits_errors = [
|
||||||
digits_errors.extend(self._check_max_digits())
|
*self._check_decimal_places(),
|
||||||
|
*self._check_max_digits(),
|
||||||
|
]
|
||||||
if not digits_errors:
|
if not digits_errors:
|
||||||
errors.extend(self._check_decimal_places_and_max_digits(**kwargs))
|
errors.extend(self._check_decimal_places_and_max_digits(**kwargs))
|
||||||
else:
|
else:
|
||||||
|
@ -1575,13 +1582,12 @@ class DecimalField(Field):
|
||||||
return self.to_python(value)
|
return self.to_python(value)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'max_digits': self.max_digits,
|
'max_digits': self.max_digits,
|
||||||
'decimal_places': self.decimal_places,
|
'decimal_places': self.decimal_places,
|
||||||
'form_class': forms.DecimalField,
|
'form_class': forms.DecimalField,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
||||||
|
|
||||||
class DurationField(Field):
|
class DurationField(Field):
|
||||||
|
@ -1639,11 +1645,10 @@ class DurationField(Field):
|
||||||
return '' if val is None else duration_string(val)
|
return '' if val is None else duration_string(val)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'form_class': forms.DurationField,
|
'form_class': forms.DurationField,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
||||||
|
|
||||||
class EmailField(CharField):
|
class EmailField(CharField):
|
||||||
|
@ -1664,11 +1669,10 @@ class EmailField(CharField):
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
# As with CharField, this will cause email validation to be performed
|
# As with CharField, this will cause email validation to be performed
|
||||||
# twice.
|
# twice.
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'form_class': forms.EmailField,
|
'form_class': forms.EmailField,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
||||||
|
|
||||||
class FilePathField(Field):
|
class FilePathField(Field):
|
||||||
|
@ -1682,9 +1686,10 @@ class FilePathField(Field):
|
||||||
super().__init__(verbose_name, name, **kwargs)
|
super().__init__(verbose_name, name, **kwargs)
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_allowing_files_or_folders(**kwargs))
|
*super().check(**kwargs),
|
||||||
return errors
|
*self._check_allowing_files_or_folders(**kwargs),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_allowing_files_or_folders(self, **kwargs):
|
def _check_allowing_files_or_folders(self, **kwargs):
|
||||||
if not self.allow_files and not self.allow_folders:
|
if not self.allow_files and not self.allow_folders:
|
||||||
|
@ -1720,16 +1725,15 @@ class FilePathField(Field):
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'path': self.path,
|
'path': self.path,
|
||||||
'match': self.match,
|
'match': self.match,
|
||||||
'recursive': self.recursive,
|
'recursive': self.recursive,
|
||||||
'form_class': forms.FilePathField,
|
'form_class': forms.FilePathField,
|
||||||
'allow_files': self.allow_files,
|
'allow_files': self.allow_files,
|
||||||
'allow_folders': self.allow_folders,
|
'allow_folders': self.allow_folders,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
||||||
def get_internal_type(self):
|
def get_internal_type(self):
|
||||||
return "FilePathField"
|
return "FilePathField"
|
||||||
|
@ -1764,9 +1768,10 @@ class FloatField(Field):
|
||||||
)
|
)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.FloatField}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.FloatField,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class IntegerField(Field):
|
class IntegerField(Field):
|
||||||
|
@ -1777,9 +1782,10 @@ class IntegerField(Field):
|
||||||
description = _("Integer")
|
description = _("Integer")
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_max_length_warning())
|
*super().check(**kwargs),
|
||||||
return errors
|
*self._check_max_length_warning(),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_max_length_warning(self):
|
def _check_max_length_warning(self):
|
||||||
if self.max_length is not None:
|
if self.max_length is not None:
|
||||||
|
@ -1836,9 +1842,10 @@ class IntegerField(Field):
|
||||||
)
|
)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.IntegerField}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.IntegerField,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class BigIntegerField(IntegerField):
|
class BigIntegerField(IntegerField):
|
||||||
|
@ -1850,10 +1857,11 @@ class BigIntegerField(IntegerField):
|
||||||
return "BigIntegerField"
|
return "BigIntegerField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'min_value': -BigIntegerField.MAX_BIGINT - 1,
|
return super().formfield(**{
|
||||||
'max_value': BigIntegerField.MAX_BIGINT}
|
'min_value': -BigIntegerField.MAX_BIGINT - 1,
|
||||||
defaults.update(kwargs)
|
'max_value': BigIntegerField.MAX_BIGINT,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class IPAddressField(Field):
|
class IPAddressField(Field):
|
||||||
|
@ -1903,9 +1911,10 @@ class GenericIPAddressField(Field):
|
||||||
super().__init__(verbose_name, name, *args, **kwargs)
|
super().__init__(verbose_name, name, *args, **kwargs)
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_blank_and_null_values(**kwargs))
|
*super().check(**kwargs),
|
||||||
return errors
|
*self._check_blank_and_null_values(**kwargs),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_blank_and_null_values(self, **kwargs):
|
def _check_blank_and_null_values(self, **kwargs):
|
||||||
if not getattr(self, 'null', False) and getattr(self, 'blank', False):
|
if not getattr(self, 'null', False) and getattr(self, 'blank', False):
|
||||||
|
@ -1959,12 +1968,11 @@ class GenericIPAddressField(Field):
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'protocol': self.protocol,
|
'protocol': self.protocol,
|
||||||
'form_class': forms.GenericIPAddressField,
|
'form_class': forms.GenericIPAddressField,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
||||||
|
|
||||||
class NullBooleanField(Field):
|
class NullBooleanField(Field):
|
||||||
|
@ -2012,9 +2020,10 @@ class NullBooleanField(Field):
|
||||||
return self.to_python(value)
|
return self.to_python(value)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.NullBooleanField}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.NullBooleanField,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class PositiveIntegerRelDbTypeMixin:
|
class PositiveIntegerRelDbTypeMixin:
|
||||||
|
@ -2041,9 +2050,10 @@ class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):
|
||||||
return "PositiveIntegerField"
|
return "PositiveIntegerField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'min_value': 0}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'min_value': 0,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):
|
class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):
|
||||||
|
@ -2053,9 +2063,10 @@ class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):
|
||||||
return "PositiveSmallIntegerField"
|
return "PositiveSmallIntegerField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'min_value': 0}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'min_value': 0,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class SlugField(CharField):
|
class SlugField(CharField):
|
||||||
|
@ -2084,9 +2095,11 @@ class SlugField(CharField):
|
||||||
return "SlugField"
|
return "SlugField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.SlugField, 'allow_unicode': self.allow_unicode}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.SlugField,
|
||||||
return super().formfield(**defaults)
|
'allow_unicode': self.allow_unicode,
|
||||||
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class SmallIntegerField(IntegerField):
|
class SmallIntegerField(IntegerField):
|
||||||
|
@ -2115,11 +2128,11 @@ class TextField(Field):
|
||||||
# Passing max_length to forms.CharField means that the value's length
|
# Passing max_length to forms.CharField means that the value's length
|
||||||
# will be validated twice. This is considered acceptable since we want
|
# will be validated twice. This is considered acceptable since we want
|
||||||
# the value in the form field (to pass into widget for example).
|
# the value in the form field (to pass into widget for example).
|
||||||
defaults = {'max_length': self.max_length}
|
return super().formfield(**{
|
||||||
if not self.choices:
|
'max_length': self.max_length,
|
||||||
defaults['widget'] = forms.Textarea
|
**({} if self.choices else {'widget': forms.Textarea}),
|
||||||
defaults.update(kwargs)
|
**kwargs,
|
||||||
return super().formfield(**defaults)
|
})
|
||||||
|
|
||||||
|
|
||||||
class TimeField(DateTimeCheckMixin, Field):
|
class TimeField(DateTimeCheckMixin, Field):
|
||||||
|
@ -2248,9 +2261,10 @@ class TimeField(DateTimeCheckMixin, Field):
|
||||||
return '' if val is None else val.isoformat()
|
return '' if val is None else val.isoformat()
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.TimeField}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.TimeField,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class URLField(CharField):
|
class URLField(CharField):
|
||||||
|
@ -2270,11 +2284,10 @@ class URLField(CharField):
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
# As with CharField, this will cause URL validation to be performed
|
# As with CharField, this will cause URL validation to be performed
|
||||||
# twice.
|
# twice.
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'form_class': forms.URLField,
|
'form_class': forms.URLField,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
||||||
|
|
||||||
class BinaryField(Field):
|
class BinaryField(Field):
|
||||||
|
@ -2365,8 +2378,7 @@ class UUIDField(Field):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'form_class': forms.UUIDField,
|
'form_class': forms.UUIDField,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
|
@ -230,10 +230,11 @@ class FileField(Field):
|
||||||
super().__init__(verbose_name, name, **kwargs)
|
super().__init__(verbose_name, name, **kwargs)
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_primary_key())
|
*super().check(**kwargs),
|
||||||
errors.extend(self._check_upload_to())
|
*self._check_primary_key(),
|
||||||
return errors
|
*self._check_upload_to(),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_primary_key(self):
|
def _check_primary_key(self):
|
||||||
if self._primary_key_set_explicitly:
|
if self._primary_key_set_explicitly:
|
||||||
|
@ -318,9 +319,11 @@ class FileField(Field):
|
||||||
setattr(instance, self.name, data)
|
setattr(instance, self.name, data)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.FileField, 'max_length': self.max_length}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.FileField,
|
||||||
return super().formfield(**defaults)
|
'max_length': self.max_length,
|
||||||
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class ImageFileDescriptor(FileDescriptor):
|
class ImageFileDescriptor(FileDescriptor):
|
||||||
|
@ -363,9 +366,10 @@ class ImageField(FileField):
|
||||||
super().__init__(verbose_name, name, **kwargs)
|
super().__init__(verbose_name, name, **kwargs)
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_image_library_installed())
|
*super().check(**kwargs),
|
||||||
return errors
|
*self._check_image_library_installed(),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_image_library_installed(self):
|
def _check_image_library_installed(self):
|
||||||
try:
|
try:
|
||||||
|
@ -458,6 +462,7 @@ class ImageField(FileField):
|
||||||
setattr(instance, self.height_field, height)
|
setattr(instance, self.height_field, height)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.ImageField}
|
return super().formfield(**{
|
||||||
defaults.update(kwargs)
|
'form_class': forms.ImageField,
|
||||||
return super().formfield(**defaults)
|
**kwargs,
|
||||||
|
})
|
||||||
|
|
|
@ -95,13 +95,14 @@ class RelatedField(FieldCacheMixin, Field):
|
||||||
return self.remote_field.model
|
return self.remote_field.model
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_related_name_is_valid())
|
*super().check(**kwargs),
|
||||||
errors.extend(self._check_related_query_name_is_valid())
|
*self._check_related_name_is_valid(),
|
||||||
errors.extend(self._check_relation_model_exists())
|
*self._check_related_query_name_is_valid(),
|
||||||
errors.extend(self._check_referencing_to_swapped_model())
|
*self._check_relation_model_exists(),
|
||||||
errors.extend(self._check_clashes())
|
*self._check_referencing_to_swapped_model(),
|
||||||
return errors
|
*self._check_clashes(),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_related_name_is_valid(self):
|
def _check_related_name_is_valid(self):
|
||||||
import keyword
|
import keyword
|
||||||
|
@ -480,10 +481,11 @@ class ForeignObject(RelatedField):
|
||||||
self.swappable = swappable
|
self.swappable = swappable
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_to_fields_exist())
|
*super().check(**kwargs),
|
||||||
errors.extend(self._check_unique_target())
|
*self._check_to_fields_exist(),
|
||||||
return errors
|
*self._check_unique_target(),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_to_fields_exist(self):
|
def _check_to_fields_exist(self):
|
||||||
# Skip nonexistent models.
|
# Skip nonexistent models.
|
||||||
|
@ -815,10 +817,11 @@ class ForeignKey(ForeignObject):
|
||||||
self.db_constraint = db_constraint
|
self.db_constraint = db_constraint
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_on_delete())
|
*super().check(**kwargs),
|
||||||
errors.extend(self._check_unique())
|
*self._check_on_delete(),
|
||||||
return errors
|
*self._check_unique(),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_on_delete(self):
|
def _check_on_delete(self):
|
||||||
on_delete = getattr(self.remote_field, 'on_delete', None)
|
on_delete = getattr(self.remote_field, 'on_delete', None)
|
||||||
|
@ -950,13 +953,12 @@ class ForeignKey(ForeignObject):
|
||||||
raise ValueError("Cannot create form field for %r yet, because "
|
raise ValueError("Cannot create form field for %r yet, because "
|
||||||
"its related model %r has not been loaded yet" %
|
"its related model %r has not been loaded yet" %
|
||||||
(self.name, self.remote_field.model))
|
(self.name, self.remote_field.model))
|
||||||
defaults = {
|
return super().formfield(**{
|
||||||
'form_class': forms.ModelChoiceField,
|
'form_class': forms.ModelChoiceField,
|
||||||
'queryset': self.remote_field.model._default_manager.using(using),
|
'queryset': self.remote_field.model._default_manager.using(using),
|
||||||
'to_field_name': self.remote_field.field_name,
|
'to_field_name': self.remote_field.field_name,
|
||||||
}
|
**kwargs,
|
||||||
defaults.update(kwargs)
|
})
|
||||||
return super().formfield(**defaults)
|
|
||||||
|
|
||||||
def db_check(self, connection):
|
def db_check(self, connection):
|
||||||
return []
|
return []
|
||||||
|
@ -1134,12 +1136,13 @@ class ManyToManyField(RelatedField):
|
||||||
self.swappable = swappable
|
self.swappable = swappable
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super().check(**kwargs)
|
return [
|
||||||
errors.extend(self._check_unique(**kwargs))
|
*super().check(**kwargs),
|
||||||
errors.extend(self._check_relationship_model(**kwargs))
|
*self._check_unique(**kwargs),
|
||||||
errors.extend(self._check_ignored_options(**kwargs))
|
*self._check_relationship_model(**kwargs),
|
||||||
errors.extend(self._check_table_uniqueness(**kwargs))
|
*self._check_ignored_options(**kwargs),
|
||||||
return errors
|
*self._check_table_uniqueness(**kwargs),
|
||||||
|
]
|
||||||
|
|
||||||
def _check_unique(self, **kwargs):
|
def _check_unique(self, **kwargs):
|
||||||
if self.unique:
|
if self.unique:
|
||||||
|
@ -1461,7 +1464,6 @@ class ManyToManyField(RelatedField):
|
||||||
|
|
||||||
def _get_path_info(self, direct=False, filtered_relation=None):
|
def _get_path_info(self, direct=False, filtered_relation=None):
|
||||||
"""Called by both direct and indirect m2m traversal."""
|
"""Called by both direct and indirect m2m traversal."""
|
||||||
pathinfos = []
|
|
||||||
int_model = self.remote_field.through
|
int_model = self.remote_field.through
|
||||||
linkfield1 = int_model._meta.get_field(self.m2m_field_name())
|
linkfield1 = int_model._meta.get_field(self.m2m_field_name())
|
||||||
linkfield2 = int_model._meta.get_field(self.m2m_reverse_field_name())
|
linkfield2 = int_model._meta.get_field(self.m2m_reverse_field_name())
|
||||||
|
@ -1484,10 +1486,7 @@ class ManyToManyField(RelatedField):
|
||||||
else:
|
else:
|
||||||
intermediate_infos = join2_initial.get_path_from_parent(join1_final.model)
|
intermediate_infos = join2_initial.get_path_from_parent(join1_final.model)
|
||||||
|
|
||||||
pathinfos.extend(join1infos)
|
return [*join1infos, *intermediate_infos, *join2infos]
|
||||||
pathinfos.extend(intermediate_infos)
|
|
||||||
pathinfos.extend(join2infos)
|
|
||||||
return pathinfos
|
|
||||||
|
|
||||||
def get_path_info(self, filtered_relation=None):
|
def get_path_info(self, filtered_relation=None):
|
||||||
return self._get_path_info(direct=True, filtered_relation=filtered_relation)
|
return self._get_path_info(direct=True, filtered_relation=filtered_relation)
|
||||||
|
@ -1624,8 +1623,8 @@ class ManyToManyField(RelatedField):
|
||||||
defaults = {
|
defaults = {
|
||||||
'form_class': forms.ModelMultipleChoiceField,
|
'form_class': forms.ModelMultipleChoiceField,
|
||||||
'queryset': self.remote_field.model._default_manager.using(using),
|
'queryset': self.remote_field.model._default_manager.using(using),
|
||||||
|
**kwargs,
|
||||||
}
|
}
|
||||||
defaults.update(kwargs)
|
|
||||||
# If initial is passed in, it's a list of related objects, but the
|
# If initial is passed in, it's a list of related objects, but the
|
||||||
# MultipleChoiceField takes a list of IDs.
|
# MultipleChoiceField takes a list of IDs.
|
||||||
if defaults.get('initial') is not None:
|
if defaults.get('initial') is not None:
|
||||||
|
|
|
@ -101,11 +101,10 @@ class BaseManager:
|
||||||
def from_queryset(cls, queryset_class, class_name=None):
|
def from_queryset(cls, queryset_class, class_name=None):
|
||||||
if class_name is None:
|
if class_name is None:
|
||||||
class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
|
class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
|
||||||
class_dict = {
|
return type(class_name, (cls,), {
|
||||||
'_queryset_class': queryset_class,
|
'_queryset_class': queryset_class,
|
||||||
}
|
**cls._get_queryset_methods(queryset_class),
|
||||||
class_dict.update(cls._get_queryset_methods(queryset_class))
|
})
|
||||||
return type(class_name, (cls,), class_dict)
|
|
||||||
|
|
||||||
def contribute_to_class(self, model, name):
|
def contribute_to_class(self, model, name):
|
||||||
if not self.name:
|
if not self.name:
|
||||||
|
|
|
@ -157,9 +157,7 @@ class NamedValuesListIterable(ValuesListIterable):
|
||||||
names = queryset._fields
|
names = queryset._fields
|
||||||
else:
|
else:
|
||||||
query = queryset.query
|
query = queryset.query
|
||||||
names = list(query.extra_select)
|
names = [*query.extra_select, *query.values_select, *query.annotation_select]
|
||||||
names.extend(query.values_select)
|
|
||||||
names.extend(query.annotation_select)
|
|
||||||
tuple_class = self.create_namedtuple_class(*names)
|
tuple_class = self.create_namedtuple_class(*names)
|
||||||
new = tuple.__new__
|
new = tuple.__new__
|
||||||
for row in super().__iter__():
|
for row in super().__iter__():
|
||||||
|
|
|
@ -476,10 +476,7 @@ class SQLCompiler:
|
||||||
params.extend(s_params)
|
params.extend(s_params)
|
||||||
out_cols.append(s_sql)
|
out_cols.append(s_sql)
|
||||||
|
|
||||||
result.append(', '.join(out_cols))
|
result += [', '.join(out_cols), 'FROM', *from_]
|
||||||
|
|
||||||
result.append('FROM')
|
|
||||||
result.extend(from_)
|
|
||||||
params.extend(f_params)
|
params.extend(f_params)
|
||||||
|
|
||||||
if self.query.select_for_update and self.connection.features.has_select_for_update:
|
if self.query.select_for_update and self.connection.features.has_select_for_update:
|
||||||
|
|
|
@ -153,7 +153,7 @@ class BoundField:
|
||||||
if id_:
|
if id_:
|
||||||
id_for_label = widget.id_for_label(id_)
|
id_for_label = widget.id_for_label(id_)
|
||||||
if id_for_label:
|
if id_for_label:
|
||||||
attrs = dict(attrs or {}, **{'for': id_for_label})
|
attrs = {**(attrs or {}), 'for': id_for_label}
|
||||||
if self.field.required and hasattr(self.form, 'required_css_class'):
|
if self.field.required and hasattr(self.form, 'required_css_class'):
|
||||||
attrs = attrs or {}
|
attrs = attrs or {}
|
||||||
if 'class' in attrs:
|
if 'class' in attrs:
|
||||||
|
|
|
@ -4,7 +4,6 @@ Field classes.
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import itertools
|
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -112,7 +111,7 @@ class Field:
|
||||||
messages.update(error_messages or {})
|
messages.update(error_messages or {})
|
||||||
self.error_messages = messages
|
self.error_messages = messages
|
||||||
|
|
||||||
self.validators = list(itertools.chain(self.default_validators, validators))
|
self.validators = [*self.default_validators, *validators]
|
||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
|
|
@ -564,9 +564,7 @@ class BaseModelFormSet(BaseFormSet):
|
||||||
queryset=None, *, initial=None, **kwargs):
|
queryset=None, *, initial=None, **kwargs):
|
||||||
self.queryset = queryset
|
self.queryset = queryset
|
||||||
self.initial_extra = initial
|
self.initial_extra = initial
|
||||||
defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
|
super().__init__(**{'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix, **kwargs})
|
||||||
defaults.update(kwargs)
|
|
||||||
super().__init__(**defaults)
|
|
||||||
|
|
||||||
def initial_form_count(self):
|
def initial_form_count(self):
|
||||||
"""Return the number of forms that are required in this FormSet."""
|
"""Return the number of forms that are required in this FormSet."""
|
||||||
|
|
|
@ -241,10 +241,7 @@ class Widget(metaclass=MediaDefiningClass):
|
||||||
|
|
||||||
def build_attrs(self, base_attrs, extra_attrs=None):
|
def build_attrs(self, base_attrs, extra_attrs=None):
|
||||||
"""Build an attribute dictionary."""
|
"""Build an attribute dictionary."""
|
||||||
attrs = base_attrs.copy()
|
return {**base_attrs, **(extra_attrs or {})}
|
||||||
if extra_attrs is not None:
|
|
||||||
attrs.update(extra_attrs)
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
def value_from_datadict(self, data, files, name):
|
def value_from_datadict(self, data, files, name):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -274,7 +274,7 @@ class RequestFactory:
|
||||||
# - HTTP_COOKIE: for cookie support,
|
# - HTTP_COOKIE: for cookie support,
|
||||||
# - REMOTE_ADDR: often useful, see #8551.
|
# - REMOTE_ADDR: often useful, see #8551.
|
||||||
# See http://www.python.org/dev/peps/pep-3333/#environ-variables
|
# See http://www.python.org/dev/peps/pep-3333/#environ-variables
|
||||||
environ = {
|
return {
|
||||||
'HTTP_COOKIE': self.cookies.output(header='', sep='; '),
|
'HTTP_COOKIE': self.cookies.output(header='', sep='; '),
|
||||||
'PATH_INFO': '/',
|
'PATH_INFO': '/',
|
||||||
'REMOTE_ADDR': '127.0.0.1',
|
'REMOTE_ADDR': '127.0.0.1',
|
||||||
|
@ -290,10 +290,9 @@ class RequestFactory:
|
||||||
'wsgi.multiprocess': True,
|
'wsgi.multiprocess': True,
|
||||||
'wsgi.multithread': False,
|
'wsgi.multithread': False,
|
||||||
'wsgi.run_once': False,
|
'wsgi.run_once': False,
|
||||||
|
**self.defaults,
|
||||||
|
**request,
|
||||||
}
|
}
|
||||||
environ.update(self.defaults)
|
|
||||||
environ.update(request)
|
|
||||||
return environ
|
|
||||||
|
|
||||||
def request(self, **request):
|
def request(self, **request):
|
||||||
"Construct a generic request object."
|
"Construct a generic request object."
|
||||||
|
@ -325,11 +324,10 @@ class RequestFactory:
|
||||||
def get(self, path, data=None, secure=False, **extra):
|
def get(self, path, data=None, secure=False, **extra):
|
||||||
"""Construct a GET request."""
|
"""Construct a GET request."""
|
||||||
data = {} if data is None else data
|
data = {} if data is None else data
|
||||||
r = {
|
return self.generic('GET', path, secure=secure, **{
|
||||||
'QUERY_STRING': urlencode(data, doseq=True),
|
'QUERY_STRING': urlencode(data, doseq=True),
|
||||||
}
|
**extra,
|
||||||
r.update(extra)
|
})
|
||||||
return self.generic('GET', path, secure=secure, **r)
|
|
||||||
|
|
||||||
def post(self, path, data=None, content_type=MULTIPART_CONTENT,
|
def post(self, path, data=None, content_type=MULTIPART_CONTENT,
|
||||||
secure=False, **extra):
|
secure=False, **extra):
|
||||||
|
@ -343,11 +341,10 @@ class RequestFactory:
|
||||||
def head(self, path, data=None, secure=False, **extra):
|
def head(self, path, data=None, secure=False, **extra):
|
||||||
"""Construct a HEAD request."""
|
"""Construct a HEAD request."""
|
||||||
data = {} if data is None else data
|
data = {} if data is None else data
|
||||||
r = {
|
return self.generic('HEAD', path, secure=secure, **{
|
||||||
'QUERY_STRING': urlencode(data, doseq=True),
|
'QUERY_STRING': urlencode(data, doseq=True),
|
||||||
}
|
**extra,
|
||||||
r.update(extra)
|
})
|
||||||
return self.generic('HEAD', path, secure=secure, **r)
|
|
||||||
|
|
||||||
def trace(self, path, secure=False, **extra):
|
def trace(self, path, secure=False, **extra):
|
||||||
"""Construct a TRACE request."""
|
"""Construct a TRACE request."""
|
||||||
|
|
|
@ -635,7 +635,7 @@ class SimpleTestCase(unittest.TestCase):
|
||||||
if field_kwargs is None:
|
if field_kwargs is None:
|
||||||
field_kwargs = {}
|
field_kwargs = {}
|
||||||
required = fieldclass(*field_args, **field_kwargs)
|
required = fieldclass(*field_args, **field_kwargs)
|
||||||
optional = fieldclass(*field_args, **dict(field_kwargs, required=False))
|
optional = fieldclass(*field_args, **{**field_kwargs, 'required': False})
|
||||||
# test valid inputs
|
# test valid inputs
|
||||||
for input, output in valid.items():
|
for input, output in valid.items():
|
||||||
self.assertEqual(required.clean(input), output)
|
self.assertEqual(required.clean(input), output)
|
||||||
|
|
|
@ -423,8 +423,10 @@ class override_settings(TestContextDecorator):
|
||||||
test_func._overridden_settings = self.options
|
test_func._overridden_settings = self.options
|
||||||
else:
|
else:
|
||||||
# Duplicate dict to prevent subclasses from altering their parent.
|
# Duplicate dict to prevent subclasses from altering their parent.
|
||||||
test_func._overridden_settings = dict(
|
test_func._overridden_settings = {
|
||||||
test_func._overridden_settings, **self.options)
|
**test_func._overridden_settings,
|
||||||
|
**self.options,
|
||||||
|
}
|
||||||
|
|
||||||
def decorate_class(self, cls):
|
def decorate_class(self, cls):
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
|
|
|
@ -440,8 +440,8 @@ class URLResolver:
|
||||||
(
|
(
|
||||||
new_matches,
|
new_matches,
|
||||||
p_pattern + pat,
|
p_pattern + pat,
|
||||||
dict(defaults, **url_pattern.default_kwargs),
|
{**defaults, **url_pattern.default_kwargs},
|
||||||
dict(self.pattern.converters, **converters)
|
{**self.pattern.converters, **converters}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
for namespace, (prefix, sub_pattern) in url_pattern.namespace_dict.items():
|
for namespace, (prefix, sub_pattern) in url_pattern.namespace_dict.items():
|
||||||
|
@ -500,7 +500,7 @@ class URLResolver:
|
||||||
else:
|
else:
|
||||||
if sub_match:
|
if sub_match:
|
||||||
# Merge captured arguments in match with submatch
|
# Merge captured arguments in match with submatch
|
||||||
sub_match_dict = dict(kwargs, **self.default_kwargs)
|
sub_match_dict = {**kwargs, **self.default_kwargs}
|
||||||
# Update the sub_match_dict with the kwargs from the sub_match.
|
# Update the sub_match_dict with the kwargs from the sub_match.
|
||||||
sub_match_dict.update(sub_match.kwargs)
|
sub_match_dict.update(sub_match.kwargs)
|
||||||
# If there are *any* named groups, ignore all non-named groups.
|
# If there are *any* named groups, ignore all non-named groups.
|
||||||
|
|
|
@ -102,8 +102,8 @@ class SyndicationFeed:
|
||||||
'feed_copyright': to_str(feed_copyright),
|
'feed_copyright': to_str(feed_copyright),
|
||||||
'id': feed_guid or link,
|
'id': feed_guid or link,
|
||||||
'ttl': to_str(ttl),
|
'ttl': to_str(ttl),
|
||||||
|
**kwargs,
|
||||||
}
|
}
|
||||||
self.feed.update(kwargs)
|
|
||||||
self.items = []
|
self.items = []
|
||||||
|
|
||||||
def add_item(self, title, link, description, author_email=None,
|
def add_item(self, title, link, description, author_email=None,
|
||||||
|
@ -119,7 +119,7 @@ class SyndicationFeed:
|
||||||
return str(s) if s is not None else s
|
return str(s) if s is not None else s
|
||||||
if categories:
|
if categories:
|
||||||
categories = [to_str(c) for c in categories]
|
categories = [to_str(c) for c in categories]
|
||||||
item = {
|
self.items.append({
|
||||||
'title': to_str(title),
|
'title': to_str(title),
|
||||||
'link': iri_to_uri(link),
|
'link': iri_to_uri(link),
|
||||||
'description': to_str(description),
|
'description': to_str(description),
|
||||||
|
@ -135,9 +135,8 @@ class SyndicationFeed:
|
||||||
'categories': categories or (),
|
'categories': categories or (),
|
||||||
'item_copyright': to_str(item_copyright),
|
'item_copyright': to_str(item_copyright),
|
||||||
'ttl': to_str(ttl),
|
'ttl': to_str(ttl),
|
||||||
}
|
**kwargs,
|
||||||
item.update(kwargs)
|
})
|
||||||
self.items.append(item)
|
|
||||||
|
|
||||||
def num_items(self):
|
def num_items(self):
|
||||||
return len(self.items)
|
return len(self.items)
|
||||||
|
|
|
@ -9,7 +9,7 @@ from functools import total_ordering, wraps
|
||||||
# CPython) is a type and its instances don't bind.
|
# CPython) is a type and its instances don't bind.
|
||||||
def curry(_curried_func, *args, **kwargs):
|
def curry(_curried_func, *args, **kwargs):
|
||||||
def _curried(*moreargs, **morekwargs):
|
def _curried(*moreargs, **morekwargs):
|
||||||
return _curried_func(*(args + moreargs), **dict(kwargs, **morekwargs))
|
return _curried_func(*(args + moreargs), **{**kwargs, **morekwargs})
|
||||||
return _curried
|
return _curried
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue