Django: ¿Cómo puedo ver una lista de patrones de url?

130

¿Cómo puedo ver los patrones de url actuales en los que se está viendo "reverse"?

Estoy llamando al revés en una vista con un argumento que creo que debería funcionar, pero no funciona. ¿De alguna manera puedo verificar qué hay allí y por qué mi patrón no lo está?

interstar
fuente
¿Activa el modo DEPURACIÓN y mira la lista de URLS en la salida de depuración?
Boatcoder

Respuestas:

181

Si desea una lista de todas las URL en su proyecto, primero necesita instalar django-extensions , agréguelo a su configuración de esta manera:

INSTALLED_APPS = (
...
'django_extensions',
...
)

Y luego, ejecuta este comando en tu terminal

./manage.py show_urls

Para más información puede consultar la documentación.

robert
fuente
3
En realidad estaba equivocado, esta característica no es proporcionada por django después de todo.
robert
Todo lo que obtengo de eso esTypeError: unsupported operand type(s) for +: 'NoneType' and 'str'
Paul Tomblin el
66
NB: debe agregar django_extensionsa su INSTALLED_APPSdespués de la instalación
Owen
80

Prueba esto:

from django.urls import get_resolver
get_resolver().reverse_dict.keys()

O si todavía estás en Django 1. *:

from django.core.urlresolvers import get_resolver
get_resolver(None).reverse_dict.keys()
SmileyChris
fuente
9
esto devuelve las funciones de vista, no las URL
Ronen Ness
3
Para que devuelva las URL, haga esto en su lugar: set (v [1] para k, v en get_resolver (None) .reverse_dict.iteritems ())
kloddant
3
O para python3:set(v[1] for k,v in get_resolver(None).reverse_dict.items())
Privado
66
django.core.urlresolversse eliminó en Django 2.0 , reemplace la línea de importación confrom django.urls import get_resolver
hoefling el
2
esto ya no funciona para mí, solo devuelve un pequeño subconjunto de las URL en mi proyecto
J__
33

Django> = solución 2.0

Probé las otras respuestas en esta publicación y no funcionaban con Django 2.X, incompletas o demasiado complejas. Por lo tanto, aquí está mi opinión sobre esto:

from django.conf import settings
from django.urls import URLPattern, URLResolver

urlconf = __import__(settings.ROOT_URLCONF, {}, {}, [''])

def list_urls(lis, acc=None):
    if acc is None:
        acc = []
    if not lis:
        return
    l = lis[0]
    if isinstance(l, URLPattern):
        yield acc + [str(l.pattern)]
    elif isinstance(l, URLResolver):
        yield from list_urls(l.url_patterns, acc + [str(l.pattern)])
    yield from list_urls(lis[1:], acc)

for p in list_urls(urlconf.urlpatterns):
    print(''.join(p))

Este código imprime todas las URL, a diferencia de otras soluciones, imprimirá la ruta completa y no solo el último nodo. p.ej:

admin/
admin/login/
admin/logout/
admin/password_change/
admin/password_change/done/
admin/jsi18n/
admin/r/<int:content_type_id>/<path:object_id>/
admin/auth/group/
admin/auth/group/add/
admin/auth/group/autocomplete/
admin/auth/group/<path:object_id>/history/
admin/auth/group/<path:object_id>/delete/
admin/auth/group/<path:object_id>/change/
admin/auth/group/<path:object_id>/
admin/auth/user/<id>/password/
admin/auth/user/
... etc, etc
Cesar Canassa
fuente
1
¿Cómo puedo hacer si quiero obtener la URL y el nombre de la vista ... Porque yo quiero obtener el nombre de la vista y el patrón como su resultado ... Por favor, ¿cómo?
Nathan Ingram
@NathanIngram La vista se almacena en la propiedad "devolución de llamada" del objeto URLPattern, por lo que puede cambiar la yield acc + [str(l.pattern)]línea a yield acc + [str(l.pattern)], l.callback. Tenga en cuenta que devolverá la función de vista en sí y no un nombre
Cesar Canassa
Me sale el error: --- >>>> TypeError: elemento de secuencia 0: instancia de str esperada, lista encontrada
Nathan Ingram
@NathanIngram "print (''. Join (p))" no funcionará porque ahora es una lista de tuplas en lugar de una lista de cadenas, intente "print (''. Join (p [0]))".
Cesar Canassa
22

Django 1.11, Python 2.7.6

cd to_your_django_project

Python manage.py shell

Luego pegue el siguiente código.

from django.conf.urls import RegexURLPattern, RegexURLResolver
from django.core import urlresolvers
urls = urlresolvers.get_resolver()

def if_none(value):
    if value:
        return value
    return ''

def print_urls(urls, parent_pattern=None):
    for url in urls.url_patterns:
        if isinstance(url, RegexURLResolver):
            print_urls(url, if_none(parent_pattern) + url.regex.pattern)
        elif isinstance(url, RegexURLPattern):
            print(if_none(parent_pattern) + url.regex.pattern)

print_urls(urls)

Salida de muestra:

^django-admin/^$
^django-admin/^login/$
^django-admin/^logout/$
^django-admin/^password_change/$
^django-admin/^password_change/done/$
^django-admin/^jsi18n/$
^django-admin/^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$
^django-admin/^wagtailimages/image/^$
^django-admin/^wagtailimages/image/^add/$
^django-admin/^wagtailimages/image/^(.+)/history/$
^django-admin/^wagtailimages/image/^(.+)/delete/$
^django-admin/^wagtailimages/image/^(.+)/change/$
^django-admin/^wagtailimages/image/^(.+)/$
...
pequeño mamífero
fuente
Esta es la respuesta que funcionó para mí, aunque tuve que agregar Nonea la línea urls = urlresolvers.get_resolver(None), y a veces recibí 'Ninguno' al comienzo de algunas URL.
Chris
17

Hay una receta en estado activo

import urls

def show_urls(urllist, depth=0):
    for entry in urllist:
        print("  " * depth, entry.regex.pattern)
        if hasattr(entry, 'url_patterns'):
            show_urls(entry.url_patterns, depth + 1)

show_urls(urls.url_patterns)
pmav99
fuente
1
Esa última línea debería ser show_urls(urls.url_patterns).
Daniel Quinn
1
Me estoy poniendo ModuleNotFoundError: No module named 'urls', no sé por qué?
Alexey
1
@Alexey Esto es algo que probablemente tenga que ver con django 2. ¿Puede confirmar esto por favor para que pueda actualizar la respuesta?
pmav99
He colocado este código en el archivo test.pyen la raíz de mi proyecto y tengo este error, también si lo hago import urlsen intérprete, también recibo este error.
Alexey
No es un problema Django 1 vs 2: import urlses una importación local, por lo que probablemente deba hacerlo from app_name import urls.
Aaron Klein
16

Estoy usando el siguiente comando:

(Python3 + Django 1.10)

from django.core.management import BaseCommand
from django.conf.urls import RegexURLPattern, RegexURLResolver
from django.core import urlresolvers


class Command(BaseCommand):

    def add_arguments(self, parser):

        pass

    def handle(self, *args, **kwargs):

        urls = urlresolvers.get_resolver()
        all_urls = list()

        def func_for_sorting(i):
            if i.name is None:
                i.name = ''
            return i.name

        def show_urls(urls):
            for url in urls.url_patterns:
                if isinstance(url, RegexURLResolver):
                    show_urls(url)
                elif isinstance(url, RegexURLPattern):
                    all_urls.append(url)
        show_urls(urls)

        all_urls.sort(key=func_for_sorting, reverse=False)

        print('-' * 100)
        for url in all_urls:
            print('| {0.regex.pattern:20} | {0.name:20} | {0.lookup_str:20} | {0.default_args} |'.format(url))
        print('-' * 100)

Uso:

./manage.py showurls

Salida de muestra:

----------------------------------------------------------------------------------------------------
| ^(.+)/$              |                      | django.views.generic.base.RedirectView | {} |
| ^(.+)/$              |                      | django.views.generic.base.RedirectView | {} |
| ^(.+)/$              |                      | django.views.generic.base.RedirectView | {} |
| ^(.+)/$              |                      | django.views.generic.base.RedirectView | {} |
| ^(.+)/$              |                      | django.views.generic.base.RedirectView | {} |
| ^(.+)/$              |                      | django.views.generic.base.RedirectView | {} |
| ^static\/(?P<path>.*)$ |                      | django.contrib.staticfiles.views.serve | {} |
| ^media\/(?P<path>.*)$ |                      | django.views.static.serve | {'document_root': '/home/wlysenko/.virtualenvs/programmerHelper/project/media'} |
| ^(?P<app_label>polls|snippets|questions)/$ | app_list             | apps.core.admin.AdminSite.app_index | {} |
| ^(?P<app_label>activity|articles|badges|books|comments|flavours|forum|marks|newsletters|notifications|opinions|polls|questions|replies|snippets|solutions|tags|testing|users|utilities|visits)/reports/$ | app_reports          | apps.core.admin.AdminSite.reports_view | {} |
| ^(?P<app_label>activity|articles|badges|books|comments|flavours|forum|marks|newsletters|notifications|opinions|polls|questions|replies|snippets|solutions|tags|testing|users|utilities|visits)/statistics/$ | app_statistics       | apps.core.admin.AdminSite.statistics_view | {} |
| articles/(?P<slug>[-\w]+)/$ | article              | apps.articles.views.ArticleDetailView | {} |
| book/(?P<slug>[-_\w]+)/$ | book                 | apps.books.views.BookDetailView | {} |
| category/(?P<slug>[-_\w]+)/$ | category             | apps.utilities.views.CategoryDetailView | {} |
| create/$             | create               | apps.users.views.UserDetailView | {} |
| delete/$             | delete               | apps.users.views.UserDetailView | {} |
| detail/(?P<email>\w+@[-_\w]+.\w+)/$ | detail               | apps.users.views.UserDetailView | {} |
| snippet/(?P<slug>[-_\w]+)/$ | detail               | apps.snippets.views.SnippetDetailView | {} |
| (?P<contenttype_model_pk>\d+)/(?P<pks_separated_commas>[-,\w]*)/$ | export               | apps.export_import_models.views.ExportTemplateView | {} |
| download_preview/$   | export_preview_download | apps.export_import_models.views.ExportPreviewDownloadView | {} |
| ^$                   | import               | apps.export_import_models.views.ImportTemplateView | {} |
| result/$             | import_result        | apps.export_import_models.views.ImportResultTemplateView | {} |
| ^$                   | index                | django.contrib.admin.sites.AdminSite.index | {} |
| ^$                   | index                | apps.core.views.IndexView | {} |
| ^jsi18n/$            | javascript-catalog   | django.views.i18n.javascript_catalog | {'packages': ('your.app.package',)} |
| ^jsi18n/$            | jsi18n               | django.contrib.admin.sites.AdminSite.i18n_javascript | {} |
| level/(?P<slug>[-_\w]+)/$ | level                | apps.users.views.UserDetailView | {} |
| ^login/$             | login                | django.contrib.admin.sites.AdminSite.login | {} |
| ^logout/$            | logout               | django.contrib.admin.sites.AdminSite.logout | {} |
| newsletter/(?P<slug>[_\w]+)/$ | newsletter           | apps.newsletters.views.NewsletterDetailView | {} |
| newsletters/$        | newsletters          | apps.newsletters.views.NewslettersListView | {} |
| notification/(?P<account_email>[-\w]+@[-\w]+.\w+)/$ | notification         | apps.notifications.views.NotificationDetailView | {} |
| ^password_change/$   | password_change      | django.contrib.admin.sites.AdminSite.password_change | {} |
| ^password_change/done/$ | password_change_done | django.contrib.admin.sites.AdminSite.password_change_done | {} |
| ^image/(?P<height>\d+)x(?P<width>\d+)/$ | placeholder          | apps.core.views.PlaceholderView | {} |
| poll/(?P<pk>\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/(?P<slug>[-\w]+)/$ | poll                 | apps.polls.views.PollDetailView | {} |
| ^add/$               | polls_choice_add     | django.contrib.admin.options.ModelAdmin.add_view | {} |
| ^(.+)/change/$       | polls_choice_change  | django.contrib.admin.options.ModelAdmin.change_view | {} |
| ^$                   | polls_choice_changelist | django.contrib.admin.options.ModelAdmin.changelist_view | {} |
| ^(.+)/delete/$       | polls_choice_delete  | django.contrib.admin.options.ModelAdmin.delete_view | {} |
| ^(.+)/history/$      | polls_choice_history | django.contrib.admin.options.ModelAdmin.history_view | {} |
| ^add/$               | polls_poll_add       | django.contrib.admin.options.ModelAdmin.add_view | {} |
| ^(.+)/change/$       | polls_poll_change    | django.contrib.admin.options.ModelAdmin.change_view | {} |
| ^$                   | polls_poll_changelist | django.contrib.admin.options.ModelAdmin.changelist_view | {} |
| ^(.+)/delete/$       | polls_poll_delete    | django.contrib.admin.options.ModelAdmin.delete_view | {} |
| ^(.+)/history/$      | polls_poll_history   | django.contrib.admin.options.ModelAdmin.history_view | {} |
| ^$                   | polls_vote_changelist | django.contrib.admin.options.ModelAdmin.changelist_view | {} |
| publisher/(?P<slug>[-_\w]+)/$ | publisher            | apps.books.views.PublisherDetailView | {} |
| question/(?P<slug>[-_\w]+)/$ | question             | apps.questions.views.QuestionDetailView | {} |
| ^add/$               | questions_answer_add | django.contrib.admin.options.ModelAdmin.add_view | {} |
| ^(.+)/change/$       | questions_answer_change | django.contrib.admin.options.ModelAdmin.change_view | {} |
| ^$                   | questions_answer_changelist | django.contrib.admin.options.ModelAdmin.changelist_view | {} |
| ^(.+)/delete/$       | questions_answer_delete | django.contrib.admin.options.ModelAdmin.delete_view | {} |
| ^(.+)/history/$      | questions_answer_history | django.contrib.admin.options.ModelAdmin.history_view | {} |
| ^add/$               | questions_question_add | django.contrib.admin.options.ModelAdmin.add_view | {} |
| ^(.+)/change/$       | questions_question_change | django.contrib.admin.options.ModelAdmin.change_view | {} |
| ^$                   | questions_question_changelist | django.contrib.admin.options.ModelAdmin.changelist_view | {} |
| ^(.+)/delete/$       | questions_question_delete | django.contrib.admin.options.ModelAdmin.delete_view | {} |
| ^(.+)/history/$      | questions_question_history | django.contrib.admin.options.ModelAdmin.history_view | {} |
| ^setlang/$           | set_language         | django.views.i18n.set_language | {} |
| ^add/$               | snippets_snippet_add | django.contrib.admin.options.ModelAdmin.add_view | {} |
| ^(.+)/change/$       | snippets_snippet_change | django.contrib.admin.options.ModelAdmin.change_view | {} |
| ^$                   | snippets_snippet_changelist | django.contrib.admin.options.ModelAdmin.changelist_view | {} |
| ^(.+)/delete/$       | snippets_snippet_delete | django.contrib.admin.options.ModelAdmin.delete_view | {} |
| ^(.+)/history/$      | snippets_snippet_history | django.contrib.admin.options.ModelAdmin.history_view | {} |
| solution/(?P<pk>\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/(?P<slug>[-_\w]+)/$ | solution             | apps.solutions.views.SolutionDetailView | {} |
| suit/(?P<slug>[-\w]+)/$ | suit                 | apps.testing.views.SuitDetailView | {} |
| tag/(?P<name>[-_\w]+)/$ | tag                  | apps.tags.views.TagDetailView | {} |
| theme/(?P<slug>[-_\w]+)/$ | theme                | apps.forum.views.SectionDetailView | {} |
| topic/(?P<slug>[-_\w]+)/$ | topic                | apps.forum.views.TopicDetailView | {} |
| update/$             | update               | apps.users.views.UserDetailView | {} |
| ^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$ | view_on_site         | django.contrib.contenttypes.views.shortcut | {} |
| writer/(?P<slug>[-_\w]+)/$ | writer               | apps.books.views.WriterDetailView | {} |
----------------------------------------------------------------------------------------------------
PADYMKO
fuente
44
Tenga en cuenta que los documentos recomiendan que no use print. En lugar de usar self.stdout.write. docs.djangoproject.com/en/1.10/howto/custom-management-commands
Dustin Wyatt
Necesitaba ver / ordenar por espacios de nombres y también ver todas las partes de URL, por lo que extendí este comando en stackoverflow.com/a/42388839/179581
Andrei
1
@Andrei, si obtuviste un resultado de tu respuesta, les daría a otros usuarios la posibilidad de ver un beneficio de tu método en mí
PADYMKO
7
def get_resolved_urls(url_patterns):
    url_patterns_resolved = []
    for entry in url_patterns:
        if hasattr(entry, 'url_patterns'):
            url_patterns_resolved += get_resolved_urls(
                entry.url_patterns)
        else:
            url_patterns_resolved.append(entry)
    return url_patterns_resolved

En python manage.py shell

import urls
get_resolved_urls(urls.urlpatterns)
Sandeep
fuente
4

En Django 3.0, es tan fácil como:

from django.urls import get_resolver
print(get_resolver().url_patterns)

Huellas dactilares: [<URLPattern '' [name='home']>, <URLPattern '/testing' [name='another_url']>]

Cameron Sima
fuente
3

He extendido el comando de Seti para mostrar el espacio de nombres, todas las partes de url, ajustar automáticamente los anchos de columna, ordenados por (espacio de nombres, nombre): https://gist.github.com/andreif/263a3fa6e7c425297ffee09c25f66b20

import sys
from django.core.management import BaseCommand
from django.conf.urls import RegexURLPattern, RegexURLResolver
from django.core import urlresolvers


def collect_urls(urls=None, namespace=None, prefix=None):
    if urls is None:
        urls = urlresolvers.get_resolver()
    _collected = []
    prefix = prefix or []
    for x in urls.url_patterns:
        if isinstance(x, RegexURLResolver):
            _collected += collect_urls(x, namespace=x.namespace or namespace,
                                       prefix=prefix + [x.regex.pattern])
        elif isinstance(x, RegexURLPattern):
            _collected.append({'namespace': namespace or '',
                               'name': x.name or '',
                               'pattern': prefix + [x.regex.pattern],
                               'lookup_str': x.lookup_str,
                               'default_args': dict(x.default_args)})
        else:
            raise NotImplementedError(repr(x))
    return _collected


def show_urls():
    all_urls = collect_urls()
    all_urls.sort(key=lambda x: (x['namespace'], x['name']))

    max_lengths = {}
    for u in all_urls:
        for k in ['pattern', 'default_args']:
            u[k] = str(u[k])
        for k, v in list(u.items())[:-1]:
            # Skip app_list due to length (contains all app names)
            if (u['namespace'], u['name'], k) == \
                    ('admin', 'app_list', 'pattern'):
                continue
            max_lengths[k] = max(len(v), max_lengths.get(k, 0))

    for u in all_urls:
        sys.stdout.write(' | '.join(
            ('{:%d}' % max_lengths.get(k, len(v))).format(v)
            for k, v in u.items()) + '\n')


class Command(BaseCommand):
    def handle(self, *args, **kwargs):
        show_urls()

Nota: el orden de las columnas se mantiene en Python 3.6 y sería necesario usarlo OrderedDicten versiones anteriores.

Actualización: una nueva versión con OrderedDict ahora vive en el paquete django-🍌s: https://github.com/5monkeys/django-bananas/blob/master/bananas/management/commands/show_urls.py

Andrei
fuente
1
de django.conf.urls import RegexURLPattern, RegexURLResolver no es más válido en django> 2.0 Pero adapté la esencia y funciona bien ahora, gracias
cwhisperer
Enfrenté este problema recientemente y actualicé la esencia. Uno necesitaría usar una revisión anterior para ejecutar en Django <2.0.
Andrei
2

Solución minimalista para django 2.0

Por ejemplo, si está buscando una URL que esté en la primera aplicación de instalted_apps, puede acceder de esta manera:

from django.urls import get_resolver
from pprint import pprint

pprint(
    get_resolver().url_patterns[0].url_patterns
)

fuente
Funciona para Django 1. * también si importa get_resolverdesde django.core.urlresolvers. Gracias marcio!
Fernando Costa Bertoldi
2

Django 1.8, Python 2.7+ Simplemente ejecute estos comandos en su Shell. Python manage.py shell y ejecuta el siguiente código.

from django.conf.urls import RegexURLPattern, RegexURLResolver
from django.core import urlresolvers
urls = urlresolvers.get_resolver(None)

def if_none(value):
    if value:
        return value
    return ''

def print_urls(urls, parent_pattern=None):
    for url in urls.url_patterns:
        if isinstance(url, RegexURLResolver):
            print_urls(url, if_none(parent_pattern) + url.regex.pattern)
        elif isinstance(url, RegexURLPattern):
            print(if_none(parent_pattern) + url.regex.pattern)

print_urls(urls)
Aditya Saini
fuente
1
¿Podría por favor proporcionar más detalles sobre su respuesta?
toshiro92
1
He editado mi respuesta, tienes que ejecutar esto en tu shell.
Aditya Saini
0

Puede crear una importación dinámica para reunir todos los patrones de URL de cada aplicación en su proyecto con un método simple como este:

def get_url_patterns():
    from django.apps import apps

    list_of_all_url_patterns = list()
    for name, app in apps.app_configs.items():
        # you have a directory structure where you should be able to build the correct path
        # my example shows that apps.[app_name].urls is where to look
        mod_to_import = f'apps.{name}.urls'
        try:
            urls = getattr(importlib.import_module(mod_to_import), "urlpatterns")
            list_of_all_url_patterns.extend(urls)
        except ImportError as ex:
            # is an app without urls
            pass

    return list_of_all_url_patterns

list_of_all_url_patterns = get_url_patterns()

Recientemente utilicé algo como esto para crear una etiqueta de plantilla para mostrar enlaces de navegación activos.

ViaTech
fuente
0
from django.urls.resolvers import RegexPattern,RoutePattern
from your_main_app import urls

def get_urls():
    url_list = []
    for url in urls.urlpatterns:
        url_list.append(url.pattern._regex) if isinstance(url.pattern, RegexPattern) else url_list.append(url.pattern._route)

    return url_list

Aquí your_main_appestá el nombre de la aplicación donde se ubica su archivo settings.py

nazmul_94_hasan
fuente