def handle_create_node(instance, node_info): pk = quote(getattr(instance, pk_attname)) node_info.update( url=self.get_admin_url('change', (quote(pk),)), move_url=self.get_admin_url('move', (quote(pk),)) )
def handle_create_node(instance, node_info): pk = quote(getattr(instance, pk_attname)) node_info.update( # url=self.get_admin_url('change', (quote(pk),)), url=reverse('xadmin:duck_personnel_personnel_change', args=(quote(pk),)), move_url=self.get_admin_url('move', (quote(pk),)) )
def test_admin_URLs_no_clash(self): """ Test that some admin URLs work correctly. """ # Should get the change_view for model instance with PK 'add', not show # the add_view response = self.client.get('/admin/admin_custom_urls/action/add/') self.assertEqual(response.status_code, 200) self.assertContains(response, 'Change action') # Ditto, but use reverse() to build the URL url = reverse('admin:%s_action_change' % Action._meta.app_label, args=(quote('add'),)) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertContains(response, 'Change action') # Should correctly get the change_view for the model instance with the # funny-looking PK (the one wth a 'path/to/html/document.html' value) url = reverse('admin:%s_action_change' % Action._meta.app_label, args=(quote("path/to/html/document.html"),)) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertContains(response, 'Change action') self.assertContains(response, 'value="path/to/html/document.html"')
def test_terms_accepted_phrase_inline_admin_permissions(self): PARegistration.objects.all().delete() # Logging as superuser. self.assertTrue(self.client.login(username='******')) self.client.get('/c/c/') # 'c' becomes the current contest url = reverse('oioioiadmin:contests_contest_change', args=(quote('c'),)) response = self.client.get(url) self.assertContains(response, 'Text asking participant to accept contest terms') # Checks if the field is editable. self.assertContains(response, 'id_terms_accepted_phrase-0-text') # Logging as contest admin. self.assertTrue(self.client.login(username='******')) self.client.get('/c/c/') # 'c' becomes the current contest url = reverse('oioioiadmin:contests_contest_change', args=(quote('c'),)) response = self.client.get(url) self.assertContains(response, 'Text asking participant to accept contest terms') # Checks if the field is editable. self.assertContains(response, 'id_terms_accepted_phrase-0-text')
def url_for_result(self, result): if (self.hpcService is None): return super(FilteredChangeList, self).url_for_result(result) pk = getattr(result, self.pk_attname) return reverse('admin:%s_%s_filteredchange' % (self.opts.app_label, self.opts.model_name), args=(quote(self.hpcService.id), quote(pk),), current_app=self.model_admin.admin_site.name)
def url_for_result(self, result): # (child fkey_list) if self.fkey_list_data: view = getattr(self.fkey_list_data['link_name'], 'change_fkeylist') args = (self.fkey_list_data['fkey_name'], quote(self.fkey_list_data['id']), quote(getattr(result, self.pk_attname)),) return reverse(view, args=args, current_app=self.model_admin.admin_site.name) return super(FkeyListChangeList, self).url_for_result(result)
def handle_create_node(instance, node_info): pk = quote(getattr(instance, pk_attname)) node_url = add_preserved_filters_to_url( self.get_admin_url('change', (quote(pk),)) ) node_info.update( url=node_url, move_url=self.get_admin_url('move', (quote(pk),)) )
def get_history_url(obj, history_index=None, site="admin"): app, model = obj._meta.app_label, obj._meta.model_name if history_index is not None: history = obj.history.order_by('history_id')[history_index] return reverse( "{site}:{app}_{model}_simple_history".format( site=site, app=app, model=model), args=[quote(obj.pk), quote(history.history_id)], ) else: return reverse("{site}:{app}_{model}_history".format( site=site, app=app, model=model), args=[quote(obj.pk)])
def get_admin_url(self): """ Returns the admin URL to edit the object represented by this comment. """ if self.content_type and self.object_pk: url_name = 'data:%s_%s_change' % (self.content_type.app_label, self.content_type.model) try: return reverse(url_name, args=(quote(self.object_pk),)) except NoReverseMatch: try: url_name = 'admin:%s_%s_change' % (self.content_type.app_label, self.content_type.model) return reverse(url_name, args=(quote(self.object_pk),)) except NoReverseMatch: pass return None
def response_add(self, request, obj, post_url_continue=None): opts = obj._meta msg_dict = {'name': force_text(opts.verbose_name), 'obj': force_text(obj)} if obj.content_block is None: # Assign object id to content block. self.content_block.object_id = obj.id self.content_block.save() # Assign content block to block. obj.content_block = self.content_block obj.save() if "_continue" in request.POST: msg = _( 'The %(name)s "%(obj)s" was added successfully. You may edit it again below.' ) % msg_dict self.message_user(request, msg, messages.SUCCESS) post_url_continue = reverse( 'admin:%s_%s_continue' % (opts.app_label, opts.model_name), args=(quote(obj.content_block.id),), current_app=self.admin_site.name ) return HttpResponseRedirect(post_url_continue) return self.response_rerender(request, obj, 'admin/glitter/update_column.html')
def compare_view(self, request, object_id, version_id, extra_context=None): """Actually compare two versions.""" opts = self.model._meta object_id = unquote(object_id) # get_for_object's ordering means this is always the latest revision. # The reversion we want to compare to current = Version.objects.get_for_object_reference(self.model, object_id)[0] revision = Version.objects.get_for_object_reference(self.model, object_id).filter(id=version_id)[0] the_diff = make_diff(current, revision) context = { "title": _("Comparing current %(model)s with revision created %(date)s") % { 'model': current, 'date' : get_date(revision), }, "opts": opts, "compare_list_url": reverse("%s:%s_%s_comparelist" % (self.admin_site.name, opts.app_label, opts.model_name), args=(quote(object_id),)), "diff_list": the_diff, } extra_context = extra_context or {} context.update(extra_context) return render(request, self.compare_template or self._get_template_list("compare.html"), context)
def get_buttons_for_obj(self, obj, allow_inspect_button=True, extra_classnames=[]): """ Provide different sets of buttons, depending on whether the model uses 'node_order_by' to automatically order tree nodes, or the positioning is user controlled. """ pk = quote(getattr(obj, self.opts.pk.attname)) buttons = [] if self.inspect_view_enabled and allow_inspect_button: buttons.append(self.inspect_button(pk, extra_classnames)) if self.permission_helper.can_edit_object(self.user, obj): buttons.append(self.edit_button(pk, extra_classnames)) buttons.append(self.move_button(pk, extra_classnames)) if self.permission_helper.has_add_permission(self.user): if self.model.node_order_by: buttons.append(self.add_child_button(pk, extra_classnames)) buttons.append(self.add_sibling_button(pk, extra_classnames)) else: buttons.append(self.add_sibling_before_button(pk, extra_classnames)) buttons.append(self.add_sibling_after_button(pk, extra_classnames)) buttons.append(self.add_child_button(pk, extra_classnames)) if self.permission_helper.can_delete_object(self.user, obj): buttons.append(self.delete_button(pk, extra_classnames)) return buttons
def status_button(self, obj): pk = getattr(obj, self.pk_attname) model_name = self.model_name.lower() if obj.has_unpublished_changes: return { 'title': _('View draft for this %(mn)s') % {'mn': model_name}, 'label': _('Draft'), 'target': '_blank', 'url': reverse('wagtailadmin_pages_view_draft', args=(quote(pk),)) } if obj.url: return { 'title': _('View this %(mn)s') % {'mn': model_name}, 'label': _('Live'), 'target': '_blank', 'url': obj.url, } else: return { 'title': _( "This %(mn)s is published but does not exist within a " "configured Site, so cannot be viewed." ) % {'mn': model_name}, 'label': _('Live'), 'url': '', 'disabled': True }
def url_for_result(self, result): pk_attname = result._meta.pk.attname pk = getattr(result, pk_attname) return reverse('admin:%s_%s_change' % (result._meta.app_label, result._meta.model_name), args=(quote(pk),), current_app=self.model_admin.admin_site.name)
def history_url_field(self, obj): # noinspection PyProtectedMember opts = self.model._meta return "<a href=%s>%s</a>" % ( reverse( "%s:%s_%s_history" % (self.admin_site.name, opts.app_label, opts.model_name), args=(quote(obj.pk),)), render_to_string('history_link.html'))
def _reversion_revisionform_view(self, request, version, template_name, extra_context=None): # Check that database transactions are supported. if not connection.features.uses_savepoints: raise ImproperlyConfigured("Cannot use VersionAdmin with a database that does not support savepoints.") # Run the view. try: with transaction.atomic(using=version.db): # Revert the revision. version.revision.revert(delete=True) # Run the normal changeform view. with self.create_revision(request): response = self.changeform_view(request, quote(version.object_id), request.path, extra_context) # Decide on whether the keep the changes. if request.method == "POST" and response.status_code == 302: set_comment(_("Reverted to previous version, saved on %(datetime)s") % { "datetime": localize(template_localtime(version.revision.date_created)), }) else: response.template_name = template_name # Set the template name to the correct template. response.render() # Eagerly render the response, so it's using the latest version. raise _RollBackRevisionView(response) # Raise exception to undo the transaction and revision. except RevertError as ex: opts = self.model._meta messages.error(request, force_text(ex)) return redirect("{}:{}_{}_changelist".format(self.admin_site.name, opts.app_label, opts.model_name)) except _RollBackRevisionView as ex: return ex.response return response
def get_buttons_for_obj(self, obj, exclude=None, classnames_add=None, classnames_exclude=None): if exclude is None: exclude = [] if classnames_add is None: classnames_add = [] if classnames_exclude is None: classnames_exclude = [] ph = self.permission_helper usr = self.request.user pk = quote(getattr(obj, self.opts.pk.attname)) btns = [] if('inspect' not in exclude and ph.user_can_inspect_obj(usr, obj)): btns.append( self.inspect_button(pk, classnames_add, classnames_exclude) ) if('edit' not in exclude and ph.user_can_edit_obj(usr, obj)): btns.append( self.edit_button(pk, classnames_add, classnames_exclude) ) if('delete' not in exclude and ph.user_can_delete_obj(usr, obj)): btns.append( self.delete_button(pk, classnames_add, classnames_exclude) ) return btns
def apply_schedule_run(request, schedule_run_pk): obj = get_object_or_404(ScheduleRun, pk=schedule_run_pk) organization_id = obj.organization_id get_object_or_404(Organization.query(request), pk=organization_id) # only used to check rights # required to get the URL of the "administration change page" # noinspection PyProtectedMember model_admin = admin.site._registry[Organization] assert isinstance(model_admin, OrganizationAdmin) # noinspection PyProtectedMember opts = model_admin.model._meta result_dict = json.loads(obj.result_dict) end = obj.celery_end d = '%(d)s, %(t)s' % {'d': date_format(end, use_l10n=True), 't': time_format(end, use_l10n=True)} if not result_dict: messages.error(request, _('Unable to apply the invalid schedule "%(d)s".') % {'d': d}) else: try: apply_schedule(organization_id, result_dict) Organization.objects.filter(pk=organization_id).update(current_schedule=obj.pk) ScheduleRun.objects.filter(organization__id=organization_id).exclude(pk=schedule_run_pk)\ .update(is_selected=False) ScheduleRun.objects.filter(pk=schedule_run_pk).update(is_selected=True) messages.success(request, _('Schedule "%(d)s" has been applied.') % {'d': d}) except ValueError as e: messages.error(request, _('Unable to apply the invalid schedule "%(d)s": %(e)s.') % {'d': d, 'e': e}) new_url = reverse('admin:%s_%s_change' % (opts.app_label, opts.model_name), args=(quote(organization_id),), current_app=model_admin.admin_site.name) return HttpResponseRedirect(new_url)
def __init__(self, model_admin, instance_pk): super(MainMenuEditView, self).__init__(model_admin) self.instance_pk = unquote(instance_pk) self.pk_safe = quote(self.instance_pk) self.site = get_object_or_404(Site, id=self.instance_pk) self.instance = self.model.get_for_site(self.site) self.instance.save()
def test_logentry_change_message(self): """ LogEntry.change_message is stored as a dumped JSON structure to be able to get the message dynamically translated at display time. """ post_data = { 'site': self.site.pk, 'title': 'Changed', 'hist': 'Some content', 'created_0': '2008-03-18', 'created_1': '11:54', } change_url = reverse('admin:admin_utils_article_change', args=[quote(self.a1.pk)]) response = self.client.post(change_url, post_data) self.assertRedirects(response, reverse('admin:admin_utils_article_changelist')) logentry = LogEntry.objects.filter(content_type__model__iexact='article').latest('id') self.assertEqual(logentry.get_change_message(), 'Changed title and hist.') with translation.override('fr'): self.assertEqual(logentry.get_change_message(), 'Title et hist modifié(s).') add_url = reverse('admin:admin_utils_article_add') post_data['title'] = 'New' response = self.client.post(add_url, post_data) self.assertRedirects(response, reverse('admin:admin_utils_article_changelist')) logentry = LogEntry.objects.filter(content_type__model__iexact='article').latest('id') self.assertEqual(logentry.get_change_message(), 'Added.') with translation.override('fr'): self.assertEqual(logentry.get_change_message(), 'Ajout.')
def history_view(self, request, object_id, extra_context=None): """Renders the history view.""" # Check if user has change permissions for model if not self.has_change_permission(request): raise PermissionDenied object_id = unquote(object_id) # Underscores in primary key get quoted to "_5F" opts = self.model._meta action_list = [ { "revision": version.revision, "url": reverse( "%s:%s_%s_revision" % (self.admin_site.name, opts.app_label, opts.model_name), args=(quote(version.object_id), version.id) ), } for version in self._reversion_order_version_queryset(Version.objects.get_for_object_reference( self.model, object_id, ).select_related("revision__user")) ] # Compile the context. context = {"action_list": action_list} context.update(extra_context or {}) return super(VersionAdmin, self).history_view(request, object_id, context)
def Comments(request, app, model, object_id): try: modeltype = ContentType.objects.using(request.database).get(app_label=app, model=model) modeltype._state.db = request.database object_id = unquote(object_id) modelinstance = modeltype.get_object_for_this_type(pk=object_id) comments = Comment.objects.using(request.database) \ .filter(content_type__pk=modeltype.id, object_pk=object_id) \ .order_by('-id') except: raise Http404('Object not found') if request.method == 'POST': comment = request.POST['comment'] if comment: Comment( content_object=modelinstance, user=request.user, comment=comment ).save(using=request.database) return HttpResponseRedirect('%s/comments/%s/%s/%s/' % (request.prefix, app, model, object_id)) else: return render_to_response('common/comments.html', { 'title': capfirst(force_text(modelinstance._meta.verbose_name) + " " + object_id), 'model': model, 'object_id': quote(object_id), 'active_tab': 'comments', 'comments': comments }, context_instance=RequestContext(request))
def get_buttons_for_obj(self, obj, exclude=[], classnames_add=[], classnames_exclude=[]): ph = self.permission_helper usr = self.request.user pk = quote(getattr(obj, self.opts.pk.attname)) btns = [] if('inspect' not in exclude and ph.user_can_inspect_obj(usr, obj)): btns.append( self.inspect_button(pk, classnames_add, classnames_exclude) ) if('edit' not in exclude and ph.user_can_edit_obj(usr, obj)): btns.append( self.edit_button(pk, classnames_add, classnames_exclude) ) if('copy' not in exclude and ph.user_can_copy_obj(usr, obj)): btns.append( self.copy_button(pk, classnames_add, classnames_exclude) ) if('unpublish' not in exclude and ph.user_can_unpublish_obj(usr, obj)): btns.append( self.unpublish_button(pk, classnames_add, classnames_exclude) ) if('delete' not in exclude and ph.user_can_delete_obj(usr, obj)): btns.append( self.delete_button(pk, classnames_add, classnames_exclude) ) return btns
def test_balloons_link_and_cookie(self): self.client.login(username='******') regenerate_url = reverse('balloons_access_regenerate', kwargs={'contest_id': self.contest.id}) response = self.client.post(regenerate_url) self.assertEqual(response.status_code, 403) self.client.login(username='******') regenerate_url = reverse('balloons_access_regenerate', kwargs={'contest_id': self.contest.id}) response = self.client.post(regenerate_url) self.assertEqual(response.status_code, 302) self.assertTrue(response['Location'].endswith( reverse('oioioiadmin:contests_contest_change', args=[quote(self.contest.id)]) )) self.client.logout() access_data = BalloonsDeliveryAccessData.objects.get() set_cookie_url = reverse('balloons_access_set_cookie', kwargs={'contest_id': self.contest.id, 'access_key': access_data.access_key}) panel_url = reverse('balloons_delivery_panel', kwargs=self.c_kwargs) cookie_key = 'balloons_access_' + self.contest.id response = self.client.get(set_cookie_url) self.assertEqual(response.status_code, 302) self.assertTrue(response['Location'].endswith(panel_url)) self.assertTrue(cookie_key in response.cookies) self.assertEqual(response.cookies[cookie_key].value, access_data.access_key)
def url_for_result(self, result): pk = getattr(result, self.pk_attname) return reverse( "entities:%s_%s_change" % (self.opts.app_label, self.opts.model_name), args=(quote(pk),), current_app=self.model_admin.admin_site.name, )
def wrapper(self, obj): result = func(self, obj) if result: # if function return something, we do nothing and just return; return result # most of the cases will trigger this ELSE branch; from django.template import Context, Template from django.core.urlresolvers import reverse from django.contrib.admin.utils import quote assert hasattr(obj, field) _field_attr = getattr(obj, field, None) if _field_attr is None: _django_template = Template('') _context = Context() else: _description = '{{name}} {{id}}' _str_template = '<a href="{{url}}">%s</a>' % _description _django_template = Template(_str_template) _pk_value = _field_attr.id url = reverse( 'admin:%s_%s_change' % (_field_attr.__class__._meta.app_label, _field_attr.__class__.__name__.lower()), args=(quote(_pk_value),), current_app=self.admin_site.name, ) _context = Context({'url': url, 'name': _field_attr.__class__._meta.verbose_name.title(), 'id': _pk_value }) return _django_template.render(_context)
def history_view(self, request, object_id, extra_context=None): if not self.has_change_permission(request): raise PermissionDenied object_id = unquote(object_id) active_lang = request.GET.get('language') or get_language() opts = self.model._meta action_list = [ { "revision": version.revision, "url": reverse("%s:%s_%s_revision" % ( self.admin_site.name, opts.app_label, opts.model_name), args=(quote(version.object_id), version.id)), } for version in self._order_version_queryset( self.revision_manager.get_for_object_reference( self.model, object_id, ).select_related("revision__user")) if simplejson.loads(version.serialized_data)[0]['fields'].get( 'language_code' ) == active_lang ] context = {"action_list": action_list} context.update(extra_context or {}) return super().history_view(request, object_id, context)
def format(obj, account=False): has_admin = obj.__class__ in admin_site._registry opts = obj._meta no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj)) if has_admin: try: admin_url = reverse('admin:%s_%s_change' % (opts.app_label, opts.model_name), None, (quote(obj._get_pk_val()),) ) except NoReverseMatch: # Change url doesn't exist -- don't display link to edit return no_edit_link p = '%s.%s' % (opts.app_label, get_permission_codename('delete', opts)) if not user.has_perm(p): perms_needed.add(opts.verbose_name) # Display a link to the admin page. context = (capfirst(opts.verbose_name), admin_url, obj) if account: context += (_("services to delete:"),) return format_html('{} <a href="{}">{}</a> {}', *context) return format_html('{}: <a href="{}">{}</a>', *context) else: # Don't display link to edit, because it either has no # admin or is edited inline. return no_edit_link
def _languages_column(self, object, all_languages=None, span_classes=''): active_languages = self.get_available_languages(object) if all_languages is None: all_languages = active_languages current_language = object.get_current_language() buttons = [] opts = self.opts for code in (all_languages or active_languages): classes = ['lang-code'] if code in active_languages: classes.append('active') else: classes.append('untranslated') if code == current_language: classes.append('current') info = opts.app_label, opts.model_name admin_url = reverse('admin:{0}_{1}_change'.format(*info), args=(quote(object.pk),), current_app=self.admin_site.name) buttons.append('<a class="{classes}" href="{href}?language={language_code}">{title}</a>'.format( language_code=code, classes=' '.join(classes), href=escape(admin_url), title=conditional_escape(self.get_language_short_title(code)) )) return '<span class="language-buttons {0}">{1}</span>'.format( span_classes, ' '.join(buttons) )
def format_callback(obj): model = obj.__class__ has_admin = model in admin_site._registry opts = obj._meta no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), obj) if has_admin: if not admin_site._registry[model].has_add_permission(request): perms_needed.add(opts.verbose_name) try: admin_url = reverse('%s:%s_%s_change' % (admin_site.name, opts.app_label, opts.model_name), None, (quote(obj.pk),)) except NoReverseMatch: # Change url doesn't exist -- don't display link to edit return no_edit_link # Display a link to the admin page. return format_html('{}: <a href="{}">{}</a>', capfirst(opts.verbose_name), admin_url, obj) else: # Don't display link to edit, because it either has no # admin or is edited inline. return no_edit_link
def create(request, app_label, model_name): model = get_snippet_model_from_url_params(app_label, model_name) permission = get_permission_name("add", model) if not request.user.has_perm(permission): raise PermissionDenied for fn in hooks.get_hooks("before_create_snippet"): result = fn(request, model) if hasattr(result, "status_code"): return result instance = model() # Set locale of the new instance if issubclass(model, TranslatableMixin): selected_locale = request.GET.get("locale") if selected_locale: instance.locale = get_object_or_404(Locale, language_code=selected_locale) else: instance.locale = Locale.get_default() # Make edit handler edit_handler = get_snippet_edit_handler(model) form_class = edit_handler.get_form_class() if request.method == "POST": form = form_class(request.POST, request.FILES, instance=instance, for_user=request.user) if form.is_valid(): with transaction.atomic(): form.save() log(instance=instance, action="wagtail.create") messages.success( request, _("%(snippet_type)s '%(instance)s' created.") % { "snippet_type": capfirst(model._meta.verbose_name), "instance": instance, }, buttons=[ messages.button( reverse( "wagtailsnippets:edit", args=(app_label, model_name, quote(instance.pk)), ), _("Edit"), ) ], ) for fn in hooks.get_hooks("after_create_snippet"): result = fn(request, instance) if hasattr(result, "status_code"): return result urlquery = "" if (isinstance(instance, TranslatableMixin) and instance.locale is not Locale.get_default()): urlquery = "?locale=" + instance.locale.language_code return redirect( reverse("wagtailsnippets:list", args=[app_label, model_name]) + urlquery) else: messages.validation_error( request, _("The snippet could not be created due to errors."), form) else: form = form_class(instance=instance, for_user=request.user) edit_handler = edit_handler.get_bound_panel(request=request, instance=instance, form=form) action_menu = SnippetActionMenu(request, view="create", model=model) context = { "model_opts": model._meta, "edit_handler": edit_handler, "form": form, "action_menu": action_menu, "locale": None, "translations": [], "media": edit_handler.media + form.media + action_menu.media, } if getattr(settings, "WAGTAIL_I18N_ENABLED", False) and issubclass( model, TranslatableMixin): context.update({ "locale": instance.locale, "translations": [{ "locale": locale, "url": reverse("wagtailsnippets:add", args=[app_label, model_name]) + "?locale=" + locale.language_code, } for locale in Locale.objects.all().exclude(id=instance.locale.id) ], }) return TemplateResponse(request, "wagtailsnippets/snippets/create.html", context)
def url_for_result(self, result): pk = getattr(result, self.pk_attname) return reverse('admin:%s_%s_change' % (self.opts.app_label, self.opts.model_name), args=(quote(pk), ), current_app=self.model_admin.admin_site.name)
def admin_urlquote(value): return quote(value)
def get_snippet_usage_url(self): return reverse( f"wagtailsnippets_{self._meta.app_label}_{self._meta.model_name}:usage", args=[quote(self.pk)], )
def test_quote(self): self.assertEqual(quote('something\nor\nother'), 'something_0Aor_0Aother')
def post(self, snippet, post_data={}): args = (snippet._meta.app_label, snippet._meta.model_name, quote(snippet.pk)) return self.client.post(reverse('wagtailsnippets:edit', args=args), post_data)
def get(self, pk, params=None): return self.client.get( reverse('wagtailsnippets:chosen', args=('tests', 'advertwithcustomprimarykey', quote(pk))), params or {})
def get_index_url(self): return reverse( "wagtailsnippets:history", args=(self.app_label, self.model_name, quote(self.object.pk)), )
def get_snippet_usage_url(self): return reverse('wagtailsnippets:usage', args=(self._meta.app_label, self._meta.model_name, quote(self.pk)))
def edit_translation(request, translation, instance): if isinstance(instance, Page): # Page # Note: Edit permission is already checked by the edit page view page_perms = instance.permissions_for_user(request.user) is_live = instance.live is_locked = instance.locked if instance.live_revision: last_published_at = instance.live_revision.created_at last_published_by = instance.live_revision.user else: last_published_at = instance.last_published_at last_published_by = None if instance.live: live_url = instance.full_url else: live_url = None can_publish = page_perms.can_publish() can_unpublish = page_perms.can_unpublish() can_lock = page_perms.can_lock() can_unlock = page_perms.can_unlock() can_delete = page_perms.can_delete() else: # Snippet # Note: Edit permission is already checked by the edit snippet view is_live = True is_locked = False last_published_at = None last_published_by = None live_url = None can_publish = True can_unpublish = False can_lock = False can_unlock = False can_delete = request.user.has_perm( get_permission_name('delete', instance.__class__)) source_instance = translation.source.get_source_instance() if request.method == 'POST': if request.POST.get('action') == 'publish': if isinstance(instance, Page): if not page_perms.can_publish(): raise PermissionDenied try: translation.save_target(user=request.user, publish=True) except ValidationError: messages.error( request, _("New validation errors were found when publishing '{object}' in {locale}. Please fix them or click publish again to ignore these translations for now." ).format( object=str(instance), locale=translation.target_locale.get_display_name())) else: # Refresh instance to title in success message is up to date instance.refresh_from_db() string_segments = translation.source.stringsegment_set.all( ).order_by('order') string_translations = string_segments.get_translations( translation.target_locale) # Using annotate_translation as this ignores errors by default (so both errors and missing segments treated the same) if string_segments.annotate_translation( translation.target_locale).filter( translation__isnull=True).exists(): # One or more strings had an error messages.warning( request, _("Published '{object}' in {locale} with missing translations - see below." ).format(object=str(instance), locale=translation.target_locale. get_display_name())) else: messages.success( request, _("Published '{object}' in {locale}.").format( object=str(instance), locale=translation.target_locale.get_display_name( ))) return redirect(request.path) string_segments = translation.source.stringsegment_set.all().order_by( 'order') string_translations = string_segments.get_translations( translation.target_locale) overridable_segments = translation.source.overridablesegment_set.all( ).order_by('order') segment_overrides = overridable_segments.get_overrides( translation.target_locale) related_object_segments = translation.source.relatedobjectsegment_set.all( ).order_by('order') tab_helper = TabHelper(source_instance) breadcrumb = [] title_segment_id = None if isinstance(instance, Page): # find the closest common ancestor of the pages that this user has direct explore permission # (i.e. add/edit/publish/lock) over; this will be the root of the breadcrumb cca = get_explorable_root_page(request.user) if cca: breadcrumb = [{ 'id': page.id, 'isRoot': page.is_root(), 'title': page.title, 'exploreUrl': reverse('wagtailadmin_explore_root') if page.is_root() else reverse('wagtailadmin_explore', args=[page.id]), } for page in instance.get_ancestors( inclusive=False).descendant_of(cca, inclusive=True)] # Set to the ID of a string segment that represents the title. # If this segment has a translation, the title will be replaced with that translation. try: title_segment_id = string_segments.get(context__path='title').id except StringSegment.DoesNotExist: pass machine_translator = None translator = get_machine_translator() if translator and translator.can_translate(translation.source.locale, translation.target_locale): machine_translator = { 'name': translator.display_name, 'url': reverse('wagtail_localize:machine_translate', args=[translation.id]), } segments = [] for segment in string_segments: try: location_info = get_segment_location_info(source_instance, tab_helper, segment.context.path) except FieldHasNoEditPanelError: continue segments.append({ 'type': 'string', 'id': segment.id, 'contentPath': segment.context.path, 'source': segment.string.data, 'location': location_info, 'editUrl': reverse('wagtail_localize:edit_string_translation', kwargs={ 'translation_id': translation.id, 'string_segment_id': segment.id }), 'order': segment.order, }) for segment in overridable_segments: try: location_info = get_segment_location_info(source_instance, tab_helper, segment.context.path, widget=True) except FieldHasNoEditPanelError: continue segments.append({ 'type': 'synchronised_value', 'id': segment.id, 'contentPath': segment.context.path, 'location': location_info, 'value': segment.data, 'editUrl': reverse('wagtail_localize:edit_override', kwargs={ 'translation_id': translation.id, 'overridable_segment_id': segment.id }), 'order': segment.order, }) def get_source_object_info(segment): instance = segment.get_source_instance() if isinstance(instance, Page): return { 'title': str(instance), 'isLive': instance.live, 'liveUrl': instance.full_url, 'editUrl': reverse('wagtailadmin_pages:edit', args=[instance.id]), 'createTranslationRequestUrl': reverse('wagtail_localize:submit_page_translation', args=[instance.id]), } else: return { 'title': str(instance), 'isLive': True, 'editUrl': reverse('wagtailsnippets:edit', args=[ instance._meta.app_label, instance._meta.model_name, quote(instance.id) ]), 'createTranslationRequestUrl': reverse('wagtail_localize:submit_snippet_translation', args=[ instance._meta.app_label, instance._meta.model_name, quote(instance.id) ]), } def get_dest_object_info(segment): instance = segment.object.get_instance_or_none( translation.target_locale) if not instance: return if isinstance(instance, Page): return { 'title': str(instance), 'isLive': instance.live, 'liveUrl': instance.full_url, 'editUrl': reverse('wagtailadmin_pages:edit', args=[instance.id]), } else: return { 'title': str(instance), 'isLive': True, 'editUrl': reverse('wagtailsnippets:edit', args=[ instance._meta.app_label, instance._meta.model_name, quote(instance.id) ]), } def get_translation_progress(segment, locale): try: translation = Translation.objects.get( source__object_id=segment.object_id, target_locale=locale, enabled=True) except Translation.DoesNotExist: return None total_segments, translated_segments = translation.get_progress() return { 'totalSegments': total_segments, 'translatedSegments': translated_segments, } for segment in related_object_segments: try: location_info = get_segment_location_info(source_instance, tab_helper, segment.context.path) except FieldHasNoEditPanelError: continue segments.append({ 'type': 'related_object', 'id': segment.id, 'contentPath': segment.context.path, 'location': location_info, 'order': segment.order, 'source': get_source_object_info(segment), 'dest': get_dest_object_info(segment), 'translationProgress': get_translation_progress(segment, translation.target_locale), }) # Order segments by how they appear in the content panels # segment['location']['order'] is the content panel ordering # segment['order'] is the model field ordering # User's expect segments to follow the panel ordering as that's the ordering # that is used in the page editor of the source page. However, segments that # come from the same streamfield/inline panel are given the same value for # panel ordering, so we need to order by model field ordering as well (all # segments have a unique value for model field ordering) segments.sort( key=lambda segment: (segment['location']['order'], segment['order'])) # Display a warning to the user if the schema of the source model has been updated since the source was last updated if translation.source.schema_out_of_date(): messages.warning( request, _("The data model for '{model_name}' has been changed since the last translation sync. " "If any new fields have been added recently, these may not be visible until the next translation sync." ).format( model_name=capfirst(source_instance._meta.verbose_name))) return render( request, 'wagtail_localize/admin/edit_translation.html', { 'translation': translation, # These props are passed directly to the TranslationEditor react component 'props': json.dumps( { 'adminBaseUrl': reverse('wagtailadmin_home'), 'object': { 'title': str(instance), 'titleSegmentId': title_segment_id, 'isLive': is_live, 'isLocked': is_locked, 'lastPublishedDate': last_published_at.strftime(DATE_FORMAT) if last_published_at is not None else None, 'lastPublishedBy': UserSerializer(last_published_by).data if last_published_by is not None else None, 'liveUrl': live_url, }, 'breadcrumb': breadcrumb, 'tabs': tab_helper.tabs_with_slugs, 'sourceLocale': { 'code': translation.source.locale.language_code, 'displayName': translation.source.locale.get_display_name(), }, 'locale': { 'code': translation.target_locale.language_code, 'displayName': translation.target_locale.get_display_name(), }, 'translations': [{ 'title': str(translated_instance), 'locale': { 'code': translated_instance.locale.language_code, 'displayName': translated_instance.locale.get_display_name(), }, 'editUrl': reverse('wagtailadmin_pages:edit', args=[translated_instance.id]) if isinstance( translated_instance, Page) else reverse('wagtailsnippets:edit', args=[ translated_instance._meta.app_label, translated_instance._meta.model_name, quote(translated_instance.id) ]), } for translated_instance in instance.get_translations(). select_related('locale')], 'perms': { 'canPublish': can_publish, 'canUnpublish': can_unpublish, 'canLock': can_lock, 'canUnlock': can_unlock, 'canDelete': can_delete, }, 'links': { 'downloadPofile': reverse('wagtail_localize:download_pofile', args=[translation.id]), 'uploadPofile': reverse('wagtail_localize:upload_pofile', args=[translation.id]), 'unpublishUrl': reverse('wagtailadmin_pages:unpublish', args=[instance.id]) if isinstance( instance, Page) else None, 'lockUrl': reverse('wagtailadmin_pages:lock', args=[instance.id]) if isinstance(instance, Page) else None, 'unlockUrl': reverse('wagtailadmin_pages:unlock', args=[instance.id]) if isinstance( instance, Page) else None, 'deleteUrl': reverse('wagtailadmin_pages:delete', args=[instance.id]) if isinstance( instance, Page) else reverse( 'wagtailsnippets:delete', args=[ instance._meta.app_label, instance._meta.model_name, quote(instance.pk) ]), 'stopTranslationUrl': reverse('wagtail_localize:stop_translation', args=[translation.id]), }, 'previewModes': [{ 'mode': mode, 'label': label, 'url': reverse('wagtail_localize:preview_translation', args=[translation.id]) if mode == instance.default_preview_mode else reverse( 'wagtail_localize:preview_translation', args=[translation.id, mode]), } for mode, label in (instance.preview_modes if isinstance( instance, Page) else [])], 'machineTranslator': machine_translator, 'segments': segments, # We serialize the translation data using Django REST Framework. # This gives us a consistent representation with the APIs so we # can dynamically update translations in the view. 'initialStringTranslations': StringTranslationSerializer(string_translations, many=True, context={ 'translation_source': translation.source }).data, 'initialOverrides': SegmentOverrideSerializer(segment_overrides, many=True, context={ 'translation_source': translation.source }).data, }, cls=DjangoJSONEncoder) })
def items_for_result(view, result): """ Generates the actual list of data. """ modeladmin = view.model_admin for field_name in view.list_display: empty_value_display = modeladmin.get_empty_value_display(field_name) row_classes = ['field-%s' % field_name] try: f, attr, value = lookup_field(field_name, result, modeladmin) except ObjectDoesNotExist: result_repr = empty_value_display else: empty_value_display = getattr(attr, 'empty_value_display', empty_value_display) if f is None or f.auto_created: allow_tags = getattr(attr, 'allow_tags', False) boolean = getattr(attr, 'boolean', False) if boolean or not value: allow_tags = True result_repr = display_for_value(value, empty_value_display, boolean) # Strip HTML tags in the resulting text, except if the # function has an "allow_tags" attribute set to True. if allow_tags: result_repr = mark_safe(result_repr) if isinstance(value, (datetime.date, datetime.time)): row_classes.append('nowrap') else: if isinstance(f, models.ManyToOneRel): field_val = getattr(result, f.name) if field_val is None: result_repr = empty_value_display else: result_repr = field_val else: result_repr = display_for_field(value, f, empty_value_display) if isinstance( f, (models.DateField, models.TimeField, models.ForeignKey)): row_classes.append('nowrap') if force_str(result_repr) == '': result_repr = mark_safe(' ') row_classes.extend( modeladmin.get_extra_class_names_for_field_col(result, field_name)) row_attrs = modeladmin.get_extra_attrs_for_field_col( result, field_name) row_attrs['class'] = ' '.join(row_classes) row_attrs_flat = flatatt(row_attrs) url_to_edit = view.url_helper.get_action_url( 'edit', quote(lookup_field('pk', result, modeladmin)[2])) if field_name in [ 'title', ]: yield format_html( '<td class="title"><div class="title-wrapper"><a href="{}">{}</a></div></td>', url_to_edit, result_repr) else: yield format_html('<td{}>{}</td>', row_attrs_flat, result_repr)
def get_link_url(self, instance, parent_context): if self._get_url_func: return self._get_url_func(instance) else: return reverse(self.url_name, args=(quote(instance.pk), ))
def get_success_message_buttons(self, instance): button_url = self.url_helper.get_action_url('edit', quote(instance.pk)) return [messages.button(button_url, _('Edit'))]
def get_action_btn(self,obj): pk = obj.id edit_url = reverse('admin:%s_%s_change' % (self.opts.app_label,self.opts.model_name),args=(quote(pk),)) delete_url = reverse('admin:%s_%s_delete' % (self.opts.app_label,self.opts.model_name),args=(quote(pk),)) history_url = reverse('admin:%s_%s_history' % (self.opts.app_label,self.opts.model_name),args=(quote(pk),)) html = ''' <a href="'''+edit_url+'''" data-toggle="tooltip" class="btn btn-sm btn-primary" data-original-title="Edit"> <i class="fas fa-edit"></i> Edit </a> <a href="'''+delete_url+'''" data-toggle="tooltip" class="btn btn-sm btn-primary" data-original-title="Delete"> <i class="fas fa-trash-alt"></i> Delete </a> <a href="'''+history_url+'''" data-toggle="tooltip" class="btn btn-sm btn-primary" data-original-title="History"> <i class="fas fa-history"></i> History </a> ''' return format_html(html)
def get_edit_item_url(self, instance): if self.edit_item_url_name is None: return None else: object_id = self.get_object_id(instance) return reverse(self.edit_item_url_name, args=(quote(object_id), ))
def edit(request, app_label, model_name, pk): model = get_snippet_model_from_url_params(app_label, model_name) permission = get_permission_name("change", model) if not request.user.has_perm(permission): raise PermissionDenied instance = get_object_or_404(model, pk=unquote(pk)) for fn in hooks.get_hooks("before_edit_snippet"): result = fn(request, instance) if hasattr(result, "status_code"): return result edit_handler = get_snippet_edit_handler(model) form_class = edit_handler.get_form_class() if request.method == "POST": form = form_class(request.POST, request.FILES, instance=instance, for_user=request.user) if form.is_valid(): with transaction.atomic(): form.save() log(instance=instance, action="wagtail.edit") messages.success( request, _("%(snippet_type)s '%(instance)s' updated.") % { "snippet_type": capfirst(model._meta.verbose_name), "instance": instance, }, buttons=[ messages.button( reverse( "wagtailsnippets:edit", args=(app_label, model_name, quote(instance.pk)), ), _("Edit"), ) ], ) for fn in hooks.get_hooks("after_edit_snippet"): result = fn(request, instance) if hasattr(result, "status_code"): return result return redirect("wagtailsnippets:list", app_label, model_name) else: messages.validation_error( request, _("The snippet could not be saved due to errors."), form) else: form = form_class(instance=instance, for_user=request.user) edit_handler = edit_handler.get_bound_panel(instance=instance, request=request, form=form) latest_log_entry = log_registry.get_logs_for_instance(instance).first() action_menu = SnippetActionMenu(request, view="edit", instance=instance) context = { "model_opts": model._meta, "instance": instance, "edit_handler": edit_handler, "form": form, "action_menu": action_menu, "locale": None, "translations": [], "latest_log_entry": latest_log_entry, "media": edit_handler.media + form.media + action_menu.media, } if getattr(settings, "WAGTAIL_I18N_ENABLED", False) and issubclass( model, TranslatableMixin): context.update({ "locale": instance.locale, "translations": [{ "locale": translation.locale, "url": reverse( "wagtailsnippets:edit", args=[app_label, model_name, quote(translation.pk)], ), } for translation in instance.get_translations().select_related( "locale")], }) return TemplateResponse(request, "wagtailsnippets/snippets/edit.html", context)
def test_get_edit(self): response = self.client.get( reverse('wagtailsnippets:edit', args=('tests', 'advert', quote(self.test_snippet.pk)))) # permission should be denied self.assertRedirects(response, reverse('wagtailadmin_home'))
def get_chosen_url(self, instance): object_id = self.get_object_id(instance) return reverse(self.chosen_url_name, args=(quote(object_id), ))
def test_get_edit(self): response = self.client.get( reverse('wagtailsnippets:edit', args=('tests', 'advert', quote(self.test_snippet.pk)))) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailsnippets/snippets/edit.html')
default_model_admin = ContestAdmin def _mixins_for_instance(self, request, instance=None): if instance: controller = instance.controller return (controller.mixins_for_admin() + controller.registration_controller().mixins_for_admin()) contest_site.register(Contest, BaseContestAdmin) contest_admin_menu_registry.register( 'contest_change', _("Settings"), lambda request: reverse('oioioiadmin:contests_contest_change', args=(quote(request.contest.id), )), order=20, ) class ProblemInstanceAdmin(admin.ModelAdmin): form = ProblemInstanceForm fields = ('contest', 'round', 'problem', 'short_name', 'submissions_limit') list_display = ('name_link', 'short_name_link', 'round', 'package', 'actions_field') readonly_fields = ('contest', 'problem') ordering = ('-round__start_date', 'short_name') def __init__(self, *args, **kwargs): # creating a thread local variable to store the request self._request_local = threading.local()
def get_edit_item_url(self, item): return reverse('wagtailsnippets:edit', args=('npcs', 'npc', quote(item.pk)))
def test_logentry_change_message_formsets(self): """ All messages for changed formsets are logged in a change message. """ a2 = Article.objects.create( site=self.site, title="Title second article", created=datetime(2012, 3, 18, 11, 54), ) post_data = { 'domain': 'example.com', # domain changed 'admin_articles-TOTAL_FORMS': '5', 'admin_articles-INITIAL_FORMS': '2', 'admin_articles-MIN_NUM_FORMS': '0', 'admin_articles-MAX_NUM_FORMS': '1000', # Changed title for 1st article 'admin_articles-0-id': str(self.a1.pk), 'admin_articles-0-site': str(self.site.pk), 'admin_articles-0-title': 'Changed Title', # Second article is deleted 'admin_articles-1-id': str(a2.pk), 'admin_articles-1-site': str(self.site.pk), 'admin_articles-1-title': 'Title second article', 'admin_articles-1-DELETE': 'on', # A new article is added 'admin_articles-2-site': str(self.site.pk), 'admin_articles-2-title': 'Added article', } change_url = reverse('admin:admin_utils_site_change', args=[quote(self.site.pk)]) response = self.client.post(change_url, post_data) self.assertRedirects(response, reverse('admin:admin_utils_site_changelist')) self.assertQuerysetEqual(Article.objects.filter(pk=a2.pk), []) logentry = LogEntry.objects.filter( content_type__model__iexact='site').latest('action_time') self.assertEqual(json.loads(logentry.change_message), [ { "changed": { "fields": ["domain"] } }, { "added": { "object": "Article object", "name": "article" } }, { "changed": { "fields": ["title"], "object": "Article object", "name": "article" } }, { "deleted": { "object": "Article object", "name": "article" } }, ]) self.assertEqual( logentry.get_change_message(), 'Changed domain. Added article "Article object". ' 'Changed title for article "Article object". Deleted article "Article object".' ) with translation.override('fr'): self.assertEqual( logentry.get_change_message(), "Domain modifié(s). Article « Article object » ajouté. " "Title modifié(s) pour l'objet article « Article object ». Article « Article object » supprimé." )
def response_add(self, request, obj, post_url_continue=None): """ Determines the HttpResponse for the add_view stage. """ opts = obj._meta preserved_filters = self.get_preserved_filters(request) # frePPLe specific: prepend the url prefix obj_url = request.prefix + reverse( "admin:%s_%s_change" % (opts.app_label, opts.model_name), args=(quote(obj.pk), ), current_app=self.admin_site.name, ) # Add a link to the object's change form if the user can edit the obj. if self.has_change_permission(request, obj): obj_repr = format_html('<a href="{}">{}</a>', urlquote(obj_url), obj) else: obj_repr = str(obj) msg_dict = {"name": opts.verbose_name, "obj": obj_repr} # Here, we distinguish between different save types by checking for # the presence of keys in request.POST. if IS_POPUP_VAR in request.POST: to_field = request.POST.get(TO_FIELD_VAR) if to_field: attr = str(to_field) else: attr = obj._meta.pk.attname value = obj.serializable_value(attr) popup_response_data = json.dumps({ "value": str(value), "obj": str(obj) }) return TemplateResponse( request, self.popup_response_template or [ "admin/%s/%s/popup_response.html" % (opts.app_label, opts.model_name), "admin/%s/popup_response.html" % opts.app_label, "admin/popup_response.html", ], {"popup_response_data": popup_response_data}, ) elif "_continue" in request.POST or ( # Redirecting after "Save as new". "_saveasnew" in request.POST and self.save_as_continue and self.has_change_permission(request, obj)): msg = _('The {name} "{obj}" was added successfully.') if self.has_change_permission(request, obj): msg = format_lazy("{} {}", msg, _("You may edit it again below.")) self.message_user(request, format_html(msg, **msg_dict), messages.SUCCESS) if post_url_continue is None: post_url_continue = obj_url post_url_continue = add_preserved_filters( { "preserved_filters": preserved_filters, "opts": opts }, post_url_continue, ) return HttpResponseRedirect(post_url_continue) elif "_addanother" in request.POST: msg = format_html( _('The {name} "{obj}" was added successfully. You may add another {name} below.' ), **msg_dict) self.message_user(request, msg, messages.SUCCESS) # frePPLe specific: prepend the url prefix redirect_url = request.prefix + request.path redirect_url = add_preserved_filters( { "preserved_filters": preserved_filters, "opts": opts }, redirect_url) return HttpResponseRedirect(redirect_url) else: msg = format_html(_('The {name} "{obj}" was added successfully.'), **msg_dict) self.message_user(request, msg, messages.SUCCESS) return self.response_post_save_add(request, obj)
class BaseContestAdmin(admin.MixinsAdmin): default_model_admin = ContestAdmin def _mixins_for_instance(self, request, instance=None): if instance: controller = instance.controller return controller.mixins_for_admin() + \ controller.registration_controller().mixins_for_admin() contest_site.register(Contest, BaseContestAdmin) contest_admin_menu_registry.register('contest_change', _("Settings"), lambda request: reverse('oioioiadmin:contests_contest_change', args=(quote(request.contest.id),)), order=20) class ProblemInstanceAdmin(admin.ModelAdmin): form = ProblemInstanceForm fields = ('contest', 'round', 'problem', 'short_name', 'submissions_limit') list_display = ('name_link', 'short_name_link', 'round', 'package', 'actions_field') readonly_fields = ('contest', 'problem') ordering = ('-round__start_date', 'short_name') def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): return is_contest_basicadmin(request)
def test_non_existant_model(self): response = self.client.get( reverse('wagtailsnippets:edit', args=('tests', 'foo', quote(self.test_snippet.pk)))) self.assertEqual(response.status_code, 404)
def comment_view(self, request, object_id, extra_context=None): request.session["lasttab"] = "comments" try: model = self.model._meta.model_name modeltype = ContentType.objects.using(request.database).get( app_label=self.model._meta.app_label, model=model) modeltype._state.db = request.database object_id = unquote(object_id) # Special treatment for buffers if model == "buffer": from freppledb.input.models import Buffer if " @ " in object_id: bufferName = object_id index = object_id.find(" @ ") b = Buffer.objects.get(item=object_id[0:index], location=object_id[index + 3:]) if b: object_id = b.id else: b = Buffer.objects.get(id=object_id) bufferName = b.item.name + " @ " + b.location.name modelinstance = modeltype.get_object_for_this_type(pk=object_id) comments = (Comment.objects.using( request.database).filter(content_type__pk=modeltype.id, object_pk=object_id).order_by("-id")) except Exception: raise Http404("Object not found") if request.method == "POST": if request.user.has_perm("common.add_comment"): comment = request.POST["comment"] att = request.FILES.get("attachment", None) if comment or att: c = Comment( content_object=modelinstance, object_repr=str(modelinstance)[:200], user=request.user, comment=comment, type="comment", ) if att: c.attachment = att c.save(using=request.database) return HttpResponseRedirect("%s%s" % (request.prefix, request.path)) else: request.session["lasttab"] = "messages" return render( request, "common/comments.html", context={ "title": force_text(modelinstance._meta.verbose_name) + " " + (bufferName if "bufferName" in vars() else object_id), "post_title": _("messages"), "model": self.model, "opts": self.model._meta, "object_id": quote(object_id), "active_tab": "comments", "comments": comments, }, )
def url_for_folder(node): return reverse('admin:core_basetreenode_changelist_obj', args=(quote(node.id), ), current_app='boss')
def url_for_document(node): return reverse('admin:core_basetreenode_change', args=(quote(node.id), ), current_app='boss')
def form_valid(self, form): parent_pk = quote(form.cleaned_data['parent_page'].pk) return redirect( self.url_helper.get_action_url('add', self.app_label, self.model_name, parent_pk))
def get(self, snippet, params={}): args = (snippet._meta.app_label, snippet._meta.model_name, quote(snippet.pk)) return self.client.get(reverse('wagtailsnippets:edit', args=args), params)