Как перенаправить на пользовательскую страницу администратора с помощью настраиваемого поля администратора в панели администратора django

#django #django-admin #custom-pages

#django #django-admin #пользовательские страницы

Вопрос:

Наличие моего PlugAdmin класса

 class PlugAdmin(admin.ModelAdmin):
    list_display = (...'custom_link')
 

admin.py среди других полей моей модели я определил custom_link поле, как показано ниже:

 def custom_link(self, obj):
        info = (obj._meta.app_label, obj._meta.model_name)
        return mark_safe('<a class="custom" href="%s">Advanced Config Page</a>' % reverse('admin:%s/%s/advanced-config' % info, args=(obj.pk,)))
 

Нажав кнопку custom_link «Моя цель — перенаправить на advanced_config_view пользовательскую страницу администратора, которая была определена правильно (как в admin.site.urls, так и в виде представления:

 def get_urls(self):
        urls = super().get_urls()
        my_urls = [
            path('<uuid:plug_id>/advanced-config/', self.admin_site.admin_view(self.advanced_config_view), name = "advanced_config"),
        ]
        return my_urls   urls

def advanced_config_view(self, request, plug_id):
    plug = Plug.objects.get(id = plug_id)
    context = dict(
       # Include common variables for rendering the admin template.
       self.admin_site.each_context(request),
       plug = plug,
    )
    return TemplateResponse(request, "custom_admin/advanced_config.html", context)
 

Моя страница не может загрузиться, и я получил сообщение об ошибке от Traceback :

 Template error:
In template /home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/contrib/admin/templates/admin/base.html, error at line 65
   Reverse for 'stations/plug/advanced-config' not found. 'stations/plug/advanced-config' is not a valid view function or pattern name.
   55 :                 <a href="{% url 'admin:logout' %}">{% translate 'Log out' %}</a>
   56 :             {% endblock %}
   57 :         </div>
   58 :         {% endif %}
   59 :         {% endblock %}
   60 :         {% block nav-global %}{% endblock %}
   61 :     </div>
   62 :     <!-- END Header -->
   63 :     {% block breadcrumbs %}
   64 :     <div class="breadcrumbs">
   65 :     <a href="{% url 'admin:inde x' %}">{% translate  'Home' %}</a>
   66 :     {% if title %} amp;rsaquo; {{ title }}{% endif %}
   67 :     </div>
   68 :     {% endblock %}
   69 :     {% endif %}
   70 : 
   71 :     <div class="main shifted" id="main">
   72 :       {% if not is_popup and is_nav_sidebar_enabled %}
   73 :         {% block nav-sidebar %}
   74 :           {% include "admin/nav_sidebar.html" %}
   75 :         {% endblock %}


Traceback (most recent call last):
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/db/models/options.py", line 575, in get_field
    return self.fields_map[field_name]

During handling of the above exception ('custom_link'), another exception occurred:
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/contrib/admin/utils.py", line 264, in lookup_field
    f = _get_non_gfk_field(opts, name)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/contrib/admin/utils.py", line 295, in _get_non_gfk_field
    field = opts.get_field(name)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/db/models/options.py", line 577, in get_field
    raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))

During handling of the above exception (Plug has no field named 'custom_link'), another exception occurred:
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/asgiref/sync.py", line 330, in thread_handler
    raise exc_info[1]
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/core/handlers/exception.py", line 38, in inner
    response = await get_response(request)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/core/handlers/base.py", line 261, in _get_response_async
    response = await sync_to_async(response.render, thread_sensitive=True)()
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/asgiref/sync.py", line 296, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "/usr/lib/python3.7/asyncio/tasks.py", line 414, in wait_for
    return await fut
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/asgiref/sync.py", line 334, in thread_handler
    return func(*args, **kwargs)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/response.py", line 83, in rendered_content
    return template.render(context, self._request)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/contrib/admin/templatetags/base.py", line 33, in render
    return super().render(context)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/template/library.py", line 214, in render
    _dict = self.func(*resolved_args, **resolved_kwargs)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/contrib/admin/templatetags/admin_list.py", line 341, in result_list
    'results': list(results(cl)),
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/contrib/admin/templatetags/admin_list.py", line 317, in results
    yield ResultList(None, items_for_result(cl, res, None))
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/contrib/admin/templatetags/admin_list.py", line 308, in __init__
    super().__init__(*items)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/contrib/admin/templatetags/admin_list.py", line 233, in items_for_result
    f, attr, value = lookup_field(field_name, result, cl.model_admin)
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/contrib/admin/utils.py", line 273, in lookup_field
    value = attr(obj)
  File "/home/giorgos/Desktop/ev-loader/backend/stations/admin.py", line 87, in custom_link
    return mark_safe('<a class="custom" href="%s">Advanced Config Page</a>' % reverse('admin:%s/%s/advanced-config' % info, args=(obj.pk,)))
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/urls/base.py", line 87, in reverse
    return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
  File "/home/giorgos/.local/share/virtualenvs/backend-tSqKtrJ_/lib/python3.7/site-packages/django/urls/resolvers.py", line 685, in _reverse_with_prefix
    raise NoReverseMatch(msg)

Exception Type: NoReverseMatch at /admin/stations/plug/
Exception Value: Reverse for 'stations/plug/advanced-config' not found. 'stations/plug/advanced-config' is not a valid view function or pattern name.
 

Как я могу исправить это, чтобы перенаправить на URL с именем advanced_config?

Пользовательский URL работает правильно.

Ответ №1:

Неисправная часть была в reverse() конструкции.

Наконец, перенаправление происходит, как и ожидалось, с :

 return mark_safe('<a class="custom" href="%s">Advanced Config Page</a>' % reverse("admin:advanced_config",  kwargs={ "plug_id": obj.pk }))
 

P.S: Пространство имен URL-адресов, определенных в get_urls() функции, — admin