Django: Wie kann ich eine Liste von URL-Mustern sehen?

130

Wie kann ich die aktuellen URL-Muster sehen, in denen "reverse" angezeigt wird?

Ich rufe Reverse in einer Ansicht mit einem Argument auf, von dem ich denke, dass es funktionieren sollte, aber nicht. Wie kann ich überprüfen, was da ist und warum mein Muster nicht?

Interstar
quelle
DEBUG-Modus aktivieren und die Liste der URLs in der Debug-Ausgabe anzeigen?
Bootscodierer

Antworten:

181

Wenn Sie eine Liste aller URLs in Ihrem Projekt wünschen, müssen Sie zuerst Django-Erweiterungen installieren und diese wie folgt zu Ihren Einstellungen hinzufügen:

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

Führen Sie dann diesen Befehl in Ihrem Terminal aus

./manage.py show_urls

Weitere Informationen finden Sie in der Dokumentation.

Robert
quelle
3
Eigentlich habe ich mich geirrt, diese Funktion wird von django doch nicht zur Verfügung gestellt.
Robert
Alles was ich davon bekomme istTypeError: unsupported operand type(s) for +: 'NoneType' and 'str'
Paul Tomblin
6
NB: Sie müssen django_extensionsIhre INSTALLED_APPSnach der Installation hinzufügen
Owen
80

Versuche dies:

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

Oder wenn Sie noch auf Django 1 sind. *:

from django.core.urlresolvers import get_resolver
get_resolver(None).reverse_dict.keys()
SmileyChris
quelle
9
Dies gibt die Ansichtsfunktionen zurück, nicht die URLs
Ronen Ness
3
Um die URLs zurückzugeben, gehen Sie stattdessen folgendermaßen vor: set (v [1] für k, v in get_resolver (None) .reverse_dict.iteritems ())
kloddant
3
Oder für Python3:set(v[1] for k,v in get_resolver(None).reverse_dict.items())
Privat
6
django.core.urlresolverswurde in Django 2.0 entfernt , ersetzen Sie die Importlinie durchfrom django.urls import get_resolver
hoefling
2
Dies funktioniert nicht mehr für mich, sondern gibt nur einen kleinen Teil der URLs in meinem Projekt zurück
J__
32

Django> = 2.0 Lösung

Ich habe die anderen Antworten in diesem Beitrag getestet und sie funktionierten entweder nicht mit Django 2.X, unvollständig oder zu komplex. Deshalb hier meine Meinung dazu:

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))

Dieser Code druckt alle URLs, im Gegensatz zu einigen anderen Lösungen wird der vollständige Pfad und nicht nur der letzte Knoten gedruckt. z.B:

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
quelle
1
Wie kann ich tun, wenn ich URL und Namen der Ansicht erhalten möchte ... Weil ich den Namen der Ansicht und das Muster wie Ihr Ergebnis erhalten möchte ... Bitte wie?
Nathan Ingram
@NathanIngram Die Ansicht wird in der Eigenschaft "callback" des URLPattern-Objekts gespeichert, sodass Sie die yield acc + [str(l.pattern)]Zeile in ändern können yield acc + [str(l.pattern)], l.callback. Denken Sie daran, dass es die Ansichtsfunktion selbst und keinen Namen
zurückgibt
Ich erhalte die Fehlermeldung: --- >>>> TypeError: Sequenzelement 0: erwartete str-Instanz, Liste gefunden
Nathan Ingram
@NathanIngram Das "print (''. Join (p))" funktioniert nicht, da es jetzt eine Liste von Tupeln anstelle einer Liste von Zeichenfolgen ist. Versuchen Sie "print (''. Join (p [0]))".
Cesar Canassa
22

Django 1.11, Python 2.7.6

cd to_your_django_project

python manage.py Shell

Fügen Sie dann den folgenden Code ein.

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)

Beispielausgabe:

^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/^(.+)/$
...
kleines Säugetier
quelle
Dies ist die Antwort, die für mich funktioniert hat, obwohl ich sie in Nonedie Zeile aufnehmen musste urls = urlresolvers.get_resolver(None), und manchmal wurde am Anfang einiger URLs "Keine" angezeigt.
Chris
17

Es gibt ein Rezept für Activestate

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
quelle
1
Diese letzte Zeile sollte sein show_urls(urls.url_patterns).
Daniel Quinn
1
Ich bekomme ModuleNotFoundError: No module named 'urls', weiß nicht warum?
Alexey
1
@Alexey Dies hat wahrscheinlich etwas mit Django 2 zu tun. Können Sie dies bitte bestätigen, damit ich die Antwort aktualisieren kann?
pmav99
Ich habe diesen Code in der Datei test.pyim Stammverzeichnis meines Projekts abgelegt und habe diesen Fehler. Auch wenn ich dies import urlsim Interpreter tue , wird dieser Fehler ebenfalls angezeigt.
Alexey
Es handelt sich nicht um ein Django 1 vs 2-Problem: Es import urlshandelt sich um einen lokalen Import, daher müssen Sie dies wahrscheinlich tun from app_name import urls.
Aaron Klein
16

Ich benutze den nächsten Befehl:

(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)

Verwendung:

./manage.py showurls

Beispielausgabe:

----------------------------------------------------------------------------------------------------
| ^(.+)/$              |                      | 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
quelle
4
Beachten Sie, dass in den Dokumenten empfohlen wird, diese nicht zu verwenden print. Verwenden Sie stattdessen self.stdout.write. docs.djangoproject.com/de/1.10/howto/custom-management-commands
Dustin Wyatt
Ich musste Namespaces sehen / sortieren und auch alle URL-Teile sehen, also erweiterte ich
Andrei
1
@Andrei, wenn Sie eine Ausgabe von Ihrer Antwort gemacht haben, würde es anderen Benutzern die Möglichkeit geben, einen Vorteil Ihrer Methode auf mich zu sehen
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

In der Python-Shell "manage.py"

import urls
get_resolved_urls(urls.urlpatterns)
Sandeep
quelle
4

In Django 3.0 ist es so einfach wie:

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

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

Cameron Sima
quelle
3

Ich habe den Befehl von Seti erweitert , um den Namespace, alle URL-Teile und die Spaltenbreiten automatisch anzupassen, sortiert nach (Namespace, Name): 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()

Hinweis: Die Spaltenreihenfolge wird in Python 3.6 beibehalten und muss OrderedDictin älteren Versionen verwendet werden.

Update: Eine neue Version mit OrderedDict befindet sich jetzt im Paket von django: https://github.com/5monkeys/django-bananas/blob/master/bananas/management/commands/show_urls.py

Andrei
quelle
1
von django.conf.urls RegexURLPattern importiert, ist RegexURLResolver nicht mehr gültig in django> 2,0 Aber ich den Kern und wroks fein jetzt, thx angepasst
cwhisperer
Ich habe mich vor kurzem mit diesem Problem befasst und das Wesentliche aktualisiert. Man müsste eine frühere Revision verwenden, um auf Django <2.0 zu laufen.
Andrei
2

Minimalistische Lösung für Django 2.0

Wenn Sie beispielsweise nach einer URL suchen, die in der ersten App von installierten_Apps enthalten ist, können Sie folgendermaßen darauf zugreifen:

from django.urls import get_resolver
from pprint import pprint

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

quelle
Werke für Django 1. * Auch wenn Sie importieren get_resolveraus django.core.urlresolvers. Danke Marcio!
Fernando Costa Bertoldi
2

Django 1.8, Python 2.7+ Führen Sie diese Befehle einfach in Ihrer Shell aus. Python verwalten.py Shell und führen Sie den folgenden Code.

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
quelle
1
Könnten Sie bitte weitere Details zu Ihrer Antwort angeben?
toshiro92
1
Ich habe meine Antwort bearbeitet, Sie müssen dies in Ihrer Shell ausführen.
Aditya Saini
0

Sie können einen dynamischen Import erstellen, um alle URL-Muster aus jeder Anwendung in Ihrem Projekt mit einer einfachen Methode wie der folgenden zu erfassen:

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()

Ich habe kürzlich so etwas verwendet, um ein Vorlagen-Tag zu erstellen, auf dem aktive Navigationslinks angezeigt werden.

ViaTech
quelle
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

Hier your_main_appist der App-Name, unter dem sich Ihre Datei settings.py befindet

nazmul_94_hasan
quelle