def __init__(self, request, model, list_display, list_display_links, list_filter, date_hierarchy, search_fields, list_select_related, list_per_page, list_max_show_all, list_editable, model_admin): self.model = model self.opts = model._meta self.lookup_opts = self.opts self.root_queryset = model_admin.get_queryset(request) self.list_display = list_display self.list_display_links = list_display_links self.list_filter = list_filter self.date_hierarchy = date_hierarchy self.search_fields = search_fields self.list_select_related = list_select_related self.list_per_page = list_per_page self.list_max_show_all = list_max_show_all self.model_admin = model_admin self.preserved_filters = model_admin.get_preserved_filters(request) # Get search parameters from the query string. try: self.page_num = int(request.GET.get(PAGE_VAR, 0)) except ValueError: self.page_num = 0 self.show_all = ALL_VAR in request.GET self.is_popup = IS_POPUP_VAR in request.GET to_field = request.GET.get(TO_FIELD_VAR) if to_field and not model_admin.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) self.to_field = to_field self.params = dict(request.GET.items()) if PAGE_VAR in self.params: del self.params[PAGE_VAR] if ERROR_FLAG in self.params: del self.params[ERROR_FLAG] if self.is_popup: self.list_editable = () else: self.list_editable = list_editable self.query = request.GET.get(SEARCH_VAR, '') self.queryset = self.get_queryset(request) self.get_results(request) if self.is_popup: title = gettext('Select %s') else: title = gettext('Select %s to change') self.title = title % self.opts.verbose_name self.pk_attname = self.lookup_opts.pk.attname
def delete_view(self, request, object_id, extra_context=None): from django.contrib.admin.options import TO_FIELD_VAR to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): from django.contrib.admin.exceptions import DisallowedModelAdminToField raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field) from django.contrib.admin.utils import unquote user = self.get_object(request, unquote(object_id), to_field) tenant = user.profile.tenant if hasattr(user, 'profile') else None if not tenant: return super().delete_view(request, object_id, extra_context) with tenant_context(tenant): return super().delete_view(request, object_id, extra_context)
def change_view(self, request, object_id, form_url='', extra_context=None): """Отмечает запрос как прочитанный""" if object_id: to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) obj = self.get_object(request, unquote(object_id), to_field) if obj and obj.read_status < 0: obj.read_status = FormRequestReadStatusEnum.READ obj.save() return super(BaseFormRequestAdmin, self).change_view(request, object_id, form_url=form_url, extra_context=extra_context)
def delete_view(self, request, object_id, extra_context=None): to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( u'The field {to_field:s} cannot be referenced.'.format( to_field=to_field)) object = self.get_object(request, unquote(object_id), to_field) if not self.has_delete_permission(request, object): raise PermissionDenied if object is None: raise Http404( _(u'{name:} object with primary key {key:s} does not exist.'). format( name=force_text(self.model._meta.verbose_name), key=escape(object_id), )) if request.POST: object_display = force_text(object) self.log_deletion(request, object, object_display) self.delete_model(request, object) return self.response_delete( request, object_display, object.serializable_value( str(to_field) if to_field else self.model._meta.pk.attname), ) context = dict( self.admin_site.each_context(request), app_label=self.model._meta.app_label, is_popup=IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, object=object, object_name=force_text(self.model._meta.verbose_name), opts=self.model._meta, preserved_filters=self.get_preserved_filters(request), title=_('Are you sure?'), to_field=to_field, ) context.update(extra_context or {}) return self.render_delete_form(request, context)
def delete_view(self, request, object_id, extra_context=None): "The 'delete' admin view for this model." opts = self.model._meta app_label = opts.app_label to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) obj = self.get_object(request, unquote(object_id), to_field) if not self.has_delete_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) # using = router.db_for_write(self.model) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. deleted_objects, model_count, perms_needed, protected = ([obj], { self.model.__name__: 1 }, [], []) if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = force_text(obj) attr = str(to_field) if to_field else opts.pk.attname obj_id = obj.serializable_value(attr) # self.log_deletion(request, obj, obj_display) self.delete_model(request, obj) return self.response_delete(request, obj_display, obj_id) object_name = force_text(opts.verbose_name) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = dict( self.admin_site.each_context(request), title=title, object_name=object_name, object=obj, deleted_objects=deleted_objects, model_count=dict(model_count).items(), perms_lacking=perms_needed, protected=protected, opts=opts, app_label=app_label, preserved_filters=self.get_preserved_filters(request), is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, ) context.update(extra_context or {}) return self.render_delete_form(request, context)
def delete_view(self, request, object_id, extra_context=None): """ The 'delete' admin view for this model. """ opts = self.model._meta app_label = opts.app_label to_field = request.POST.get('_to_field', request.GET.get('_to_field')) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) obj = self.get_object(request, unquote(object_id)) if not self.has_delete_permission(request, obj): raise PermissionDenied if obj is None: # Translators: Translation included with Django raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) # frePPLe specific selection of the database using = request.database # Populate deleted_objects, a data structure of all related objects that # will also be deleted. (deleted_objects, model_count, perms_needed, protected) = get_deleted_objects([obj], opts, request.user, self.admin_site, using) # Update the links to the related objects. frePPLe specific. if request.prefix: def replace_url(a): if isinstance(a, list): return [replace_url(i) for i in a] else: return mark_safe( a.replace('href="', 'href="%s' % request.prefix)) deleted_objects = [replace_url(i) for i in deleted_objects] protected = [replace_url(i) for i in protected] if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = force_text(obj) attr = str(to_field) if to_field else opts.pk.attname obj_id = obj.serializable_value(attr) self.log_deletion(request, obj, obj_display) self.delete_model(request, obj) return self.response_delete(request, obj_display, obj_id) object_name = force_text(opts.verbose_name) context = dict( self.admin_site.each_context(request), title=capfirst(object_name + ' ' + unquote(object_id)), object_name=object_name, object=obj, deleted_objects=deleted_objects, model_count=dict(model_count).items(), perms_lacking=perms_needed, protected=protected, opts=opts, app_label=app_label, preserved_filters=self.get_preserved_filters(request), is_popup=('_popup' in request.POST or '_popup' in request.GET), to_field=to_field, ) context.update(extra_context or {}) return self.render_delete_form(request, context)
def _changeform_view(self, request, object_id, form_url, extra_context): to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect(request, opts, object_id) ModelForm = self.get_form(request, obj, change=not add) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() # on save if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) # on update if all_valid(formsets) and form_validated: try: # must not fail when there's an error getting the old object old_object = new_object.__class__.objects.get(pk=new_object.pk) except Exception: pass self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) change_message = self.construct_change_message(request, form, formsets, add) if len(change_message) > 0: changes = change_message[0].get('changed') if changes: changes['old_values'] = [] changes['new_values'] = [] changed_fields = changes['fields'] for changed_field in changed_fields: try: # when we failed to get the old object or there's an error, silently continue old = getattr(old_object, changed_field) new = getattr(new_object, changed_field) changes['old_values'].append(str(old)) changes['new_values'].append(str(new)) except Exception: pass if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets(request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) if not add and not self.has_change_permission(request, obj): readonly_fields = flatten_fieldsets(self.get_fieldsets(request, obj)) else: readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), # Clear prepopulated fields on a view-only form to avoid a crash. self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {}, readonly_fields, model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media if add: title = _('Add %s') elif self.has_change_permission(request, obj): title = _('Change %s') else: title = _('View %s') context = { **self.admin_site.each_context(request), 'title': title % opts.verbose_name, 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, 'to_field': to_field, 'media': media, 'inline_admin_formsets': inline_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'preserved_filters': self.get_preserved_filters(request), } # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def _changeform_view(self, request, object_id, form_url, extra_context): """ A copy of original django method with 4 tricks 1. Calls whole_changeform_validation 2. Calls pre_save() before saving 3. Calls post_save() after saving 4. emits the signal changeform_saved signal :param request: :param object_id: :param form_url: :param extra_context: :return: """ to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) ModelForm = self.get_form(request, obj, change=not add) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid( formsets ) and form_validated and self.whole_changeform_validation( request, form, formsets, not add): self.pre_save(form, formsets, change=not add) self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) self.post_save(request, new_object, form, formsets, not add) changeform_saved.send(self.model, instance=new_object, created=add) change_message = self.construct_change_message( request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) if not add and not self.has_change_permission(request, obj): readonly_fields = flatten_fieldsets( self.get_fieldsets(request, obj)) else: readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), # Clear prepopulated fields on a view-only form to avoid a crash. self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {}, readonly_fields, model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media if add: title = _('Add %s') elif self.has_change_permission(request, obj): title = _('Change %s') else: title = _('View %s') context = { **self.admin_site.each_context(request), 'title': title % opts.verbose_name, 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, 'to_field': to_field, 'media': media, 'inline_admin_formsets': inline_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'preserved_filters': self.get_preserved_filters(request), } # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def _delete_view(self, request, object_id, extra_context): "The 'delete' admin view for this model." opts = self.model._meta app_label = opts.app_label to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) obj = self.get_object(request, unquote(object_id), to_field) if not self.has_delete_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) using = router.db_for_write(self.model) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. (deleted_objects, model_count, perms_needed, protected) = get_deleted_objects([obj], opts, request.user, self.admin_site, using) if request.POST and not protected: # The user has confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = force_text(obj) attr = str(to_field) if to_field else opts.pk.attname obj_id = obj.serializable_value(attr) response = self.do_deleting(request, obj, obj_display, obj_id) if response: return response model_form = self.get_form(request, obj) form = model_form(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) admin_form = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), self.get_prepopulated_fields(request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = self.media + admin_form.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media context = dict( self.admin_site.each_context(request), title=(_('Change %s')) % force_text(opts.verbose_name), adminform=admin_form, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=helpers.AdminErrorList(form, formsets), preserved_filters=self.get_preserved_filters(request), ) return self.render_change_form(request, context, add=False, change=True, obj=obj, form_url='') object_name = force_text(opts.verbose_name) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = dict( self.admin_site.each_context(request), title=title, object_name=object_name, object=obj, deleted_objects=deleted_objects, model_count=dict(model_count).items(), perms_lacking=perms_needed, protected=protected, opts=opts, app_label=app_label, preserved_filters=self.get_preserved_filters(request), is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, ) context.update(extra_context or {}) return self.render_delete_form(request, context)
def _changeform_view(self, request, object_id, form_url, extra_context): """ I know overriding such a long method is terrible! But I do not know what a better approach would be. I will take a look at this patch method to try to patch all_valid(). https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch """ to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if request.method == 'POST': if not self.has_change_permission(request, obj): raise PermissionDenied else: if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) fieldsets = self.get_fieldsets(request, obj) ModelForm = self.get_form(request, obj, change=not add, fields=flatten_fieldsets(fieldsets)) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if self.all_valid(form, formsets) and form_validated: self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) change_message = self.construct_change_message( request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) if not add and not self.has_change_permission(request, obj): readonly_fields = flatten_fieldsets(fieldsets) else: readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm( form, list(fieldsets), # Clear prepopulated fields on a view-only form to avoid a crash. self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {}, readonly_fields, model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media if add: title = _('Add %s') elif self.has_change_permission(request, obj): title = _('Change %s') else: title = _('View %s') context = { **self.admin_site.each_context(request), 'title': title % opts.verbose_name, 'subtitle': str(obj) if obj else None, 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, 'to_field': to_field, 'media': media, 'inline_admin_formsets': inline_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'preserved_filters': self.get_preserved_filters(request), } # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def _change_confirmation_view(self, request, object_id, form_url, extra_context): # noqa: C901 to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field ) model = self.model opts = model._meta add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if obj is None: return self._get_obj_does_not_exist_redirect(request, opts, object_id) if not self.has_view_or_change_permission(request, obj): raise PermissionDenied ModelForm = self.get_form(request, obj=obj, change=not add) is_agent_initial = obj.is_agent form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() new_object = self.save_form(request, form, change=not add) if form_validated else form.instance is_agent_disabled = False if form_validated: is_agent_changed = form.fields['is_agent'].has_changed( is_agent_initial, new_object.is_agent) if 'is_agent' in form.fields else False is_agent_disabled = is_agent_changed and not new_object.is_agent is_confirm_required = bool(is_agent_disabled and new_object.user_schedules.exists()) if not is_confirm_required: return super()._changeform_view(request, object_id, form_url, extra_context) # Parse raw form data from POST form_data = {} # Parse the original save action from request save_action = None for key in request.POST: if key in ["_save", "_saveasnew", "_addanother", "_continue"]: save_action = key if key.startswith("_") or key == "csrfmiddlewaretoken": continue form_data[key] = request.POST.get(key) context = { **self.admin_site.each_context(request), "preserved_filters": self.get_preserved_filters(request), "title": _('Confirm user change'), "subtitle": str(obj), "object_name": str(obj), "object_id": object_id, "app_label": opts.app_label, "model_name": opts.model_name, "opts": opts, "form_data": form_data, "add": add, "submit_name": save_action, **(extra_context or {}), } return self.render_change_confirmation(request, context)
def changeform_view(self, request, object_id=None, form_url='', extra_context=None): """ This follows closely the base implementation from Django 1.7's django.contrib.admin.options.ModelAdmin, with the explicitly marked modifications. """ to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id)) if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.' ) % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) if request.method == 'POST' and "_saveasnew" in request.POST: return self.add_view( request, form_url=reverse('admin:%s_%s_add' % (opts.app_label, opts.model_name), current_app=self.admin_site.name)) #### begin modification #### # make sure that the user has a full session length time for the current # edit activity request.session.set_expiry(settings.SESSION_COOKIE_AGE) #### end modification #### ModelForm = self.get_form(request, obj) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=not add) else: form_validated = False new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: #### begin modification #### unsaved_formsets = [] for formset in formsets: parent_fk_name = getattr(formset, 'parent_fk_name', '') # for the moment ignore all formsets that are no reverse # inlines if add: if not parent_fk_name: unsaved_formsets.append(formset) continue # this replaces the call to self.save_formsets() changes = formset.save() # if there are any changes in the current inline and if this # inline is a reverse inline, then we need to manually make # sure that the inline data is connected to the parent # object: if changes: if parent_fk_name: assert len(changes) == 1 setattr(new_object, parent_fk_name, changes[0]) # If we have deleted a one-to-one inline, we must manually # unset the field value. if formset.deleted_objects: if parent_fk_name: setattr(new_object, parent_fk_name, None) self.save_model(request, new_object, form, not add) form.save_m2m() for formset in unsaved_formsets: self.save_formset(request, form, formset, add) # for resource info, explicitly write its metadata XML and # storage object to the storage folder if self.model.__schema_name__ == "resourceInfo": new_object.storage_object.update_storage() #### end modification #### if add: self.log_addition(request, new_object) return self.response_add(request, new_object) else: change_message = self.construct_change_message( request, form, formsets) self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, self.model(), change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) #### begin modification #### media = self.media or [] #### end modification #### inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media #### begin modification #### adminForm = OrderedAdminForm( form, list(self.get_fieldsets_with_inlines(request)), self.prepopulated_fields, self.get_readonly_fields(request, obj), model_admin=self, inlines=inline_formsets) media = media + adminForm.media #### end modification #### context = dict(self.admin_site.each_context(), title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name), adminform=adminForm, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.REQUEST or \ IS_POPUP_O2M_VAR in request.REQUEST), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=helpers.AdminErrorList(form, formsets), preserved_filters=self.get_preserved_filters(request), kb_link=settings.KNOWLEDGE_BASE_URL, app_label=opts.app_label, show_delete=False, ) context.update(extra_context or {}) #### begin modification #### if not add: # redirection for reusable entities which are no master copies: if hasattr(obj, 'copy_status') and obj.copy_status != MASTER: context['url'] = obj.source_url context_instance = template.RequestContext( request, current_app=self.admin_site.name) return render_to_response('admin/repository/cannot_edit.html', context, context_instance=context_instance) # redirection for resources and their parts which are no master copies: else: for res in [ r for r in get_root_resources(obj) if not r.storage_object.master_copy ]: context['redirection_url'] = model_utils.get_lr_master_url( res) context['resource'] = res context_instance = template.RequestContext( request, current_app=self.admin_site.name) return render_to_response( 'admin/repository/cannot_edit.html', context, context_instance=context_instance) #### end modification #### return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def reset_view(self, request, object_id, extra_context=None): # based on ModelAdmin.delete_view, slightly modified to delete obj.questions.answers.all() instead of obj with transaction.atomic(using=router.db_for_write(self.model)): opts = self.model._meta app_label = opts.app_label to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field) obj = self.get_object(request, unquote(object_id), to_field) if obj is None: return self._get_obj_does_not_exist_redirect(request, opts, object_id) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. qs = FormQuestionAnswer.objects.filter(question__form=obj).prefetch_related('question', 'question__form', 'user') deleted_objects, model_count, perms_needed, protected = self.get_deleted_objects(qs, request) if request.POST and not protected: # The user has confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = str(obj) attr = str(to_field) if to_field else opts.pk.attname obj_id = obj.serializable_value(attr) qs.delete() self.message_user( request, _('The %(name)s “%(obj)s” was deleted successfully.') % { 'name': 'odpowiedzi do wszystkich pytań z formularza', 'obj': obj_display, }, messages.SUCCESS, ) if self.has_change_permission(request, None): post_url = reverse( 'admin:%s_%s_change' % (opts.app_label, opts.model_name), args=[obj_id], current_app=self.admin_site.name, ) else: post_url = reverse('admin:index', current_app=self.admin_site.name) return HttpResponseRedirect(post_url) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": 'odpowiedzi do wszystkich pytań z formularza'} else: title = _("Are you sure?") context = { **self.admin_site.each_context(request), 'title': title, 'object_name': 'wszystkie odpowiedzi do wszystkich pytań z formularza', 'object': obj, 'deleted_objects': deleted_objects, 'model_count': dict(model_count).items(), 'perms_lacking': perms_needed, 'protected': protected, 'opts': opts, 'app_label': app_label, 'preserved_filters': self.get_preserved_filters(request), 'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, 'to_field': to_field, **(extra_context or {}), } return self.render_delete_form(request, context)
def _change_confirmation_view(self, request, object_id, form_url, extra_context): # This code is taken from super()._changeform_view # https://github.com/django/django/blob/master/django/contrib/admin/options.py#L1575-L1592 to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if SAVE_AS_NEW in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) if not self.has_view_or_change_permission(request, obj): raise PermissionDenied fieldsets = self.get_fieldsets(request, obj) ModelForm = self.get_form(request, obj, change=not add, fields=flatten_fieldsets(fieldsets)) form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) # End code from super()._changeform_view # form.is_valid() checks both errors and "is_bound" # If form has errors, show the errors on the form instead of showing confirmation page if not form_validated: log("Invalid Form: return early") log(form.errors) # We must ensure that we ask for confirmation when showing errors extra_context = self._add_confirmation_options_to_extra_context( extra_context) return super()._changeform_view(request, object_id, form_url, extra_context) add_or_new = add or SAVE_AS_NEW in request.POST # Get changed data to show on confirmation changed_data = self._get_changed_data(form, model, obj, add_or_new) changed_confirmation_fields = set( self.get_confirmation_fields(request, obj)) & set( changed_data.keys()) if not bool(changed_confirmation_fields): log("No change detected") # No confirmation required for changed fields, continue to save return super()._changeform_view(request, object_id, form_url, extra_context) # Parse the original save action from request save_action = None # No cover: There would not be a case of not request.POST.keys() and form is valid for key in request.POST.keys(): # pragma: no cover if key in SAVE_ACTIONS: save_action = key break cleared_fields = [] if form.is_multipart(): log("Caching files") cache.set(CACHE_KEYS["object"], new_object, CACHE_TIMEOUT) # Save files as tempfiles for field_name in request.FILES: file = request.FILES[field_name] self._file_cache.set( format_cache_key(model=model.__name__, field=field_name), file) # Handle when files are cleared - since the `form` object would not hold that info cleared_fields = self._get_cleared_fields(request) log("Render Change Confirmation") title_action = _("adding") if add_or_new else _("changing") context = { **self.admin_site.each_context(request), "preserved_filters": self.get_preserved_filters(request), "title": f"{_('Confirm')} {title_action} {opts.verbose_name}", "subtitle": str(obj), "object_name": str(obj), "object_id": object_id, "app_label": opts.app_label, "model_name": opts.model_name, "opts": opts, "changed_data": changed_data, "add": add, "save_as_new": SAVE_AS_NEW in request.POST, "submit_name": save_action, "form": form, "cleared_fields": cleared_fields, "formsets": formsets, **(extra_context or {}), } return self.render_change_confirmation(request, context)
def changeform_view(self, request, object_id=None, form_url='', extra_context=None): """ This follows closely the base implementation from Django 1.7's django.contrib.admin.options.ModelAdmin with the explicitly marked modifications. """ to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id)) if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.' ) % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) if request.method == 'POST' and "_saveasnew" in request.POST: return self.add_view( request, form_url=reverse('admin:%s_%s_add' % (opts.app_label, opts.model_name), current_app=self.admin_site.name)) #### begin modification #### # make sure that the user has a full session length time for the current # edit activity request.session.set_expiry(settings.SESSION_COOKIE_AGE) #### end modification #### ModelForm = self.get_form(request, obj) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=not add) else: form_validated = False new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) if add: self.log_addition(request, new_object) return self.response_add(request, new_object) else: change_message = self.construct_change_message( request, form, formsets) self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, self.model(), change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request, obj)), self.get_prepopulated_fields( request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media context = dict(self.admin_site.each_context(), title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name), adminform=adminForm, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.REQUEST or \ IS_POPUP_O2M_VAR in request.REQUEST), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=helpers.AdminErrorList(form, formsets), preserved_filters=self.get_preserved_filters(request), kb_link=settings.KNOWLEDGE_BASE_URL, app_label=opts.app_label, show_delete=False, ) context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def changeform_view(self, request, object_id=None, form_url='', extra_context=None): base_model = self.model.get_base_model() content_type = request.POST.get( 'target_type', request.GET.get('target_type', None)) or None content_type = ContentType.objects.filter(id=content_type).first() parent_id = request.POST.get( 'target_page', request.GET.get('target_page', None)) or None parent = base_model.objects.filter(id=parent_id).first() parent = parent.specific if parent else None msg, url = None, None if not object_id: if not content_type: url = '%s?target_type=%s' % ( self.get_admin_url_for_model(base_model, 'prepare'), ContentType.objects.get_for_model(self.model).id) elif not issubclass(content_type.model_class(), base_model): msg = _('ContentType "%s" is not subclass of base Page.' ' It should be one of Page classes.') % content_type url = self.get_admin_url_for_model(base_model, 'prepare') elif content_type.model_class() is not self.model: msg = _('Page type "%s" does not match admin model class' ' "%s".') % ( content_type, self.model.__name__, ) url = '%s?target_type=%s' % (self.get_admin_url_for_model( base_model, 'prepare'), content_type.id) elif parent_id and not parent: msg = _('Invalid "target_page" value, page does not exist.') url = '%s?target_type=%s' % (self.get_admin_url_for_model( base_model, 'prepare'), content_type.id) elif parent and not self.model.can_create_at(parent): msg = _('Page type "%s" can not be created in "%s" parent' ' page.') % ( self.model.__name__, parent, ) url = '%s?target_type=%s' % (self.get_admin_url_for_model( base_model, 'prepare'), content_type.id) elif not content_type.model_class().is_creatable: msg = _('Page type "%s" can not be created manually' ' in admin interface.') % content_type url = self.get_admin_url_for_model(base_model, 'prepare') elif (self.model.max_count and self.model.objects.count() >= self.model.max_count): msg = _('Page type "%s" exceeded max_count instances limit' ' (%d).') % ( self.model.__name__, self.model.max_count, ) url = self.get_admin_url_for_model(base_model, 'prepare') else: to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s can not be referenced." % to_field) # redirect if concrete type of obj and admin model do not match obj = self.get_object(request, unquote(object_id), to_field) obj = obj.specific if obj else None if obj and type(obj) is not self.model: url = '%s?_changelist_filters=e%%3D%s' % ( self.get_admin_url_for_model( type(obj), 'change', args=(quote( obj.pk), )), ERROR_VALUE_FOR_REDIRECT) if msg: self.message_user(request, msg, messages.ERROR) if url: return redirect(url) return super().changeform_view(request, object_id=object_id, form_url=form_url, extra_context=extra_context)
def __init__( self, request, model, list_display, list_display_links, list_filter, date_hierarchy, search_fields, list_select_related, list_per_page, list_max_show_all, list_editable, model_admin, sortable_by, search_help_text, ): self.model = model self.opts = model._meta self.lookup_opts = self.opts self.root_queryset = model_admin.get_queryset(request) self.list_display = list_display self.list_display_links = list_display_links self.list_filter = list_filter self.has_filters = None self.has_active_filters = None self.clear_all_filters_qs = None self.date_hierarchy = date_hierarchy self.search_fields = search_fields self.list_select_related = list_select_related self.list_per_page = list_per_page self.list_max_show_all = list_max_show_all self.model_admin = model_admin self.preserved_filters = model_admin.get_preserved_filters(request) self.sortable_by = sortable_by self.search_help_text = search_help_text # Get search parameters from the query string. _search_form = self.search_form_class(request.GET) if not _search_form.is_valid(): for error in _search_form.errors.values(): messages.error(request, ", ".join(error)) self.query = _search_form.cleaned_data.get(SEARCH_VAR) or "" try: self.page_num = int(request.GET.get(PAGE_VAR, 1)) except ValueError: self.page_num = 1 self.show_all = ALL_VAR in request.GET self.is_popup = IS_POPUP_VAR in request.GET to_field = request.GET.get(TO_FIELD_VAR) if to_field and not model_admin.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field ) self.to_field = to_field self.params = dict(request.GET.items()) if PAGE_VAR in self.params: del self.params[PAGE_VAR] if ERROR_FLAG in self.params: del self.params[ERROR_FLAG] if self.is_popup: self.list_editable = () else: self.list_editable = list_editable self.queryset = self.get_queryset(request) self.get_results(request) if self.is_popup: title = gettext("Select %s") elif self.model_admin.has_change_permission(request): title = gettext("Select %s to change") else: title = gettext("Select %s to view") self.title = title % self.opts.verbose_name self.pk_attname = self.lookup_opts.pk.attname
def bulk_view(self, request, form_url='', extra_context=None): to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta continue_requested = request.POST.get('_continue', request.GET.get('_continue')) force_continue = False inline = self.get_bulk_inline(request) formset_class = inline.get_formset(request) formset_params = {} prefix = formset_class.get_default_prefix() queryset = inline.get_queryset(request) if not self.has_add_permission(request): formset_class.max_num = 0 if request.method == 'GET': if 'pks' in request.GET and self.has_change_permission(request): pks = [ opts.pk.to_python(pk) for pk in request.GET.get('pks').split(',') ] queryset = queryset.filter(pk__in=pks) else: queryset = queryset.none() elif request.method == 'POST': management_form = ManagementForm(request.POST, prefix=prefix) if not management_form.is_valid(): raise ValidationError( _('ManagementForm data is missing or has been tampered with' ), code='missing_management_form', ) if not self.has_add_permission( request) and management_form.cleaned_data[ INITIAL_FORM_COUNT] < management_form.cleaned_data[ TOTAL_FORM_COUNT]: raise PermissionDenied if not self.has_change_permission( request ) and management_form.cleaned_data[INITIAL_FORM_COUNT] > 0: raise PermissionDenied queryset = self.transform_queryset(request, queryset, management_form, prefix) post, files, force_continue = self.transform_post_and_files( request, prefix) formset_params.update({ 'data': post, 'files': files, }) formset_params['queryset'] = queryset formset = formset_class(**formset_params) if request.method == 'POST': if formset.is_valid(): self.save_formset(request, form=None, formset=formset, change=False) if continue_requested or force_continue: # The implementation of ModelAdmin redirects to the change view if valid and continue was requested # The change view then reads the edited model again from database # In our case, we can't make a redirect as we would loose the information which models should be edited # Thus, we create a new formset with the edited models and continue as this would have been a usual GET request if self.has_change_permission(request): queryset = _ListQueryset(queryset) queryset.extend(formset.new_objects) else: queryset = _ListQueryset() formset_params.update({ 'data': None, 'files': None, 'queryset': queryset, }) formset = formset_class(**formset_params) msg = _( 'The %s were bulk added successfully. You may edit them again below.' ) % (force_text(opts.verbose_name_plural), ) self.message_user(request, msg, messages.SUCCESS) else: return self.response_bulk(request, formset) media = self.media inline_formsets = self.get_inline_formsets(request, [formset], [inline], obj=None) for inline_formset in inline_formsets: media = media + inline_formset.media errors = ErrorList() if formset.is_bound: errors.extend(formset.non_form_errors()) for formset_errors in formset.errors: errors.extend(list(six.itervalues(formset_errors))) print("type(inline_formsets)") print(type(inline_formsets)) print(inline_formsets) print(*inline_formsets, sep=", ") print("request") print(type(request)) print(request) context = dict( self.admin_site.each_context(request) if django.VERSION >= (1, 8) else self.admin_site.each_context(), bulk=True, bulk_formset_prefix=prefix, bulk_upload_fields=self.get_bulk_upload_fields(request), title=_('Bulk add %s') % force_text(opts.verbose_name_plural), is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=errors, preserved_filters=self.get_preserved_filters(request), # adminform=inline_formsets, # adminform=super(BulkModelAdmin, self).get_form(request, **kwargs) #kwargs not define # adminform=super(BulkModelAdmin, self).get_form(request) #object 'ContainerForm' has no attribute 'form' # searching for ContainerForm gives me nothing #writing a dummy form - uses models # adminform=DummyModelForm # but that ModelForm has no modelclass, nothing in models.py ) context.update(extra_context or {}) # print(context) return self.render_change_form(request, context, add=True, change=False, obj=None, form_url=form_url)
def _delete_view(self, request, object_id, extra_context): opts = self.model._meta app_label = opts.app_label to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) obj = self.get_object(request, unquote(object_id), to_field) if not self.has_delete_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) using = router.db_for_write(self.model) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. (deleted_objects, model_count, perms_needed, protected) = get_deleted_objects([obj], opts, request.user, self.admin_site, using) if request.POST and not protected: # The user has confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = force_text(obj) attr = str(to_field) if to_field else opts.pk.attname course_id = obj.course.id obj_id = obj.serializable_value(attr) self.log_deletion(request, obj, obj_display) self.delete_model(request, obj) return self.response_delete(request, obj_display, obj_id, course_id) object_name = force_text(opts.verbose_name) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = dict( self.admin_site.each_context(request), title=title, object_name=object_name, object=obj, deleted_objects=deleted_objects, model_count=dict(model_count).items(), perms_lacking=perms_needed, protected=protected, opts=opts, app_label=app_label, preserved_filters=self.get_preserved_filters(request), is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, ) context.update(extra_context or {}) return self.render_delete_form(request, context)
def changeform_view(self, request, object_id=None, form_url='', extra_context=None): """ Overriding the changeform view of ModelAdmin to allow the form view to be displayed when the user only has view permissions. In this case, the form view will be displayed in readonly mode and without action buttons """ to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_change_permission( request, obj) and not self.has_view_permission( request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.' ) % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) if request.method == 'POST' and "_saveasnew" in request.POST: return self.add_view( request, form_url=reverse('admin:%s_%s_add' % (opts.app_label, opts.model_name), current_app=self.admin_site.name)) ModelForm = self.get_form(request, obj) # do not save the change if I'm not allowed to: if request.method == 'POST' and self.has_change_permission( request, obj): form = ModelForm(request.POST, request.FILES, instance=obj) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=not add) else: form_validated = False new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) if add: self.log_addition(request, new_object) return self.response_add(request, new_object) else: change_message = self.construct_change_message( request, form, formsets) self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, self.model(), change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request, obj)), self.get_prepopulated_fields( request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media context = dict( self.admin_site.each_context(request), title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name), adminform=adminForm, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=helpers.AdminErrorList(form, formsets), preserved_filters=self.get_preserved_filters(request), ) context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def view_view(self, request, object_id, form_url='', extra_context=None): extra_context = extra_context or {} extra_context['has_add_permission'] = self.has_add_permission(request) ''' Code copied from ChangeForm ''' to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_view_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.' ) % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) # if request.method == 'POST' and "_saveasnew" in request.POST: # return self.add_view(request, form_url=reverse('admin:%s_%s_add' % ( # opts.app_label, opts.model_name), current_app=self.admin_site.name)) context = dict( self.admin_site.each_context(request), title=obj, app_label=opts.app_label, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, # media=media, preserved_filters=self.get_preserved_filters(request), ) context.update(extra_context or {}) opts = self.model._meta app_label = opts.app_label preserved_filters = self.get_preserved_filters(request) form_url = add_preserved_filters( { 'preserved_filters': preserved_filters, 'opts': opts }, form_url) view_on_site_url = self.get_view_on_site_url(obj) context.update({ 'add': add, 'change': not add, 'has_add_permission': self.has_add_permission(request), 'has_change_permission': self.has_change_permission(request, obj), 'has_delete_permission': self.has_delete_permission(request, obj), 'has_file_field': True, 'has_absolute_url': view_on_site_url is not None, 'absolute_url': view_on_site_url, 'form_url': form_url, 'opts': opts, 'content_type_id': get_content_type_for_model(self.model).pk, 'save_as': self.save_as, 'save_on_top': self.save_on_top, 'to_field_var': TO_FIELD_VAR, 'is_popup_var': IS_POPUP_VAR, 'app_label': app_label, }) request.current_app = self.admin_site.name return TemplateResponse( request, self.view_template or [ "admin/%s/%s/view.html" % (opts.app_label, opts.model_name), "admin/%s/view.html" % opts.app_label, f"{app_settings.RA_THEME}/view.html", ], context)
def bulk_view(self, request, form_url='', extra_context=None): to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta continue_requested = request.POST.get('_continue', request.GET.get('_continue')) force_continue = False inline = self.get_bulk_inline(request) formset_class = inline.get_formset(request) formset_params = {} prefix = formset_class.get_default_prefix() queryset = inline.get_queryset(request) if not self.has_add_permission(request): formset_class.max_num = 0 if request.method == 'GET': if 'pks' in request.GET and self.has_change_permission(request): pks = [ opts.pk.to_python(pk) for pk in request.GET.get('pks').split(',') ] queryset = queryset.filter(pk__in=pks) else: queryset = queryset.none() elif request.method == 'POST': management_form = ManagementForm(request.POST, prefix=prefix) if not management_form.is_valid(): raise ValidationError( _('ManagementForm data is missing or has been tampered with' ), code='missing_management_form', ) if not self.has_add_permission( request) and management_form.cleaned_data[ INITIAL_FORM_COUNT] < management_form.cleaned_data[ TOTAL_FORM_COUNT]: raise PermissionDenied if not self.has_change_permission( request ) and management_form.cleaned_data[INITIAL_FORM_COUNT] > 0: raise PermissionDenied queryset = self.transform_queryset(request, queryset, management_form, prefix) post, files, force_continue = self.transform_post_and_files( request, prefix) formset_params.update({ 'data': post, 'files': files, }) formset_params['queryset'] = queryset formset = formset_class(**formset_params) if request.method == 'POST': if formset.is_valid(): self.save_formset(request, form=None, formset=formset, change=False) if continue_requested or force_continue: # The implementation of ModelAdmin redirects to the change view if valid and continue was requested # The change view then reads the edited model again from database # In our case, we can't make a redirect as we would loose the information which models should be edited # Thus, we create a new formset with the edited models and continue as this would have been a usual GET request if self.has_change_permission(request): queryset = _ListQueryset(queryset) queryset.extend(formset.new_objects) else: queryset = _ListQueryset() formset_params.update({ 'data': None, 'files': None, 'queryset': queryset, }) formset = formset_class(**formset_params) msg = _( 'The %s were bulk added successfully. You may edit them again below.' ) % (force_text(opts.verbose_name_plural), ) self.message_user(request, msg, messages.SUCCESS) else: return self.response_bulk(request, formset) media = self.media inline_formsets = self.get_inline_formsets(request, [formset], [inline], obj=None) for inline_formset in inline_formsets: media = media + inline_formset.media errors = ErrorList() if formset.is_bound: errors.extend(formset.non_form_errors()) for formset_errors in formset.errors: errors.extend(list(iter(formset_errors.values()))) context = self.admin_site.each_context(request) context.update({ 'bulk': True, 'bulk_formset_prefix': prefix, 'bulk_upload_fields': self.get_bulk_upload_fields(request), 'title': _('Bulk add %s') % force_text(opts.verbose_name_plural), 'is_popup': (IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), 'to_field': to_field, 'media': media, 'inline_admin_formsets': inline_formsets, 'errors': errors, 'preserved_filters': self.get_preserved_filters(request), 'adminform': admin.helpers.AdminForm(ManagementForm(), [], {}), }) context.update(extra_context or {}) return self.render_change_form(request, context, add=True, change=False, obj=None, form_url=form_url)
def _changeform_view(self, request, object_id, form_url, extra_context): to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) ModelForm = self.get_form(request, obj) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=not add) else: form_validated = False new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) change_message = self.construct_change_message( request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj, initial=self.choice_field_value) formsets, inline_instances = self._create_formsets(request, obj, change=True) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request, obj)), self.get_prepopulated_fields( request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media context = dict( self.admin_site.each_context(request), title=(_('Add %s') if add else _('Change %s')) % opts.verbose_name, adminform=adminForm, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=helpers.AdminErrorList(form, formsets), preserved_filters=self.get_preserved_filters(request), ) # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def changeform_view(self, request, object_id=None, form_url='', extra_context=None): to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.' ) % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) form = SimpleJSONForm() if request.method == 'POST': form = SimpleJSONForm(request.POST, instance=obj) if form.is_valid(): form_validated = True form.save(self.model) else: form_validated = False else: if obj: form = SimpleJSONForm(instance=obj) else: form = SimpleJSONForm() adminForm = helpers.AdminForm( form, form.get_fieldsets(), #list(self.get_fieldsets(request, obj)), {}, #self.get_prepopulated_fields(request, obj), [], #[self.get_readonly_fields(request, obj)], model_admin=self) media = self.media + adminForm.media context = dict( self.admin_site.each_context(request), title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name), adminform=adminForm, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, errors=helpers.AdminErrorList(form, []), preserved_filters=self.get_preserved_filters(request), ) # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def delete_view(self, request, object_id, extra_context=None): """ This method overrides the 'delete' admin view. Changes include handling exceptions raised while deleting a model and displaying the exception message to the user in a readable format instead of showing the exception page to the user """ opts = self.model._meta app_label = opts.app_label to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) obj = self.get_object(request, unquote(object_id), to_field) if not self.has_delete_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) using = router.db_for_write(self.model) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. (deleted_objects, model_count, perms_needed, protected) = get_deleted_objects([obj], opts, request.user, self.admin_site, using) if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = force_text(obj) attr = str(to_field) if to_field else opts.pk.attname obj_id = obj.serializable_value(attr) # start: base changes try: self.delete_model(request, obj) except Exception as e: return self.response_delete(request, obj_display, obj_id, msg=e.message, msg_type=messages.ERROR) self.log_deletion(request, obj, obj_display) # end: base changes return self.response_delete(request, obj_display, obj_id) object_name = force_text(opts.verbose_name) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = dict( self.admin_site.each_context(request), title=title, object_name=object_name, object=obj, deleted_objects=deleted_objects, model_count=dict(model_count).items(), perms_lacking=perms_needed, protected=protected, opts=opts, app_label=app_label, preserved_filters=self.get_preserved_filters(request), is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, ) context.update(extra_context or {}) return self.render_delete_form(request, context)
def _changeform_view(self, request, object_id, form_url, extra_context): # noqa """ Based on https://github.com/django/django/blob/2.2.17/django/contrib/admin/options.py#L1531 The creation of the materialized view needed to happen on background """ to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( f"The field {to_field} cannot be referenced.") opts = self.model._meta if request.method == "POST" and "_saveasnew" in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if request.method == "POST": if not self.has_change_permission(request, obj): raise PermissionDenied else: if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) ModelForm = self.get_form(request, obj, change=not add) if request.method == "POST": obj_dict = obj.to_dict() if obj else None form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: self.background_task = create_materialized_view.delay( request.user.pk, obj_dict, serializers.serialize("json", [new_object]), self.construct_change_message(request, form, formsets, add), ) if add: return self.response_add(request, new_object) return self.response_change(request, new_object) else: if add: form = ModelForm( initial=self.get_changeform_initial_data(request)) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) if not add and not self.has_change_permission(request, obj): readonly_fields = flatten_fieldsets( self.get_fieldsets(request, obj)) else: readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), # Clear prepopulated fields on a view-only form to avoid a crash. self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {}, readonly_fields, model_admin=self, ) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media if add: title = _("Add %s") elif self.has_change_permission(request, obj): title = _("Change %s") else: title = _("View %s") context = { **self.admin_site.each_context(request), "title": title % opts.verbose_name, "adminform": adminForm, "object_id": object_id, "original": obj, "is_popup": IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, "to_field": to_field, "media": media, "inline_admin_formsets": inline_formsets, "errors": helpers.AdminErrorList(form, formsets), "preserved_filters": self.get_preserved_filters(request), "show_save_and_continue": False, } context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def _delete_view(self, request, object_id, extra_context): """ The 'delete' admin view for this model. """ opts = self.model._meta app_label = opts.app_label to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field ) obj = self.get_object(request, unquote(object_id), to_field) if not self.has_delete_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect(request, opts, object_id) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. ( deleted_objects, model_count, perms_needed, protected, ) = self.get_deleted_objects([obj], request) # frePPLe specific: Update the links to the related objects. if request.prefix: def replace_url(a): if isinstance(a, list): return [replace_url(i) for i in a] else: return mark_safe(a.replace('href="', 'href="%s' % request.prefix)) deleted_objects = [replace_url(i) for i in deleted_objects] protected = [replace_url(i) for i in protected] if request.POST and not protected: # The user has confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = str(obj) attr = str(to_field) if to_field else opts.pk.attname obj_id = obj.serializable_value(attr) self.log_deletion(request, obj, obj_display) self.delete_model(request, obj) return self.response_delete(request, obj_display, obj_id) object_name = str(opts.verbose_name) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = { **self.admin_site.each_context(request), "title": title, "object_name": object_name, "object": obj, "object_id": obj, "deleted_objects": deleted_objects, "model_count": dict(model_count).items(), "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": app_label, "preserved_filters": self.get_preserved_filters(request), "is_popup": (IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), "to_field": to_field, **(extra_context or {}), } return self.render_delete_form(request, context)
def changeform_view(self, request, object_id=None, form_url='', extra_context=None): contents = None to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.' ) % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) ModelForm = self.get_form(request, obj) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) contents = [] all_content_forms_valid = True if obj and obj.contents: for content in obj.contents.all(): content = content.polymorph() content.build_admin_form(request.POST, request.FILES) if not content.is_admin_form_valid(): all_content_forms_valid = False contents.append(content) if form.is_valid() and all_content_forms_valid: form_validated = True new_object = self.save_form(request, form, change=not add) for content in contents: content.save_admin_form(request) else: form_validated = False new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) change_message = self.construct_change_message( request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: all_content_forms_valid = True if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj) contents = [] if obj.contents: for content in obj.contents.all(): content = content.polymorph() content.build_admin_form() contents.append(content) formsets, inline_instances = self._create_formsets(request, obj, change=True) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request, obj)), self.get_prepopulated_fields( request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media context = dict( self.admin_site.each_context(request), title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name), adminform=adminForm, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=helpers.AdminErrorList(form, formsets) or not all_content_forms_valid, preserved_filters=self.get_preserved_filters(request), contents=contents, copy_url_name='admin:' + self.model._meta.model_name + '_copy', copy_supported=hasattr(obj, 'copy'), change_form_extend_template=self.change_form_extend_template, show_xprez_toolbar=self._show_xprez_toolbar(request, object_id)) # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)